In Thumb2, direct branches can be encoded as either a "short" conditional branch...
authorOwen Anderson <resistor@mac.com>
Mon, 13 Dec 2010 19:31:11 +0000 (19:31 +0000)
committerOwen Anderson <resistor@mac.com>
Mon, 13 Dec 2010 19:31:11 +0000 (19:31 +0000)
as a "long" direct branch.  While the mnemonics are the same, they encode the branch offset differently, and
the Darwin assembler appears to prefer the "long" form for direct branches.  Thus, in the name of bitwise
equivalence, provide encoding and fixup support for it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121710 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmBackend.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMFixupKinds.h
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
utils/TableGen/EDEmitter.cpp
utils/TableGen/X86RecognizableInstr.cpp

index ffa9307c9a73f243a6779c38cdd3448437c5d6a2..cb0c54386ed67e95d7663b157d773d7d5ef039cd 100644 (file)
@@ -140,11 +140,32 @@ 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: {
+  case ARM::fixup_t2_uncondbranch: {
     Value = Value - 4;
     Value >>= 1; // Low bit is not encoded.
 
     uint32_t out = 0;
+    bool I =  Value & 0x800000;
+    bool J1 = Value & 0x400000;
+    bool J2 = Value & 0x200000;
+    J1 ^= I;
+    J2 ^= I;
+    
+    out |= I  << 26; // S bit
+    out |= !J1 << 13; // J1 bit
+    out |= !J2 << 11; // J2 bit
+    out |= (Value & 0x1FF800)  << 5; // imm6 field
+    out |= (Value & 0x0007FF);        // imm11 field
+    
+    uint64_t swapped = (out & 0xFFFF0000) >> 16;
+    swapped |= (out & 0x0000FFFF) << 16;
+    return swapped;
+  }
+  case ARM::fixup_t2_condbranch: {
+    Value = Value - 4;
+    Value >>= 1; // Low bit is not encoded.
+    
+    uint64_t out = 0;
     out |= (Value & 0x80000) << 7; // S bit
     out |= (Value & 0x40000) >> 7; // J2 bit
     out |= (Value & 0x20000) >> 4; // J1 bit
@@ -332,7 +353,8 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
 
   case FK_Data_4:
   case ARM::fixup_t2_ldst_pcrel_12:
-  case ARM::fixup_t2_branch:
+  case ARM::fixup_t2_condbranch:
+  case ARM::fixup_t2_uncondbranch:
   case ARM::fixup_t2_pcrel_10:
   case ARM::fixup_arm_thumb_bl:
   case ARM::fixup_arm_thumb_blx:
index 823947395f24aa2f19bee8e05b2c224a77a056af..101c07b4db623c4fedef3492f26827d3b1f63223 100644 (file)
@@ -183,6 +183,8 @@ namespace {
       const { return 0; }
     unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
+    unsigned getUnconditionalBranchTargetOpValue(const MachineInstr &MI,
+      unsigned Op) const { return 0; }
     unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getSOImmOpValue(const MachineInstr &MI, unsigned Op)
index d21a81a0fcb58cacecb25100d9064ed801db1ed2..48d495396e2285bf4ffedb64db7e97c5e7e62ae1 100644 (file)
@@ -36,9 +36,12 @@ 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_t2_condbranch - 20-bit PC relative relocation for Thumb2 direct 
+  // uconditional branch instructions.
+  fixup_t2_condbranch,
+  // fixup_t2_uncondbranch - 20-bit PC relative relocation for Thumb2 direct 
+  // branch unconditional branch instructions.
+  fixup_t2_uncondbranch,
 
   // fixup_arm_thumb_br - 12-bit fixup for Thumb B instructions.
   fixup_arm_thumb_br,
index f93d8ff2e3097bf569080670bdcb0f028a32bd8c..71948e1b641cefce64bafbb709c1c0c6b3f5791c 100644 (file)
@@ -293,6 +293,10 @@ def brtarget : Operand<OtherVT> {
   let EncoderMethod = "getBranchTargetOpValue";
 }
 
+def uncondbrtarget : Operand<OtherVT> {
+  let EncoderMethod = "getUnconditionalBranchTargetOpValue";
+}
+
 // Call target.
 def bltarget : Operand<i32> {
   // Encoded the same as branch targets.
index c83f5bd06b1236793539b02acd61a96809c31da0..2fedb5398ebc2b2c1c540c0fa408c21cc0159634 100644 (file)
@@ -2961,7 +2961,7 @@ def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p,
 
 let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
 let isPredicable = 1 in
-def t2B   : T2XI<(outs), (ins brtarget:$target), IIC_Br,
+def t2B   : T2XI<(outs), (ins uncondbrtarget:$target), IIC_Br,
                  "b.w\t$target",
                  [(br bb:$target)]> {
   let Inst{31-27} = 0b11110;
index 833bd22c7482dbf253c71dd0f87c5a38133187e6..7f34ee96e379ed4eeebb3d0ef26d230bff9ead53 100644 (file)
@@ -57,7 +57,8 @@ public:
                                                 MCFixupKindInfo::FKF_IsAligned},
 { "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_t2_condbranch",     0,            32,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_uncondbranch",   0,            32,  MCFixupKindInfo::FKF_IsPCRel },
 { "fixup_arm_thumb_br",      0,            16,  MCFixupKindInfo::FKF_IsPCRel },
 { "fixup_arm_thumb_bl",      0,            32,  MCFixupKindInfo::FKF_IsPCRel },
 { "fixup_arm_thumb_blx",     7,            21,  MCFixupKindInfo::FKF_IsPCRel },
@@ -122,6 +123,12 @@ public:
   uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                                   SmallVectorImpl<MCFixup> &Fixups) const;
 
+  /// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+  /// immediate Thumb2 direct branch target.
+  uint32_t getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                                  SmallVectorImpl<MCFixup> &Fixups) const;
+  
+
   /// getAdrLabelOpValue - Return encoding info for 12-bit immediate
   /// ADR label target.
   uint32_t getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
@@ -499,10 +506,34 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
   // coupling between MC and TM anywhere we can help it.
   const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
   if (Subtarget.isThumb2())
-    return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_branch, Fixups);
+    return
+      ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_condbranch, Fixups);
   return ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_arm_branch, Fixups);
 }
 
