From a08b587494a09a94a72245dd9d7088564e511f4e Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 16 Feb 2010 05:03:17 +0000 Subject: [PATCH] make pcrel immediate values relative to the start of the field, 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 | 16 +++++++++++++--- test/MC/AsmParser/X86/x86_64-new-encoder.s | 10 +++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index d0ec0de6913..3f18696d855 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/lib/Target/X86/X86MCCodeEmitter.cpp @@ -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), diff --git a/test/MC/AsmParser/X86/x86_64-new-encoder.s b/test/MC/AsmParser/X86/x86_64-new-encoder.s index 7536a014148..56ec0b38994 100644 --- a/test/MC/AsmParser/X86/x86_64-new-encoder.s +++ b/test/MC/AsmParser/X86/x86_64-new-encoder.s @@ -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 -- 2.34.1