From: Owen Anderson Date: Wed, 31 Aug 2011 18:30:20 +0000 (+0000) Subject: Fix roundtripping of Thumb BL/BLX instructions with immediate offsets instead of... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=559c277aa9242dd5b32d2f2ccc353d938f886ee9;p=oota-llvm.git 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 --- diff --git a/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index 7cac54c610b..f6b8af87b54 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 &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 &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 &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 94ba83928a3..d47b8eb0fa3 100644 --- a/test/MC/ARM/basic-thumb-instructions.s +++ b/test/MC/ARM/basic-thumb-instructions.s @@ -117,6 +117,15 @@ _func: @ CHECK: b #1838 @ encoding: [0x97,0xe3] @ 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 @------------------------------------------------------------------------------