Fix Thumb2 BCC encoding and fixups.
authorOwen Anderson <resistor@mac.com>
Thu, 9 Dec 2010 00:27:41 +0000 (00:27 +0000)
committerOwen Anderson <resistor@mac.com>
Thu, 9 Dec 2010 00:27:41 +0000 (00:27 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121329 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmBackend.cpp
lib/Target/ARM/ARMFixupKinds.h
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMMCCodeEmitter.cpp

index 1754870b95c54bc185046912b192249a7bd65577..00cd4e79de977bae9fd73164c9da77a1caa4fd97 100644 (file)
@@ -127,6 +127,21 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
     // These values don't encode the low two bits since they're always zero.
     // Offset by 8 just as above.
     return 0xffffff & ((Value - 8) >> 2);
+  case ARM::fixup_t2_branch: {
+    Value = Value - 6;
+    Value >>= 1; // Low bit is not encoded.
+    
+    uint64_t out = 0;
+    Value |= (Value & 0x80000) << 7; // S bit
+    Value |= (Value & 0x40000) >> 7; // J2 bit
+    Value |= (Value & 0x20000) >> 4; // J1 bit
+    Value |= (Value & 0x1F800) << 5; // imm6 field
+    Value |= (Value & 0x007FF);      // imm11 field
+    
+    uint64_t swapped = (out & 0xFFFF0000) >> 16;
+    swapped |= (out & 0x0000FFFF) << 16;
+    return swapped;
+  }
   case ARM::fixup_arm_thumb_bl: {
     // The value doesn't encode the low bit (always zero) and is offset by
     // four. The value is encoded into disjoint bit positions in the destination
@@ -273,6 +288,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
     return 3;
 
   case FK_Data_4:
+  case ARM::fixup_t2_branch:
   case ARM::fixup_t2_pcrel_10:
   case ARM::fixup_arm_thumb_bl:
     return 4;
index 1c7435fd7d286624e2ea52903062167b9cea53de..c18d84861e2e768506345ebc4573fa343c604909 100644 (file)
@@ -23,7 +23,7 @@ enum Fixups {
   // (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.
+  // the short-swapped encoding of Thumb2 instructions.
   fixup_t2_pcrel_10,
   // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
   // instruction.
@@ -31,6 +31,9 @@ enum Fixups {
   // fixup_arm_branch - 24-bit PC relative relocation for direct branch
   // instructions.
   fixup_arm_branch,
+  // fixup_t2_branch - 20-bit PC relative relocation for Thumb2 direct branch
+  // instructions.
+  fixup_t2_branch,
 
   // fixup_arm_thumb_bl - Fixup for Thumb BL/BLX instructions.
   fixup_arm_thumb_bl,
index 2614a61f1a321ce83de3c15ecb08c2e167d511f8..d94b5c0c0d354740a7ebe176542e409925b8a72a 100644 (file)
@@ -3023,13 +3023,16 @@ def t2Bcc : T2I<(outs), (ins brtarget:$target), IIC_Br,
   let Inst{31-27} = 0b11110;
   let Inst{15-14} = 0b10;
   let Inst{12} = 0;
-
-  bits<20> target;
-  let Inst{26} = target{19};
-  let Inst{11} = target{18};
-  let Inst{13} = target{17};
-  let Inst{21-16} = target{16-11};
-  let Inst{10-0} = target{10-0};
+  
+  bits<4> p;
+  let Inst{25-22} = p;
+
+  bits<21> target;
+  let Inst{26} = target{20};
+  let Inst{11} = target{19};
+  let Inst{13} = target{18};
+  let Inst{21-16} = target{17-12};
+  let Inst{10-0} = target{11-1};
 }
 
 
index ef9fac436c748ced9f21c8383be02f7de0ce109a..ebcab8b8d33cd4127b3f8f96fe2f97c2bf78aa90 100644 (file)
@@ -51,6 +51,7 @@ public:
       { "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_t2_branch",          0,    32,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_bl",       0,    32,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_br",       0,    16,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_thumb_cp",       1,    8,    MCFixupKindInfo::FKF_IsPCRel },
@@ -454,6 +455,9 @@ getThumbBRTargetOpValue(const MCInst &MI, unsigned OpIdx,
 uint32_t ARMMCCodeEmitter::
 getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                        SmallVectorImpl<MCFixup> &Fixups) const {
+  const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
+  if (Subtarget.isThumb2())
+    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_branch, Fixups);
   return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
 }