In Thumb2, direct branches can be encoded as either a "short" conditional branch...
[oota-llvm.git] / lib / Target / ARM / ARMMCCodeEmitter.cpp
index df28a992913607315a114357c75022ef872d1d55..7f34ee96e379ed4eeebb3d0ef26d230bff9ead53 100644 (file)
@@ -45,24 +45,28 @@ public:
 
   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
     const static MCFixupKindInfo Infos[] = {
-      // name                       off   bits  flags
-      { "fixup_arm_ldst_pcrel_12",  1,    24,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_t2_ldst_pcrel_12",   0,    32,   MCFixupKindInfo::FKF_IsPCRel |
+// This table *must* be in the order that the fixup_* kinds are defined in
+// ARMFixupKinds.h.
+//
+// Name                      Offset (bits) Size (bits)     Flags
+{ "fixup_arm_ldst_pcrel_12", 1,            24,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_ldst_pcrel_12",  0,            32,  MCFixupKindInfo::FKF_IsPCRel |
                                                 MCFixupKindInfo::FKF_IsAligned},
-      { "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_t2_branch",          0,    32,   MCFixupKindInfo::FKF_IsPCRel |
+{ "fixup_arm_pcrel_10",      1,            24,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_t2_pcrel_10",       0,            32,  MCFixupKindInfo::FKF_IsPCRel |
                                                 MCFixupKindInfo::FKF_IsAligned},
-      { "fixup_arm_thumb_bl",       0,    32,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_thumb_blx",      0,    32,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_thumb_cb",       0,    16,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_thumb_cp",       1,    8,    MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_thumb_br",       0,    16,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_thumb_bcc",      1,    8,    MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_movt_hi16",      0,    16,   0 },
-      { "fixup_arm_movw_lo16",      0,    16,   0 },
+{ "fixup_arm_adr_pcrel_12",  1,            24,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_branch",        1,            24,  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 },
+{ "fixup_arm_thumb_cb",      0,            16,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_cp",      1,             8,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_thumb_bcc",     1,             8,  MCFixupKindInfo::FKF_IsPCRel },
+{ "fixup_arm_movt_hi16",     0,            16,  0 },
+{ "fixup_arm_movw_lo16",     0,            16,  0 },
     };
 
     if (Kind < FirstTargetFixupKind)
@@ -119,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,
@@ -129,6 +139,10 @@ public:
   uint32_t getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
                                    SmallVectorImpl<MCFixup> &Fixups) const;
 
+  /// getTAddrModeRegRegOpValue - Return encoding for 'reg + reg' operand.
+  uint32_t getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
+                                     SmallVectorImpl<MCFixup> &Fixups) const;
+
   /// getT2AddrModeImm8s4OpValue - Return encoding info for 'reg +/- imm8<<2'
   /// operand.
   uint32_t getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
@@ -223,7 +237,7 @@ public:
     Binary |= ARM_AM::getSOImmValImm((unsigned)SoImmVal);
     return Binary;
   }
-  
+
   /// getT2SOImmOpValue - Return an encoded 12-bit shifted-immediate value.
   unsigned getT2SOImmOpValue(const MCInst &MI, unsigned Op,
                            SmallVectorImpl<MCFixup> &Fixups) const {
@@ -314,14 +328,14 @@ MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &, TargetMachine &TM,
   return new ARMMCCodeEmitter(TM, Ctx);
 }
 
-/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing 
-/// instructions, and rewrite them to their Thumb2 form if we are currently in 
+/// NEONThumb2DataIPostEncoder - Post-process encoded NEON data-processing
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
 /// Thumb2 mode.
 unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
                                                  unsigned EncodedValue) const {
   const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
   if (Subtarget.isThumb2()) {
-    // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved 
+    // NEON Thumb2 data-processsing encodings are very simple: bit 24 is moved
     // to bit 12 of the high half-word (i.e. bit 28), and bits 27-24 are
     // set to 1111.
     unsigned Bit24 = EncodedValue & 0x01000000;
@@ -330,12 +344,12 @@ unsigned ARMMCCodeEmitter::NEONThumb2DataIPostEncoder(const MCInst &MI,
     EncodedValue |= Bit28;
     EncodedValue |= 0x0F000000;
   }
-  
+
   return EncodedValue;
 }
 
 /// NEONThumb2LoadStorePostEncoder - Post-process encoded NEON load/store
-/// instructions, and rewrite them to their Thumb2 form if we are currently in 
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
 /// Thumb2 mode.
 unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
                                                  unsigned EncodedValue) const {
@@ -344,12 +358,12 @@ unsigned ARMMCCodeEmitter::NEONThumb2LoadStorePostEncoder(const MCInst &MI,
     EncodedValue &= 0xF0FFFFFF;
     EncodedValue |= 0x09000000;
   }
-  
+
   return EncodedValue;
 }
 
 /// NEONThumb2DupPostEncoder - Post-process encoded NEON vdup
