[llvm-commits] [llvm] r137244 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/AsmParser/ARMAsmParser.cpp test/MC/ARM/arm-memory-instructions.s test/MC/ARM/diagnostics.s

Jim Grosbach grosbach at apple.com
Wed Aug 10 13:29:20 PDT 2011


Author: grosbach
Date: Wed Aug 10 15:29:19 2011
New Revision: 137244

URL: http://llvm.org/viewvc/llvm-project?rev=137244&view=rev
Log:
ARM LDRD(immediate) assembly parsing and encoding support.

Modified:
    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/trunk/test/MC/ARM/arm-memory-instructions.s
    llvm/trunk/test/MC/ARM/diagnostics.s

Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137244&r1=137243&r2=137244&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Aug 10 15:29:19 2011
@@ -710,20 +710,26 @@
 // addrmode3 := reg +/- reg
 // addrmode3 := reg +/- imm8
 //
-//def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; }
+// FIXME: split into imm vs. reg versions.
+def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; }
 def addrmode3 : Operand<i32>,
                 ComplexPattern<i32, 3, "SelectAddrMode3", []> {
   let EncoderMethod = "getAddrMode3OpValue";
   let PrintMethod = "printAddrMode3Operand";
+  let ParserMatchClass = AddrMode3AsmOperand;
   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm);
 }
 
+// FIXME: split into imm vs. reg versions.
+// FIXME: parser method to handle +/- register.
+def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; }
 def am3offset : Operand<i32>,
                 ComplexPattern<i32, 2, "SelectAddrMode3Offset",
                                [], [SDNPWantRoot]> {
   let EncoderMethod = "getAddrMode3OffsetOpValue";
   let DecoderMethod = "DecodeAddrMode3Offset";
   let PrintMethod = "printAddrMode3OffsetOperand";
+  let ParserMatchClass = AM3OffsetAsmOperand;
   let MIOperandInfo = (ops GPR, i32imm);
 }
 
@@ -2030,20 +2036,22 @@
   let Inst{11-8}  = addr{7-4};    // imm7_4/zero
   let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
   let DecoderMethod = "DecodeAddrMode3Instruction";
+  let AsmMatchConverter = "cvtLdrdPre";
 }
 def LDRD_POST: AI3ldstidx<0b1101, 0, 1, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb),
-                          (ins GPR:$Rn, am3offset:$offset), IndexModePost,
-                          LdMiscFrm, IIC_iLoad_d_ru,
-                          "ldrd", "\t$Rt, $Rt2, [$Rn], $offset",
-                          "$Rn = $Rn_wb", []> {
+                          (ins addr_offset_none:$addr, am3offset:$offset),
+                          IndexModePost, LdMiscFrm, IIC_iLoad_d_ru,
+                          "ldrd", "\t$Rt, $Rt2, $addr, $offset",
+                          "$addr.base = $Rn_wb", []> {
   bits<10> offset;
-  bits<4> Rn;
+  bits<4> addr;
   let Inst{23}    = offset{8};      // U bit
   let Inst{22}    = offset{9};      // 1 == imm8, 0 == Rm
-  let Inst{19-16} = Rn;
+  let Inst{19-16} = addr;
   let Inst{11-8}  = offset{7-4};    // imm7_4/zero
   let Inst{3-0}   = offset{3-0};    // imm3_0/Rm
   let DecoderMethod = "DecodeAddrMode3Instruction";
+//  let AsmMatchConverter = "cvtLdrdPost";
 }
 } // hasExtraDefRegAllocReq = 1
 } // mayLoad = 1, neverHasSideEffects = 1

Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=137244&r1=137243&r2=137244&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Aug 10 15:29:19 2011
@@ -128,6 +128,8 @@
                              const SmallVectorImpl<MCParsedAsmOperand*> &);
   bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
                              const SmallVectorImpl<MCParsedAsmOperand*> &);
+  bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
+                  const SmallVectorImpl<MCParsedAsmOperand*> &);
 
   bool validateInstruction(MCInst &Inst,
                            const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
@@ -534,6 +536,29 @@
     int64_t Val = CE->getValue();
     return Val > -4096 && Val < 4096;
   }
+  bool isAddrMode3() const {
+    if (Kind != Memory)
+      return false;
+    // No shifts are legal for AM3.
+    if (Mem.ShiftType != ARM_AM::no_shift) return false;
+    // Check for register offset.
+    if (Mem.OffsetRegNum) return true;
+    // Immediate offset in range [-255, 255].
+    if (!Mem.OffsetImm) return true;
+    int64_t Val = Mem.OffsetImm->getValue();
+    return Val > -256 && Val < 256;
+  }
+  bool isAM3Offset() const {
+    if (Kind != Immediate && Kind != PostIndexRegister)
+      return false;
+    if (Kind == PostIndexRegister)
+      return PostIdxReg.ShiftTy == ARM_AM::no_shift;
+    // Immediate offset in range [-255, 255].
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    int64_t Val = CE->getValue();
+    return Val > -256 && Val < 256;
+  }
   bool isAddrMode5() const {
     if (Kind != Memory)
       return false;
@@ -814,6 +839,46 @@
     Inst.addOperand(MCOperand::CreateImm(Val));
   }
 
