Index: lib/Target/ARM/ARMInstrVFP.td =================================================================== --- lib/Target/ARM/ARMInstrVFP.td +++ lib/Target/ARM/ARMInstrVFP.td @@ -259,23 +259,37 @@ // 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">; +class VFPLdStMultipleAlias + : InstAlias; +def : VFPLdStMultipleAlias<"fldmias", "", VLDMSIA, spr_reglist>; +def : VFPLdStMultipleAlias<"fldmfds", "", VLDMSIA, spr_reglist>; +def : VFPLdStMultipleAlias<"fldmias", "!", VLDMSIA_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fldmfds", "!", VLDMSIA_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fldmdbs", "!", VLDMSDB_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fldmeas", "!", VLDMSDB_UPD, spr_reglist>; + +def : VFPLdStMultipleAlias<"fldmiad", "", VLDMDIA, dpr_reglist>; +def : VFPLdStMultipleAlias<"fldmfdd", "", VLDMDIA, dpr_reglist>; +def : VFPLdStMultipleAlias<"fldmiad", "!", VLDMDIA_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fldmfdd", "!", VLDMDIA_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fldmdbd", "!", VLDMDDB_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fldmead", "!", VLDMDDB_UPD, dpr_reglist>; + +def : VFPLdStMultipleAlias<"fstmias", "", VSTMSIA, spr_reglist>; +def : VFPLdStMultipleAlias<"fstmeas", "", VSTMSIA, spr_reglist>; +def : VFPLdStMultipleAlias<"fstmias", "!", VSTMSIA_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fstmeas", "!", VSTMSIA_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fstmdbs", "!", VSTMSDB_UPD, spr_reglist>; +def : VFPLdStMultipleAlias<"fstmfds", "!", VSTMSDB_UPD, spr_reglist>; + +def : VFPLdStMultipleAlias<"fstmiad", "", VSTMDIA, dpr_reglist>; +def : VFPLdStMultipleAlias<"fstmaed", "", VSTMDIA, dpr_reglist>; +def : VFPLdStMultipleAlias<"fstmiad", "!", VSTMDIA_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fstmead", "!", VSTMDIA_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fstmdbd", "!", VSTMDDB_UPD, dpr_reglist>; +def : VFPLdStMultipleAlias<"fstmfdd", "!", VSTMDDB_UPD, dpr_reglist>; def : InstAlias<"vpush${p} $r", (VSTMDDB_UPD SP, pred:$p, dpr_reglist:$r), 0>, Requires<[HasVFP2]>; Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5515,7 +5515,8 @@ Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" || Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" || Mnemonic == "bxns" || Mnemonic == "blxns" || - (Mnemonic == "movs" && isThumb()))) { + (Mnemonic == "movs" && isThumb()) || + Mnemonic.startswith("fldm") || Mnemonic.startswith("fstm"))) { Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1); CarrySetting = true; } @@ -5846,25 +5847,6 @@ static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features, unsigned VariantID); -static bool RequiresVFPRegListValidation(StringRef Inst, - bool &AcceptSinglePrecisionOnly, - bool &AcceptDoublePrecisionOnly) { - if (Inst.size() < 7) - return false; - - if (Inst.startswith("fldm") || Inst.startswith("fstm")) { - StringRef AddressingMode = Inst.substr(4, 2); - if (AddressingMode == "ia" || AddressingMode == "db" || - AddressingMode == "ea" || AddressingMode == "fd") { - AcceptSinglePrecisionOnly = Inst[6] == 's'; - AcceptDoublePrecisionOnly = Inst[6] == 'd' || Inst[6] == 'x'; - return true; - } - } - - return false; -} - // The GNU assembler has aliases of ldrd and strd with the second register // omitted. We don't have a way to do that in tablegen, so fix it up here. // @@ -5915,13 +5897,6 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { MCAsmParser &Parser = getParser(); - // FIXME: Can this be done via tablegen in some fashion? - bool RequireVFPRegisterListCheck; - bool AcceptSinglePrecisionOnly; - bool AcceptDoublePrecisionOnly; - RequireVFPRegisterListCheck = - RequiresVFPRegListValidation(Name, AcceptSinglePrecisionOnly, - AcceptDoublePrecisionOnly); // Apply mnemonic aliases before doing anything else, as the destination // mnemonic may include suffices and we want to handle them normally. @@ -6079,16 +6054,6 @@ if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) return true; - if (RequireVFPRegisterListCheck) { - ARMOperand &Op = static_cast(*Operands.back()); - if (AcceptSinglePrecisionOnly && !Op.isSPRRegList()) - return Error(Op.getStartLoc(), - "VFP/Neon single precision register expected"); - if (AcceptDoublePrecisionOnly && !Op.isDPRRegList()) - return Error(Op.getStartLoc(), - "VFP/Neon double precision register expected"); - } - tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); // Some instructions, mostly Thumb, have forms for the same mnemonic that Index: test/MC/ARM/vfp-aliases-diagnostics.s =================================================================== --- test/MC/ARM/vfp-aliases-diagnostics.s +++ test/MC/ARM/vfp-aliases-diagnostics.s @@ -31,67 +31,67 @@ fldmeax sp!, {s0} @ CHECK-LABEL: aliases -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmfdd sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmead sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmdbd sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmiad sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fstmfds sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fstmeas sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fstmdbs sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fstmias sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fldmias sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fldmdbs sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fldmeas sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon single precision register expected +@ CHECK: error: operand must be a list of registers in range [s0, s31] @ CHECK: fldmfds sp!, {d0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmiad sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmdbd sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmead sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmfdd sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmeax sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmfdx sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmfdx sp!, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fldmeax sp!, {s0} @ CHECK: ^ @@ -99,16 +99,16 @@ fstmiaxhs r0, {s0} fstmiaxls r0, {s0} fstmiaxvs r0, {s0} -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmiaxcs r0, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmiaxhs r0, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmiaxls r0, {s0} @ CHECK: ^ -@ CHECK: error: VFP/Neon double precision register expected +@ CHECK: error: operand must be a list of registers in range [d0, d31] @ CHECK: fstmiaxvs r0, {s0} @ CHECK: ^