Fix generation of the address size override prefix. Add assertions for

the invalid cases. At least 16bit operand in 64bit mode is currently not
rejected in the parser.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153166 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Joerg Sonnenberger 2012-03-21 05:48:07 +00:00
parent 10fa51b950
commit 4fd3d29275
2 changed files with 64 additions and 5 deletions

View File

@ -46,6 +46,11 @@ public:
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
}
bool is32BitMode() const {
// FIXME: Can tablegen auto-generate this?
return (STI.getFeatureBits() & X86::Mode64Bit) == 0;
}
static unsigned GetX86RegNum(const MCOperand &MO) {
return X86_MC::getX86RegNum(MO.getReg());
}
@ -154,9 +159,8 @@ static MCFixupKind getImmFixupKind(uint64_t TSFlags) {
return MCFixup::getKindForSize(Size, isPCRel);
}
/// Is32BitMemOperand - Return true if the specified instruction with a memory
/// operand should emit the 0x67 prefix byte in 64-bit mode due to a 32-bit
/// memory operand. Op specifies the operand # of the memoperand.
/// Is32BitMemOperand - Return true if the specified instruction has
/// a 32-bit memory operand. Op specifies the operand # of the memoperand.
static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg);
const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
@ -169,6 +173,34 @@ static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
return false;
}
/// Is64BitMemOperand - Return true if the specified instruction has
/// a 64-bit memory operand. Op specifies the operand # of the memoperand.
static bool Is64BitMemOperand(const MCInst &MI, unsigned Op) {
const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg);
const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
if ((BaseReg.getReg() != 0 &&
X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg.getReg())) ||
(IndexReg.getReg() != 0 &&
X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg.getReg())))
return true;
return false;
}
/// Is16BitMemOperand - Return true if the specified instruction has
/// a 16-bit memory operand. Op specifies the operand # of the memoperand.
static bool Is16BitMemOperand(const MCInst &MI, unsigned Op) {
const MCOperand &BaseReg = MI.getOperand(Op+X86::AddrBaseReg);
const MCOperand &IndexReg = MI.getOperand(Op+X86::AddrIndexReg);
if ((BaseReg.getReg() != 0 &&
X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg.getReg())) ||
(IndexReg.getReg() != 0 &&
X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg.getReg())))
return true;
return false;
}
/// StartsWithGlobalOffsetTable - Check if this expression starts with
/// _GLOBAL_OFFSET_TABLE_ and if it is of the form
/// _GLOBAL_OFFSET_TABLE_-symbol. This is needed to support PIC on ELF
@ -817,8 +849,22 @@ void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
EmitByte(0xF3, CurByte, OS);
// Emit the address size opcode prefix as needed.
if ((TSFlags & X86II::AdSize) ||
(MemOperand != -1 && is64BitMode() && Is32BitMemOperand(MI, MemOperand)))
bool need_address_override;
if (TSFlags & X86II::AdSize) {
need_address_override = true;
} else if (MemOperand == -1) {
need_address_override = false;
} else if (is64BitMode()) {
assert(!Is16BitMemOperand(MI, MemOperand));
need_address_override = Is32BitMemOperand(MI, MemOperand);
} else if (is32BitMode()) {
assert(!Is64BitMemOperand(MI, MemOperand));
need_address_override = Is16BitMemOperand(MI, MemOperand);
} else {
need_address_override = false;
}
if (need_address_override)
EmitByte(0x67, CurByte, OS);
// Emit the operand size opcode prefix as needed.

View File

@ -0,0 +1,13 @@
// RUN: llvm-mc -triple x86_64-unknown-unknown --show-encoding %s | FileCheck %s
.code64
movb $0x0, (%esi)
// CHECK: encoding: [0x67,0xc6,0x06,0x00]
movb $0x0, (%rsi)
// CHECK: encoding: [0xc6,0x06,0x00]
.code32
movb $0x0, (%si)
// CHECK: encoding: [0x67,0xc6,0x06,0x00]
movb $0x0, (%esi)
// CHECK: encoding: [0xc6,0x06,0x00]