ARM: provide VFP aliases for pre-V6 mnemonics
authorSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 29 Dec 2013 17:58:35 +0000 (17:58 +0000)
committerSaleem Abdulrasool <compnerd@compnerd.org>
Sun, 29 Dec 2013 17:58:35 +0000 (17:58 +0000)
In order to provide compatibility with the GNU assembler, provide aliases for
pre-UAL mnemonics for floating point operations.

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

lib/Target/ARM/ARMInstrVFP.td
lib/Target/ARM/AsmParser/ARMAsmParser.cpp
test/MC/ARM/vfp-aliases-diagnostics.s [new file with mode: 0644]
test/MC/ARM/vfp-aliases.s [new file with mode: 0644]

index 0912b473cbb522bcd2822c8bcf2232239957a72a..a5494819d1660993ded0473bdc8677012e6e52bb 100644 (file)
@@ -207,6 +207,27 @@ defm VSTM : vfp_ldst_mult<"vstm", 0, IIC_fpStore_m, IIC_fpStore_mu>;
 def : MnemonicAlias<"vldm", "vldmia">;
 def : MnemonicAlias<"vstm", "vstmia">;
 
+// FLDM/FSTM - Load / Store multiple single / double precision registers for
+// pre-ARMv6 cores.
+// These instructions are deprecated!
+def : VFP2MnemonicAlias<"fldmias", "vldmia">;
+def : VFP2MnemonicAlias<"fldmdbs", "vldmdb">;
+def : VFP2MnemonicAlias<"fldmeas", "vldmdb">;
+def : VFP2MnemonicAlias<"fldmfds", "vldmia">;
+def : VFP2MnemonicAlias<"fldmiad", "vldmia">;
+def : VFP2MnemonicAlias<"fldmdbd", "vldmdb">;
+def : VFP2MnemonicAlias<"fldmead", "vldmdb">;
+def : VFP2MnemonicAlias<"fldmfdd", "vldmia">;
+
+def : VFP2MnemonicAlias<"fstmias", "vstmia">;
+def : VFP2MnemonicAlias<"fstmdbs", "vstmdb">;
+def : VFP2MnemonicAlias<"fstmeas", "vstmia">;
+def : VFP2MnemonicAlias<"fstmfds", "vstmdb">;
+def : VFP2MnemonicAlias<"fstmiad", "vstmia">;
+def : VFP2MnemonicAlias<"fstmdbd", "vstmdb">;
+def : VFP2MnemonicAlias<"fstmead", "vstmia">;
+def : VFP2MnemonicAlias<"fstmfdd", "vstmdb">;
+
 def : InstAlias<"vpush${p} $r", (VSTMDDB_UPD SP, pred:$p, dpr_reglist:$r)>,
                 Requires<[HasVFP2]>;
 def : InstAlias<"vpush${p} $r", (VSTMSDB_UPD SP, pred:$p, spr_reglist:$r)>,
@@ -247,7 +268,7 @@ multiclass vfp_ldstx_mult<string asm, bit L_bit> {
     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{21}    = 1;            // Writeback
     let Inst{20}    = L_bit;
   }
 }
