ARM: add fstmx and fldmx instructions for assembly
authorTim Northover <tnorthover@apple.com>
Fri, 31 May 2013 15:55:51 +0000 (15:55 +0000)
committerTim Northover <tnorthover@apple.com>
Fri, 31 May 2013 15:55:51 +0000 (15:55 +0000)
These instructions are deprecated oddities, but we still need to be able to
disassemble (and reassemble) them if and when they're encountered.

Patch by Amaury de la Vieuville.

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

lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrVFP.td
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
test/MC/ARM/simple-fp-encoding.s
test/MC/Disassembler/ARM/fp-encoding.txt
test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt [new file with mode: 0644]

index 67a6820932fc188700e5dc1356ee9fe2e681ddb3..bd9a212928eba8d09240cb59b9ce5d678284ca46 100644 (file)
@@ -1389,7 +1389,6 @@ class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
   let Inst{15-12} = Dd{3-0};
   let Inst{7-0}   = addr{7-0};    // imm8
 
-  // TODO: Mark the instructions with the appropriate subtarget info.
   let Inst{27-24} = opcod1;
   let Inst{21-20} = opcod2;
   let Inst{11-9}  = 0b101;
@@ -1415,7 +1414,6 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
   let Inst{15-12} = Sd{4-1};
   let Inst{7-0}   = addr{7-0};    // imm8
 
-  // TODO: Mark the instructions with the appropriate subtarget info.
   let Inst{27-24} = opcod1;
   let Inst{21-20} = opcod2;
   let Inst{11-9}  = 0b101;
@@ -1437,6 +1435,28 @@ class PseudoVFPLdStM<dag oops, dag iops, InstrItinClass itin, string cstr,
 }
 
 // Load / store multiple
+
+// Unknown precision
+class AXXI4<dag oops, dag iops, IndexMode im,
+            string asm, string cstr, list<dag> pattern>
+  : VFPXI<oops, iops, AddrMode4, 4, im,
+          VFPLdStFrm, NoItinerary, asm, cstr, pattern> {
+  // Instruction operands.
+  bits<4>  Rn;
+  bits<13> regs;
+
+  // Encode instruction operands.
+  let Inst{19-16} = Rn;
+  let Inst{22}    = 0;
+  let Inst{15-12} = regs{11-8};
+  let Inst{7-1}   = regs{7-1};
+
+  let Inst{27-25} = 0b110;
+  let Inst{11-8}  = 0b1011;
+  let Inst{0}     = 1;
+}
+
+// Double precision
 class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
             string asm, string cstr, list<dag> pattern>
   : VFPXI<oops, iops, AddrMode4, 4, im,
@@ -1449,14 +1469,15 @@ class AXDI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
   let Inst{19-16} = Rn;
   let Inst{22}    = regs{12};
   let Inst{15-12} = regs{11-8};
-  let Inst{7-0}   = regs{7-0};
+  let Inst{7-1}   = regs{7-1};
 
-  // TODO: Mark the instructions with the appropriate subtarget info.
   let Inst{27-25} = 0b110;
   let Inst{11-9}  = 0b101;
   let Inst{8}     = 1;          // Double precision
+  let Inst{0}     = 0;
 }
 
+// Single Precision
 class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
             string asm, string cstr, list<dag> pattern>
   : VFPXI<oops, iops, AddrMode4, 4, im,
@@ -1471,7 +1492,6 @@ class AXSI4<dag oops, dag iops, IndexMode im, InstrItinClass itin,
   let Inst{15-12} = regs{12-9};
   let Inst{7-0}   = regs{7-0};
 
-  // TODO: Mark the instructions with the appropriate subtarget info.
   let Inst{27-25} = 0b110;
   let Inst{11-9}  = 0b101;
   let Inst{8}     = 0;          // Single precision
index b5a896c69985adaca3c1d1b1c5430fd52bd8fd7f..2380528e130ce9e3ff4186fa7814a773ecff87a1 100644 (file)
@@ -224,7 +224,36 @@ defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
 defm : VFPDTAnyInstAlias<"vpop${p}", "$r",
                          (VLDMDIA_UPD SP, pred:$p, dpr_reglist:$r)>;
 
-// FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores
+// FLDMX, FSTMX - Load and store multiple unknown precision registers for
+// pre-armv6 cores.
+// These instruction are deprecated so we don't want them to get selected.
+multiclass vfp_ldstx_mult<string asm, bit L_bit> {
+  // Unknown precision
+  def XIA :
+    AXXI4<(outs), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+          IndexModeNone, !strconcat(asm, "iax${p}\t$Rn, $regs"), "", []> {
+    let Inst{24-23} = 0b01;       // Increment After
+    let Inst{21}    = 0;          // No writeback
+    let Inst{20}    = L_bit;
+  }
+  def XIA_UPD :
+    AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+          IndexModeUpd, !strconcat(asm, "iax${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+    let Inst{24-23} = 0b01;         // Increment After
+    let Inst{21}    = 1;            // Writeback
+    let Inst{20}    = L_bit;
+  }
+  def XDB_UPD :
+    AXXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, dpr_reglist:$regs, variable_ops),
+          IndexModeUpd, !strconcat(asm, "dbx${p}\t$Rn!, $regs"), "$Rn = $wb", []> {
+    let Inst{24-23} = 0b10;         // Decrement Before
+    let Inst{21}    = 1;
+    let Inst{20}    = L_bit;
+  }
+}
+
+defm FLDM : vfp_ldstx_mult<"fldm", 1>;
+defm FSTM : vfp_ldstx_mult<"fstm", 0>;
 
 //===----------------------------------------------------------------------===//
 // FP Binary Operations.
