From 1cf44fc051e05c7cd96a4b071b654381338baae9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 19 Jun 2010 00:34:00 +0000 Subject: [PATCH] fix rdar://7873482 by teaching the instruction encoder to emit segment prefixes. Daniel wrote most of this patch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106364 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86MCCodeEmitter.cpp | 52 ++++++++++++++++++---- test/MC/AsmParser/X86/x86_32-new-encoder.s | 5 +++ test/MC/AsmParser/X86/x86_64-new-encoder.s | 6 +++ 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index d553b74a6bc..bff0e599871 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/X86MCCodeEmitter.cpp @@ -99,6 +99,9 @@ public: } + void EmitSegmentOverridePrefix(const MCOperand &Op, unsigned TSFlags, + unsigned &CurByte, raw_ostream &OS) const; + void EmitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, uint64_t TSFlags, unsigned &CurByte, raw_ostream &OS, @@ -188,6 +191,32 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind, EmitConstant(0, Size, CurByte, OS); } +void X86MCCodeEmitter::EmitSegmentOverridePrefix(const MCOperand &Op, + unsigned TSFlags, + unsigned &CurByte, + raw_ostream &OS) const { + // If no segment register is present, we don't need anything. + if (Op.getReg() == 0) + return; + +#if 0 + // Otherwise, emit an address size prefix if we didn't already emit one. + if (Is64BitMode && !(TSFlags & X86II::AdSize)) + EmitByte(0x67, CurByte, OS); +#endif + + // Check if we need an override. + switch (Op.getReg()) { + case X86::CS: EmitByte(0x2E, CurByte, OS); return; + case X86::SS: EmitByte(0x36, CurByte, OS); return; + case X86::DS: EmitByte(0x3E, CurByte, OS); return; + case X86::ES: EmitByte(0x26, CurByte, OS); return; + case X86::FS: EmitByte(0x64, CurByte, OS); return; + case X86::GS: EmitByte(0x65, CurByte, OS); return; + } + + assert(0 && "Invalid segment register!"); +} void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, @@ -737,6 +766,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, break; case X86II::MRMDestMem: + EmitSegmentOverridePrefix(MI.getOperand(CurOp + 4), TSFlags, CurByte, OS); EmitByte(BaseOpcode, CurByte, OS); EmitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands)), @@ -757,22 +787,25 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, break; case X86II::MRMSrcMem: { - EmitByte(BaseOpcode, CurByte, OS); + int AddrOperands = X86AddrNumOperands; + unsigned FirstMemOp = CurOp+1; + if (IsAVXForm) { + ++AddrOperands; + ++FirstMemOp; // Skip the register source (which is encoded in VEX_VVVV). + } // FIXME: Maybe lea should have its own form? This is a horrible hack. - int AddrOperands; if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || Opcode == X86::LEA16r || Opcode == X86::LEA32r) - AddrOperands = X86AddrNumOperands - 1; // No segment register + --AddrOperands; // No segment register else - AddrOperands = X86AddrNumOperands; + EmitSegmentOverridePrefix(MI.getOperand(FirstMemOp+4), + TSFlags, CurByte, OS); - if (IsAVXForm) - AddrOperands++; + EmitByte(BaseOpcode, CurByte, OS); - // Skip the register source (which is encoded in VEX_VVVV) - EmitMemModRMByte(MI, IsAVXForm ? CurOp+2 : CurOp+1, - GetX86RegNum(MI.getOperand(CurOp)), + + EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)), TSFlags, CurByte, OS, Fixups); CurOp += AddrOperands + 1; break; @@ -791,6 +824,7 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: case X86II::MRM6m: case X86II::MRM7m: + EmitSegmentOverridePrefix(MI.getOperand(CurOp+4), TSFlags, CurByte, OS); EmitByte(BaseOpcode, CurByte, OS); EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m, TSFlags, CurByte, OS, Fixups); diff --git a/test/MC/AsmParser/X86/x86_32-new-encoder.s b/test/MC/AsmParser/X86/x86_32-new-encoder.s index 2363d60f290..c93b698d0b3 100644 --- a/test/MC/AsmParser/X86/x86_32-new-encoder.s +++ b/test/MC/AsmParser/X86/x86_32-new-encoder.s @@ -393,3 +393,8 @@ retl // CHECK: wait // CHECK: encoding: [0x9b] fwait + +// rdar://7873482 +// CHECK: [0x65,0x8b,0x05,0x7c,0x00,0x00,0x00] +// FIXME: This is a correct bug poor encoding: Use 65 a1 7c 00 00 00 + movl %gs:124, %eax diff --git a/test/MC/AsmParser/X86/x86_64-new-encoder.s b/test/MC/AsmParser/X86/x86_64-new-encoder.s index 0c8ee89df72..1858441870a 100644 --- a/test/MC/AsmParser/X86/x86_64-new-encoder.s +++ b/test/MC/AsmParser/X86/x86_64-new-encoder.s @@ -144,3 +144,9 @@ btq $0x01,%rdx // CHECK: movzbq (%rsp), %rsi // CHECK: encoding: [0x48,0x0f,0xb6,0x34,0x24] movzx 0(%rsp), %rsi + + +// rdar://7873482 +// CHECK: [0x65,0x8b,0x04,0x25,0x7c,0x00,0x00,0x00] + movl %gs:124, %eax +