ARM assembly parsing and encoding for LDC{2}{L}/STC{2}{L} instructions.
authorJim Grosbach <grosbach@apple.com>
Tue, 11 Oct 2011 21:55:36 +0000 (21:55 +0000)
committerJim Grosbach <grosbach@apple.com>
Tue, 11 Oct 2011 21:55:36 +0000 (21:55 +0000)
Fill out the rest of the encoding information, update to properly mark
the LDC/STC instructions as predicable while the LDC2/STC2 instructions are
not, and adjust the parser accordingly.

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

lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/basic-arm-instructions.s

index a89a5898eba12bfc0c9c5f331c15a4823db07acf..d43da911e228b6451d4b23183a768d664a99956c 100644 (file)
@@ -651,8 +651,10 @@ def postidx_imm8 : Operand<i32> {
 // 9 bit value:
 //  {8}       1 is imm8 is non-negative. 0 otherwise.
 //  {7-0}     [0,255] imm8 value, scaled by 4.
+def PostIdxImm8s4AsmOperand : AsmOperandClass { let Name = "PostIdxImm8s4"; }
 def postidx_imm8s4 : Operand<i32> {
   let PrintMethod = "printPostIdxImm8s4Operand";
+  let ParserMatchClass = PostIdxImm8s4AsmOperand;
   let MIOperandInfo = (ops i32imm);
 }
 
@@ -4246,117 +4248,168 @@ def CDP2 : ABXI<0b1110, (outs), (ins p_imm:$cop, imm0_15:$opc1,
 
 class ACI<dag oops, dag iops, string opc, string asm,
           IndexMode im = IndexModeNone>
+  : I<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
+      opc, asm, "", []> {
+  let Inst{27-25} = 0b110;
+}
+class ACInoP<dag oops, dag iops, string opc, string asm,
+          IndexMode im = IndexModeNone>
   : InoP<oops, iops, AddrModeNone, 4, im, BrFrm, NoItinerary,
          opc, asm, "", []> {
+  let Inst{31-28} = 0b1111;
   let Inst{27-25} = 0b110;
 }
-
-multiclass LdStCop<bits<4> op31_28, bit load, dag ops, string opc, string cond>{
-  def _OFFSET : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
-      !strconcat(opc, cond), "\t$cop, $CRd, $addr"> {
-    let Inst{31-28} = op31_28;
+multiclass LdStCop<bit load, bit Dbit, string asm> {
+  def _OFFSET : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
+                    asm, "\t$cop, $CRd, $addr"> {
+    bits<13> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 1; // P = 1
+    let Inst{23} = addr{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 0; // W = 0
-    let Inst{22} = 0; // D = 0
     let Inst{20} = load;
+    let Inst{19-16} = addr{12-9};
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = addr{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def _PRE : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
-      !strconcat(opc, cond), "\t$cop, $CRd, $addr!", IndexModePre> {
-    let Inst{31-28} = op31_28;
+  def _PRE : ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
+                 asm, "\t$cop, $CRd, $addr!", IndexModePre> {
+    bits<13> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 1; // P = 1
+    let Inst{23} = addr{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 1; // W = 1
-    let Inst{22} = 0; // D = 0
     let Inst{20} = load;
+    let Inst{19-16} = addr{12-9};
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = addr{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def _POST : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
-            postidx_imm8s4:$offset), ops),
-      !strconcat(opc, cond), "\t$cop, $CRd, $addr, $offset",
-      IndexModePost> {
-    let Inst{31-28} = op31_28;
+  def _POST: ACI<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
+                              postidx_imm8s4:$offset),
+                 asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
+    bits<9> offset;
+    bits<4> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 0; // P = 0
+    let Inst{23} = offset{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 1; // W = 1
-    let Inst{22} = 0; // D = 0
     let Inst{20} = load;
+    let Inst{19-16} = addr;
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = offset{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
   def _OPTION : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base,
-                nohash_imm:$option),
-            ops),
-      !strconcat(opc, cond), "\t$cop, $CRd, $base, \\{$option\\}"> {
-    let Inst{31-28} = op31_28;
+                    (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
+                         nohash_imm:$option),
+      asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
+    bits<8> option;
+    bits<4> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 0; // P = 0
     let Inst{23} = 1; // U = 1
+    let Inst{22} = Dbit;
     let Inst{21} = 0; // W = 0
-    let Inst{22} = 0; // D = 0
     let Inst{20} = load;
+    let Inst{19-16} = addr;
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = option;
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def L_OFFSET : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
-      !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr"> {
-    let Inst{31-28} = op31_28;
+}
+multiclass LdSt2Cop<bit load, bit Dbit, string asm> {
+  def _OFFSET : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
+                       asm, "\t$cop, $CRd, $addr"> {
+    bits<13> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 1; // P = 1
+    let Inst{23} = addr{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 0; // W = 0
-    let Inst{22} = 1; // D = 1
     let Inst{20} = load;
+    let Inst{19-16} = addr{12-9};
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = addr{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def L_PRE : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr), ops),
-      !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr!",
-      IndexModePre> {
-    let Inst{31-28} = op31_28;
+  def _PRE : ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addrmode5:$addr),
+                    asm, "\t$cop, $CRd, $addr!", IndexModePre> {
+    bits<13> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 1; // P = 1
+    let Inst{23} = addr{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 1; // W = 1
-    let Inst{22} = 1; // D = 1
     let Inst{20} = load;
+    let Inst{19-16} = addr{12-9};
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = addr{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def L_POST : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
-            postidx_imm8s4:$offset), ops),
-      !strconcat(!strconcat(opc, "l"), cond), "\t$cop, $CRd, $addr, $offset",
-      IndexModePost> {
-    let Inst{31-28} = op31_28;
+  def _POST: ACInoP<(outs), (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
+                                 postidx_imm8s4:$offset),
+                 asm, "\t$cop, $CRd, $addr, $offset", IndexModePost> {
+    bits<9> offset;
+    bits<4> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 0; // P = 0
+    let Inst{23} = offset{8};
+    let Inst{22} = Dbit;
     let Inst{21} = 1; // W = 1
-    let Inst{22} = 1; // D = 1
     let Inst{20} = load;
+    let Inst{19-16} = addr;
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = offset{7-0};
     let DecoderMethod = "DecodeCopMemInstruction";
   }
-
-  def L_OPTION : ACI<(outs),
-      !con((ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$base,
-                nohash_imm:$option),
-            ops),
-      !strconcat(!strconcat(opc, "l"), cond),
-      "\t$cop, $CRd, $base, \\{$option\\}"> {
-    let Inst{31-28} = op31_28;
+  def _OPTION : ACInoP<(outs),
+                       (ins p_imm:$cop, c_imm:$CRd, addr_offset_none:$addr,
+                            nohash_imm:$option),
+      asm, "\t$cop, $CRd, $addr, \\{$option\\}"> {
+    bits<8> option;
+    bits<4> addr;
+    bits<4> cop;
+    bits<4> CRd;
     let Inst{24} = 0; // P = 0
     let Inst{23} = 1; // U = 1
+    let Inst{22} = Dbit;
     let Inst{21} = 0; // W = 0
-    let Inst{22} = 1; // D = 1
     let Inst{20} = load;
+    let Inst{19-16} = addr;
+    let Inst{15-12} = CRd;
+    let Inst{11-8} = cop;
+    let Inst{7-0} = option;
     let DecoderMethod = "DecodeCopMemInstruction";
   }
 }
 
-defm LDC  : LdStCop<{?,?,?,?}, 1, (ins pred:$p), "ldc",  "${p}">;
-defm LDC2 : LdStCop<0b1111,    1, (ins),         "ldc2", "">;
-defm STC  : LdStCop<{?,?,?,?}, 0, (ins pred:$p), "stc",  "${p}">;
-defm STC2 : LdStCop<0b1111,    0, (ins),         "stc2", "">;
+defm LDC   : LdStCop <1, 0, "ldc">;
+defm LDCL  : LdStCop <1, 1, "ldcl">;
+defm STC   : LdStCop <0, 0, "stc">;
+defm STCL  : LdStCop <0, 1, "stcl">;
+defm LDC2  : LdSt2Cop<1, 0, "ldc2">;
+defm LDC2L : LdSt2Cop<1, 1, "ldc2l">;
+defm STC2  : LdSt2Cop<0, 0, "stc2">;
+defm STC2L : LdSt2Cop<0, 1, "stc2l">;
 
 //===----------------------------------------------------------------------===//
 // Move between coprocessor and ARM core register.
index bdebc76a9b1f7cfa8c3ac59ec232a7bb03144a0a..afb6e5684dd796e2f648497c8c057ec413754ee2 100644 (file)
@@ -874,6 +874,15 @@ public:
     int64_t Val = CE->getValue();
     return (Val > -256 && Val < 256) || (Val == INT32_MIN);
   }
+  bool isPostIdxImm8s4() const {
+    if (Kind != k_Immediate)
+      return false;
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE) return false;
+    int64_t Val = CE->getValue();
+    return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
+      (Val == INT32_MIN);
+  }
 
   bool isMSRMask() const { return Kind == k_MSRMask; }
   bool isProcIFlags() const { return Kind == k_ProcIFlags; }
@@ -1356,6 +1365,18 @@ public:
     Inst.addOperand(MCOperand::CreateImm(Imm));
   }
 
+  void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
+    assert(N == 1 && "Invalid number of operands!");
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    assert(CE && "non-constant post-idx-imm8s4 operand!");
+    int Imm = CE->getValue();
+    bool isAdd = Imm >= 0;
+    if (Imm == INT32_MIN) Imm = 0;
+    // Immediate is scaled by 4.
+    Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
+    Inst.addOperand(MCOperand::CreateImm(Imm));
+  }
+
   void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
     assert(N == 2 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
@@ -3539,8 +3560,9 @@ getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
       Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
       (Mnemonic == "clrex" && !isThumb()) ||
       (Mnemonic == "nop" && isThumbOne()) ||
-      ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw") &&
-       !isThumb()) ||
+      ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
+        Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
+        Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
       ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
        !isThumb()) ||
       Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
index 38aa1067c2d9896454c7133bebbd54f35568abb7..04054e95c0ef589d93ed38b22c609e14aa2ac365 100644 (file)
@@ -642,6 +642,87 @@ Lforward:
 @ CHECK: isb sy                         @ encoding: [0x6f,0xf0,0x7f,0xf5]
 
 
+@------------------------------------------------------------------------------
+@ LDC{L}/LDC2{L}
+@------------------------------------------------------------------------------
+        ldc2 p0, c8, [r1, #4]
+        ldc2 p1, c7, [r2]
+        ldc2 p2, c6, [r3, #-224]
+        ldc2 p3, c5, [r4, #-120]!
+        ldc2 p4, c4, [r5], #16
+        ldc2 p5, c3, [r6], #-72
+        ldc2l p6, c2, [r7, #4]
+        ldc2l p7, c1, [r8]
+        ldc2l p8, c0, [r9, #-224]
+        ldc2l p9, c1, [r10, #-120]!
+        ldc2l p10, c2, [r11], #16
+        ldc2l p11, c3, [r12], #-72
+
+        ldc p12, c4, [r0, #4]
+        ldc p13, c5, [r1]
+        ldc p14, c6, [r2, #-224]
+        ldc p15, c7, [r3, #-120]!
+        ldc p5, c8, [r4], #16
+        ldc p4, c9, [r5], #-72
+        ldcl p3, c10, [r6, #4]
+        ldcl p2, c11, [r7]
+        ldcl p1, c12, [r8, #-224]
+        ldcl p0, c13, [r9, #-120]!
+        ldcl p6, c14, [r10], #16
+        ldcl p7, c15, [r11], #-72
+
+        ldclo p12, c4, [r0, #4]
+        ldchi p13, c5, [r1]
+        ldccs p14, c6, [r2, #-224]
+        ldccc p15, c7, [r3, #-120]!
+        ldceq p5, c8, [r4], #16
+        ldcgt p4, c9, [r5], #-72
+        ldcllt p3, c10, [r6, #4]
+        ldclge p2, c11, [r7]
+        ldclle p1, c12, [r8, #-224]
+        ldclne p0, c13, [r9, #-120]!
+        ldcleq p6, c14, [r10], #16
+        ldclhi p7, c15, [r11], #-72
+
+@ CHECK: ldc2  p0, c8, [r1, #4]        @ encoding: [0x01,0x80,0x91,0xfd]
+@ CHECK: ldc2  p1, c7, [r2]            @ encoding: [0x00,0x71,0x92,0xfd]
+@ CHECK: ldc2  p2, c6, [r3, #-224]     @ encoding: [0x38,0x62,0x13,0xfd]
+@ CHECK: ldc2  p3, c5, [r4, #-120]!    @ encoding: [0x1e,0x53,0x34,0xfd]
+@ CHECK: ldc2  p4, c4, [r5], #16       @ encoding: [0x04,0x44,0xb5,0xfc]
+@ CHECK: ldc2  p5, c3, [r6], #-72      @ encoding: [0x12,0x35,0x36,0xfc]
+@ CHECK: ldc2l p6, c2, [r7, #4]        @ encoding: [0x01,0x26,0xd7,0xfd]
+@ CHECK: ldc2l p7, c1, [r8]            @ encoding: [0x00,0x17,0xd8,0xfd]
+@ CHECK: ldc2l p8, c0, [r9, #-224]     @ encoding: [0x38,0x08,0x59,0xfd]
+@ CHECK: ldc2l p9, c1, [r10, #-120]!   @ encoding: [0x1e,0x19,0x7a,0xfd]
+@ CHECK: ldc2l p10, c2, [r11], #16     @ encoding: [0x04,0x2a,0xfb,0xfc]
+@ CHECK: ldc2l p11, c3, [r12], #-72    @ encoding: [0x12,0x3b,0x7c,0xfc]
+
+@ CHECK: ldc   p12, c4, [r0, #4]       @ encoding: [0x01,0x4c,0x90,0xed]
+@ CHECK: ldc   p13, c5, [r1]           @ encoding: [0x00,0x5d,0x91,0xed]
+@ CHECK: ldc   p14, c6, [r2, #-224]    @ encoding: [0x38,0x6e,0x12,0xed]
+@ CHECK: ldc   p15, c7, [r3, #-120]!   @ encoding: [0x1e,0x7f,0x33,0xed]
+@ CHECK: ldc   p5, c8, [r4], #16       @ encoding: [0x04,0x85,0xb4,0xec]
+@ CHECK: ldc   p4, c9, [r5], #-72      @ encoding: [0x12,0x94,0x35,0xec]
+@ CHECK: ldcl  p3, c10, [r6, #4]       @ encoding: [0x01,0xa3,0xd6,0xed]
+@ CHECK: ldcl  p2, c11, [r7]           @ encoding: [0x00,0xb2,0xd7,0xed]
+@ CHECK: ldcl  p1, c12, [r8, #-224]    @ encoding: [0x38,0xc1,0x58,0xed]
+@ CHECK: ldcl  p0, c13, [r9, #-120]!   @ encoding: [0x1e,0xd0,0x79,0xed]
+@ CHECK: ldcl  p6, c14, [r10], #16     @ encoding: [0x04,0xe6,0xfa,0xec]
+@ CHECK: ldcl  p7, c15, [r11], #-72    @ encoding: [0x12,0xf7,0x7b,0xec]
+
+@ CHECK: ldclo p12, c4, [r0, #4]       @ encoding: [0x01,0x4c,0x90,0x3d]
+@ CHECK: ldchi p13, c5, [r1]           @ encoding: [0x00,0x5d,0x91,0x8d]
+@ CHECK: ldchs p14, c6, [r2, #-224]    @ encoding: [0x38,0x6e,0x12,0x2d]
+@ CHECK: ldclo p15, c7, [r3, #-120]!   @ encoding: [0x1e,0x7f,0x33,0x3d]
+@ CHECK: ldceq p5, c8, [r4], #16       @ encoding: [0x04,0x85,0xb4,0x0c]
+@ CHECK: ldcgt p4, c9, [r5], #-72      @ encoding: [0x12,0x94,0x35,0xcc]
+@ CHECK: ldcllt        p3, c10, [r6, #4]       @ encoding: [0x01,0xa3,0xd6,0xbd]
+@ CHECK: ldclge        p2, c11, [r7]           @ encoding: [0x00,0xb2,0xd7,0xad]
+@ CHECK: ldclle        p1, c12, [r8, #-224]    @ encoding: [0x38,0xc1,0x58,0xdd]
+@ CHECK: ldclne        p0, c13, [r9, #-120]!   @ encoding: [0x1e,0xd0,0x79,0x1d]
+@ CHECK: ldcleq        p6, c14, [r10], #16     @ encoding: [0x04,0xe6,0xfa,0x0c]
+@ CHECK: ldclhi        p7, c15, [r11], #-72    @ encoding: [0x12,0xf7,0x7b,0x8c]
+
 
 @------------------------------------------------------------------------------
 @ LDM*