diff options
author | Owen Anderson <resistor@mac.com> | 2011-08-31 18:30:20 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2011-08-31 18:30:20 +0000 |
commit | 559c277aa9242dd5b32d2f2ccc353d938f886ee9 (patch) | |
tree | 4451bc7917f1b705dc2dd1d0c541c308724d30ef | |
parent | c9a9b442853ee086492d6ad1384a2de2fea9b43b (diff) |
Fix roundtripping of Thumb BL/BLX instructions with immediate offsets instead of labels.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138874 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 34 | ||||
-rw-r--r-- | test/MC/ARM/basic-thumb-instructions.s | 9 |
2 files changed, 40 insertions, 3 deletions
diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 7cac54c610..f6b8af87b5 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -465,11 +465,34 @@ static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, return 0; } +// Thumb BL and BLX use a strange offset encoding where bits 22 and 21 are +// determined by negating them and XOR'ing them with bit 23. +static int32_t encodeThumbBLOffset(int32_t offset) { + offset >>= 1; + uint32_t S = (offset & 0x800000) >> 23; + uint32_t J1 = (offset & 0x400000) >> 22; + uint32_t J2 = (offset & 0x200000) >> 21; + J1 = (~J1 & 0x1); + J2 = (~J2 & 0x1); + J1 ^= S; + J2 ^= S; + + offset &= ~0x600000; + offset |= J1 << 22; + offset |= J2 << 21; + + return offset; +} + /// getThumbBLTargetOpValue - Return encoding info for immediate branch target. uint32_t ARMMCCodeEmitter:: getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, Fixups); + const MCOperand MO = MI.getOperand(OpIdx); + if (MO.isExpr()) + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_bl, + Fixups); + return encodeThumbBLOffset(MO.getImm()); } /// getThumbBLXTargetOpValue - Return encoding info for Thumb immediate @@ -477,7 +500,11 @@ getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx, uint32_t ARMMCCodeEmitter:: getThumbBLXTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, Fixups); + const MCOperand MO = MI.getOperand(OpIdx); + if (MO.isExpr()) + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_blx, + Fixups); + return encodeThumbBLOffset(MO.getImm()); } /// getThumbBRTargetOpValue - Return encoding info for Thumb branch target. @@ -486,7 +513,8 @@ getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &Fixups) const { const MCOperand MO = MI.getOperand(OpIdx); if (MO.isExpr()) - return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, Fixups); + return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_thumb_br, + Fixups); return (MO.getImm() >> 1); } diff --git a/test/MC/ARM/basic-thumb-instructions.s b/test/MC/ARM/basic-thumb-instructions.s index 94ba83928a..d47b8eb0fa 100644 --- a/test/MC/ARM/basic-thumb-instructions.s +++ b/test/MC/ARM/basic-thumb-instructions.s @@ -118,6 +118,15 @@ _func: @ CHECK: b #-420 @ encoding: [0x2e,0xe7] @------------------------------------------------------------------------------ +@ BL/BLX +@------------------------------------------------------------------------------ + blx #884800 + blx #1769600 + +@ CHECK: blx #884800 @ encoding: [0xd8,0xf0,0x20,0xe8] +@ CHECK: blx #1769600 @ encoding: [0xb0,0xf1,0x40,0xe8] + +@------------------------------------------------------------------------------ @ BICS @------------------------------------------------------------------------------ bics r1, r6 |