index 9c13c604638d2c4cc08e44323f4bc916af4eea73..824ffbf3386383969b23fd269a25302fa5c9ce0c 100644 (file)
@@ -1150,6 +1150,13 @@ static DecodeStatus DecodeSPRRegListOperand(MCInst &Inst, unsigned Val,
   unsigned Vd = fieldFromInstruction(Val, 8, 5);
   unsigned regs = fieldFromInstruction(Val, 0, 8);
 
+  // In case of unpredictable encoding, tweak the operands.
+  if (regs == 0 || (Vd + regs) > 32) {
+    regs = Vd + regs > 32 ? 32 - Vd : regs;
+    regs = std::max( 1u, regs);
+    S = MCDisassembler::SoftFail;
+  }
+
   if (!Check(S, DecodeSPRRegisterClass(Inst, Vd, Address, Decoder)))
     return MCDisassembler::Fail;
   for (unsigned i = 0; i < (regs - 1); ++i) {
@@ -1165,9 +1172,15 @@ static DecodeStatus DecodeDPRRegListOperand(MCInst &Inst, unsigned Val,
   DecodeStatus S = MCDisassembler::Success;
 
   unsigned Vd = fieldFromInstruction(Val, 8, 5);
-  unsigned regs = fieldFromInstruction(Val, 0, 8);
+  unsigned regs = fieldFromInstruction(Val, 1, 7);
 
-  regs = regs >> 1;
+  // In case of unpredictable encoding, tweak the operands.
+  if (regs == 0 || regs > 16 || (Vd + regs) > 32) {
+    regs = Vd + regs > 32 ? 32 - Vd : regs;
+    regs = std::max( 1u, regs);
+    regs = std::min(16u, regs);
+    S = MCDisassembler::SoftFail;
+  }
 
   if (!Check(S, DecodeDPRRegisterClass(Inst, Vd, Address, Decoder)))
       return MCDisassembler::Fail;
index 2a226205a086d27387ee1c27fe21baeaf941239f..0561b449072176d908356e0b3bf60baac5f85c63 100644 (file)
         vstmia  r1, {s2,s3-s6,s7}
         vstmdb sp!, {q4-q7}
 
+        fldmiax r5!, {d0-d2}
+        fldmiaxeq r0, {d4,d5}
+        fldmdbxne r5!, {d4,d5,d6}
+@ CHECK: fldmiax r5!, {d0, d1, d2}      @ encoding: [0x07,0x0b,0xb5,0xec]
+@ CHECK: fldmiaxeq r0, {d4, d5}         @ encoding: [0x05,0x4b,0x90,0x0c]
+@ CHECK: fldmdbxne r5!, {d4, d5, d6}    @ encoding: [0x07,0x4b,0x35,0x1d]
+
+        fstmiax r5!, {d0-d7}
+        fstmiaxeq r4, {d8,d9}
+        fstmdbxne r7!, {d2-d4}
+@ CHECK: fstmiax r5!, {d0, d1, d2, d3, d4, d5, d6, d7} @ encoding: [0x11,0x0b,0xa5,0xec]
+@ CHECK: fstmiaxeq r4, {d8, d9}         @ encoding: [0x05,0x8b,0x84,0x0c]
+@ CHECK: fstmdbxne r7!, {d2, d3, d4}    @ encoding: [0x07,0x2b,0x27,0x1d]
+
 @ CHECK: vcvtr.s32.f64  s0, d0 @ encoding: [0x40,0x0b,0xbd,0xee]
 @ CHECK: vcvtr.s32.f32  s0, s1 @ encoding: [0x60,0x0a,0xbd,0xee]
 @ CHECK: vcvtr.u32.f64  s0, d0 @ encoding: [0x40,0x0b,0xbc,0xee]
index 8dedf808c180d982147ce16002c1db7db39d2336..531793dbefbbb6789ab39cc5a45a3cd56aee219c 100644 (file)
 # CHECK: vldmdbeq r5!, {s21, s22, s23}
 # CHECK: vldmdbeq r7!, {d14, d15, d16, d17}
 
+0x0d 0x4b 0x96 0x0c
+0x0f 0x3b 0xb7 0x0c
+0x09 0x1b 0x38 0xed
+# CHECK: fldmiaxeq r6, {d4, d5, d6, d7, d8, d9}
+# CHECK: fldmiaxeq r7!, {d3, d4, d5, d6, d7, d8, d9}
+# CHECK: fldmdbx   r8!, {d1, d2, d3, d4}
+
+0x07 0x2b 0x83 0xec
+0x05 0x5b 0xa3 0x0c
+0x0f 0x3b 0x20 0x1d
+# CHECK: fstmiax   r3, {d2, d3, d4}
+# CHECK: fstmiaxeq r3!, {d5, d6}
+# CHECK: fstmdbxne r0!, {d3, d4, d5, d6, d7, d8, d9}
+
 0x04 0x7a 0xa6 0x0c
 0x0c 0xfb 0xa4 0x0c
 0x03 0xaa 0xf8 0x0c
diff --git a/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt b/test/MC/Disassembler/ARM/invalid-FSTMX-arm.txt
new file mode 100644 (file)
index 0000000..b81b4e8
--- /dev/null
@@ -0,0 +1,8 @@
+# RUN: llvm-mc --disassemble %s -triple=armv7 2>&1 | FileCheck %s -check-prefix=CHECK-WARN
+# RUN: llvm-mc --disassemble %s -triple=armv7 2>&1 | FileCheck %s
+
+# offset=1
+# CHECK-WARN: potentially undefined
+# CHECK-WARN: 0x01 0xdb 0x84 0xec
+# CHECK: fstmiax r4, {d13}
+0x01 0xdb 0x84 0xec