Add fixup for Thumb1 BL/BLX instructions.
authorJim Grosbach <grosbach@apple.com>
Mon, 6 Dec 2010 23:57:07 +0000 (23:57 +0000)
committerJim Grosbach <grosbach@apple.com>
Mon, 6 Dec 2010 23:57:07 +0000 (23:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121072 91177308-0d34-0410-b5e6-96231b3b80d8

lib/MC/ELFObjectWriter.cpp
lib/Target/ARM/ARMAsmBackend.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMFixupKinds.h
lib/Target/ARM/ARMInstrThumb.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
utils/TableGen/EDEmitter.cpp

index 549288773bb313c6405735c560632909b221e630..4daab49089aca36b34a04764900a29c40f6f1b2e 100644 (file)
@@ -1546,6 +1546,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
     case ARM::fixup_arm_ldst_pcrel_12:
     case ARM::fixup_arm_pcrel_10:
     case ARM::fixup_arm_adr_pcrel_12:
+    case ARM::fixup_arm_thumb_bl:
       assert(0 && "Unimplemented"); break;
     case ARM::fixup_arm_branch:
       return ELF::R_ARM_CALL; break;
index 536923e47bfd88b3c513dcc324f0b45682b9f8fe..7b9e59f9a9d35fa862739cd44f7e9eae346d9676 100644 (file)
@@ -103,7 +103,18 @@ static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
   case ARM::fixup_arm_branch:
     // 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);
+    return 0xffffff & ((Value - 8) >> 2);
+  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
+    // opcode. x = unchanged, I = immediate value bit, S = sign extension bit
+    // xxxxxSIIIIIIIIII xxxxxIIIIIIIIIII
+    // Note that the halfwords are stored high first, low second; so we need
+    // to transpose the fixup value here to map properly.
+    uint32_t Binary = 0x3fffff & ((Value - 4) >> 1);
+    Binary = ((Binary & 0x7ff) << 16) | (Binary >> 11);
+    return Binary;
+  }
   case ARM::fixup_arm_pcrel_10: {
     // Offset by 8 just as above.
     Value = Value - 8;
@@ -198,12 +209,17 @@ public:
 
 static unsigned getFixupKindNumBytes(unsigned Kind) {
   switch (Kind) {
-  default: llvm_unreachable("Unknown fixup kind!");
-  case FK_Data_4: return 4;
-  case ARM::fixup_arm_ldst_pcrel_12: return 3;
-  case ARM::fixup_arm_pcrel_10: return 3;
-  case ARM::fixup_arm_adr_pcrel_12: return 3;
-  case ARM::fixup_arm_branch: return 3;
+  default:
+    llvm_unreachable("Unknown fixup kind!");
+  case FK_Data_4:
+    return 4;
+  case ARM::fixup_arm_ldst_pcrel_12:
+  case ARM::fixup_arm_pcrel_10:
+  case ARM::fixup_arm_adr_pcrel_12:
+  case ARM::fixup_arm_branch:
+    return 3;
+  case ARM::fixup_arm_thumb_bl:
+    return 4;
   }
 }
 
index e253a865a08607152e620c2a68a43c628e29e30f..4424f775b10460a47c1f3a4f0e56ff6974bd862d 100644 (file)
@@ -171,6 +171,8 @@ namespace {
       const { return 0; }
     unsigned getAdrLabelOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
+    unsigned getThumbBLTargetOpValue(const MachineInstr &MI, unsigned Op)
+      const { return 0; }
     unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getCCOutOpValue(const MachineInstr &MI, unsigned Op)
index 1ec0ba42435aa85781612a42224db9cdbaf57716..c905611906fac430ff885a510c0bbed3a9daa091 100644 (file)
@@ -25,9 +25,11 @@ enum Fixups {
   // fixup_arm_adr_pcrel_12 - 12-bit PC relative relocation for the ADR
   // instruction.
   fixup_arm_adr_pcrel_12,
-  // fixup_arm_brnach - 24-bit PC relative relocation for direct branch
+  // fixup_arm_branch - 24-bit PC relative relocation for direct branch
   // instructions.
   fixup_arm_branch,
+  // fixup_arm_thumb_bl - Fixup for Thumb BL/BLX instructions.
+  fixup_arm_thumb_bl,
 
   // The next two are for the movt/movw pair
   // the 16bit imm field are split into imm{15-12} and imm{11-0}
index a8681aef3c84c5d5442be2788f1de3d7fc2de390..67f7da64ddf713ba83febb52ad799bc8d758bd8f 100644 (file)
@@ -74,6 +74,10 @@ def t_imm_s4 : Operand<i32> {
 
 // Define Thumb specific addressing modes.
 
+def t_bltarget : Operand<i32> {
+  let EncoderMethod = "getThumbBLTargetOpValue";
+}
+
 def MemModeThumbAsmOperand : AsmOperandClass {
   let Name = "MemModeThumb";
   let SuperClasses = [];
@@ -366,22 +370,29 @@ let isCall = 1,
   Uses = [SP] in {
   // Also used for Thumb2
   def tBL  : TIx2<0b11110, 0b11, 1,
-                  (outs), (ins i32imm:$func, variable_ops), IIC_Br,
+                  (outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
                   "bl\t$func",
                   [(ARMtcall tglobaladdr:$func)]>,
              Requires<[IsThumb, IsNotDarwin]> {
+    bits<21> func;
+    let Inst{25-16} = func{20-11};
     let Inst{13} = 1;
     let Inst{11} = 1;
+    let Inst{10-0} = func{10-0};
   }
 
   // ARMv5T and above, also used for Thumb2
   def tBLXi : TIx2<0b11110, 0b11, 0,
-                   (outs), (ins i32imm:$func, variable_ops), IIC_Br,
+                   (outs), (ins t_bltarget:$func, variable_ops), IIC_Br,
                    "blx\t$func",
                    [(ARMcall tglobaladdr:$func)]>,
               Requires<[IsThumb, HasV5T, IsNotDarwin]> {
+    bits<21> func;
+    let Inst{25-16} = func{20-11};
     let Inst{13} = 1;
     let Inst{11} = 1;
+    let Inst{10-1} = func{10-1};
+    let Inst{0} = 0; // func{0} is assumed zero
   }
 
   // Also used for Thumb2
@@ -412,23 +423,29 @@ let isCall = 1,
   Uses = [R7, SP] in {
   // Also used for Thumb2
   def tBLr9 : TIx2<0b11110, 0b11, 1,
-                   (outs), (ins pred:$p, i32imm:$func, variable_ops), IIC_Br,
-                   "bl${p}\t$func",
+                   (outs), (ins pred:$p, t_bltarget:$func, variable_ops),
+                   IIC_Br, "bl${p}\t$func",
                    [(ARMtcall tglobaladdr:$func)]>,
               Requires<[IsThumb, IsDarwin]> {
-    let Inst{13}    = 1;
-    let Inst{11}    = 1;
+    bits<21> func;
+    let Inst{25-16} = func{20-11};
+    let Inst{13} = 1;
+    let Inst{11} = 1;
+    let Inst{10-0} = func{10-0};
   }
 
   // ARMv5T and above, also used for Thumb2
   def tBLXi_r9 : TIx2<0b11110, 0b11, 0,
-                      (outs), (ins pred:$p, i32imm:$func, variable_ops),
-                      IIC_Br,
-                      "blx${p}\t$func",
+                      (outs), (ins pred:$p, t_bltarget:$func, variable_ops),
+                      IIC_Br, "blx${p}\t$func",
                       [(ARMcall tglobaladdr:$func)]>,
                  Requires<[IsThumb, HasV5T, IsDarwin]> {
+    bits<21> func;
+    let Inst{25-16} = func{20-11};
     let Inst{13} = 1;
     let Inst{11} = 1;
+    let Inst{10-1} = func{10-1};
+    let Inst{0} = 0; // func{0} is assumed zero
   }
 
   // Also used for Thumb2
index bdac5adf4cd8c57dd621d3111ccd3983132f59ad..b8939a1531c3a4b41cfaf5a15ede74f86fb6556c 100644 (file)
@@ -50,6 +50,7 @@ public:
       { "fixup_arm_pcrel_10",       1,    24,   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 },
       { "fixup_arm_movt_hi16",      0,    16,   0 },
       { "fixup_arm_movw_lo16",      0,    16,   0 },
     };
@@ -81,6 +82,11 @@ public:
                               unsigned &Reg, unsigned &Imm,
                               SmallVectorImpl<MCFixup> &Fixups) const;
 
+  /// getThumbBLTargetOpValue - Return encoding info for Thumb immediate
+  /// branch target.
+  uint32_t getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                                   SmallVectorImpl<MCFixup> &Fixups) const;
+
   /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
   /// branch target.
   uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
@@ -395,6 +401,24 @@ EncodeAddrModeOpValues(const MCInst &MI, unsigned OpIdx, unsigned &Reg,
   return isAdd;
 }
 
+/// getThumbBLTargetOpValue - Return encoding info for immediate
+/// branch target.
+uint32_t ARMMCCodeEmitter::
+getThumbBLTargetOpValue(const MCInst &MI, unsigned OpIdx,
+                        SmallVectorImpl<MCFixup> &Fixups) const {
+  const MCOperand &MO = MI.getOperand(OpIdx);
+
+  // If the destination is an immediate, we have nothing to do.
+  if (MO.isImm()) return MO.getImm();
+  assert (MO.isExpr() && "Unexpected branch target type!");
+  const MCExpr *Expr = MO.getExpr();
+  MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_thumb_bl);
+  Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+  // All of the information is in the fixup.
+  return 0;
+}
+
 /// getBranchTargetOpValue - Return encoding info for 24-bit immediate
 /// branch target.
 uint32_t ARMMCCodeEmitter::
index f3056e05317c1e110615311777268adde35f3e4f..68568c8df5423e048ddc882f62231c9e2fa7fbe3 100644 (file)
@@ -587,6 +587,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   IMM("neon_vcvt_imm32");
 
   MISC("brtarget", "kOperandTypeARMBranchTarget");                // ?
+  MISC("t_bltarget", "kOperandTypeARMBranchTarget");              // ?
   MISC("bltarget", "kOperandTypeARMBranchTarget");                // ?
   MISC("so_reg", "kOperandTypeARMSoReg");                         // R, R, I
   MISC("shift_so_reg", "kOperandTypeARMSoReg");                   // R, R, I