diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2013-12-29 17:58:35 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2013-12-29 17:58:35 +0000 |
commit | dd2836776f435d4b6de8d780228d02da15c37e7f (patch) | |
tree | b590a63a75333b7fe300e24b1f61547ae10a0608 | |
parent | a4f62f85a2b5613fc4c0c04114843f03361a85ad (diff) | |
download | llvm-dd2836776f435d4b6de8d780228d02da15c37e7f.tar.gz llvm-dd2836776f435d4b6de8d780228d02da15c37e7f.tar.bz2 llvm-dd2836776f435d4b6de8d780228d02da15c37e7f.tar.xz |
ARM: provide VFP aliases for pre-V6 mnemonics
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
-rw-r--r-- | lib/Target/ARM/ARMInstrVFP.td | 29 | ||||
-rw-r--r-- | lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 29 | ||||
-rw-r--r-- | test/MC/ARM/vfp-aliases-diagnostics.s | 97 | ||||
-rw-r--r-- | test/MC/ARM/vfp-aliases.s | 53 |
4 files changed, 207 insertions, 1 deletions
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 0912b473cb..a5494819d1 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -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. // diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index d4122bcb4a..c0e5472346 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -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 index 0000000000..911c23b235 --- /dev/null +++ b/test/MC/ARM/vfp-aliases-diagnostics.s @@ -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 index 0000000000..1ed6e53b80 --- /dev/null +++ b/test/MC/ARM/vfp-aliases.s @@ -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} + |