+/// getUnconditionalBranchTargetOpValue - Return encoding info for 24-bit
+/// immediate branch target.
+uint32_t ARMMCCodeEmitter::
+getUnconditionalBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                       SmallVectorImpl<MCFixup> &Fixups) const {
+  unsigned Val =
+    ::getBranchTargetOpValue(MI, OpIdx, ARM::fixup_t2_uncondbranch, Fixups);
+  bool I  = (Val & 0x800000);
+  bool J1 = (Val & 0x400000);
+  bool J2 = (Val & 0x200000);
+  if (I ^ J1)
+    Val &= ~0x400000;
+  else
+    Val |= 0x400000;
+    
+  if (I ^ J2)
+    Val &= ~0x200000;
+  else
+    Val |= 0x200000;
+  
+  return Val;
+}
+
 /// getAdrLabelOpValue - Return encoding info for 12-bit immediate ADR label
 /// target.
 uint32_t ARMMCCodeEmitter::
index be1ed8f792bd9514cd669864148ae8780449e380..dede4b0244642c03253dd4d0f17c0e2b11062c24 100644 (file)
@@ -322,6 +322,7 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
   PCR("offset32");
   PCR("offset64");
   PCR("brtarget");
+  PCR("uncondbrtarget");
   PCR("bltarget");
 
   return 1;
@@ -587,6 +588,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   IMM("neon_vcvt_imm32");
 
   MISC("brtarget", "kOperandTypeARMBranchTarget");                // ?
+  MISC("uncondbrtarget", "kOperandTypeARMBranchTarget");           // ?
   MISC("t_brtarget", "kOperandTypeARMBranchTarget");              // ?
   MISC("t_bcctarget", "kOperandTypeARMBranchTarget");             // ?
   MISC("t_cbtarget", "kOperandTypeARMBranchTarget");              // ?
index e3cad1aaa89fc29da7b40e45e423eb2fd428bf02..ccd3efd980a260ae69ca45be9f286e076308c583 100644 (file)
@@ -857,6 +857,7 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
   TYPE("i32imm_pcrel",        TYPE_REL32)
   TYPE("SSECC",               TYPE_IMM3)
   TYPE("brtarget",            TYPE_RELv)
+  TYPE("uncondbrtarget",      TYPE_RELv)
   TYPE("brtarget8",           TYPE_REL8)
   TYPE("f80mem",              TYPE_M80FP)
   TYPE("lea32mem",            TYPE_LEA)