-/// instructions, and rewrite them to their Thumb2 form if we are currently in 
+/// instructions, and rewrite them to their Thumb2 form if we are currently in
 /// Thumb2 mode.
 unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
                                                  unsigned EncodedValue) const {
@@ -358,7 +372,7 @@ unsigned ARMMCCodeEmitter::NEONThumb2DupPostEncoder(const MCInst &MI,
     EncodedValue &= 0x00FFFFFF;
     EncodedValue |= 0xEE000000;
   }
-  
+
   return EncodedValue;
 }
 
@@ -488,12 +502,38 @@ getThumbCBTargetOpValue(const MCInst &MI, unsigned OpIdx,
 uint32_t ARMMCCodeEmitter::
 getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx,
                        SmallVectorImpl<MCFixup> &Fixups) const {
+  // FIXME: This really, really shouldn't use TargetMachine. We don't want
+  // 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::
@@ -504,6 +544,17 @@ getAdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
                                   Fixups);
 }
 
+/// getTAddrModeRegRegOpValue - Return encoding info for 'reg + reg' operand.
+uint32_t ARMMCCodeEmitter::
+getTAddrModeRegRegOpValue(const MCInst &MI, unsigned OpIdx,
+                        SmallVectorImpl<MCFixup> &Fixups) const {
+  const MCOperand &MO1 = MI.getOperand(OpIdx);
+  const MCOperand &MO2 = MI.getOperand(OpIdx+1);
+  unsigned Rn = getARMRegisterNumbering(MO1.getReg());
+  unsigned Rm = getARMRegisterNumbering(MO2.getReg());
+  return (Rm << 3) | Rn;
+}
+
 /// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12' operand.
 uint32_t ARMMCCodeEmitter::
 getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
@@ -526,7 +577,7 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
       Expr = MO.getExpr();
     else
       Expr = MO2.getExpr();
-    
+
     const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
     MCFixupKind Kind;
     if (Subtarget.isThumb2())
@@ -586,10 +637,10 @@ getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
                   SmallVectorImpl<MCFixup> &Fixups) const {
   // {20-16} = imm{15-12}
   // {11-0}  = imm{11-0}
-  const MCOperand &MO = MI.getOperand(OpIdx); 
+  const MCOperand &MO = MI.getOperand(OpIdx);
   if (MO.isImm()) {
     return static_cast<unsigned>(MO.getImm());
-  } else if (const MCSymbolRefExpr *Expr = 
+  } else if (const MCSymbolRefExpr *Expr =
              dyn_cast<MCSymbolRefExpr>(MO.getExpr())) {
     MCFixupKind Kind;
     switch (Expr->getKind()) {
@@ -878,8 +929,8 @@ getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
                 SmallVectorImpl<MCFixup> &Fixups) const {
   const MCOperand &MO1 = MI.getOperand(OpNum);
   const MCOperand &MO2 = MI.getOperand(OpNum+1);
-  const MCOperand &MO3 = MI.getOperand(OpNum+2);                 
-  
+  const MCOperand &MO3 = MI.getOperand(OpNum+2);
+
   // Encoded as [Rn, Rm, imm].
   // FIXME: Needs fixup support.
   unsigned Value = getARMRegisterNumbering(MO1.getReg());
@@ -887,7 +938,7 @@ getT2AddrModeSORegOpValue(const MCInst &MI, unsigned OpNum,
   Value |= getARMRegisterNumbering(MO2.getReg());
   Value <<= 2;
   Value |= MO3.getImm();
-  
+
   return Value;
 }
 
@@ -899,7 +950,7 @@ getT2AddrModeImm8OpValue(const MCInst &MI, unsigned OpNum,
 
   // FIXME: Needs fixup support.
   unsigned Value = getARMRegisterNumbering(MO1.getReg());
-  
+
   // Even though the immediate is 8 bits long, we need 9 bits in order
   // to represent the (inverse of the) sign bit.
   Value <<= 9;