ARM assembly parsing and encoding for LDR instructions.
authorJim Grosbach <grosbach@apple.com>
Thu, 4 Aug 2011 23:01:30 +0000 (23:01 +0000)
committerJim Grosbach <grosbach@apple.com>
Thu, 4 Aug 2011 23:01:30 +0000 (23:01 +0000)
Enhance support for LDR instruction assembly parsing for post-indexed
addressing with immediate values. Add tests.

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

lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp

index 9fac575c1dbddb5f65d0a38626c97b045ff94f53..1ef9dbc1f81926f208a434ab01c3f2b963f0e603 100644 (file)
@@ -673,11 +673,15 @@ def am2offset_reg : Operand<i32>,
   let MIOperandInfo = (ops GPR, i32imm);
 }
 
+// FIXME: am2offset_imm should only need the immediate, not the GPR. Having
+// the GPR is purely vestigal at this point.
+def AM2OffsetImmAsmOperand : AsmOperandClass { let Name = "AM2OffsetImm"; }
 def am2offset_imm : Operand<i32>,
                 ComplexPattern<i32, 2, "SelectAddrMode2OffsetImm",
                 [], [SDNPWantRoot]> {
   let EncoderMethod = "getAddrMode2OffsetOpValue";
   let PrintMethod = "printAddrMode2OffsetOperand";
+  let ParserMatchClass = AM2OffsetImmAsmOperand;
   let MIOperandInfo = (ops GPR, i32imm);
 }
 
@@ -1910,31 +1914,33 @@ multiclass AI2_ldridx<bit isByte, string opc, InstrItinClass itin> {
   }
 
   def _POST_REG : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
-                       (ins GPR:$Rn, am2offset_reg:$offset),
+                       (ins addr_offset_none:$addr, am2offset_reg:$offset),
                        IndexModePost, LdFrm, itin,
-                       opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
+                       opc, "\t$Rt, $addr, $offset",
+                       "$addr.base = $Rn_wb", []> {
      // {12}     isAdd
      // {11-0}   imm12/Rm
      bits<14> offset;
-     bits<4> Rn;
+     bits<4> addr;
      let Inst{25} = 1;
      let Inst{23} = offset{12};
-     let Inst{19-16} = Rn;
+     let Inst{19-16} = addr;
      let Inst{11-0} = offset{11-0};
      let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    }
 
    def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
-                       (ins GPR:$Rn, am2offset_imm:$offset),
+                       (ins addr_offset_none:$addr, am2offset_imm:$offset),
                       IndexModePost, LdFrm, itin,
-                      opc, "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", []> {
+                      opc, "\t$Rt, $addr, $offset",
+                      "$addr.base = $Rn_wb", []> {
     // {12}     isAdd
     // {11-0}   imm12/Rm
     bits<14> offset;
-    bits<4> Rn;
+    bits<4> addr;
     let Inst{25} = 0;
     let Inst{23} = offset{12};
-    let Inst{19-16} = Rn;
+    let Inst{19-16} = addr;
     let Inst{11-0} = offset{11-0};
     let DecoderMethod = "DecodeAddrMode2IdxInstruction";
   }
index bc97b032dcf9b69b1dc98eeacd38638c836c54f9..dcc86957ade24b1e6b40e310652b8f33e2c87562 100644 (file)
@@ -520,6 +520,15 @@ public:
     int64_t Val = Mem.OffsetImm->getValue();
     return Val > -4096 && Val < 4096;
   }
+  bool isAM2OffsetImm() const {
+    if (Kind != Immediate)
+      return false;
+    // Immediate offset in range [-4095, 4095].
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    int64_t Val = CE->getValue();
+    return Val > -4096 && Val < 4096;
+  }
   bool isAddrMode5() const {
     if (Kind != Memory)
       return false;
@@ -780,6 +789,20 @@ public:
     Inst.addOperand(MCOperand::CreateImm(Val));
   }
 
+  void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 2 && "Invalid number of operands!");
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    assert(CE && "non-constant AM2OffsetImm operand!");
+    int32_t Val = CE->getValue();
+    ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
+    // Special case for #-0
+    if (Val == INT32_MIN) Val = 0;
+    if (Val < 0) Val = -Val;
+    Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
+    Inst.addOperand(MCOperand::CreateReg(0));
+    Inst.addOperand(MCOperand::CreateImm(Val));
+  }
+
   void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
     assert(N == 2 && "Invalid number of operands!");
     // The lower two bits are always zero and as such are not encoded.