Add correct encodings for STRD and LDRD, including fixup support. Additionally,...
authorOwen Anderson <resistor@mac.com>
Wed, 1 Dec 2010 19:18:46 +0000 (19:18 +0000)
committerOwen Anderson <resistor@mac.com>
Wed, 1 Dec 2010 19:18:46 +0000 (19:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120589 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/ARMInstrFormats.td
lib/Target/ARM/ARMInstrThumb2.td
lib/Target/ARM/ARMMCCodeEmitter.cpp
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/CodeGen/Thumb2/thumb2-ldrd.ll
test/MC/Disassembler/ARM/thumb-tests.txt

index 641354c43cf86c58ff99ccf6d72337cf7ab1a205..1bad8ebaf8a3466de8f3f5ba7345a9bc388ad915 100644 (file)
@@ -409,7 +409,7 @@ namespace {
       case FK_PCRel_2:
       case FK_PCRel_4:
       case ARM::fixup_arm_pcrel_12:
-      case ARM::fixup_arm_vfp_pcrel_10:
+      case ARM::fixup_arm_pcrel_10:
       case ARM::fixup_arm_branch:
         return true;
       }
@@ -1457,7 +1457,7 @@ unsigned ARMELFObjectWriter::GetRelocType(const MCValue &Target,
     switch ((unsigned)Fixup.getKind()) {
     default: llvm_unreachable("invalid fixup kind!");
     case ARM::fixup_arm_pcrel_12:
-    case ARM::fixup_arm_vfp_pcrel_10:
+    case ARM::fixup_arm_pcrel_10:
       assert(0 && "Unimplemented"); break;
     case ARM::fixup_arm_branch:
       return ELF::R_ARM_CALL; break;
index ac0f160a9c3d0097a5c2c08ede0d82133945b556..0672899d7b32499aabc1ae80149393a2f5fac315 100644 (file)
@@ -64,7 +64,7 @@ protected:
       // These values don't encode the low two bits since they're always zero.
       // Offset by 8 just as above.
       return (Value - 8) >> 2;
-    case ARM::fixup_arm_vfp_pcrel_10: {
+    case ARM::fixup_arm_pcrel_10: {
       // Offset by 8 just as above.
       Value = Value - 8;
       bool isAdd = true;
@@ -202,7 +202,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
   default: llvm_unreachable("Unknown fixup kind!");
   case FK_Data_4: return 4;
   case ARM::fixup_arm_pcrel_12: return 3;
-  case ARM::fixup_arm_vfp_pcrel_10: return 3;
+  case ARM::fixup_arm_pcrel_10: return 3;
   case ARM::fixup_arm_branch: return 3;
   }
 }
index 9d2edf485480710dd94d8d11c1414edfaf58ce50..ab554f3916de3c8db3620565cac41e5d18f9ab5e 100644 (file)
@@ -181,6 +181,8 @@ namespace {
       const { return 0; }
     unsigned getT2AddrModeImm8OpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
+    unsigned getT2AddrModeImm8s4OpValue(const MachineInstr &MI, unsigned Op)
+      const { return 0; }
     unsigned getT2AddrModeImm8OffsetOpValue(const MachineInstr &MI, unsigned Op)
       const { return 0; }
     unsigned getT2AddrModeImm12OffsetOpValue(const MachineInstr &MI,unsigned Op)
index 33c9328b84625f7b1ea261eaef3a678cf2cbbbc6..7f6a855d84ca6c6973697c2af14aebc647a062be 100644 (file)
@@ -17,10 +17,10 @@ namespace ARM {
 enum Fixups {
   // fixup_arm_pcrel_12 - 12-bit PC relative relocation for symbol addresses
   fixup_arm_pcrel_12 = FirstTargetFixupKind,
-  // fixup_arm_vfp_pcrel_10 - 10-bit PC relative relocation for symbol addresses
-  // used in VFP instructions where the lower 2 bits are not encoded (so it's
-  // encoded as an 8-bit immediate).
-  fixup_arm_vfp_pcrel_10,
+  // 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
+  // (so it's encoded as an 8-bit immediate).
+  fixup_arm_pcrel_10,
   // fixup_arm_brnach - 24-bit PC relative relocation for direct branch
   // instructions.
   fixup_arm_branch,
index d911fe9c61fc2479a368b36e7877ff2d1a16a209..66234451951acc9ccc66eef300bc261a2db58dec 100644 (file)
@@ -1010,6 +1010,15 @@ class T2Ii8s4<bit P, bit W, bit load, dag oops, dag iops, InstrItinClass itin,
   let Inst{22}    = 1;
   let Inst{21}    = W;
   let Inst{20}    = load;
+  
+  bits<4> Rt;
+  bits<4> Rt2;
+  bits<13> addr;
+  let Inst{15-12} = Rt{3-0};
+  let Inst{11-8}  = Rt2{3-0};
+  let Inst{19-16} = addr{12-9};
+  let Inst{23}    = addr{8};
+  let Inst{7-0}   = addr{7-0};
 }
 
 class T2sI<dag oops, dag iops, InstrItinClass itin,
index 1066660ae1b2f1ad41609491d8093a487be8b7ed..a24710ffa81d75102f4fe72efe24876e86fd7d37 100644 (file)
@@ -149,6 +149,7 @@ def t2am_imm8_offset : Operand<i32>,
 // t2addrmode_imm8s4  := reg +/- (imm8 << 2)
 def t2addrmode_imm8s4 : Operand<i32> {
   let PrintMethod = "printT2AddrModeImm8s4Operand";
+  string EncoderMethod = "getT2AddrModeImm8s4OpValue";
   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
 }
 
@@ -1263,17 +1264,11 @@ defm t2LDRSH : T2I_ld<1, 0b01, "ldrsh", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
 defm t2LDRSB : T2I_ld<1, 0b00, "ldrsb", IIC_iLoad_bh_i, IIC_iLoad_bh_si,
                       UnOpFrag<(sextloadi8  node:$Src)>>;
 
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1,
-    isCodeGenOnly = 1 in { // $dst doesn't exist in asmstring?
+let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in {
 // Load doubleword
-def t2LDRDi8  : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2),
+def t2LDRDi8  : T2Ii8s4<1, 0, 1, (outs rGPR:$Rt, rGPR:$Rt2),
                         (ins t2addrmode_imm8s4:$addr),
-                        IIC_iLoad_d_i, "ldrd", "\t$dst1, $addr", []>;
-def t2LDRDpci : T2Ii8s4<1, 0, 1, (outs rGPR:$dst1, rGPR:$dst2),
-                        (ins i32imm:$addr), IIC_iLoad_d_i,
-                       "ldrd", "\t$dst1, $addr", []> {
-  let Inst{19-16} = 0b1111; // Rn
-}
+                        IIC_iLoad_d_i, "ldrd", "\t$Rt, $Rt2, $addr", []>;
 } // mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1
 
 // zextload i1 -> zextload i8
@@ -1431,11 +1426,10 @@ defm t2STRH:T2I_st<0b01,"strh", IIC_iStore_bh_i, IIC_iStore_bh_si,
                    BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>;
 
 // Store doubleword
-let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1,
-    isCodeGenOnly = 1 in  // $src2 doesn't exist in asm string
+let mayLoad = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in
 def t2STRDi8 : T2Ii8s4<1, 0, 0, (outs),
-                       (ins GPR:$src1, GPR:$src2, t2addrmode_imm8s4:$addr),
-               IIC_iStore_d_r, "strd", "\t$src1, $addr", []>;
+                       (ins GPR:$Rt, GPR:$Rt2, t2addrmode_imm8s4:$addr),
+               IIC_iStore_d_r, "strd", "\t$Rt, $Rt2, $addr", []>;
 
 // Indexed stores
 def t2STR_PRE  : T2Iidxst<0, 0b10, 1, (outs GPR:$base_wb),
@@ -1509,21 +1503,21 @@ def t2STRHT  : T2IstT<0b01, "strht", IIC_iStore_bh_i>;
 // ldrd / strd pre / post variants
 // For disassembly only.
 
-def t2LDRD_PRE  : T2Ii8s4<1, 1, 1, (outs GPR:$dst1, GPR:$dst2),
+def t2LDRD_PRE  : T2Ii8s4<1, 1, 1, (outs GPR:$Rt, GPR:$Rt2),
                  (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
-                 "ldrd", "\t$dst1, $dst2, [$base, $imm]!", []>;
+                 "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
 
-def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$dst1, GPR:$dst2),
+def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$Rt, GPR:$Rt2),
                  (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru,
-                 "ldrd", "\t$dst1, $dst2, [$base], $imm", []>;
+                 "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>;
 
 def t2STRD_PRE  : T2Ii8s4<1, 1, 0, (outs),
-                 (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm),
-                 IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base, $imm]!", []>;
+                 (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
+                 IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>;
 
 def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs),
-                 (ins GPR:$src1, GPR:$src2, GPR:$base, t2am_imm8s4_offset:$imm),
-                 IIC_iStore_d_ru, "strd", "\t$src1, $src2, [$base], $imm", []>;
+                 (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm),
+                 IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>;
 
 // T2Ipl (Preload Data/Instruction) signals the memory system of possible future
 // data/instruction access.  These are for disassembly only.
index 0000b4dfdc32ecaaaa45b1e5c1b4a584de296d5c..207332fba729081a2423a14df90e5a33bff42815 100644 (file)
@@ -47,7 +47,7 @@ public:
     const static MCFixupKindInfo Infos[] = {
       // name                     offset  bits  flags
       { "fixup_arm_pcrel_12",     1,      24,   MCFixupKindInfo::FKF_IsPCRel },
-      { "fixup_arm_vfp_pcrel_10", 1,      24,   MCFixupKindInfo::FKF_IsPCRel },
+      { "fixup_arm_pcrel_10",     1,      24,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_branch",       1,      24,   MCFixupKindInfo::FKF_IsPCRel },
       { "fixup_arm_movt_hi16",    0,      16,   0 },
       { "fixup_arm_movw_lo16",    0,      16,   0 },
@@ -90,6 +90,12 @@ public:
   uint32_t getAddrModeImm12OpValue(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,
+                                   SmallVectorImpl<MCFixup> &Fixups) const;
+
+
   /// getLdStSORegOpValue - Return encoding info for 'reg +/- reg shop imm'
   /// operand as needed by load/store instructions.
   uint32_t getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
@@ -422,6 +428,40 @@ getAddrModeImm12OpValue(const MCInst &MI, unsigned OpIdx,
   return Binary;
 }
 
+/// getT2AddrModeImm8s4OpValue - Return encoding info for
+/// 'reg +/- imm8<<2' operand.
+uint32_t ARMMCCodeEmitter::
+getT2AddrModeImm8s4OpValue(const MCInst &MI, unsigned OpIdx,
+                        SmallVectorImpl<MCFixup> &Fixups) const {
+  // {17-13} = reg
+  // {12}    = (U)nsigned (add == '1', sub == '0')
+  // {11-0}  = imm8
+  unsigned Reg, Imm8;
+  bool isAdd = true;
+  // If The first operand isn't a register, we have a label reference.
+  const MCOperand &MO = MI.getOperand(OpIdx);
+  if (!MO.isReg()) {
+    Reg = getARMRegisterNumbering(ARM::PC);   // Rn is PC.
+    Imm8 = 0;
+    isAdd = false ; // 'U' bit is set as part of the fixup.
+
+    assert(MO.isExpr() && "Unexpected machine operand type!");
+    const MCExpr *Expr = MO.getExpr();
+    MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_10);
+    Fixups.push_back(MCFixup::Create(0, Expr, Kind));
+
+    ++MCNumCPRelocations;
+  } else
+    isAdd = EncodeAddrModeOpValues(MI, OpIdx, Reg, Imm8, Fixups);
+
+  uint32_t Binary = (Imm8 >> 2) & 0xff;
+  // Immediate is always encoded as positive. The 'U' bit controls add vs sub.
+  if (isAdd)
+    Binary |= (1 << 9);
+  Binary |= (Reg << 9);
+  return Binary;
+}
+
 uint32_t ARMMCCodeEmitter::
 getMovtImmOpValue(const MCInst &MI, unsigned OpIdx,
                   SmallVectorImpl<MCFixup> &Fixups) const {
@@ -613,7 +653,7 @@ getAddrMode5OpValue(const MCInst &MI, unsigned OpIdx,
 
     assert(MO.isExpr() && "Unexpected machine operand type!");
     const MCExpr *Expr = MO.getExpr();
-    MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_vfp_pcrel_10);
+    MCFixupKind Kind = MCFixupKind(ARM::fixup_arm_pcrel_12);
     Fixups.push_back(MCFixup::Create(0, Expr, Kind));
 
     ++MCNumCPRelocations;
index d4aa03c3db2dcdfe18b165ed53d33b9f0bf7b654..c3d24d2d70ec1fd8a1b055cb781a92775da4676d 100644 (file)
@@ -253,9 +253,6 @@ static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
   default:
     return Opcode; // Return unmorphed opcode.
 
-  case ARM::t2LDRDi8:
-    return ARM::t2LDRDpci;
-
   case ARM::t2LDR_POST:   case ARM::t2LDR_PRE:
   case ARM::t2LDRi12:     case ARM::t2LDRi8:
   case ARM::t2LDRs:       case ARM::t2LDRT:
index 22d4e88ed17d664ea2ccf713e40e6f547ac8fe94..a747d5f75697a74b8fb41d5b8284ef49fcb55ce8 100644 (file)
@@ -4,7 +4,7 @@
 
 define i64 @t(i64 %a) nounwind readonly {
 entry:
-;CHECK: ldrd r2, [r2]
+;CHECK: ldrd r2, r3, [r2]
        %0 = load i64** @b, align 4
        %1 = load i64* %0, align 4
        %2 = mul i64 %1, %a
index 06d12fed87fb7744e5f75fe17a40117889115641..dfd80b39eff3f7f5745c8afb8b3c59d2d8ab21cb 100644 (file)
@@ -63,7 +63,7 @@
 # CHECK:       ssat    r0, #17, r12
 0x0c 0xf3 0x10 0x00
 
-# CHECK:       strd    r0, [r7, #64]
+# CHECK:       strd    r0, r1, [r7, #64]
 0xc7 0xe9 0x10 0x01
 
 # CHECK:       sub     sp, #60