From 4fd3d292753bd8232a76d5ac6b107f5899e5bfaa Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Wed, 21 Mar 2012 05:48:07 +0000 Subject: [PATCH] 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 --- .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 56 +++++++++++++++++-- test/MC/X86/address-size.s | 13 +++++ 2 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 test/MC/X86/address-size.s diff --git a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 37727b6c344..0d8ee174d51 100644 --- a/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -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. diff --git a/test/MC/X86/address-size.s b/test/MC/X86/address-size.s new file mode 100644 index 00000000000..b105b40ec56 --- /dev/null +++ b/test/MC/X86/address-size.s @@ -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]