+  void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
+    assert(N == 3 && "Invalid number of operands!");
+    int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0;
+    if (!Mem.OffsetRegNum) {
+      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::getAM3Opc(AddSub, Val);
+    } else {
+      // For register offset, we encode the shift type and negation flag
+      // here.
+      Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
+    }
+    Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum));
+    Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum));
+    Inst.addOperand(MCOperand::CreateImm(Val));
+  }
+
+  void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
+    assert(N == 2 && "Invalid number of operands!");
+    if (Kind == PostIndexRegister) {
+      int32_t Val =
+        ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
+      Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
+      Inst.addOperand(MCOperand::CreateImm(Val));
+    }
+
+    // Constant offset.
+    const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
+    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.
@@ -2046,6 +2111,24 @@
   return true;
 }
 
+/// cvtLdrdPre - Convert parsed operands to MCInst.
+/// Needed here because the Asm Gen Matcher can't handle properly tied operands
+/// when they refer multiple MIOperands inside a single one.
+bool ARMAsmParser::
+cvtLdrdPre(MCInst &Inst, unsigned Opcode,
+           const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  // Rt, Rt2
+  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
+  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
+  // Create a writeback register dummy placeholder.
+  Inst.addOperand(MCOperand::CreateImm(0));
+  // addr
+  ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
+  // pred
+  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
+  return true;
+}
+
 /// Parse an ARM memory expression, return false if successful else return true
 /// or an error.  The first token must be a '[' when called.
 bool ARMAsmParser::
@@ -2645,6 +2728,9 @@
 validateInstruction(MCInst &Inst,
                     const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
   switch (Inst.getOpcode()) {
+  case ARM::LDRD:
+  case ARM::LDRD_PRE:
+  case ARM::LDRD_POST:
   case ARM::LDREXD: {
     // Rt2 must be Rt + 1.
     unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
@@ -2654,6 +2740,9 @@
                    "destination operands must be sequential");
     return false;
   }
+  case ARM::STRgD:
+  case ARM::STRgD_PRE:
+  case ARM::STRgD_POST:
   case ARM::STREXD: {
     // Rt2 must be Rt + 1.
     unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());

Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm-memory-instructions.s?rev=137244&r1=137243&r2=137244&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/arm-memory-instructions.s (original)
+++ llvm/trunk/test/MC/ARM/arm-memory-instructions.s Wed Aug 10 15:29:19 2011
@@ -105,3 +105,17 @@
 @ CHECK: ldrbt	r2, [r8], #-8           @ encoding: [0x08,0x20,0x78,0xe4]
 @ CHECK: ldrbt	r8, [r7], r6            @ encoding: [0x06,0x80,0xf7,0xe6]
 @ CHECK: ldrbt	r1, [r2], -r6, lsl #12  @ encoding: [0x06,0x16,0x72,0xe6]
+
+
+ at ------------------------------------------------------------------------------
+@ LDRD (immediate)
+ at ------------------------------------------------------------------------------
+        ldrd r3, r4, [r5]
+        ldrd r7, r8, [r2, #15]
+        ldrd r1, r2, [r9, #32]!
+        ldrd r6, r7, [r1], #8
+
+@ CHECK: ldrd	r3, r4, [r5]            @ encoding: [0xd0,0x30,0xc5,0xe1]
+@ CHECK: ldrd	r7, r8, [r2, #15]       @ encoding: [0xdf,0x70,0xc2,0xe1]
+@ CHECK: ldrd	r1, r2, [r9, #32]!      @ encoding: [0xd0,0x12,0xe9,0xe1]
+@ CHECK: ldrd	r6, r7, [r1], #8        @ encoding: [0xd8,0x60,0xc1,0xe0]

Modified: llvm/trunk/test/MC/ARM/diagnostics.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/diagnostics.s?rev=137244&r1=137243&r2=137244&view=diff
==============================================================================
--- llvm/trunk/test/MC/ARM/diagnostics.s (original)
+++ llvm/trunk/test/MC/ARM/diagnostics.s Wed Aug 10 15:29:19 2011
@@ -283,3 +283,17 @@
 @ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb]
 @ CHECK-ERRORS:         ubfxgt r4, r5, #16, #17
 @ CHECK-ERRORS:                             ^
+
+        @ Out of order Rt/Rt2 operands for ldrd
+        ldrd  r4, r3, [r8]
+        ldrd  r4, r3, [r8, #8]!
+        ldrd  r4, r3, [r8], #8
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS:         ldrd  r4, r3, [r8]
+@ CHECK-ERRORS:                   ^
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS:         ldrd  r4, r3, [r8, #8]!
+@ CHECK-ERRORS:                   ^
+@ CHECK-ERRORS: error: destination operands must be sequential
+@ CHECK-ERRORS:         ldrd  r4, r3, [r8], #8
+@ CHECK-ERRORS:                   ^





More information about the llvm-commits mailing list