aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2010-12-08 00:18:36 +0000
committerOwen Anderson <resistor@mac.com>2010-12-08 00:18:36 +0000
commitd8e351b96f5fd7007fbdd636acaa1fc9f6e18f3c (patch)
tree0c76b83a6946f82c9a16aff12aad8823ae11c93a
parente113ae56d9ee2fddce14f5caaae1229e70ee0a00 (diff)
VLDR fixups need special handling under Thumb. While the encoding is the same,
the order of the bytes in the data stream is flipped around. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121215 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMAsmBackend.cpp12
-rw-r--r--lib/Target/ARM/ARMFixupKinds.h5
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp8
3 files changed, 23 insertions, 2 deletions
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index 96a5548134..7c4823d8ba 100644
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/ARMAsmBackend.cpp
@@ -115,6 +115,7 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
Binary = ((Binary & 0x7ff) << 16) | (Binary >> 11);
return Binary;
}
+ case ARM::fixup_t2_pcrel_10:
case ARM::fixup_arm_pcrel_10: {
// Offset by 8 just as above.
Value = Value - 8;
@@ -127,6 +128,16 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
Value >>= 2;
assert ((Value < 256) && "Out of range pc-relative fixup value!");
Value |= isAdd << 23;
+
+ // Same addressing mode as fixup_arm_pcrel_10, but with the bytes reordered.
+ if (Kind == ARM::fixup_t2_pcrel_10) {
+ uint64_t swapped = (Value & 0x00FF0000) >> 16;
+ swapped |= (Value & 0xFF000000) >> 16;
+ swapped |= (Value & 0x000000FF) << 16;
+ swapped |= (Value & 0x0000FF00) << 16;
+ return swapped;
+ }
+
return Value;
}
}
@@ -218,6 +229,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case ARM::fixup_arm_adr_pcrel_12:
case ARM::fixup_arm_branch:
return 3;
+ case ARM::fixup_t2_pcrel_10:
case ARM::fixup_arm_thumb_bl:
return 4;
}
diff --git a/lib/Target/ARM/ARMFixupKinds.h b/lib/Target/ARM/ARMFixupKinds.h
index c905611906..0136e0c004 100644
--- a/lib/Target/ARM/ARMFixupKinds.h
+++ b/lib/Target/ARM/ARMFixupKinds.h
@@ -19,9 +19,12 @@ enum Fixups {
// addresses
fixup_arm_ldst_pcrel_12 = FirstTargetFixupKind,
// fixup_arm_pcrel_10 - 10-bit PC relative relocation for symbol addresses
- // used in VFP and Thumb2 instructions where the lower 2 bits are not encoded
+ // used in VFP instructions where the lower 2 bits are not encoded
// (so it's encoded as an 8-bit immediate).
fixup_arm_pcrel_10,
+ // fixup_t2_pcrel_10 - Equivalent to fixup_arm_pcrel_10, accounting for
+ // the byteswapped encoding of Thumb2 instructions.
+ fixup_t2_pcrel_10,
// fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
// instruction.
fixup_arm_adr_pcrel_12,
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index 229e00e65d..ba1f6d30ca 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -48,6 +48,7 @@ public:
// name off bits flags
{ "fixup_arm_ldst_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_pcrel_10", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_t2_pcrel_10", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_adr_pcrel_12", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_branch", 1, 24, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_arm_thumb_bl", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
@@ -737,7 +738,12 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
assert(MO.isExpr() && "Unexpected machine operand type!");
const MCExpr *Expr = MO.getExpr();
- MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
+ MCFixupKind Kind;
+ const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+ if (Subtarget.isThumb2())
+ Kind = MCFixupKind(ARM::fixup_t2_pcrel_10);
+ else
+ Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
Fixups.push_back(MCFixup::Create(0, Expr, Kind));
++MCNumCPRelocations;