fix rdar://7873482 by teaching the instruction encoder to emit
authorChris Lattner <sabre@nondot.org>
Sat, 19 Jun 2010 00:34:00 +0000 (00:34 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 19 Jun 2010 00:34:00 +0000 (00:34 +0000)
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
test/MC/AsmParser/X86/x86_32-new-encoder.s
test/MC/AsmParser/X86/x86_64-new-encoder.s

index d553b74a6bc8497b8979c9c524a0abca57654139..bff0e599871099ab78dff2020289d0cad504e88f 100644 (file)
@@ -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);
index 2363d60f2909e19e6601449a856dcf54415a5657..c93b698d0b3d9012ee9301f06b857da682ce6b72 100644 (file)
@@ -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
index 0c8ee89df72744920ff820eccb7bff0295460cb7..1858441870acabac13024a6c5dc79f4c98dfe300 100644 (file)
@@ -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
+