make pcrel immediate values relative to the start of the field,
authorChris Lattner <sabre@nondot.org>
Tue, 16 Feb 2010 05:03:17 +0000 (05:03 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 16 Feb 2010 05:03:17 +0000 (05:03 +0000)
not the end of the field, fixing rdar://7651978

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96330 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86MCCodeEmitter.cpp
test/MC/AsmParser/X86/x86_64-new-encoder.s

index d0ec0de6913083906c7e7f1ef7b83716c9c760ae..3f18696d8555c5f3b3d779407050f8a28e2c5d68 100644 (file)
@@ -153,14 +153,25 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
   // If this is a simple integer displacement that doesn't require a relocation,
   // emit it now.
   if (DispOp.isImm()) {
+    // FIXME: is this right for pc-rel encoding??  Probably need to emit this as
+    // a fixup if so.
     EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS);
     return;
   }
 
   // If we have an immoffset, add it to the expression.
   const MCExpr *Expr = DispOp.getExpr();
+  
+  // If the fixup is pc-relative, we need to bias the value to be relative to
+  // the start of the field, not the end of the field.
+  if (FixupKind == MCFixupKind(X86::reloc_pcrel_4byte) ||
+      FixupKind == MCFixupKind(X86::reloc_riprel_4byte))
+    ImmOffset -= 4;
+  if (FixupKind == MCFixupKind(X86::reloc_pcrel_1byte))
+    ImmOffset -= 1;
+  
   if (ImmOffset)
-    Expr = MCBinaryExpr::CreateAdd(Expr,MCConstantExpr::Create(ImmOffset, Ctx),
+    Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(ImmOffset, Ctx),
                                    Ctx);
   
   // Emit a symbolic constant as a fixup and 4 zeros.
@@ -192,6 +203,7 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op,
     // the size of the immediate field.  If we have this case, add it into the
     // expression to emit.
     int ImmSize = X86II::hasImm(TSFlags) ? X86II::getSizeOfImm(TSFlags) : 0;
+    
     EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_riprel_4byte),
                   CurByte, OS, Fixups, -ImmSize);
     return;
@@ -616,8 +628,6 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
   
   // If there is a remaining operand, it must be a trailing immediate.  Emit it
   // according to the right size for the instruction.
-  // FIXME: This should pass in whether the value is pc relative or not.  This
-  // information should be aquired from TSFlags as well.
   if (CurOp != NumOps)
     EmitImmediate(MI.getOperand(CurOp++),
                   X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags),
index 7536a0141480943e2bf3a1f9cb271b98d6858abf..56ec0b38994fa6c98cc5aa38c612c020a2a2a060 100644 (file)
@@ -3,24 +3,24 @@
 movl   foo(%rip), %eax
 // CHECK: movl foo(%rip), %eax
 // CHECK: encoding: [0x8b,0x05,A,A,A,A]
-// CHECK: fixup A - offset: 2, value: foo, kind: reloc_riprel_4byte
+// CHECK: fixup A - offset: 2, value: foo-4, kind: reloc_riprel_4byte
 
 movb   $12, foo(%rip)
 // CHECK: movb $12, foo(%rip)
 // CHECK: encoding: [0xc6,0x05,A,A,A,A,0x0c]
-// CHECK:    fixup A - offset: 2, value: foo-1, kind: reloc_riprel_4byte
+// CHECK:    fixup A - offset: 2, value: foo-5, kind: reloc_riprel_4byte
 
 movw   $12, foo(%rip)
 // CHECK: movw $12, foo(%rip)
 // CHECK: encoding: [0x66,0xc7,0x05,A,A,A,A,0x0c,0x00]
-// CHECK:    fixup A - offset: 3, value: foo-2, kind: reloc_riprel_4byte
+// CHECK:    fixup A - offset: 3, value: foo-6, kind: reloc_riprel_4byte
 
 movl   $12, foo(%rip)
 // CHECK: movl $12, foo(%rip)
 // CHECK: encoding: [0xc7,0x05,A,A,A,A,0x0c,0x00,0x00,0x00]
-// CHECK:    fixup A - offset: 2, value: foo-4, kind: reloc_riprel_4byte
+// CHECK:    fixup A - offset: 2, value: foo-8, kind: reloc_riprel_4byte
 
 movq   $12, foo(%rip)
 // CHECK:  movq        $12, foo(%rip)
 // CHECK: encoding: [0x48,0xc7,0x05,A,A,A,A,0x0c,0x00,0x00,0x00]
-// CHECK:    fixup A - offset: 3, value: foo-4, kind: reloc_riprel_4byte
+// CHECK:    fixup A - offset: 3, value: foo-8, kind: reloc_riprel_4byte