[llvm-commits] [llvm] r107917 - in /llvm/trunk: lib/Target/X86/X86MCCodeEmitter.cpp test/MC/AsmParser/X86/x86_64-encoding.s

Chris Lattner sabre at nondot.org
Thu Jul 8 15:28:12 PDT 2010


Author: lattner
Date: Thu Jul  8 17:28:12 2010
New Revision: 107917

URL: http://llvm.org/viewvc/llvm-project?rev=107917&view=rev
Log:
Rework segment prefix emission code to handle segments
in memory operands at the same type as hard coded segments.
This fixes problems where we'd emit the segment override after
the REX prefix on instructions like:
mov %gs:(%rdi), %rax

This fixes rdar://8127102.  I have several cleanup patches coming
next.

Modified:
    llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp
    llvm/trunk/test/MC/AsmParser/X86/x86_64-encoding.s

Modified: llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp?rev=107917&r1=107916&r2=107917&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp Thu Jul  8 17:28:12 2010
@@ -121,9 +121,6 @@
   }
   
   
-  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,
@@ -136,7 +133,7 @@
                            const MCInst &MI, const TargetInstrDesc &Desc,
                            raw_ostream &OS) const;
 
-  void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
+  void EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte, int MemOperand,
                         const MCInst &MI, const TargetInstrDesc &Desc,
                         raw_ostream &OS) const;
 };
@@ -214,27 +211,6 @@
   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;
-
-  // 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,
                                         uint64_t TSFlags, unsigned &CurByte,
@@ -662,8 +638,11 @@
 }
 
 /// EmitOpcodePrefix - Emit all instruction prefixes prior to the opcode.
+///
+/// MemOperand is the operand # of the start of a memory operand if present.  If
+/// Not present, it is -1.
 void X86MCCodeEmitter::EmitOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
-                                        const MCInst &MI, 
+                                        int MemOperand, const MCInst &MI, 
                                         const TargetInstrDesc &Desc,
                                         raw_ostream &OS) const {
 
@@ -674,7 +653,24 @@
   // Emit segment override opcode prefix as needed.
   switch (TSFlags & X86II::SegOvrMask) {
   default: assert(0 && "Invalid segment!");
-  case 0: break;  // No segment override!
+  case 0:
+    // No segment override, check for explicit one on memory operand.
+    if (MemOperand != -1 &&   // If the instruction has a memory operand.
+        // FIXME: This is disgusting.
+        MI.getOpcode() != X86::LEA64r && MI.getOpcode() != X86::LEA64_32r &&
+        MI.getOpcode() != X86::LEA16r && MI.getOpcode() != X86::LEA32r) {
+      switch (MI.getOperand(MemOperand+X86AddrSegment).getReg()) {
+      default: assert(0 && "Unknown segment register!");
+      case 0: break;
+      case X86::CS: EmitByte(0x2E, CurByte, OS); break;
+      case X86::SS: EmitByte(0x36, CurByte, OS); break;
+      case X86::DS: EmitByte(0x3E, CurByte, OS); break;
+      case X86::ES: EmitByte(0x26, CurByte, OS); break;
+      case X86::FS: EmitByte(0x64, CurByte, OS); break;
+      case X86::GS: EmitByte(0x65, CurByte, OS); break;
+      }
+    }
+    break;
   case X86II::FS:
     EmitByte(0x64, CurByte, OS);
     break;
@@ -757,6 +753,17 @@
   const TargetInstrDesc &Desc = TII.get(Opcode);
   uint64_t TSFlags = Desc.TSFlags;
 
+  
+  // If this is a two-address instruction, skip one of the register operands.
+  // FIXME: This should be handled during MCInst lowering.
+  unsigned NumOps = Desc.getNumOperands();
+  unsigned CurOp = 0;
+  if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1)
+    ++CurOp;
+  else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0)
+    // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
+    --NumOps;
+  
   // Keep track of the current byte being emitted.
   unsigned CurByte = 0;
   
@@ -770,24 +777,17 @@
     HasVEXPrefix = true;
   if ((TSFlags >> 32) & X86II::VEX_4V)
     HasVEX_4V = true;
-
-  // FIXME: We should emit the prefixes in exactly the same order as GAS does,
-  // in order to provide diffability.
-
+  
+  // Determine where the memory operand starts, if present.
+  int MemoryOperand = X86II::getMemoryOperandNo(TSFlags);
+  if (MemoryOperand != -1) MemoryOperand += CurOp;
+  
   if (!HasVEXPrefix)
-    EmitOpcodePrefix(TSFlags, CurByte, MI, Desc, OS);
+    EmitOpcodePrefix(TSFlags, CurByte, MemoryOperand, MI, Desc, OS);
   else
+    // FIXME: Segment overrides??
     EmitVEXOpcodePrefix(TSFlags, CurByte, MI, Desc, OS);
   
-  // If this is a two-address instruction, skip one of the register operands.
-  unsigned NumOps = Desc.getNumOperands();
-  unsigned CurOp = 0;
-  if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1)
-    ++CurOp;
-  else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0)
-    // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
-    --NumOps;
-  
   unsigned char BaseOpcode = X86II::getBaseOpcodeFor(TSFlags);
   unsigned SrcRegNum = 0;
   switch (TSFlags & X86II::FormMask) {
@@ -812,7 +812,6 @@
     break;
   
   case X86II::MRMDestMem:
-    EmitSegmentOverridePrefix(MI.getOperand(CurOp + 4), TSFlags, CurByte, OS);
     EmitByte(BaseOpcode, CurByte, OS);
     EmitMemModRMByte(MI, CurOp,
                      GetX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands)),
@@ -844,12 +843,8 @@
     if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r ||
         Opcode == X86::LEA16r || Opcode == X86::LEA32r)
       --AddrOperands; // No segment register
-    else
-      EmitSegmentOverridePrefix(MI.getOperand(FirstMemOp+4),
-                                TSFlags, CurByte, OS);
 
     EmitByte(BaseOpcode, CurByte, OS);
-
     
     EmitMemModRMByte(MI, FirstMemOp, GetX86RegNum(MI.getOperand(CurOp)),
                      TSFlags, CurByte, OS, Fixups);
@@ -872,7 +867,6 @@
   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);

Modified: llvm/trunk/test/MC/AsmParser/X86/x86_64-encoding.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/X86/x86_64-encoding.s?rev=107917&r1=107916&r2=107917&view=diff
==============================================================================
--- llvm/trunk/test/MC/AsmParser/X86/x86_64-encoding.s (original)
+++ llvm/trunk/test/MC/AsmParser/X86/x86_64-encoding.s Thu Jul  8 17:28:12 2010
@@ -4,6 +4,11 @@
 // CHECK: callw 42
 // CHECK: encoding: [0x66,0xe8,A,A]
        callw 42
+       
+// rdar://8127102
+// CHECK: movq	%gs:(%rdi), %rax
+// CHECK: encoding: [0x65,0x48,0x8b,0x07]
+movq	%gs:(%rdi), %rax
 
 // CHECK: crc32b 	%bl, %eax
 // CHECK:  encoding: [0xf2,0x0f,0x38,0xf0,0xc3]





More information about the llvm-commits mailing list