@@ -255,6 +276,12 @@ multiclass vfp_ldstx_mult<string asm, bit L_bit> {
 defm FLDM : vfp_ldstx_mult<"fldm", 1>;
 defm FSTM : vfp_ldstx_mult<"fstm", 0>;
 
+def : VFP2MnemonicAlias<"fldmeax", "fldmdbx">;
+def : VFP2MnemonicAlias<"fldmfdx", "fldmiax">;
+
+def : VFP2MnemonicAlias<"fstmeax", "fstmiax">;
+def : VFP2MnemonicAlias<"fstmfdx", "fstmdbx">;
+
 //===----------------------------------------------------------------------===//
 // FP Binary Operations.
 //
index d4122bcb4af26953f84ac40713f5d47aaf665c82..c0e547234695f2d226f22ab798bebe5fd88c1f56 100644 (file)
@@ -5111,6 +5111,15 @@ static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features,
 bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                                     SMLoc NameLoc,
                                SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  // FIXME: Can this be done via tablegen in some fashion?
+  bool HasPrecisionRestrictions;
+  bool AcceptDoublePrecisionOnly;
+  bool AcceptSinglePrecisionOnly;
+  HasPrecisionRestrictions = Name.startswith("fldm") || Name.startswith("fstm");
+  AcceptDoublePrecisionOnly =
+    HasPrecisionRestrictions && (Name.back() == 'd' || Name.back() == 'x');
+  AcceptSinglePrecisionOnly = HasPrecisionRestrictions && Name.back() == 's';
+
   // Apply mnemonic aliases before doing anything else, as the destination
   // mnemonic may include suffices and we want to handle them normally.
   // The generic tblgen'erated code does this later, at the start of
@@ -5279,6 +5288,26 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
 
   Parser.Lex(); // Consume the EndOfStatement
 
+  if (HasPrecisionRestrictions) {
+    ARMOperand *Op = static_cast<ARMOperand*>(Operands.back());
+    assert(Op->isRegList());
+    const SmallVectorImpl<unsigned> &RegList = Op->getRegList();
+    for (SmallVectorImpl<unsigned>::const_iterator RLI = RegList.begin(),
+                                                   RLE = RegList.end();
+         RLI != RLE; ++RLI) {
+      if (AcceptSinglePrecisionOnly &&
+          !ARMMCRegisterClasses[ARM::SPRRegClassID].contains(*RLI))
+        return Error(Op->getStartLoc(),
+                     "VFP/Neon single precision register expected");
+      else if (AcceptDoublePrecisionOnly &&
+               !ARMMCRegisterClasses[ARM::DPRRegClassID].contains(*RLI))
+        return Error(Op->getStartLoc(),
+                     "VFP/Neon double precision register expected");
+      else
+        llvm_unreachable("must have single or double precision restrictions");
+    }
+  }
+
   // Some instructions, mostly Thumb, have forms for the same mnemonic that
   // do and don't have a cc_out optional-def operand. With some spot-checks
   // of the operand list, we can figure out which variant we're trying to
diff --git a/test/MC/ARM/vfp-aliases-diagnostics.s b/test/MC/ARM/vfp-aliases-diagnostics.s
new file mode 100644 (file)
index 0000000..911c23b
--- /dev/null
@@ -0,0 +1,97 @@
+@ RUN: not llvm-mc -triple armv7-eabi -filetype asm -o /dev/null %s 2>&1 \
+@ RUN:   | FileCheck %s
+
+       .syntax unified
+       .fpu vfp
+
+       .type aliases,%function
+aliases:
+       fstmfdd sp!, {s0}
+       fstmead sp!, {s0}
+       fstmdbd sp!, {s0}
+       fstmiad sp!, {s0}
+       fstmfds sp!, {d0}
+       fstmeas sp!, {d0}
+       fstmdbs sp!, {d0}
+       fstmias sp!, {d0}
+
+       fldmias sp!, {d0}
+       fldmdbs sp!, {d0}
+       fldmeas sp!, {d0}
+       fldmfds sp!, {d0}
+       fldmiad sp!, {s0}
+       fldmdbd sp!, {s0}
+       fldmead sp!, {s0}
+       fldmfdd sp!, {s0}
+
+       fstmeax sp!, {s0}
+       fldmfdx sp!, {s0}
+
+       fstmfdx sp!, {s0}
+       fldmeax sp!, {s0}
+
+@ CHECK-LABEL: aliases
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmfdd sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmead sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmdbd sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmiad sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fstmfds sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fstmeas sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fstmdbs sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fstmias sp!, {d0}
+@ CHECK:                     ^
+
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fldmias sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fldmdbs sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fldmeas sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon single precision register expected
+@ CHECK:       fldmfds sp!, {d0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmiad sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmdbd sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmead sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmfdd sp!, {s0}
+@ CHECK:                     ^
+
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmeax sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmfdx sp!, {s0}
+@ CHECK:                     ^
+
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fstmfdx sp!, {s0}
+@ CHECK:                     ^
+@ CHECK: error: VFP/Neon double precision register expected
+@ CHECK:       fldmeax sp!, {s0}
+@ CHECK:                     ^
+
diff --git a/test/MC/ARM/vfp-aliases.s b/test/MC/ARM/vfp-aliases.s
new file mode 100644 (file)
index 0000000..1ed6e53
--- /dev/null
@@ -0,0 +1,53 @@
+@ RUN: llvm-mc -triple armv7-eabi -filetype asm -o - %s | FileCheck %s
+
+       .syntax unified
+       .fpu vfp
+
+       .type aliases,%function
+aliases:
+       fstmfdd sp!, {d0}
+       fstmead sp!, {d0}
+       fstmdbd sp!, {d0}
+       fstmiad sp!, {d0}
+       fstmfds sp!, {s0}
+       fstmeas sp!, {s0}
+       fstmdbs sp!, {s0}
+       fstmias sp!, {s0}
+
+       fldmias sp!, {s0}
+       fldmdbs sp!, {s0}
+       fldmeas sp!, {s0}
+       fldmfds sp!, {s0}
+       fldmiad sp!, {d0}
+       fldmdbd sp!, {d0}
+       fldmead sp!, {d0}
+       fldmfdd sp!, {d0}
+
+       fstmeax sp!, {d0}
+       fldmfdx sp!, {d0}
+
+       fstmfdx sp!, {d0}
+       fldmeax sp!, {d0}
+
+@ CHECK-LABEL: aliases
+@ CHECK:       vpush {d0}
+@ CHECK:       vstmia sp!, {d0}
+@ CHECK:       vpush {d0}
+@ CHECK:       vstmia sp!, {d0}
+@ CHECK:       vpush {s0}
+@ CHECK:       vstmia sp!, {s0}
+@ CHECK:       vpush {s0}
+@ CHECK:       vstmia sp!, {s0}
+@ CHECK:       vpop {s0}
+@ CHECK:       vldmdb sp!, {s0}
+@ CHECK:       vldmdb sp!, {s0}
+@ CHECK:       vpop {s0}
+@ CHECK:       vpop {d0}
+@ CHECK:       vldmdb sp!, {d0}
+@ CHECK:       vldmdb sp!, {d0}
+@ CHECK:       vpop {d0}
+@ CHECK:       fstmiax sp!, {d0}
+@ CHECK:       fldmiax sp!, {d0}
+@ CHECK:       fstmdbx sp!, {d0}
+@ CHECK:       fldmdbx sp!, {d0}
+