From 295cdd5c3dbd14406bf9cce01e3dfd787fb1ddda Mon Sep 17 00:00:00 2001 From: Alfie Richards <156316945+AlfieRichardsArm@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:25:13 +0000 Subject: [PATCH] [ARM][TableGen][MC] Change the ARM mnemonic operands to be optional for ASM parsing (#83436) This changs the way the assembly matcher works for Aarch32 parsing. Previously there was a pile of hacks which dictated whether the CC, CCOut, and VCC operands should be present which de-facto chose if the wide/narrow (or thumb1/thumb2/arm) instruction version were chosen. This meant much of the TableGen machinery present for the assembly matching was effectively being bypassed and worked around. This patch makes the CC and CCOut operands optional which allows the ASM matcher operate as it was designed and means we can avoid doing some of the hacks done previously. This also adds the option for the target to allow the prioritizing the smaller instruction encodings as is required for Aarch32. --- llvm/include/llvm/Target/Target.td | 2 - llvm/lib/Target/ARM/ARM.td | 1 + llvm/lib/Target/ARM/ARMInstrFormats.td | 18 +- llvm/lib/Target/ARM/ARMInstrThumb.td | 4 +- llvm/lib/Target/ARM/ARMInstrThumb2.td | 10 +- .../lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 1290 +++++++++-------- llvm/test/MC/ARM/arm-branch-errors.s | 4 +- llvm/test/MC/ARM/arm11-hint-instr.s | 8 +- llvm/test/MC/ARM/cde-fp-vec.s | 22 +- llvm/test/MC/ARM/cde-vec-pred.s | 2 +- llvm/test/MC/ARM/cps.s | 2 +- llvm/test/MC/ARM/diagnostics.s | 2 +- .../MC/ARM/directive-arch_extension-crypto.s | 15 +- llvm/test/MC/ARM/invalid-fp-armv8.s | 4 +- llvm/test/MC/ARM/lsl-zero-errors.s | 8 +- llvm/test/MC/ARM/mve-load-store.s | 912 ++++++------ llvm/test/MC/ARM/mve-misc.s | 59 +- llvm/test/MC/ARM/neon-complex.s | 24 +- llvm/test/MC/ARM/no-mve.s | 6 +- llvm/test/MC/ARM/not-armv4.s | 14 +- llvm/test/MC/ARM/register-token-source-loc.s | 3 + llvm/test/MC/ARM/tMOVSr.s | 5 +- llvm/test/MC/ARM/thumb-diagnostics.s | 33 +- llvm/test/MC/ARM/thumb-mov.s | 16 +- llvm/test/MC/ARM/thumb2-diagnostics.s | 4 +- llvm/test/MC/ARM/vfp4.s | 4 +- .../ARM/cortex-a57-basic-instructions.s | 2 +- llvm/utils/TableGen/AsmMatcherEmitter.cpp | 4 + 28 files changed, 1343 insertions(+), 1135 deletions(-) diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index e27ecb21ecbc3..4f0c10049ee70 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -947,8 +947,6 @@ class AsmOperandClass { /// instruction if it hasn't matched all the operands yet. However, this /// error will be suppressed if all of the remaining unmatched operands are /// marked as IsOptional. - /// - /// Optional arguments must be at the end of the operand list. bit IsOptional = false; /// The name of the method on the target specific asm parser that returns the diff --git a/llvm/lib/Target/ARM/ARM.td b/llvm/lib/Target/ARM/ARM.td index 4510c7cf4f42e..66596dbda83c9 100644 --- a/llvm/lib/Target/ARM/ARM.td +++ b/llvm/lib/Target/ARM/ARM.td @@ -1742,6 +1742,7 @@ def ARMAsmWriter : AsmWriter { def ARMAsmParser : AsmParser { bit ReportMultipleNearMisses = 1; + let PreferSmallerInstructions = true; } def ARMAsmParserVariant : AsmParserVariant { diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td index 404085820a666..d0678f378da1e 100644 --- a/llvm/lib/Target/ARM/ARMInstrFormats.td +++ b/llvm/lib/Target/ARM/ARMInstrFormats.td @@ -155,7 +155,11 @@ def iflags_op : Operand { // ARM Predicate operand. Default to 14 = always (AL). Second part is CC // register whose default is 0 (no register). -def CondCodeOperand : AsmOperandClass { let Name = "CondCode"; } +def CondCodeOperand : AsmOperandClass { + let Name = "CondCode"; + let DefaultMethod = "defaultCondCodeOp"; + let IsOptional = true; +} def pred : PredicateOperand { let PrintMethod = "printPredicateOperand"; @@ -174,7 +178,11 @@ def cmovpred : Operand, PredicateOp, } // Conditional code result for instructions whose 's' bit is set, e.g. subs. -def CCOutOperand : AsmOperandClass { let Name = "CCOut"; } +def CCOutOperand : AsmOperandClass { + let Name = "CCOut"; + let DefaultMethod = "defaultCCOutOp"; + let IsOptional = true; +} def cc_out : OptionalDefOperand { let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; @@ -202,10 +210,14 @@ def inv_cond_XFORM : SDNodeXForm - : InstTemplate { let OutOperandList = oops; let InOperandList = iops; diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index be0ca964d3f91..e7f4059935138 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -1210,7 +1210,7 @@ def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255_expr:$imm8), IIC_iMOVi, // Because we have an explicit tMOVSr below, we need an alias to handle // the immediate "movs" form here. Blech. def : tInstAlias <"movs $Rdn, $imm8", - (tMOVi8 tGPR:$Rdn, CPSR, imm0_255_expr:$imm8, 14, 0)>; + (tMOVi8 tGPR:$Rdn, CPSR, imm0_255_expr:$imm8, 14, zero_reg)>; // A7-73: MOV(2) - mov setting flag. @@ -1768,7 +1768,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { // In Thumb1, "nop" is encoded as a "mov r8, r8". Technically, the bf00 // encoding is available on ARMv6K, but we don't differentiate that finely. -def : InstAlias<"nop", (tMOVr R8, R8, 14, 0), 0>, Requires<[IsThumb, IsThumb1Only]>; +def : InstAlias<"nop", (tMOVr R8, R8, 14, zero_reg), 0>, Requires<[IsThumb, IsThumb1Only]>; // "neg" is and alias for "rsb rd, rn, #0" diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td index acd46e8093aa7..f227d68deeb8b 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb2.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td @@ -5092,14 +5092,14 @@ def : InstAlias<"dmb${p}.w", (t2DMB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}.w\t$opt", (t2DSB memb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}", (t2DSB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"dsb${p}.w", (t2DSB 0xf, pred:$p), 0>, Requires<[HasDB]>; -def : InstAlias<"isb${p}.w\t$opt", (t2ISB memb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; +def : InstAlias<"isb${p}.w\t$opt", (t2ISB instsyncb_opt:$opt, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"isb${p}", (t2ISB 0xf, pred:$p), 0>, Requires<[HasDB]>; def : InstAlias<"isb${p}.w", (t2ISB 0xf, pred:$p), 0>, Requires<[HasDB]>; -// Non-predicable aliases of a predicable DSB: the predicate is (14, 0) where -// 14 = AL (always execute) and 0 = "instruction doesn't read the CPSR". -def : InstAlias<"ssbb", (t2DSB 0x0, 14, 0), 1>, Requires<[HasDB, IsThumb2]>; -def : InstAlias<"pssbb", (t2DSB 0x4, 14, 0), 1>, Requires<[HasDB, IsThumb2]>; +// Non-predicable aliases of a predicable DSB: the predicate is (14, zero_reg) where +// 14 = AL (always execute) and zero_reg = "instruction doesn't read the CPSR". +def : InstAlias<"ssbb", (t2DSB 0x0, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; +def : InstAlias<"pssbb", (t2DSB 0x4, 14, zero_reg), 1>, Requires<[HasDB, IsThumb2]>; // Armv8-R 'Data Full Barrier' def : InstAlias<"dfb${p}", (t2DSB 0xc, pred:$p), 1>, Requires<[HasDFB]>; diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index c320bf723c88b..1892a5f2fa98f 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -25,6 +26,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -47,6 +49,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SMLoc.h" @@ -79,6 +82,7 @@ extern const ARMInstrTable ARMDescs; } // end namespace llvm namespace { +class ARMOperand; enum class ImplicitItModeTy { Always, Never, ARMOnly, ThumbOnly }; @@ -446,9 +450,10 @@ class ARMAsmParser : public MCTargetAsmParser { } bool validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo, bool IsARPop = false); + unsigned MnemonicOpsEndInd, unsigned ListIndex, + bool IsARPop = false); bool validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo); + unsigned MnemonicOpsEndInd, unsigned ListIndex); int tryParseRegister(bool AllowOutofBoundReg = false); bool tryParseRegisterWithWriteBack(OperandVector &); @@ -505,6 +510,10 @@ class ARMAsmParser : public MCTargetAsmParser { bool parseDirectiveSEHEpilogEnd(SMLoc L); bool parseDirectiveSEHCustom(SMLoc L); + std::unique_ptr defaultCondCodeOp(); + std::unique_ptr defaultCCOutOp(); + std::unique_ptr defaultVPTPredOp(); + bool isMnemonicVPTPredicable(StringRef Mnemonic, StringRef ExtraToken); StringRef splitMnemonic(StringRef Mnemonic, StringRef ExtraToken, ARMCC::CondCodes &PredicationCode, @@ -517,9 +526,13 @@ class ARMAsmParser : public MCTargetAsmParser { bool &CanAcceptVPTPredicationCode); bool enableArchExtFeature(StringRef Name, SMLoc &ExtLoc); - void tryConvertingToTwoOperandForm(StringRef Mnemonic, bool CarrySetting, - OperandVector &Operands); - bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands); + void tryConvertingToTwoOperandForm(StringRef Mnemonic, + ARMCC::CondCodes PredicationCode, + bool CarrySetting, OperandVector &Operands, + unsigned MnemonicOpsEndInd); + + bool CDEConvertDualRegOperand(StringRef Mnemonic, OperandVector &Operands, + unsigned MnemonicOpsEndInd); bool isThumb() const { // FIXME: Can tablegen auto-generate this? @@ -659,15 +672,20 @@ class ARMAsmParser : public MCTargetAsmParser { void cvtThumbBranches(MCInst &Inst, const OperandVector &); void cvtMVEVMOVQtoDReg(MCInst &Inst, const OperandVector &); - bool validateInstruction(MCInst &Inst, const OperandVector &Ops); - bool processInstruction(MCInst &Inst, const OperandVector &Ops, MCStreamer &Out); - bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands); - bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands); - bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, OperandVector &Operands); + bool validateInstruction(MCInst &Inst, const OperandVector &Ops, + unsigned MnemonicOpsEndInd); + bool processInstruction(MCInst &Inst, const OperandVector &Ops, + unsigned MnemonicOpsEndInd, MCStreamer &Out); + bool shouldOmitVectorPredicateOperand(StringRef Mnemonic, + OperandVector &Operands, + unsigned MnemonicOpsEndInd); bool isITBlockTerminator(MCInst &Inst) const; - void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands); - bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, - bool Load, bool ARMMode, bool Writeback); + + void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands, + unsigned MnemonicOpsEndInd); + bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, bool Load, + bool ARMMode, bool Writeback, + unsigned MnemonicOpsEndInd); public: enum ARMMatchResultTy { @@ -716,6 +734,9 @@ class ARMAsmParser : public MCTargetAsmParser { unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, unsigned Kind) override; unsigned checkTargetMatchPredicate(MCInst &Inst) override; + unsigned + checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) override; bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, @@ -1347,6 +1368,14 @@ class ARMOperand : public MCParsedAsmOperand { bool isRegListWithAPSR() const { return Kind == k_RegisterListWithAPSR || Kind == k_RegisterList; } + bool isDReg() const { + return isReg() && + ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg.RegNum); + } + bool isQReg() const { + return isReg() && + ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg.RegNum); + } bool isDPRRegList() const { return Kind == k_DPRRegisterList; } bool isSPRRegList() const { return Kind == k_SPRRegisterList; } bool isFPSRegListWithVPR() const { return Kind == k_FPSRegisterListWithVPR; } @@ -2012,6 +2041,8 @@ class ARMOperand : public MCParsedAsmOperand { bool isProcIFlags() const { return Kind == k_ProcIFlags; } // NEON operands. + bool isVectorList() const { return Kind == k_VectorList; } + bool isSingleSpacedVectorList() const { return Kind == k_VectorList && !VectorList.isDoubleSpaced; } @@ -2452,6 +2483,20 @@ class ARMOperand : public MCParsedAsmOperand { CC == ARMCC::GT || CC == ARMCC::LE || CC == ARMCC::GE; } + void setVecListDPair(unsigned int DPair) { + Kind = k_VectorList; + VectorList.RegNum = DPair; + VectorList.Count = 2; + VectorList.isDoubleSpaced = false; + } + + void setVecListOneD(unsigned int DReg) { + Kind = k_VectorList; + VectorList.RegNum = DReg; + VectorList.Count = 1; + VectorList.isDoubleSpaced = false; + } + void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) @@ -4054,6 +4099,63 @@ static MCRegister MatchRegisterName(StringRef Name); /// } +static bool isDataTypeToken(StringRef Tok) { + static const DenseSet DataTypes{ + ".8", ".16", ".32", ".64", ".i8", ".i16", ".i32", ".i64", + ".u8", ".u16", ".u32", ".u64", ".s8", ".s16", ".s32", ".s64", + ".p8", ".p16", ".f32", ".f64", ".f", ".d"}; + return DataTypes.contains(Tok); +} + +static unsigned getMnemonicOpsEndInd(const OperandVector &Operands) { + unsigned MnemonicOpsEndInd = 1; + // Special case for CPS which has a Mnemonic side token for possibly storing + // ie/id variant + if (Operands[0]->isToken() && + static_cast(*Operands[0]).getToken() == "cps") { + if (Operands.size() > 1 && Operands[1]->isImm() && + static_cast(*Operands[1]).getImm()->getKind() == + llvm::MCExpr::Constant && + (dyn_cast( + static_cast(*Operands[1]).getImm()) + ->getValue() == ARM_PROC::IE || + dyn_cast( + static_cast(*Operands[1]).getImm()) + ->getValue() == ARM_PROC::ID)) + ++MnemonicOpsEndInd; + } + + // In some circumstances the condition code moves to the right + bool RHSCondCode = false; + while (MnemonicOpsEndInd < Operands.size()) { + auto Op = static_cast(*Operands[MnemonicOpsEndInd]); + // Special case for it instructions which have a condition code on the RHS + if (Op.isITMask()) { + RHSCondCode = true; + MnemonicOpsEndInd++; + } else if (Op.isToken() && + ( + // There are several special cases not covered by + // isDataTypeToken + Op.getToken() == ".w" || Op.getToken() == ".bf16" || + Op.getToken() == ".p64" || Op.getToken() == ".f16" || + isDataTypeToken(Op.getToken()))) { + // In the mnemonic operators the cond code must always precede the data + // type. So we can now safely assume any subsequent cond code is on the + // RHS. As is the case for VCMP and VPT. + RHSCondCode = true; + MnemonicOpsEndInd++; + } + // Skip all mnemonic operator types + else if (Op.isCCOut() || (Op.isCondCode() && !RHSCondCode) || + Op.isVPTPred() || (Op.isToken() && Op.getToken() == ".w")) + MnemonicOpsEndInd++; + else + break; + } + return MnemonicOpsEndInd; +} + bool ARMAsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) { const AsmToken &Tok = getParser().getTok(); @@ -4680,6 +4782,8 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { // As an extension (to match gas), support a plain D register or Q register // (without encosing curly braces) as a single or double entry list, // respectively. + // If there is no lane supplied, just parse as a register and + // use the custom matcher to convert to list if necessary if (!hasMVE() && Parser.getTok().is(AsmToken::Identifier)) { SMLoc E = Parser.getTok().getEndLoc(); int Reg = tryParseRegister(); @@ -4691,7 +4795,7 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); break; case AllLanes: Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false, @@ -4712,9 +4816,7 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { return Res; switch (LaneKind) { case NoLanes: - Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, - &ARMMCRegisterClasses[ARM::DPairRegClassID]); - Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E)); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); break; case AllLanes: Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0, @@ -4730,7 +4832,8 @@ ParseStatus ARMAsmParser::parseVectorList(OperandVector &Operands) { } return ParseStatus::Success; } - return Error(S, "vector register expected"); + Operands.push_back(ARMOperand::CreateReg(Reg, S, E)); + return ParseStatus::Success; } if (Parser.getTok().isNot(AsmToken::LCurly)) @@ -5060,6 +5163,10 @@ ParseStatus ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) { /// parseMSRMaskOperand - Try to parse mask flags from MSR instruction. ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { + // Don't parse two MSR registers in a row + if (static_cast(*Operands.back()).isMSRMask() || + static_cast(*Operands.back()).isBankedReg()) + return ParseStatus::NoMatch; MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -5157,6 +5264,10 @@ ParseStatus ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) { /// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for /// use in the MRS/MSR instructions added to support virtualization. ParseStatus ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) { + // Don't parse two Banked registers in a row + if (static_cast(*Operands.back()).isBankedReg() || + static_cast(*Operands.back()).isMSRMask()) + return ParseStatus::NoMatch; MCAsmParser &Parser = getParser(); SMLoc S = Parser.getTok().getLoc(); const AsmToken &Tok = Parser.getTok(); @@ -5190,7 +5301,7 @@ ParseStatus ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, // There must be a '#' and a shift amount. if (Parser.getTok().isNot(AsmToken::Hash) && Parser.getTok().isNot(AsmToken::Dollar)) - return Error(Parser.getTok().getLoc(), "'#' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat hash token. const MCExpr *ShiftAmount; @@ -5240,7 +5351,7 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { const AsmToken &Tok = Parser.getTok(); SMLoc S = Tok.getLoc(); if (Tok.isNot(AsmToken::Identifier)) - return Error(S, "shift operator 'asr' or 'lsl' expected"); + return ParseStatus::NoMatch; StringRef ShiftName = Tok.getString(); bool isASR; if (ShiftName == "lsl" || ShiftName == "LSL") @@ -5248,7 +5359,7 @@ ParseStatus ARMAsmParser::parseShifterImm(OperandVector &Operands) { else if (ShiftName == "asr" || ShiftName == "ASR") isASR = true; else - return Error(S, "shift operator 'asr' or 'lsl' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat the operator. // A '#' and a shift amount. @@ -5441,7 +5552,7 @@ ParseStatus ARMAsmParser::parseBitfield(OperandVector &Operands) { // The bitfield descriptor is really two operands, the LSB and the width. if (Parser.getTok().isNot(AsmToken::Hash) && Parser.getTok().isNot(AsmToken::Dollar)) - return Error(Parser.getTok().getLoc(), "'#' expected"); + return ParseStatus::NoMatch; Parser.Lex(); // Eat hash token. const MCExpr *LSBExpr; @@ -5600,37 +5711,86 @@ ParseStatus ARMAsmParser::parseAM3Offset(OperandVector &Operands) { return ParseStatus::Success; } +// Finds the index of the first CondCode operator, if there is none returns 0 +unsigned findCondCodeInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + auto Op = static_cast(*Operands[I]); + if (Op.isCondCode()) + return I; + } + return 0; +} + +unsigned findCCOutInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + auto Op = static_cast(*Operands[I]); + if (Op.isCCOut()) + return I; + } + return 0; +} + /// Convert parsed operands to MCInst. Needed here because this instruction /// only has two register operands, but multiplication is commutative so /// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN". void ARMAsmParser::cvtThumbMultiply(MCInst &Inst, const OperandVector &Operands) { - ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); - ((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1); - // If we have a three-operand form, make sure to set Rn to be the operand - // that isn't the same as Rd. - unsigned RegOp = 4; - if (Operands.size() == 6 && - ((ARMOperand &)*Operands[4]).getReg() == - ((ARMOperand &)*Operands[3]).getReg()) - RegOp = 5; - ((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1); - Inst.addOperand(Inst.getOperand(0)); - ((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2); + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); + unsigned CondOutI = findCCOutInd(Operands, MnemonicOpsEndInd); + + // 2 operand form + unsigned RegRd = MnemonicOpsEndInd; + unsigned RegRn = MnemonicOpsEndInd + 1; + unsigned RegRm = MnemonicOpsEndInd; + + if (Operands.size() == MnemonicOpsEndInd + 3) { + // If we have a three-operand form, make sure to set Rn to be the operand + // that isn't the same as Rd. + if (((ARMOperand &)*Operands[RegRd]).getReg() == + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 1]).getReg()) { + RegRn = MnemonicOpsEndInd + 2; + RegRm = MnemonicOpsEndInd + 1; + } else { + RegRn = MnemonicOpsEndInd + 1; + RegRm = MnemonicOpsEndInd + 2; + } + } + + // Rd + ((ARMOperand &)*Operands[RegRd]).addRegOperands(Inst, 1); + // CCOut + if (CondOutI != 0) { + ((ARMOperand &)*Operands[CondOutI]).addCCOutOperands(Inst, 1); + } else { + ARMOperand Op = *ARMOperand::CreateCCOut(0, Operands[0]->getEndLoc()); + Op.addCCOutOperands(Inst, 1); + } + // Rn + ((ARMOperand &)*Operands[RegRn]).addRegOperands(Inst, 1); + // Rm + ((ARMOperand &)*Operands[RegRm]).addRegOperands(Inst, 1); + + // Cond code + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); + } else { + ARMOperand Op = + *ARMOperand::CreateCondCode(llvm::ARMCC::AL, Operands[0]->getEndLoc()); + Op.addCondCodeOperands(Inst, 2); + } } void ARMAsmParser::cvtThumbBranches(MCInst &Inst, const OperandVector &Operands) { - int CondOp = -1, ImmOp = -1; - switch(Inst.getOpcode()) { - case ARM::tB: - case ARM::tBcc: CondOp = 1; ImmOp = 2; break; - - case ARM::t2B: - case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); + unsigned Cond = + (CondI == 0 ? ARMCC::AL + : static_cast(*Operands[CondI]).getCondCode()); - default: llvm_unreachable("Unexpected instruction in cvtThumbBranches"); - } // first decide whether or not the branch should be conditional // by looking at it's location relative to an IT block if(inITBlock()) { @@ -5641,9 +5801,6 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break; } } else { - // outside IT blocks we can only have unconditional branches with AL - // condition code or conditional branches with non-AL condition code - unsigned Cond = static_cast(*Operands[CondOp]).getCondCode(); switch(Inst.getOpcode()) { case ARM::tB: case ARM::tBcc: @@ -5660,36 +5817,56 @@ void ARMAsmParser::cvtThumbBranches(MCInst &Inst, switch(Inst.getOpcode()) { // classify tB as either t2B or t1B based on range of immediate operand case ARM::tB: { - ARMOperand &op = static_cast(*Operands[ImmOp]); + ARMOperand &op = static_cast(*Operands[MnemonicOpsEndInd]); if (!op.isSignedOffset<11, 1>() && isThumb() && hasV8MBaseline()) Inst.setOpcode(ARM::t2B); break; } // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand case ARM::tBcc: { - ARMOperand &op = static_cast(*Operands[ImmOp]); + ARMOperand &op = static_cast(*Operands[MnemonicOpsEndInd]); if (!op.isSignedOffset<8, 1>() && isThumb() && hasV8MBaseline()) Inst.setOpcode(ARM::t2Bcc); break; } } - ((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1); - ((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2); + ((ARMOperand &)*Operands[MnemonicOpsEndInd]).addImmOperands(Inst, 1); + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]).addCondCodeOperands(Inst, 2); + } else { + ARMOperand Op = + *ARMOperand::CreateCondCode(llvm::ARMCC::AL, Operands[0]->getEndLoc()); + Op.addCondCodeOperands(Inst, 2); + } } void ARMAsmParser::cvtMVEVMOVQtoDReg( MCInst &Inst, const OperandVector &Operands) { - // mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 - assert(Operands.size() == 8); + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + unsigned CondI = findCondCodeInd(Operands, MnemonicOpsEndInd); - ((ARMOperand &)*Operands[2]).addRegOperands(Inst, 1); // Rt - ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1); // Rt2 - ((ARMOperand &)*Operands[4]).addRegOperands(Inst, 1); // Qd - ((ARMOperand &)*Operands[5]).addMVEPairVectorIndexOperands(Inst, 1); // idx + // mnemonic, condition code, Rt, Rt2, Qd, idx, Qd again, idx2 + assert(Operands.size() == MnemonicOpsEndInd + 6); + + ((ARMOperand &)*Operands[MnemonicOpsEndInd]).addRegOperands(Inst, 1); // Rt + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 1]) + .addRegOperands(Inst, 1); // Rt2 + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 2]) + .addRegOperands(Inst, 1); // Qd + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 3]) + .addMVEPairVectorIndexOperands(Inst, 1); // idx // skip second copy of Qd in Operands[6] - ((ARMOperand &)*Operands[7]).addMVEPairVectorIndexOperands(Inst, 1); // idx2 - ((ARMOperand &)*Operands[1]).addCondCodeOperands(Inst, 2); // condition code + ((ARMOperand &)*Operands[MnemonicOpsEndInd + 5]) + .addMVEPairVectorIndexOperands(Inst, 1); // idx2 + if (CondI != 0) { + ((ARMOperand &)*Operands[CondI]) + .addCondCodeOperands(Inst, 2); // condition code + } else { + ARMOperand Op = + *ARMOperand::CreateCondCode(ARMCC::AL, Operands[0]->getEndLoc()); + Op.addCondCodeOperands(Inst, 2); + } } /// Parse an ARM memory expression, return false if successful else return true @@ -5948,6 +6125,8 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St, /// parseFPImm - A floating point immediate expression operand. ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { + LLVM_DEBUG(dbgs() << "PARSE FPImm, Ops: " << Operands.size()); + MCAsmParser &Parser = getParser(); // Anything that can accept a floating point constant as an operand // needs to go through here, as the regular parseExpression is @@ -5974,10 +6153,19 @@ ParseStatus ARMAsmParser::parseFPImm(OperandVector &Operands) { // integer constant. Make sure we don't try to parse an FPImm // for these: // vmov.i{8|16|32|64} , #imm - ARMOperand &TyOp = static_cast(*Operands[2]); - bool isVmovf = TyOp.isToken() && - (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || - TyOp.getToken() == ".f16"); + + bool isVmovf = false; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + for (unsigned I = 1; I < MnemonicOpsEndInd; ++I) { + ARMOperand &TyOp = static_cast(*Operands[I]); + if (TyOp.isToken() && + (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64" || + TyOp.getToken() == ".f16")) { + isVmovf = true; + break; + } + } + ARMOperand &Mnemonic = static_cast(*Operands[0]); bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" || Mnemonic.getToken() == "fconsts"); @@ -6493,18 +6681,30 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic, CanAcceptPredicationCode = true; } +bool operandsContainWide(OperandVector &Operands, unsigned MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) { + auto &Op = static_cast(*Operands[I]); + if (Op.isToken() && Op.getToken() == ".w") + return true; + } + return false; +} + // Some Thumb instructions have two operand forms that are not // available as three operand, convert to two operand form if possible. // // FIXME: We would really like to be able to tablegen'erate this. -void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, - bool CarrySetting, - OperandVector &Operands) { - if (Operands.size() != 6) +void ARMAsmParser::tryConvertingToTwoOperandForm( + StringRef Mnemonic, ARMCC::CondCodes PredicationCode, bool CarrySetting, + OperandVector &Operands, unsigned MnemonicOpsEndInd) { + + if (operandsContainWide(Operands, MnemonicOpsEndInd)) + return; + if (Operands.size() != MnemonicOpsEndInd + 3) return; - const auto &Op3 = static_cast(*Operands[3]); - auto &Op4 = static_cast(*Operands[4]); + const auto &Op3 = static_cast(*Operands[MnemonicOpsEndInd]); + auto &Op4 = static_cast(*Operands[MnemonicOpsEndInd + 1]); if (!Op3.isReg() || !Op4.isReg()) return; @@ -6515,7 +6715,7 @@ void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, // it in processInstruction(), but the 3 operand form of ADD (t2ADDrr) // won't accept SP or PC so we do the transformation here taking care // with immediate range in the 'add sp, sp #imm' case. - auto &Op5 = static_cast(*Operands[5]); + auto &Op5 = static_cast(*Operands[MnemonicOpsEndInd + 2]); if (isThumbTwo()) { if (Mnemonic != "add") return; @@ -6575,7 +6775,7 @@ void ARMAsmParser::tryConvertingToTwoOperandForm(StringRef Mnemonic, if (Transform) { if (Swap) std::swap(Op4, Op5); - Operands.erase(Operands.begin() + 3); + Operands.erase(Operands.begin() + MnemonicOpsEndInd); } } @@ -6600,183 +6800,9 @@ static bool isThumbI8Relocation(MCParsedAsmOperand &MCOp) { return false; } -bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic, - OperandVector &Operands) { - // FIXME: This is all horribly hacky. We really need a better way to deal - // with optional operands like this in the matcher table. - - // The 'mov' mnemonic is special. One variant has a cc_out operand, while - // another does not. Specifically, the MOVW instruction does not. So we - // special case it here and remove the defaulted (non-setting) cc_out - // operand if that's the instruction we're trying to match. - // - // We do this as post-processing of the explicit operands rather than just - // conditionally adding the cc_out in the first place because we need - // to check the type of the parsed immediate operand. - if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() && - !static_cast(*Operands[4]).isModImm() && - static_cast(*Operands[4]).isImm0_65535Expr() && - static_cast(*Operands[1]).getReg() == 0) - return true; - - if (Mnemonic == "movs" && Operands.size() > 3 && isThumb() && - isThumbI8Relocation(*Operands[3])) - return true; - - // Register-register 'add' for thumb does not have a cc_out operand - // when there are only two register operands. - if (isThumb() && Mnemonic == "add" && Operands.size() == 5 && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[4]).isReg() && - static_cast(*Operands[1]).getReg() == 0) - return true; - // Register-register 'add' for thumb does not have a cc_out operand - // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do - // have to check the immediate range here since Thumb2 has a variant - // that can handle a different range and has a cc_out operand. - if (((isThumb() && Mnemonic == "add") || - (isThumbTwo() && Mnemonic == "sub")) && - Operands.size() == 6 && static_cast(*Operands[3]).isReg() && - static_cast(*Operands[4]).isReg() && - static_cast(*Operands[4]).getReg() == ARM::SP && - static_cast(*Operands[1]).getReg() == 0 && - ((Mnemonic == "add" && static_cast(*Operands[5]).isReg()) || - static_cast(*Operands[5]).isImm0_1020s4())) - return true; - // For Thumb2, add/sub immediate does not have a cc_out operand for the - // imm0_4095 variant. That's the least-preferred variant when - // selecting via the generic "add" mnemonic, so to know that we - // should remove the cc_out operand, we have to explicitly check that - // it's not one of the other variants. Ugh. - if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && - Operands.size() == 6 && static_cast(*Operands[3]).isReg() && - static_cast(*Operands[4]).isReg() && - static_cast(*Operands[5]).isImm()) { - // Nest conditions rather than one big 'if' statement for readability. - // - // If both registers are low, we're in an IT block, and the immediate is - // in range, we should use encoding T1 instead, which has a cc_out. - if (inITBlock() && - isARMLowRegister(static_cast(*Operands[3]).getReg()) && - isARMLowRegister(static_cast(*Operands[4]).getReg()) && - static_cast(*Operands[5]).isImm0_7()) - return false; - // Check against T3. If the second register is the PC, this is an - // alternate form of ADR, which uses encoding T4, so check for that too. - if (static_cast(*Operands[4]).getReg() != ARM::PC && - (static_cast(*Operands[5]).isT2SOImm() || - static_cast(*Operands[5]).isT2SOImmNeg())) - return false; - - // Otherwise, we use encoding T4, which does not have a cc_out - // operand. - return true; - } - - // The thumb2 multiply instruction doesn't have a CCOut register, so - // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to - // use the 16-bit encoding or not. - if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 && - static_cast(*Operands[1]).getReg() == 0 && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[4]).isReg() && - static_cast(*Operands[5]).isReg() && - // If the registers aren't low regs, the destination reg isn't the - // same as one of the source regs, or the cc_out operand is zero - // outside of an IT block, we have to use the 32-bit encoding, so - // remove the cc_out operand. - (!isARMLowRegister(static_cast(*Operands[3]).getReg()) || - !isARMLowRegister(static_cast(*Operands[4]).getReg()) || - !isARMLowRegister(static_cast(*Operands[5]).getReg()) || - !inITBlock() || (static_cast(*Operands[3]).getReg() != - static_cast(*Operands[5]).getReg() && - static_cast(*Operands[3]).getReg() != - static_cast(*Operands[4]).getReg()))) - return true; - - // Also check the 'mul' syntax variant that doesn't specify an explicit - // destination register. - if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 && - static_cast(*Operands[1]).getReg() == 0 && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[4]).isReg() && - // If the registers aren't low regs or the cc_out operand is zero - // outside of an IT block, we have to use the 32-bit encoding, so - // remove the cc_out operand. - (!isARMLowRegister(static_cast(*Operands[3]).getReg()) || - !isARMLowRegister(static_cast(*Operands[4]).getReg()) || - !inITBlock())) - return true; - - // Register-register 'add/sub' for thumb does not have a cc_out operand - // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also - // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't - // right, this will result in better diagnostics (which operand is off) - // anyway. - if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") && - (Operands.size() == 5 || Operands.size() == 6) && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[3]).getReg() == ARM::SP && - static_cast(*Operands[1]).getReg() == 0 && - (static_cast(*Operands[4]).isImm() || - (Operands.size() == 6 && - static_cast(*Operands[5]).isImm()))) { - // Thumb2 (add|sub){s}{p}.w GPRnopc, sp, #{T2SOImm} has cc_out - return (!(isThumbTwo() && - (static_cast(*Operands[4]).isT2SOImm() || - static_cast(*Operands[4]).isT2SOImmNeg()))); - } - // Fixme: Should join all the thumb+thumb2 (add|sub) in a single if case - // Thumb2 ADD r0, #4095 -> ADDW r0, r0, #4095 (T4) - // Thumb2 SUB r0, #4095 -> SUBW r0, r0, #4095 - if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") && - (Operands.size() == 5) && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[3]).getReg() != ARM::SP && - static_cast(*Operands[3]).getReg() != ARM::PC && - static_cast(*Operands[1]).getReg() == 0 && - static_cast(*Operands[4]).isImm()) { - const ARMOperand &IMM = static_cast(*Operands[4]); - if (IMM.isT2SOImm() || IMM.isT2SOImmNeg()) - return false; // add.w / sub.w - if (const MCConstantExpr *CE = dyn_cast(IMM.getImm())) { - const int64_t Value = CE->getValue(); - // Thumb1 imm8 sub / add - if ((Value < ((1 << 7) - 1) << 2) && inITBlock() && (!(Value & 3)) && - isARMLowRegister(static_cast(*Operands[3]).getReg())) - return false; - return true; // Thumb2 T4 addw / subw - } - } - return false; -} - -bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic, - OperandVector &Operands) { - // VRINT{Z, X} have a predicate operand in VFP, but not in NEON - unsigned RegIdx = 3; - if ((((Mnemonic == "vrintz" || Mnemonic == "vrintx") && !hasMVE()) || - Mnemonic == "vrintr") && - (static_cast(*Operands[2]).getToken() == ".f32" || - static_cast(*Operands[2]).getToken() == ".f16")) { - if (static_cast(*Operands[3]).isToken() && - (static_cast(*Operands[3]).getToken() == ".f32" || - static_cast(*Operands[3]).getToken() == ".f16")) - RegIdx = 4; - - if (static_cast(*Operands[RegIdx]).isReg() && - (ARMMCRegisterClasses[ARM::DPRRegClassID].contains( - static_cast(*Operands[RegIdx]).getReg()) || - ARMMCRegisterClasses[ARM::QPRRegClassID].contains( - static_cast(*Operands[RegIdx]).getReg()))) - return true; - } - return false; -} - -bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, - OperandVector &Operands) { - if (!hasMVE() || Operands.size() < 3) +bool ARMAsmParser::shouldOmitVectorPredicateOperand( + StringRef Mnemonic, OperandVector &Operands, unsigned MnemonicOpsEndInd) { + if (!hasMVE() || Operands.size() <= MnemonicOpsEndInd) return true; if (Mnemonic.starts_with("vld2") || Mnemonic.starts_with("vld4") || @@ -6806,24 +6832,13 @@ bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic, // MQPR, to more accurately report errors when using Q registers // outside of the allowed range. if (static_cast(*Operand).isVectorIndex() || - (Operand->isReg() && - (ARMMCRegisterClasses[ARM::QPRRegClassID].contains( - Operand->getReg())))) + static_cast(*Operand).isQReg()) return false; } return true; } } -static bool isDataTypeToken(StringRef Tok) { - return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" || - Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" || - Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" || - Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" || - Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" || - Tok == ".f" || Tok == ".d"; -} - // FIXME: This bit should probably be handled via an explicit match class // in the .td files that matches the suffix instead of having it be // a literal string token the way it is now. @@ -6844,14 +6859,15 @@ static void applyMnemonicAliases(StringRef &Mnemonic, // bail out, and let the assembly parser report an error on the instruction as // it is written. void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, - OperandVector &Operands) { + OperandVector &Operands, + unsigned MnemonicOpsEndInd) { if (Mnemonic != "ldrd" && Mnemonic != "strd") return; - if (Operands.size() < 4) + if (Operands.size() < MnemonicOpsEndInd + 2) return; - ARMOperand &Op2 = static_cast(*Operands[2]); - ARMOperand &Op3 = static_cast(*Operands[3]); + ARMOperand &Op2 = static_cast(*Operands[MnemonicOpsEndInd]); + ARMOperand &Op3 = static_cast(*Operands[MnemonicOpsEndInd + 1]); if (!Op2.isReg()) return; @@ -6876,7 +6892,7 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, return; Operands.insert( - Operands.begin() + 3, + Operands.begin() + MnemonicOpsEndInd + 1, ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc())); } @@ -6886,19 +6902,17 @@ void ARMAsmParser::fixupGNULDRDAlias(StringRef Mnemonic, // operand. If the conversion fails an error is diagnosed, and the function // returns true. bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, - OperandVector &Operands) { + OperandVector &Operands, + unsigned MnemonicOpsEndInd) { assert(MS.isCDEDualRegInstr(Mnemonic)); - bool isPredicable = - Mnemonic == "cx1da" || Mnemonic == "cx2da" || Mnemonic == "cx3da"; - size_t NumPredOps = isPredicable ? 1 : 0; - if (Operands.size() <= 3 + NumPredOps) + if (Operands.size() < 3 + MnemonicOpsEndInd) return false; StringRef Op2Diag( "operand must be an even-numbered register in the range [r0, r10]"); - const MCParsedAsmOperand &Op2 = *Operands[2 + NumPredOps]; + const MCParsedAsmOperand &Op2 = *Operands[MnemonicOpsEndInd + 1]; if (!Op2.isReg()) return Error(Op2.getStartLoc(), Op2Diag); @@ -6933,16 +6947,43 @@ bool ARMAsmParser::CDEConvertDualRegOperand(StringRef Mnemonic, break; } - const MCParsedAsmOperand &Op3 = *Operands[3 + NumPredOps]; + const MCParsedAsmOperand &Op3 = *Operands[MnemonicOpsEndInd + 2]; if (!Op3.isReg() || Op3.getReg() != RNext) return Error(Op3.getStartLoc(), "operand must be a consecutive register"); - Operands.erase(Operands.begin() + 3 + NumPredOps); - Operands[2 + NumPredOps] = + Operands.erase(Operands.begin() + MnemonicOpsEndInd + 2); + Operands[MnemonicOpsEndInd + 1] = ARMOperand::CreateReg(RPair, Op2.getStartLoc(), Op2.getEndLoc()); return false; } +void removeCondCode(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast(*Operands[I]).isCondCode()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + +void removeCCOut(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast(*Operands[I]).isCCOut()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + +void removeVPTCondCode(OperandVector &Operands, unsigned &MnemonicOpsEndInd) { + for (unsigned I = 0; I < MnemonicOpsEndInd; ++I) + if (static_cast(*Operands[I]).isVPTPred()) { + Operands.erase(Operands.begin() + I); + --MnemonicOpsEndInd; + break; + } +} + /// Parse an arm instruction mnemonic followed by its operands. bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { @@ -7055,14 +7096,14 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } // Add the carry setting operand, if necessary. - if (CanAcceptCarrySet) { + if (CanAcceptCarrySet && CarrySetting) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size()); Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0, Loc)); } // Add the predication code operand, if necessary. - if (CanAcceptPredicationCode) { + if (CanAcceptPredicationCode && PredicationCode != llvm::ARMCC::AL) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); Operands.push_back(ARMOperand::CreateCondCode( @@ -7070,14 +7111,9 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } // Add the VPT predication code operand, if necessary. - // FIXME: We don't add them for the instructions filtered below as these can - // have custom operands which need special parsing. This parsing requires - // the operand to be in the same place in the OperandVector as their - // definition in tblgen. Since these instructions may also have the - // scalar predication operand we do not add the vector one and leave until - // now to fix it up. - if (CanAcceptVPTPredicationCode && Mnemonic != "vmov" && - !Mnemonic.starts_with("vcmp") && + // Dont add in certain cases of VCVT as this needs to be disambiguated + // after operand parsing. + if (CanAcceptVPTPredicationCode && VPTPredicationCode != llvm::ARMVCC::None && !(Mnemonic.starts_with("vcvt") && Mnemonic != "vcvta" && Mnemonic != "vcvtn" && Mnemonic != "vcvtp" && Mnemonic != "vcvtm")) { SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + @@ -7123,6 +7159,11 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + // This marks the end of the LHS Mnemonic operators. + // This is used for indexing into the non-menmonic operators as some of the + // mnemonic operators are optional and therfore indexes can differ. + unsigned MnemonicOpsEndInd = Operands.size(); + // Read the remaining operands. if (getLexer().isNot(AsmToken::EndOfStatement)) { // Read the first operand. @@ -7141,7 +7182,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list")) return true; - tryConvertingToTwoOperandForm(Mnemonic, CarrySetting, Operands); + tryConvertingToTwoOperandForm(Mnemonic, PredicationCode, CarrySetting, + Operands, MnemonicOpsEndInd); if (hasCDE() && MS.isCDEInstr(Mnemonic)) { // Dual-register instructions use even-odd register pairs as their @@ -7152,33 +7194,16 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, // returns false, the function either succeeded or an error (e.g. missing // operand) will be diagnosed elsewhere. if (MS.isCDEDualRegInstr(Mnemonic)) { - bool GotError = CDEConvertDualRegOperand(Mnemonic, Operands); + bool GotError = + CDEConvertDualRegOperand(Mnemonic, Operands, MnemonicOpsEndInd); if (GotError) return GotError; } } - // 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 - // parse and adjust accordingly before actually matching. We shouldn't ever - // try to remove a cc_out operand that was explicitly set on the - // mnemonic, of course (CarrySetting == true). Reason number #317 the - // table driven matcher doesn't fit well with the ARM instruction set. - if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) - Operands.erase(Operands.begin() + 1); - - // Some instructions have the same mnemonic, but don't always - // have a predicate. Distinguish them here and delete the - // appropriate predicate if needed. This could be either the scalar - // predication code or the vector predication code. - if (PredicationCode == ARMCC::AL && - shouldOmitPredicateOperand(Mnemonic, Operands)) - Operands.erase(Operands.begin() + 1); - - if (hasMVE()) { - if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands) && + if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd) && Mnemonic == "vmov" && PredicationCode == ARMCC::LT) { // Very nasty hack to deal with the vector predicated variant of vmovlt // the scalar predicated vmov with condition 'lt'. We can not tell them @@ -7193,7 +7218,8 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.insert(Operands.begin(), ARMOperand::CreateToken(StringRef("vmovlt"), MLoc)); } else if (Mnemonic == "vcvt" && PredicationCode == ARMCC::NE && - !shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + !shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // Another nasty hack to deal with the ambiguity between vcvt with scalar // predication 'ne' and vcvtn with vector predication 'e'. As above we // can only distinguish between the two after we have parsed their @@ -7208,36 +7234,33 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.insert(Operands.begin(), ARMOperand::CreateToken(StringRef("vcvtn"), MLoc)); } else if (Mnemonic == "vmul" && PredicationCode == ARMCC::LT && - !shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + !shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // Another hack, this time to distinguish between scalar predicated vmul // with 'lt' predication code and the vector instruction vmullt with // vector predication code "none" - Operands.erase(Operands.begin() + 1); + removeCondCode(Operands, MnemonicOpsEndInd); Operands.erase(Operands.begin()); SMLoc MLoc = SMLoc::getFromPointer(NameLoc.getPointer()); Operands.insert(Operands.begin(), ARMOperand::CreateToken(StringRef("vmullt"), MLoc)); - } - // For vmov and vcmp, as mentioned earlier, we did not add the vector - // predication code, since these may contain operands that require - // special parsing. So now we have to see if they require vector - // predication and replace the scalar one with the vector predication - // operand if that is the case. - else if (Mnemonic == "vmov" || Mnemonic.starts_with("vcmp") || - (Mnemonic.starts_with("vcvt") && !Mnemonic.starts_with("vcvta") && - !Mnemonic.starts_with("vcvtn") && - !Mnemonic.starts_with("vcvtp") && - !Mnemonic.starts_with("vcvtm"))) { - if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { + } else if (Mnemonic.starts_with("vcvt") && !Mnemonic.starts_with("vcvta") && + !Mnemonic.starts_with("vcvtn") && + !Mnemonic.starts_with("vcvtp") && + !Mnemonic.starts_with("vcvtm")) { + if (!shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { // We could not split the vector predicate off vcvt because it might // have been the scalar vcvtt instruction. Now we know its a vector // instruction, we still need to check whether its the vector // predicated vcvt with 'Then' predication or the vector vcvtt. We can // distinguish the two based on the suffixes, if it is any of // ".f16.f32", ".f32.f16", ".f16.f64" or ".f64.f16" then it is the vcvtt. - if (Mnemonic.starts_with("vcvtt") && Operands.size() >= 4) { - auto Sz1 = static_cast(*Operands[2]); - auto Sz2 = static_cast(*Operands[3]); + if (Mnemonic.starts_with("vcvtt") && MnemonicOpsEndInd > 2) { + auto Sz1 = + static_cast(*Operands[MnemonicOpsEndInd - 2]); + auto Sz2 = + static_cast(*Operands[MnemonicOpsEndInd - 1]); if (!(Sz1.isToken() && Sz1.getToken().starts_with(".f") && Sz2.isToken() && Sz2.getToken().starts_with(".f"))) { Operands.erase(Operands.begin()); @@ -7249,24 +7272,21 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, ARMOperand::CreateToken(Mnemonic, MLoc)); } } - Operands.erase(Operands.begin() + 1); SMLoc PLoc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() + CarrySetting); + // Add VPTPred Operands.insert(Operands.begin() + 1, ARMOperand::CreateVPTPred( ARMVCC::VPTCodes(VPTPredicationCode), PLoc)); + ++MnemonicOpsEndInd; } } else if (CanAcceptVPTPredicationCode) { // For all other instructions, make sure only one of the two // predication operands is left behind, depending on whether we should // use the vector predication. - if (shouldOmitVectorPredicateOperand(Mnemonic, Operands)) { - if (CanAcceptPredicationCode) - Operands.erase(Operands.begin() + 2); - else - Operands.erase(Operands.begin() + 1); - } else if (CanAcceptPredicationCode && PredicationCode == ARMCC::AL) { - Operands.erase(Operands.begin() + 1); + if (shouldOmitVectorPredicateOperand(Mnemonic, Operands, + MnemonicOpsEndInd)) { + removeVPTCondCode(Operands, MnemonicOpsEndInd); } } } @@ -7291,69 +7311,73 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } - // ARM mode 'blx' need special handling, as the register operand version - // is predicable, but the label operand version is not. So, we can't rely - // on the Mnemonic based checking to correctly figure out when to put - // a k_CondCode operand in the list. If we're trying to match the label - // version, remove the k_CondCode operand here. - if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 && - static_cast(*Operands[2]).isImm()) - Operands.erase(Operands.begin() + 1); - - // Adjust operands of ldrexd/strexd to MCK_GPRPair. - // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, - // a single GPRPair reg operand is used in the .td file to replace the two - // GPRs. However, when parsing from asm, the two GRPs cannot be - // automatically - // expressed as a GPRPair, so we have to manually merge them. - // FIXME: We would really like to be able to tablegen'erate this. - if (!isThumb() && Operands.size() > 4 && - (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || - Mnemonic == "stlexd")) { - bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); - unsigned Idx = isLoad ? 2 : 3; - ARMOperand &Op1 = static_cast(*Operands[Idx]); - ARMOperand &Op2 = static_cast(*Operands[Idx + 1]); - - const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); - // Adjust only if Op1 and Op2 are GPRs. - if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) && - MRC.contains(Op2.getReg())) { - unsigned Reg1 = Op1.getReg(); - unsigned Reg2 = Op2.getReg(); - unsigned Rt = MRI->getEncodingValue(Reg1); - unsigned Rt2 = MRI->getEncodingValue(Reg2); - - // Rt2 must be Rt + 1 and Rt must be even. - if (Rt + 1 != Rt2 || (Rt & 1)) { - return Error(Op2.getStartLoc(), - isLoad ? "destination operands must be sequential" - : "source operands must be sequential"); - } - unsigned NewReg = MRI->getMatchingSuperReg( - Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); - Operands[Idx] = - ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); - Operands.erase(Operands.begin() + Idx + 1); + // ARM mode 'blx' need special handling, as the register operand version + // is predicable, but the label operand version is not. So, we can't rely + // on the Mnemonic based checking to correctly figure out when to put + // a k_CondCode operand in the list. If we're trying to match the label + // version, remove the k_CondCode operand here. + if (!isThumb() && Mnemonic == "blx" && + Operands.size() == MnemonicOpsEndInd + 1 && + static_cast(*Operands[MnemonicOpsEndInd]).isImm()) + removeCondCode(Operands, MnemonicOpsEndInd); + + // Adjust operands of ldrexd/strexd to MCK_GPRPair. + // ldrexd/strexd require even/odd GPR pair. To enforce this constraint, + // a single GPRPair reg operand is used in the .td file to replace the two + // GPRs. However, when parsing from asm, the two GRPs cannot be + // automatically + // expressed as a GPRPair, so we have to manually merge them. + // FIXME: We would really like to be able to tablegen'erate this. + if (!isThumb() && Operands.size() > MnemonicOpsEndInd + 1 && + (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" || + Mnemonic == "stlexd")) { + bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd"); + unsigned Idx = isLoad ? MnemonicOpsEndInd : MnemonicOpsEndInd + 1; + ARMOperand &Op1 = static_cast(*Operands[Idx]); + ARMOperand &Op2 = static_cast(*Operands[Idx + 1]); + + const MCRegisterClass &MRC = MRI->getRegClass(ARM::GPRRegClassID); + // Adjust only if Op1 and Op2 are GPRs. + if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) && + MRC.contains(Op2.getReg())) { + unsigned Reg1 = Op1.getReg(); + unsigned Reg2 = Op2.getReg(); + unsigned Rt = MRI->getEncodingValue(Reg1); + unsigned Rt2 = MRI->getEncodingValue(Reg2); + + // Rt2 must be Rt + 1 and Rt must be even. + if (Rt + 1 != Rt2 || (Rt & 1)) { + return Error(Op2.getStartLoc(), + isLoad ? "destination operands must be sequential" + : "source operands must be sequential"); } + unsigned NewReg = MRI->getMatchingSuperReg( + Reg1, ARM::gsub_0, &(MRI->getRegClass(ARM::GPRPairRegClassID))); + Operands[Idx] = + ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc()); + Operands.erase(Operands.begin() + Idx + 1); + } } // GNU Assembler extension (compatibility). - fixupGNULDRDAlias(Mnemonic, Operands); + fixupGNULDRDAlias(Mnemonic, Operands, MnemonicOpsEndInd); // FIXME: As said above, this is all a pretty gross hack. This instruction // does not fit with other "subs" and tblgen. // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction // so the Mnemonic is the original name "subs" and delete the predicate // operand so it will match the table entry. - if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 && - static_cast(*Operands[3]).isReg() && - static_cast(*Operands[3]).getReg() == ARM::PC && - static_cast(*Operands[4]).isReg() && - static_cast(*Operands[4]).getReg() == ARM::LR && - static_cast(*Operands[5]).isImm()) { + if (isThumbTwo() && Mnemonic == "sub" && + Operands.size() == MnemonicOpsEndInd + 3 && + static_cast(*Operands[MnemonicOpsEndInd]).isReg() && + static_cast(*Operands[MnemonicOpsEndInd]).getReg() == + ARM::PC && + static_cast(*Operands[MnemonicOpsEndInd + 1]).isReg() && + static_cast(*Operands[MnemonicOpsEndInd + 1]).getReg() == + ARM::LR && + static_cast(*Operands[MnemonicOpsEndInd + 2]).isImm()) { Operands.front() = ARMOperand::CreateToken(Name, NameLoc); - Operands.erase(Operands.begin() + 1); + removeCCOut(Operands, MnemonicOpsEndInd); } return false; } @@ -7398,49 +7422,61 @@ static bool instIsBreakpoint(const MCInst &Inst) { Inst.getOpcode() == ARM::HLT; } +unsigned getRegListInd(const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { + for (unsigned I = MnemonicOpsEndInd; I < Operands.size(); ++I) { + const ARMOperand &Op = static_cast(*Operands[I]); + if (Op.isRegList()) { + return I; + } + } + return 0; +} + bool ARMAsmParser::validatetLDMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo, bool IsARPop) { - const ARMOperand &Op = static_cast(*Operands[ListNo]); - bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; - - bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); - bool ListContainsLR = listContainsReg(Inst, ListNo, ARM::LR); - bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + unsigned MnemonicOpsEndInd, + unsigned ListIndex, bool IsARPop) { + bool ListContainsSP = listContainsReg(Inst, ListIndex, ARM::SP); + bool ListContainsLR = listContainsReg(Inst, ListIndex, ARM::LR); + bool ListContainsPC = listContainsReg(Inst, ListIndex, ARM::PC); if (!IsARPop && ListContainsSP) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP may not be in the register list"); - else if (ListContainsPC && ListContainsLR) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "PC and LR may not be in the register list simultaneously"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP may not be in the register list"); + if (ListContainsPC && ListContainsLR) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "PC and LR may not be in the register list simultaneously"); return false; } bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst, const OperandVector &Operands, - unsigned ListNo) { - const ARMOperand &Op = static_cast(*Operands[ListNo]); - bool HasWritebackToken = Op.isToken() && Op.getToken() == "!"; - - bool ListContainsSP = listContainsReg(Inst, ListNo, ARM::SP); - bool ListContainsPC = listContainsReg(Inst, ListNo, ARM::PC); + unsigned MnemonicOpsEndInd, + unsigned ListIndex) { + bool ListContainsSP = listContainsReg(Inst, ListIndex, ARM::SP); + bool ListContainsPC = listContainsReg(Inst, ListIndex, ARM::PC); if (ListContainsSP && ListContainsPC) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP and PC may not be in the register list"); - else if (ListContainsSP) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "SP may not be in the register list"); - else if (ListContainsPC) - return Error(Operands[ListNo + HasWritebackToken]->getStartLoc(), - "PC may not be in the register list"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP and PC may not be in the register list"); + if (ListContainsSP) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "SP may not be in the register list"); + if (ListContainsPC) + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "PC may not be in the register list"); return false; } -bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, - const OperandVector &Operands, - bool Load, bool ARMMode, bool Writeback) { +bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands, + bool Load, bool ARMMode, bool Writeback, + unsigned MnemonicOpsEndInd) { unsigned RtIndex = Load || !Writeback ? 0 : 1; unsigned Rt = MRI->getEncodingValue(Inst.getOperand(RtIndex).getReg()); unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(RtIndex + 1).getReg()); @@ -7448,21 +7484,21 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (ARMMode) { // Rt can't be R14. if (Rt == 14) - return Error(Operands[3]->getStartLoc(), - "Rt can't be R14"); + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Rt can't be R14"); // Rt must be even-numbered. if ((Rt & 1) == 1) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "Rt must be even-numbered"); // Rt2 must be Rt + 1. if (Rt2 != Rt + 1) { if (Load) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands must be sequential"); else - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "source operands must be sequential"); } @@ -7472,7 +7508,7 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (!ARMMode && Load) { if (Rt2 == Rt) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands can't be identical"); } @@ -7481,11 +7517,11 @@ bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst, if (Rn == Rt || Rn == Rt2) { if (Load) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "base register needs to be different from destination " "registers"); else - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source register and base register can't be identical"); } @@ -7523,7 +7559,8 @@ static bool isARMMCExpr(MCParsedAsmOperand &MCOp) { // FIXME: We would really like to be able to tablegen'erate this. bool ARMAsmParser::validateInstruction(MCInst &Inst, - const OperandVector &Operands) { + const OperandVector &Operands, + unsigned MnemonicOpsEndInd) { const MCInstrDesc &MCID = MII.get(Inst.getOpcode()); SMLoc Loc = Operands[0]->getStartLoc(); @@ -7538,7 +7575,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm()); if (Cond != currentITCond()) { // Find the condition code Operand to get its SMLoc information. - SMLoc CondLoc; + SMLoc CondLoc = Operands[0]->getEndLoc(); for (unsigned I = 1; I < Operands.size(); ++I) if (static_cast(*Operands[I]).isCondCode()) CondLoc = Operands[I]->getStartLoc(); @@ -7608,9 +7645,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::VLSTM_T2: { // Since in some cases both T1 and T2 are valid, tablegen can not always // pick the correct instruction. - if (Operands.size() == 4) { // a register list has been provided + if (Operands.size() == + MnemonicOpsEndInd + 2) { // a register list has been provided ARMOperand &Op = static_cast( - *Operands[3]); // the register list, a dpr_reglist + *Operands[MnemonicOpsEndInd + 1]); // the register list, a dpr_reglist assert(Op.isDPRRegList()); auto &RegList = Op.getRegList(); // T2 requires v8.1-M.Main (cannot be handled by tablegen) @@ -7644,50 +7682,50 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::LDRD: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ true, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::LDRD_PRE: case ARM::LDRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ true, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2LDRDi8: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ false, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::t2LDRD_PRE: case ARM::t2LDRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ true, /*ARMMode*/ false, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2BXJ: { const unsigned RmReg = Inst.getOperand(0).getReg(); // Rm = SP is no longer unpredictable in v8-A if (RmReg == ARM::SP && !hasV8Ops()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "r13 (SP) is an unpredictable operand to BXJ"); return false; } case ARM::STRD: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, - /*Writeback*/false)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ true, + /*Writeback*/ false, MnemonicOpsEndInd)) return true; break; case ARM::STRD_PRE: case ARM::STRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ true, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::t2STRD_PRE: case ARM::t2STRD_POST: - if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/false, - /*Writeback*/true)) + if (validateLDRDSTRD(Inst, Operands, /*Load*/ false, /*ARMMode*/ false, + /*Writeback*/ true, MnemonicOpsEndInd)) return true; break; case ARM::STR_PRE_IMM: @@ -7711,7 +7749,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "source register and base register can't be identical"); return false; } @@ -7724,19 +7762,19 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(1).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination register and base register can't be identical"); if (Inst.getOpcode() == ARM::t2LDR_POST_imm || Inst.getOpcode() == ARM::t2STR_POST_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } if (Inst.getOpcode() == ARM::t2STR_PRE_imm || Inst.getOpcode() == ARM::t2STR_POST_imm) { if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "operand must be a register in range [r0, r14]"); } } @@ -7755,17 +7793,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2STRB_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRB_OFFSET_imm || Inst.getOpcode() == ARM::t2STRB_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRB (literal)"); } return false; @@ -7783,17 +7821,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2STRH_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRH_OFFSET_imm || Inst.getOpcode() == ARM::t2STRH_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7806,16 +7844,16 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2LDRSB_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRSB_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7828,16 +7866,16 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, Inst.getOpcode() == ARM::t2LDRSH_PRE_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 255 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [-255, 255]"); } else if (Inst.getOpcode() == ARM::t2LDRSH_OFFSET_imm) { int Imm = Inst.getOperand(2).getImm(); if (Imm > 0 || Imm < -255) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "operand must be in range [0, 255] with a negative sign"); } if (Inst.getOperand(0).getReg() == ARM::PC) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "if operand is PC, should call the LDRH (literal)"); } return false; @@ -7872,7 +7910,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg()); if (Rt == Rn) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination register and base register can't be identical"); return false; } @@ -7916,10 +7954,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Qm = MRI->getEncodingValue(Inst.getOperand(QmIdx).getReg()); if (Qd == Qm) { - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), Twine("destination vector register and vector ") + - (QmIsPointer ? "pointer" : "offset") + - " register can't be identical"); + (QmIsPointer ? "pointer" : "offset") + + " register can't be identical"); } return false; } @@ -7932,7 +7970,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, unsigned LSB = Inst.getOperand(2).getImm(); unsigned Widthm1 = Inst.getOperand(3).getImm(); if (Widthm1 >= 32 - LSB) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "bitfield width must be in range [1,32-lsb]"); return false; } @@ -7946,24 +7984,29 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // in the register list. unsigned Rn = Inst.getOperand(0).getReg(); bool HasWritebackToken = - (static_cast(*Operands[3]).isToken() && - static_cast(*Operands[3]).getToken() == "!"); + (static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isToken() && + static_cast(*Operands[MnemonicOpsEndInd + 1]) + .getToken() == "!"); + bool ListContainsBase; if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo()) - return Error(Operands[3 + HasWritebackToken]->getStartLoc(), - "registers must be in range r0-r7"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "registers must be in range r0-r7"); // If we should have writeback, then there should be a '!' token. if (!ListContainsBase && !HasWritebackToken && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), - "writeback operator '!' expected"); + return Error( + Operands[getRegListInd(Operands, MnemonicOpsEndInd)]->getStartLoc(), + "writeback operator '!' expected"); // If we should not have writeback, there must not be a '!'. This is // true even for the 32-bit wide encodings. if (ListContainsBase && HasWritebackToken) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; } @@ -7981,12 +8024,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; case ARM::t2LDMIA: case ARM::t2LDMDB: - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; case ARM::t2STMIA: case ARM::t2STMDB: - if (validatetSTMRegList(Inst, Operands, 3)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; break; case ARM::t2LDMIA_UPD: @@ -7998,10 +8041,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, "writeback register not allowed in register list"); if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { - if (validatetLDMRegList(Inst, Operands, 3)) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; } else { - if (validatetSTMRegList(Inst, Operands, 3)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 3)) return true; } break; @@ -8011,7 +8054,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::sysLDMDB_UPD: case ARM::sysLDMIB_UPD: if (!listContainsReg(Inst, 3, ARM::PC)) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "writeback register only allowed on system LDM " "if PC in register-list"); break; @@ -8019,26 +8062,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::sysSTMDA_UPD: case ARM::sysSTMDB_UPD: case ARM::sysSTMIB_UPD: - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "system STM cannot have writeback register"); - case ARM::tMUL: - // The second source operand must be the same register as the destination - // operand. - // - // In this case, we must directly check the parsed operands because the - // cvtThumbMultiply() function is written in such a way that it guarantees - // this first statement is always true for the new Inst. Essentially, the - // destination is unconditionally copied into the second source operand - // without checking to see if it matches what we actually parsed. - if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() != - ((ARMOperand &)*Operands[5]).getReg()) && - (((ARMOperand &)*Operands[3]).getReg() != - ((ARMOperand &)*Operands[4]).getReg())) { - return Error(Operands[3]->getStartLoc(), - "destination register must match source register"); - } - break; - // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2, // so only issue a diagnostic for thumb1. The instructions will be // switched to the t2 encodings in processInstruction() if necessary. @@ -8046,9 +8071,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, bool ListContainsBase; if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "registers must be in range r0-r7 or pc"); - if (validatetLDMRegList(Inst, Operands, 2, !isMClass())) + if (validatetLDMRegList(Inst, Operands, MnemonicOpsEndInd, 2, !isMClass())) return true; break; } @@ -8056,9 +8081,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, bool ListContainsBase; if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) && !isThumbTwo()) - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "registers must be in range r0-r7 or lr"); - if (validatetSTMRegList(Inst, Operands, 2)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 2)) return true; break; } @@ -8067,17 +8092,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(), 0, ListContainsBase); if (InvalidLowList && !isThumbTwo()) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "registers must be in range r0-r7"); // This would be converted to a 32-bit stm, but that's not valid if the // writeback register is in the list. if (InvalidLowList && ListContainsBase) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "writeback operator '!' not allowed when base register " "in register list"); - if (validatetSTMRegList(Inst, Operands, 4)) + if (validatetSTMRegList(Inst, Operands, MnemonicOpsEndInd, 4)) return true; break; } @@ -8086,7 +8111,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // same, we need thumb2 (for the wide encoding), or we have an error. if (!isThumbTwo() && Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) { - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source register must be the same as destination"); } break; @@ -8097,17 +8122,20 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::t2SUBrs: if (Inst.getOperand(0).getReg() == ARM::SP && Inst.getOperand(1).getReg() != ARM::SP) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "source register must be sp if destination is sp"); break; // Final range checking for Thumb unconditional branch instructions. case ARM::tB: - if (!(static_cast(*Operands[2])).isSignedOffset<11, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!(static_cast(*Operands[MnemonicOpsEndInd])) + .isSignedOffset<11, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "branch target out of range"); break; case ARM::t2B: { - int op = (Operands[2]->isImm()) ? 2 : 3; + int op = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; ARMOperand &Operand = static_cast(*Operands[op]); // Delay the checks of symbolic expressions until they are resolved. if (!isa(Operand.getImm()) && @@ -8117,19 +8145,24 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, } // Final range checking for Thumb conditional branch instructions. case ARM::tBcc: - if (!static_cast(*Operands[2]).isSignedOffset<8, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!static_cast(*Operands[MnemonicOpsEndInd]) + .isSignedOffset<8, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "branch target out of range"); break; case ARM::t2Bcc: { - int Op = (Operands[2]->isImm()) ? 2 : 3; + int Op = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; if (!static_cast(*Operands[Op]).isSignedOffset<20, 1>()) return Error(Operands[Op]->getStartLoc(), "branch target out of range"); break; } case ARM::tCBZ: case ARM::tCBNZ: { - if (!static_cast(*Operands[2]).isUnsignedOffset<6, 1>()) - return Error(Operands[2]->getStartLoc(), "branch target out of range"); + if (!static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isUnsignedOffset<6, 1>()) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), + "branch target out of range"); break; } case ARM::MOVi16: @@ -8143,7 +8176,8 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, // want the behavior of silently truncating, which can be unexpected and // lead to bugs that are difficult to find since this is an easy mistake // to make. - int i = (Operands[3]->isImm()) ? 3 : 4; + int i = (Operands[MnemonicOpsEndInd]->isImm()) ? MnemonicOpsEndInd + : MnemonicOpsEndInd + 1; ARMOperand &Op = static_cast(*Operands[i]); const MCConstantExpr *CE = dyn_cast(Op.getImm()); if (CE) break; @@ -8158,7 +8192,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::tADDi8: { - MCParsedAsmOperand &Op = *Operands[4]; + MCParsedAsmOperand &Op = *Operands[MnemonicOpsEndInd + 1]; if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) return Error(Op.getStartLoc(), "Immediate expression for Thumb adds requires :lower0_7:," @@ -8166,7 +8200,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, break; } case ARM::tMOVi8: { - MCParsedAsmOperand &Op = *Operands[2]; + MCParsedAsmOperand &Op = *Operands[MnemonicOpsEndInd]; if (isARMMCExpr(Op) && !isThumbI8Relocation(Op)) return Error(Op.getStartLoc(), "Immediate expression for Thumb movs requires :lower0_7:," @@ -8193,30 +8227,36 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::t2BFr: case ARM::t2BFLi: case ARM::t2BFLr: { - if (!static_cast(*Operands[2]).isUnsignedOffset<4, 1>() || - (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) - return Error(Operands[2]->getStartLoc(), + if (!static_cast(*Operands[MnemonicOpsEndInd]) + .isUnsignedOffset<4, 1>() || + (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch location out of range or not a multiple of 2"); + } if (Opcode == ARM::t2BFi) { - if (!static_cast(*Operands[3]).isSignedOffset<16, 1>()) - return Error(Operands[3]->getStartLoc(), + if (!static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<16, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch target out of range or not a multiple of 2"); } else if (Opcode == ARM::t2BFLi) { - if (!static_cast(*Operands[3]).isSignedOffset<18, 1>()) - return Error(Operands[3]->getStartLoc(), + if (!static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<18, 1>()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "branch target out of range or not a multiple of 2"); } break; } case ARM::t2BFic: { - if (!static_cast(*Operands[1]).isUnsignedOffset<4, 1>() || + if (!static_cast(*Operands[MnemonicOpsEndInd]) + .isUnsignedOffset<4, 1>() || (Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == 0)) return Error(Operands[1]->getStartLoc(), "branch location out of range or not a multiple of 2"); - if (!static_cast(*Operands[2]).isSignedOffset<16, 1>()) - return Error(Operands[2]->getStartLoc(), + if (!static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isSignedOffset<16, 1>()) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "branch target out of range or not a multiple of 2"); assert(Inst.getOperand(0).isImm() == Inst.getOperand(2).isImm() && @@ -8237,7 +8277,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, if (Inst.getOperand(i).isReg() && !ARMMCRegisterClasses[ARM::GPRwithAPSRnospRegClassID].contains( Inst.getOperand(i).getReg())) { - return Error(Operands[2]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "invalid register in register list. Valid registers are " "r0-r12, lr/r14 and APSR."); } @@ -8269,7 +8309,7 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(2).getReg()); const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(3).getReg()); if (Sm1 != Sm + 1) - return Error(Operands[5]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), "source operands must be sequential"); break; } @@ -8278,16 +8318,17 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, const unsigned Sm = MRI->getEncodingValue(Inst.getOperand(0).getReg()); const unsigned Sm1 = MRI->getEncodingValue(Inst.getOperand(1).getReg()); if (Sm1 != Sm + 1) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "destination operands must be sequential"); break; } case ARM::VLDMDIA: case ARM::VSTMDIA: { - ARMOperand &Op = static_cast(*Operands[3]); + ARMOperand &Op = + static_cast(*Operands[MnemonicOpsEndInd + 1]); auto &RegList = Op.getRegList(); if (RegList.size() < 1 || RegList.size() > 16) - return Error(Operands[3]->getStartLoc(), + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), "list of registers must be at least 1 and at most 16"); break; } @@ -8298,13 +8339,15 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::MVE_VMULLTs32: case ARM::MVE_VMULLBu32: case ARM::MVE_VMULLTu32: { - if (Operands[3]->getReg() == Operands[4]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qn register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qn register can't be identical"); } - if (Operands[3]->getReg() == Operands[5]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qm register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 2]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qm register can't be identical"); } break; } @@ -8313,41 +8356,56 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, case ARM::MVE_VREV64_32: case ARM::MVE_VQDMULL_qr_s32bh: case ARM::MVE_VQDMULL_qr_s32th: { - if (Operands[3]->getReg() == Operands[4]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qn register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qn register can't be identical"); } break; } case ARM::MVE_VCADDi32: case ARM::MVE_VCADDf32: case ARM::MVE_VHCADDs32: { - if (Operands[3]->getReg() == Operands[5]->getReg()) { - return Error (Operands[3]->getStartLoc(), - "Qd register and Qm register can't be identical"); + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 2]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Qd register and Qm register can't be identical"); } break; } case ARM::MVE_VMOV_rr_q: { - if (Operands[4]->getReg() != Operands[6]->getReg()) - return Error (Operands[4]->getStartLoc(), "Q-registers must be the same"); - if (static_cast(*Operands[5]).getVectorIndex() != - static_cast(*Operands[7]).getVectorIndex() + 2) - return Error (Operands[5]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); + if (Operands[MnemonicOpsEndInd + 2]->getReg() != + Operands[MnemonicOpsEndInd + 4]->getReg()) + return Error(Operands[MnemonicOpsEndInd + 2]->getStartLoc(), + "Q-registers must be the same"); + if (static_cast(*Operands[MnemonicOpsEndInd + 3]) + .getVectorIndex() != + static_cast(*Operands[MnemonicOpsEndInd + 5]) + .getVectorIndex() + + 2) + return Error(Operands[MnemonicOpsEndInd + 3]->getStartLoc(), + "Q-register indexes must be 2 and 0 or 3 and 1"); break; } case ARM::MVE_VMOV_q_rr: { - if (Operands[2]->getReg() != Operands[4]->getReg()) - return Error (Operands[2]->getStartLoc(), "Q-registers must be the same"); - if (static_cast(*Operands[3]).getVectorIndex() != - static_cast(*Operands[5]).getVectorIndex() + 2) - return Error (Operands[3]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1"); + if (Operands[MnemonicOpsEndInd]->getReg() != + Operands[MnemonicOpsEndInd + 2]->getReg()) + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), + "Q-registers must be the same"); + if (static_cast(*Operands[MnemonicOpsEndInd + 1]) + .getVectorIndex() != + static_cast(*Operands[MnemonicOpsEndInd + 3]) + .getVectorIndex() + + 2) + return Error(Operands[MnemonicOpsEndInd + 1]->getStartLoc(), + "Q-register indexes must be 2 and 0 or 3 and 1"); break; } case ARM::MVE_SQRSHR: case ARM::MVE_UQRSHL: { - if (Operands[2]->getReg() == Operands[3]->getReg()) { - return Error(Operands[2]->getStartLoc(), + if (Operands[MnemonicOpsEndInd]->getReg() == + Operands[MnemonicOpsEndInd + 1]->getReg()) { + return Error(Operands[MnemonicOpsEndInd]->getStartLoc(), "Rda register and Rm register can't be identical"); } break; @@ -8751,6 +8809,7 @@ static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) { bool ARMAsmParser::processInstruction(MCInst &Inst, const OperandVector &Operands, + unsigned MnemonicOpsEndInd, MCStreamer &Out) { // Check if we have the wide qualifier, because if it's present we // must avoid selecting a 16-bit thumb instruction. @@ -8768,9 +8827,10 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, case ARM::VLSTM: { // In some cases both T1 and T2 are valid, causing tablegen pick T1 instead // of T2 - if (Operands.size() == 4) { // a register list has been provided + if (Operands.size() == + MnemonicOpsEndInd + 2) { // a register list has been provided ARMOperand &Op = static_cast( - *Operands[3]); // the register list, a dpr_reglist + *Operands[MnemonicOpsEndInd + 1]); // the register list, a dpr_reglist assert(Op.isDPRRegList()); auto &RegList = Op.getRegList(); // When the register list is {d0-d31} the instruction has to be the T2 @@ -9097,9 +9157,7 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, else if (Inst.getOpcode() == ARM::t2LDRConstPool) TmpInst.setOpcode(ARM::t2LDRpci); const ARMOperand &PoolOperand = - (HasWideQualifier ? - static_cast(*Operands[4]) : - static_cast(*Operands[3])); + static_cast(*Operands[MnemonicOpsEndInd + 1]); const MCExpr *SubExprVal = PoolOperand.getConstantPoolImm(); // If SubExprVal is a constant we may be able to use a MOV if (isa(SubExprVal) && @@ -10526,7 +10584,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // to encoding T2 if is specified and encoding T2 is preferred // to encoding T1 if is omitted." if (Inst.getOperand(3).isImm() && - (unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { + (unsigned)Inst.getOperand(3).getImm() < 8 && + Operands.size() == MnemonicOpsEndInd + 3) { Inst.setOpcode(ARM::tADDi3); return true; } @@ -10536,7 +10595,8 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // explicitly specified. From the ARM ARM: "Encoding T1 is preferred // to encoding T2 if is specified and encoding T2 is preferred // to encoding T1 if is omitted." - if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) { + if ((unsigned)Inst.getOperand(3).getImm() < 8 && + Operands.size() == MnemonicOpsEndInd + 3) { Inst.setOpcode(ARM::tSUBi3); return true; } @@ -10656,8 +10716,10 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, // an error in validateInstruction(). unsigned Rn = Inst.getOperand(0).getReg(); bool hasWritebackToken = - (static_cast(*Operands[3]).isToken() && - static_cast(*Operands[3]).getToken() == "!"); + (static_cast(*Operands[MnemonicOpsEndInd + 1]) + .isToken() && + static_cast(*Operands[MnemonicOpsEndInd + 1]) + .getToken() == "!"); bool listContainsBase; if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) || (!listContainsBase && !hasWritebackToken) || @@ -10956,6 +11018,26 @@ bool ARMAsmParser::processInstruction(MCInst &Inst, return false; } +unsigned +ARMAsmParser::checkEarlyTargetMatchPredicate(MCInst &Inst, + const OperandVector &Operands) { + unsigned Opc = Inst.getOpcode(); + switch (Opc) { + // Prevent the mov r8 r8 encoding for nop being selected when the v6/thumb 2 + // encoding is available. + case ARM::tMOVr: { + if (Operands[0]->isToken() && + static_cast(*Operands[0]).getToken() == "nop" && + ((isThumb() && !isThumbOne()) || hasV6MOps())) { + return Match_MnemonicFail; + } + } + LLVM_FALLTHROUGH; + default: + return Match_Success; + } +} + unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // 16-bit thumb arithmetic instructions either require or preclude the 'S' // suffix depending on whether they're in an IT block or not. @@ -10966,22 +11048,23 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { "optionally flag setting instruction missing optional def operand"); assert(MCID.NumOperands == Inst.getNumOperands() && "operand count mismatch!"); - // Find the optional-def operand (cc_out). - unsigned OpNo; - for (OpNo = 0; - OpNo < MCID.NumOperands && !MCID.operands()[OpNo].isOptionalDef(); - ++OpNo) - ; + bool IsCPSR = false; + // Check if the instruction has CPSR set. + for (unsigned OpNo = 0; OpNo < MCID.NumOperands; ++OpNo) { + if (MCID.operands()[OpNo].isOptionalDef() && + Inst.getOperand(OpNo).isReg() && + Inst.getOperand(OpNo).getReg() == ARM::CPSR) + IsCPSR = true; + } + // If we're parsing Thumb1, reject it completely. - if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR) + if (isThumbOne() && !IsCPSR) return Match_RequiresFlagSetting; // If we're parsing Thumb2, which form is legal depends on whether we're // in an IT block. - if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR && - !inITBlock()) + if (isThumbTwo() && !IsCPSR && !inITBlock()) return Match_RequiresITBlock; - if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR && - inITBlock()) + if (isThumbTwo() && IsCPSR && inITBlock()) return Match_RequiresNotITBlock; // LSL with zero immediate is not allowed in an IT block if (Opc == ARM::tLSLri && Inst.getOperand(3).getImm() == 0 && inITBlock()) @@ -11042,6 +11125,14 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) { if (!hasV8Ops() && (Inst.getOperand(0).getReg() == ARM::SP)) return Match_RequiresV8; break; + case ARM::tMUL: + // The second source operand must be the same register as the destination + // operand. + // FIXME: Ideally this would be handled by ARMGenAsmMatcher and + // emitAsmTiedOperandConstraints. + if (Inst.getOperand(0).getReg() != Inst.getOperand(3).getReg()) + return Match_InvalidTiedOperand; + break; default: break; } @@ -11200,6 +11291,9 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, MatchResult = MatchInstruction(Operands, Inst, NearMisses, MatchingInlineAsm, PendConditionalInstruction, Out); + // Find the number of operators that are part of the Mnumonic (LHS). + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + switch (MatchResult) { case Match_Success: LLVM_DEBUG(dbgs() << "Parsed as: "; @@ -11208,7 +11302,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // Context sensitive operand constraints aren't handled by the matcher, // so check them here. - if (validateInstruction(Inst, Operands)) { + if (validateInstruction(Inst, Operands, MnemonicOpsEndInd)) { // Still progress the IT block, otherwise one wrong condition causes // nasty cascading errors. forwardITPosition(); @@ -11221,7 +11315,7 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, // encoding is selected. Loop on it while changes happen so the // individual transformations can chain off each other. E.g., // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8) - while (processInstruction(Inst, Operands, Out)) + while (processInstruction(Inst, Operands, MnemonicOpsEndInd, Out)) LLVM_DEBUG(dbgs() << "Changed to: "; Inst.dump_pretty(dbgs(), MII.getName(Inst.getOpcode())); dbgs() << "\n"); @@ -12562,6 +12656,8 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, SmallSet FeatureMissesSeen; bool ReportedTooFewOperands = false; + unsigned MnemonicOpsEndInd = getMnemonicOpsEndInd(Operands); + // Process the near-misses in reverse order, so that we see more general ones // first, and so can avoid emitting more specific ones. for (NearMissInfo &I : reverse(NearMissesIn)) { @@ -12670,6 +12766,16 @@ ARMAsmParser::FilterNearMisses(SmallVectorImpl &NearMissesIn, case Match_RequiresFlagSetting: Message.Message = "no flag-preserving variant of this instruction available"; break; + case Match_InvalidTiedOperand: { + ARMOperand &Op = static_cast(*Operands[0]); + if (Op.isToken() && Op.getToken() == "mul") { + Message.Message = "destination register must match a source register"; + Message.Loc = Operands[MnemonicOpsEndInd]->getStartLoc(); + } else { + llvm_unreachable("Match_InvalidTiedOperand only used for tMUL."); + } + break; + } case Match_InvalidOperand: Message.Message = "invalid operand for instruction"; break; @@ -12869,11 +12975,29 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp, if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP) return Match_Success; return Match_rGPR; - case MCK_GPRPair: - if (Op.isReg() && - MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg())) + // Note: This mutates the operand which could cause issues for future + // matches if this one fails later. + // It would be better to do this in addVecList but as this doesn't have access + // to MRI this isn't possible. + // If trying to match a VecListDPair with a Q register, convert Q to list. + case MCK_VecListDPair: + if (Op.isQReg() && !hasMVE()) { + auto DPair = getDRegFromQReg(Op.getReg()); + DPair = MRI->getMatchingSuperReg( + DPair, ARM::dsub_0, &ARMMCRegisterClasses[ARM::DPairRegClassID]); + Op.setVecListDPair(DPair); return Match_Success; - break; + } + return Match_InvalidOperand; + // Note: This mutates the operand (see above). + // If trying to match a VecListDPair with a D register, convert D singleton + // list. + case MCK_VecListOneD: + if (Op.isDReg() && !hasMVE()) { + Op.setVecListOneD(Op.getReg()); + return Match_Success; + } + return Match_InvalidOperand; } return Match_InvalidOperand; } @@ -12921,3 +13045,15 @@ bool ARMAsmParser::isMnemonicVPTPredicable(StringRef Mnemonic, std::begin(predicable_prefixes), std::end(predicable_prefixes), [&Mnemonic](const char *prefix) { return Mnemonic.starts_with(prefix); }); } + +std::unique_ptr ARMAsmParser::defaultCondCodeOp() { + return ARMOperand::CreateCondCode(ARMCC::AL, SMLoc()); +} + +std::unique_ptr ARMAsmParser::defaultCCOutOp() { + return ARMOperand::CreateCCOut(0, SMLoc()); +} + +std::unique_ptr ARMAsmParser::defaultVPTPredOp() { + return ARMOperand::CreateVPTPred(ARMVCC::None, SMLoc()); +} diff --git a/llvm/test/MC/ARM/arm-branch-errors.s b/llvm/test/MC/ARM/arm-branch-errors.s index bbf6445f5c18a..5d7ae12fb3bc0 100644 --- a/llvm/test/MC/ARM/arm-branch-errors.s +++ b/llvm/test/MC/ARM/arm-branch-errors.s @@ -10,13 +10,13 @@ @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: b #2 -@ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction +@ CHECK: note: instruction requires: thumb @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: bl #2 @ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction @ CHECK: error: invalid instruction, any one of the following would fix this: @ CHECK: beq #2 -@ CHECK: note: instruction requires: thumb @ CHECK: note: invalid operand for instruction +@ CHECK: note: instruction requires: thumb diff --git a/llvm/test/MC/ARM/arm11-hint-instr.s b/llvm/test/MC/ARM/arm11-hint-instr.s index 4193a686870ab..d9eaa5a89ab23 100644 --- a/llvm/test/MC/ARM/arm11-hint-instr.s +++ b/llvm/test/MC/ARM/arm11-hint-instr.s @@ -65,7 +65,13 @@ @ CHECK-THUMB: wfe @ encoding: [0x20,0xbf] @ CHECK-THUMB: wfi @ encoding: [0x30,0xbf] @ CHECK-THUMB: sev @ encoding: [0x40,0xbf] -@ CHECK-ERROR-THUMB: error: instruction requires: v7 clrex +@ CHECK-ERROR-THUMB: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERROR-THUMB: clrex +@ CHECK-ERROR-THUMB: ^ +@ CHECK-ERROR-THUMB: note: instruction requires: v7 clrex +@ CHECK-ERROR-THUMB: clrex +@ CHECK-ERROR-THUMB: ^ +@ CHECK-ERROR-THUMB: note: instruction requires: arm-mode @ CHECK-ERROR-THUMB: clrex @ CHECK-ERROR-THUMB: ^ diff --git a/llvm/test/MC/ARM/cde-fp-vec.s b/llvm/test/MC/ARM/cde-fp-vec.s index 4b139579b719b..fa18ffa766e2e 100644 --- a/llvm/test/MC/ARM/cde-fp-vec.s +++ b/llvm/test/MC/ARM/cde-fp-vec.s @@ -12,7 +12,7 @@ ittt eq vcx1a p1, s7, #2047 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: instructions in IT block must be predicable vcx2 p0, d0, d15, #0 -// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: error: invalid instruction +// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: error: instruction requires: mve // ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: error: instructions in IT block must be predicable vcx3 p0, q0, q7, q0, #12 nop @@ -33,12 +33,15 @@ vcx1a p1, d3, #2047 // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: vcx1 p0, q1, #1234 // CHECK-MVE-NEXT: vcx1a p1, q5, #4095 @ encoding: [0x2f,0xfd,0xff,0xa1] -// ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction +// ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: instruction requires: mve vcx1a p1, q5, #4095 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction vcx1a p1, s7, s7, #2047 -// ERROR: [[@LINE+1]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] +// ERROR-FP: [[@LINE+4]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] +// ERROR-MVE: [[@LINE+3]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [q0, q7] +// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: note: operand must be an immediate in the range [0,2047] vcx1 p0, d0, #2048 // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,2047] vcx1a p1, s0, #2048 @@ -51,10 +54,13 @@ vcx1 p8, d0, #1234 vcx1 p0, d16, #1234 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: invalid instruction vcx1 p0, s32, #1234 -// ERROR-FP: [[@LINE+4]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: -// ERROR-FP: [[@LINE+3]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] -// ERROR-FP: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] -// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [q0, q7] +// ERROR-FP: [[@LINE+7]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: +// ERROR-FP: [[@LINE+6]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] +// ERROR-FP: [[@LINE+5]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] +// ERROR-MVE: [[@LINE+4]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: +// ERROR-MVE: [[@LINE+3]]:{{[0-9]+}}: note: operand must be a register in range [q0, q7] +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] +// ERROR-MVE: [[@LINE+1]]:{{[0-9]+}}: note: operand must be a register in range [d0, d15] vcx1 p0, q8, #1234 // ERROR: [[@LINE+3]]:{{[0-9]+}}: error: invalid instruction, any one of the following would fix this: // ERROR: [[@LINE+2]]:{{[0-9]+}}: note: operand must be a register in range [s0, s31] @@ -116,7 +122,7 @@ vcx3a p1, d1, d11, d12, #8 // ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: operand must be an immediate in the range [0,15] // ERROR-FP: error: invalid instruction vcx3a p1, q1, q2, q3, #16 -// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: invalid instruction +// ERROR-MVE: [[@LINE+2]]:{{[0-9]+}}: error: operand must be a register in range [d0, d15] // ERROR-FP: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [d0, d15] vcx3 p0, d0, q0, d7, #1 // ERROR: [[@LINE+1]]:{{[0-9]+}}: error: operand must be a register in range [s0, s31] diff --git a/llvm/test/MC/ARM/cde-vec-pred.s b/llvm/test/MC/ARM/cde-vec-pred.s index 6274fafa1224a..9932f8d000337 100644 --- a/llvm/test/MC/ARM/cde-vec-pred.s +++ b/llvm/test/MC/ARM/cde-vec-pred.s @@ -19,7 +19,7 @@ vcx3at p1, q3, q7, q6, #15 vcx3e p0, q0, q2, q0, #12 vpt.i8 eq, q0, q0 -// ERROR: [[@LINE+1]]:{{[0-9]+}}: error: incorrect predication in VPT block; got 'none', but expected 't' +// ERROR: error: incorrect predication in VPT block; got 'none', but expected 't' vcx1 p0, q1, #1234 vpt.i8 eq, q0, q0 diff --git a/llvm/test/MC/ARM/cps.s b/llvm/test/MC/ARM/cps.s index bafdfdea537b8..1034ed93810dd 100644 --- a/llvm/test/MC/ARM/cps.s +++ b/llvm/test/MC/ARM/cps.s @@ -26,6 +26,6 @@ @ V6-ERRORS: note: too many operands for instruction @ V6-ERRORS: error: invalid instruction, any one of the following would fix this: @ V6-ERRORS: cps #0 -@ V6-ERRORS: note: too few operands for instruction @ V6-ERRORS: note: instruction requires: arm-mode @ V6-ERRORS: note: instruction requires: thumb2 +@ V6-ERRORS: note: too few operands for instruction diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s index e6d80ea7a6280..fa23a7da1e404 100644 --- a/llvm/test/MC/ARM/diagnostics.s +++ b/llvm/test/MC/ARM/diagnostics.s @@ -288,7 +288,7 @@ @ CHECK-ERRORS: error: 'asr' shift amount must be in range [1,32] @ CHECK-ERRORS: ssat r8, #1, r10, asr #33 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: shift operator 'asr' or 'lsl' expected +@ CHECK-ERRORS: error: operand must be a register in range [r0, r14] @ CHECK-ERRORS: ssat r8, #1, r10, lsr #5 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: '#' expected diff --git a/llvm/test/MC/ARM/directive-arch_extension-crypto.s b/llvm/test/MC/ARM/directive-arch_extension-crypto.s index 8d3cd9e5e1d0d..05b6d9e040188 100644 --- a/llvm/test/MC/ARM/directive-arch_extension-crypto.s +++ b/llvm/test/MC/ARM/directive-arch_extension-crypto.s @@ -10,15 +10,16 @@ .syntax unified .arch_extension crypto -@ CHECK-V7: error: architectural extension 'crypto' is not allowed for the current base architecture +@ CHECK-V7: architectural extension 'crypto' is not allowed for the current base architecture @ CHECK-V7-NEXT: .arch_extension crypto @ CHECK-V7-NEXT: ^ .type crypto,%function crypto: vmull.p64 q0, d0, d1 -@ CHECK-V7: error: instruction requires: aes armv8 - +@ CHECK-V7: error: invalid instruction, any one of the following would fix this: +@ CHECK-V7: note: invalid operand for instruction +@ CHECK-V7: note: instruction requires: aes armv8 aesd.8 q0, q1 @ CHECK-V7: error: instruction requires: aes armv8 aese.8 q0, q1 @@ -51,14 +52,18 @@ crypto: @ CHECK-V7: error: instruction requires: sha2 armv8 .arch_extension nocrypto +@ CHECK-V7: error: architectural extension 'sha2' is not allowed for the current base architecture +@ CHECK-V7: error: architectural extension 'aes' is not allowed for the current base architecture @ CHECK-V7: error: architectural extension 'crypto' is not allowed for the current base architecture -@ CHECK-V7-NEXT: .arch_extension nocrypto +@ CHECK-V7-NEXT: .arch_extension nocrypto @ CHECK-V7-NEXT: ^ .type nocrypto,%function nocrypto: vmull.p64 q0, d0, d1 -@ CHECK-V7: error: instruction requires: aes armv8 +@ CHECK-V7: error: invalid instruction, any one of the following +@ CHECK-V7: note: invalid operand for instruction +@ CHECK-V7: note: instruction requires: aes armv8 @ CHECK-V8: error: instruction requires: aes aesd.8 q0, q1 diff --git a/llvm/test/MC/ARM/invalid-fp-armv8.s b/llvm/test/MC/ARM/invalid-fp-armv8.s index dca0e448d1140..c8ce261791cfd 100644 --- a/llvm/test/MC/ARM/invalid-fp-armv8.s +++ b/llvm/test/MC/ARM/invalid-fp-armv8.s @@ -88,6 +88,8 @@ vrinta.f64.f64 s3, q0 vrintn.f32.f32 d3, d0 @ V8: error: instruction requires: NEON vrintp.f32 q3, q0 -@ V8: error: instruction requires: NEON +@ V8: error: invalid instruction, any one of the following would fix this: +@ V8: note: instruction requires: mve.fp +@ V8: note: instruction requires: NEON vrintmlt.f32 q3, q0 @ V8: error: instruction 'vrintm' is not predicable, but condition code specified diff --git a/llvm/test/MC/ARM/lsl-zero-errors.s b/llvm/test/MC/ARM/lsl-zero-errors.s index e021aa9eb986d..1e51c587211d1 100644 --- a/llvm/test/MC/ARM/lsl-zero-errors.s +++ b/llvm/test/MC/ARM/lsl-zero-errors.s @@ -55,22 +55,22 @@ // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov pc, r0, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 // CHECK-THUMBV8: note: operand must be a register in range [r0, r14] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov r0, pc, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: note: invalid operand for instruction // CHECK-NONARM: note: invalid operand for instruction // CHECK-NONARM: note: operand must be an immediate in the range [256,65535] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: mov pc, pc, lsl #0 -// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 // CHECK-THUMBV8: note: operand must be a register in range [r0, r14] +// CHECK-NONARM: note: operand must be a register in range [r0, r15] // CHECK-NONARM: error: invalid instruction, any one of the following would fix this: // CHECK-NONARM-NEXT: movs pc, r0, lsl #0 @@ -134,8 +134,8 @@ // FIXME: We should consistently have the "requires ARMv8" error here // CHECK-THUMBV7: error: invalid instruction, any one of the following would fix this: // CHECK-THUMBV7-NEXT: mov sp, sp, lsl #0 -// CHECK-THUMBV7: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: note: operand must be a register in range [r0, r12] or r14 +// CHECK-THUMBV7: note: operand must be a register in range [r0, r15] // CHECK-THUMBV7: error: invalid instruction, any one of the following would fix this: // CHECK-THUMBV7-NEXT: movs sp, sp, lsl #0 diff --git a/llvm/test/MC/ARM/mve-load-store.s b/llvm/test/MC/ARM/mve-load-store.s index 5c6d2a172b252..797ab1e22dd01 100644 --- a/llvm/test/MC/ARM/mve-load-store.s +++ b/llvm/test/MC/ARM/mve-load-store.s @@ -5,55 +5,55 @@ # RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0] # CHECK: vldrb.u8 q1, [r0] @ encoding: [0x90,0xed,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q1, [r0] # CHECK: vldrb.u8 q0, [r11] @ encoding: [0x9b,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r11] # CHECK: vldrb.u8 q3, [r11] @ encoding: [0x9b,0xed,0x00,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q3, [r11] # CHECK: vldrb.u8 q0, [r4, #56] @ encoding: [0x94,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r4, #56] # CHECK: vldrb.u8 q4, [r4, #56] @ encoding: [0x94,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q4, [r4, #56] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r8, #56] # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4], #-25 @ encoding: [0x34,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r4], #-25 # CHECK: vldrb.u8 q5, [r10], #-25 @ encoding: [0x3a,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [r10], #-25 # CHECK: vldrb.u8 q5, [sp, #-25] @ encoding: [0x1d,0xed,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [sp, #-25] # CHECK: vldrb.u8 q5, [sp, #-127] @ encoding: [0x1d,0xed,0x7f,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q5, [sp, #-127] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -69,55 +69,55 @@ vldrb.u8 q0, [r0, #-128]! vldrb.u8 q0, [r0], #128 # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r0] # CHECK: vstrb.8 q1, [r0] @ encoding: [0x80,0xed,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q1, [r0] # CHECK: vstrb.8 q0, [r11] @ encoding: [0x8b,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r11] # CHECK: vstrb.8 q3, [r11] @ encoding: [0x8b,0xed,0x00,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r11] # CHECK: vstrb.8 q0, [r4, #56] @ encoding: [0x84,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r4, #56] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q4, [r4, #56] # CHECK: vstrb.8 q0, [r8, #56] @ encoding: [0x88,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r8, #56] # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4], #-25 @ encoding: [0x24,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r4], #-25 # CHECK: vstrb.8 q5, [r10], #-25 @ encoding: [0x2a,0xec,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [r10], #-25 # CHECK: vstrb.8 q5, [sp, #-25] @ encoding: [0x0d,0xed,0x19,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [sp, #-25] # CHECK: vstrb.8 q5, [sp, #127] @ encoding: [0x8d,0xed,0x7f,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q5, [sp, #127] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -133,735 +133,735 @@ vstrb.u8 q0, [r0, #-128]! vstrb.u8 q0, [r0], #128 # CHECK: vldrb.u16 q0, [r0] @ encoding: [0x90,0xfd,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0] # CHECK: vldrb.u16 q1, [r0] @ encoding: [0x90,0xfd,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q1, [r0] # CHECK: vldrb.u16 q0, [r7] @ encoding: [0x97,0xfd,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r7] # CHECK: vldrb.u16 q3, [r7] @ encoding: [0x97,0xfd,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q3, [r7] # CHECK: vldrb.u16 q0, [r4, #56] @ encoding: [0x94,0xfd,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r4, #56] # CHECK: vldrb.u16 q4, [r4, #56] @ encoding: [0x94,0xfd,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q4, [r4, #56] # CHECK: vldrb.u16 q0, [r2, #56] @ encoding: [0x92,0xfd,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r2, #56] # CHECK: vldrb.u16 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4, #56]! # CHECK: vldrb.u16 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4, #56]! # CHECK: vldrb.u16 q5, [r4], #-1 @ encoding: [0x34,0xfc,0x81,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r4], #-1 # CHECK: vldrb.u16 q5, [r3], #-25 @ encoding: [0x33,0xfc,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r3], #-25 # CHECK: vldrb.u16 q5, [r6, #-25] @ encoding: [0x16,0xfd,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r6, #-25] # CHECK: vldrb.u16 q5, [r6, #-64] @ encoding: [0x16,0xfd,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q5, [r6, #-64] # CHECK: vldrb.s16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0] # CHECK: vldrb.s16 q1, [r0] @ encoding: [0x90,0xed,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q1, [r0] # CHECK: vldrb.s16 q0, [r7] @ encoding: [0x97,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r7] # CHECK: vldrb.s16 q3, [r7] @ encoding: [0x97,0xed,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q3, [r7] # CHECK: vldrb.s16 q0, [r4, #56] @ encoding: [0x94,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r4, #56] # CHECK: vldrb.s16 q4, [r4, #56] @ encoding: [0x94,0xed,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q4, [r4, #56] # CHECK: vldrb.s16 q0, [r2, #56] @ encoding: [0x92,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r2, #56] # CHECK: vldrb.s16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4, #56]! # CHECK: vldrb.s16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4, #56]! # CHECK: vldrb.s16 q5, [r4], #-25 @ encoding: [0x34,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r4], #-25 # CHECK: vldrb.s16 q5, [r3], #-25 @ encoding: [0x33,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r3], #-25 # CHECK: vldrb.s16 q5, [r6, #-25] @ encoding: [0x16,0xed,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r6, #-25] # CHECK: vldrb.s16 q5, [r6, #-64] @ encoding: [0x16,0xed,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q5, [r6, #-64] # CHECK: vstrb.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r0] # CHECK: vstrb.16 q1, [r0] @ encoding: [0x80,0xed,0x80,0x2e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q1, [r0] # CHECK: vstrb.16 q0, [r7] @ encoding: [0x87,0xed,0x80,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r7] # CHECK: vstrb.16 q3, [r7] @ encoding: [0x87,0xed,0x80,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [r7] # CHECK: vstrb.16 q0, [r4, #56] @ encoding: [0x84,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r4, #56] # CHECK: vstrb.16 q4, [r4, #56] @ encoding: [0x84,0xed,0xb8,0x8e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q4, [r4, #56] # CHECK: vstrb.16 q0, [r5, #56] @ encoding: [0x85,0xed,0xb8,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r5, #56] # CHECK: vstrb.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4, #56]! # CHECK: vstrb.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0xb8,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4, #56]! # CHECK: vstrb.16 q5, [r4], #-25 @ encoding: [0x24,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r4], #-25 # CHECK: vstrb.16 q5, [r3], #-25 @ encoding: [0x23,0xec,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r3], #-25 # CHECK: vstrb.16 q5, [r2, #-25] @ encoding: [0x02,0xed,0x99,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r2, #-25] # CHECK: vstrb.16 q5, [r2, #-64] @ encoding: [0x02,0xed,0xc0,0xae] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q5, [r2, #-64] # CHECK: vldrb.u32 q0, [r0] @ encoding: [0x90,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0] # CHECK: vldrb.u32 q1, [r0] @ encoding: [0x90,0xfd,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q1, [r0] # CHECK: vldrb.u32 q0, [r7] @ encoding: [0x97,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r7] # CHECK: vldrb.u32 q3, [r7] @ encoding: [0x97,0xfd,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q3, [r7] # CHECK: vldrb.u32 q0, [r4, #56] @ encoding: [0x94,0xfd,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r4, #56] # CHECK: vldrb.u32 q4, [r4, #56] @ encoding: [0x94,0xfd,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q4, [r4, #56] # CHECK: vldrb.u32 q0, [r2, #56] @ encoding: [0x92,0xfd,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r2, #56] # CHECK: vldrb.u32 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4, #56]! # CHECK: vldrb.u32 q5, [r4, #56]! @ encoding: [0xb4,0xfd,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4, #56]! # CHECK: vldrb.u32 q5, [r4], #-25 @ encoding: [0x34,0xfc,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r4], #-25 # CHECK: vldrb.u32 q5, [r3], #-25 @ encoding: [0x33,0xfc,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r3], #-25 # CHECK: vldrb.u32 q5, [r6, #-25] @ encoding: [0x16,0xfd,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r6, #-25] # CHECK: vldrb.u32 q5, [r6, #-64] @ encoding: [0x16,0xfd,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q5, [r6, #-64] # CHECK: vldrb.s32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0] # CHECK: vldrb.s32 q1, [r0] @ encoding: [0x90,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q1, [r0] # CHECK: vldrb.s32 q0, [r7] @ encoding: [0x97,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r7] # CHECK: vldrb.s32 q3, [r7] @ encoding: [0x97,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q3, [r7] # CHECK: vldrb.s32 q0, [r4, #56] @ encoding: [0x94,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r4, #56] # CHECK: vldrb.s32 q4, [r4, #56] @ encoding: [0x94,0xed,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q4, [r4, #56] # CHECK: vldrb.s32 q0, [r2, #56] @ encoding: [0x92,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r2, #56] # CHECK: vldrb.s32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4, #56]! # CHECK: vldrb.s32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4, #56]! # CHECK: vldrb.s32 q5, [r4], #-25 @ encoding: [0x34,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r4], #-25 # CHECK: vldrb.s32 q5, [r3], #-25 @ encoding: [0x33,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r3], #-25 # CHECK: vldrb.s32 q5, [r6, #-25] @ encoding: [0x16,0xed,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r6, #-25] # CHECK: vldrb.s32 q5, [r6, #-64] @ encoding: [0x16,0xed,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q5, [r6, #-64] # CHECK: vstrb.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r0] # CHECK: vstrb.32 q1, [r0] @ encoding: [0x80,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q1, [r0] # CHECK: vstrb.32 q0, [r7] @ encoding: [0x87,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r7] # CHECK: vstrb.32 q3, [r7] @ encoding: [0x87,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r7] # CHECK: vstrb.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r4, #56] # CHECK: vstrb.32 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q4, [r4, #56] # CHECK: vstrb.32 q0, [r5, #56] @ encoding: [0x85,0xed,0x38,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r5, #56] # CHECK: vstrb.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4, #56]! # CHECK: vstrb.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4, #56]! # CHECK: vstrb.32 q5, [r4], #-25 @ encoding: [0x24,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r4], #-25 # CHECK: vstrb.32 q5, [r3], #-25 @ encoding: [0x23,0xec,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r3], #-25 # CHECK: vstrb.32 q5, [r2, #-25] @ encoding: [0x02,0xed,0x19,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r2, #-25] # CHECK: vstrb.32 q5, [r2, #-64] @ encoding: [0x02,0xed,0x40,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q5, [r2, #-64] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0] # CHECK: vldrh.u16 q1, [r0] @ encoding: [0x90,0xed,0x80,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q1, [r0] # CHECK: vldrh.u16 q0, [r11] @ encoding: [0x9b,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r11] # CHECK: vldrh.u16 q3, [r11] @ encoding: [0x9b,0xed,0x80,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q3, [r11] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r4, #56] # CHECK: vldrh.u16 q4, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q4, [r4, #56] # CHECK: vldrh.u16 q0, [r8, #56] @ encoding: [0x98,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r8, #56] # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4], #-26 @ encoding: [0x34,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r4], #-26 # CHECK: vldrh.u16 q5, [r10], #-26 @ encoding: [0x3a,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r10], #-26 # CHECK: vldrh.u16 q5, [sp, #-26] @ encoding: [0x1d,0xed,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-26] # CHECK: vldrh.u16 q5, [sp, #-64] @ encoding: [0x1d,0xed,0xa0,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-64] # CHECK: vldrh.u16 q5, [sp, #-254] @ encoding: [0x1d,0xed,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [sp, #-254] # CHECK: vldrh.u16 q5, [r10], #254 @ encoding: [0xba,0xec,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q5, [r10], #254 # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0] # CHECK: vstrh.16 q1, [r0] @ encoding: [0x80,0xed,0x80,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q1, [r0] # CHECK: vstrh.16 q0, [r11] @ encoding: [0x8b,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r11] # CHECK: vstrh.16 q3, [r11] @ encoding: [0x8b,0xed,0x80,0x7e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r11] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r4, #56] # CHECK: vstrh.16 q4, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q4, [r4, #56] # CHECK: vstrh.16 q0, [r8, #56] @ encoding: [0x88,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r8, #56] # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4], #-26 @ encoding: [0x24,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r4], #-26 # CHECK: vstrh.16 q5, [r10], #-26 @ encoding: [0x2a,0xec,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r10], #-26 # CHECK: vstrh.16 q5, [sp, #-26] @ encoding: [0x0d,0xed,0x8d,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-26] # CHECK: vstrh.16 q5, [sp, #-64] @ encoding: [0x0d,0xed,0xa0,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-64] # CHECK: vstrh.16 q5, [sp, #-254] @ encoding: [0x0d,0xed,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [sp, #-254] # CHECK: vstrh.16 q5, [r10], #254 @ encoding: [0xaa,0xec,0xff,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q5, [r10], #254 # CHECK: vldrh.u32 q0, [r0] @ encoding: [0x98,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0] # CHECK: vldrh.u32 q1, [r0] @ encoding: [0x98,0xfd,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q1, [r0] # CHECK: vldrh.u32 q0, [r7] @ encoding: [0x9f,0xfd,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r7] # CHECK: vldrh.u32 q3, [r7] @ encoding: [0x9f,0xfd,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q3, [r7] # CHECK: vldrh.u32 q0, [r4, #56] @ encoding: [0x9c,0xfd,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r4, #56] # CHECK: vldrh.u32 q4, [r4, #56] @ encoding: [0x9c,0xfd,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q4, [r4, #56] # CHECK: vldrh.u32 q0, [r2, #56] @ encoding: [0x9a,0xfd,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r2, #56] # CHECK: vldrh.u32 q5, [r4, #56]! @ encoding: [0xbc,0xfd,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #56]! # CHECK: vldrh.u32 q5, [r4, #56]! @ encoding: [0xbc,0xfd,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #56]! # CHECK: vldrh.u32 q5, [r4], #-26 @ encoding: [0x3c,0xfc,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4], #-26 # CHECK: vldrh.u32 q5, [r3], #-26 @ encoding: [0x3b,0xfc,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r3], #-26 # CHECK: vldrh.u32 q5, [r6, #-26] @ encoding: [0x1e,0xfd,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-26] # CHECK: vldrh.u32 q5, [r6, #-64] @ encoding: [0x1e,0xfd,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-64] # CHECK: vldrh.u32 q5, [r6, #-254] @ encoding: [0x1e,0xfd,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r6, #-254] # CHECK: vldrh.u32 q5, [r4, #254]! @ encoding: [0xbc,0xfd,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q5, [r4, #254]! # CHECK: vldrh.s32 q0, [r0] @ encoding: [0x98,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0] # CHECK: vldrh.s32 q1, [r0] @ encoding: [0x98,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q1, [r0] # CHECK: vldrh.s32 q0, [r7] @ encoding: [0x9f,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r7] # CHECK: vldrh.s32 q3, [r7] @ encoding: [0x9f,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q3, [r7] # CHECK: vldrh.s32 q0, [r4, #56] @ encoding: [0x9c,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r4, #56] # CHECK: vldrh.s32 q4, [r4, #56] @ encoding: [0x9c,0xed,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q4, [r4, #56] # CHECK: vldrh.s32 q0, [r2, #56] @ encoding: [0x9a,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r2, #56] # CHECK: vldrh.s32 q5, [r4, #56]! @ encoding: [0xbc,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #56]! # CHECK: vldrh.s32 q5, [r4, #56]! @ encoding: [0xbc,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #56]! # CHECK: vldrh.s32 q5, [r4], #-26 @ encoding: [0x3c,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4], #-26 # CHECK: vldrh.s32 q5, [r3], #-26 @ encoding: [0x3b,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r3], #-26 # CHECK: vldrh.s32 q5, [r6, #-26] @ encoding: [0x1e,0xed,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-26] # CHECK: vldrh.s32 q5, [r6, #-64] @ encoding: [0x1e,0xed,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-64] # CHECK: vldrh.s32 q5, [r6, #-254] @ encoding: [0x1e,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r6, #-254] # CHECK: vldrh.s32 q5, [r4, #254]! @ encoding: [0xbc,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q5, [r4, #254]! # CHECK: vstrh.32 q0, [r0] @ encoding: [0x88,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r0] # CHECK: vstrh.32 q1, [r0] @ encoding: [0x88,0xed,0x00,0x2f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q1, [r0] # CHECK: vstrh.32 q0, [r7] @ encoding: [0x8f,0xed,0x00,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r7] # CHECK: vstrh.32 q3, [r7] @ encoding: [0x8f,0xed,0x00,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r7] # CHECK: vstrh.32 q0, [r4, #56] @ encoding: [0x8c,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r4, #56] # CHECK: vstrh.32 q4, [r4, #56] @ encoding: [0x8c,0xed,0x1c,0x8f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q4, [r4, #56] # CHECK: vstrh.32 q0, [r5, #56] @ encoding: [0x8d,0xed,0x1c,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r5, #56] # CHECK: vstrh.32 q5, [r4, #56]! @ encoding: [0xac,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #56]! # CHECK: vstrh.32 q5, [r4, #56]! @ encoding: [0xac,0xed,0x1c,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #56]! # CHECK: vstrh.32 q5, [r4], #-26 @ encoding: [0x2c,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4], #-26 # CHECK: vstrh.32 q5, [r3], #-26 @ encoding: [0x2b,0xec,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r3], #-26 # CHECK: vstrh.32 q5, [r2, #-26] @ encoding: [0x0a,0xed,0x0d,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-26] # CHECK: vstrh.32 q5, [r2, #-64] @ encoding: [0x0a,0xed,0x20,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-64] # CHECK: vstrh.32 q5, [r2, #-254] @ encoding: [0x0a,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r2, #-254] # CHECK: vstrh.32 q5, [r4, #254]! @ encoding: [0xac,0xed,0x7f,0xaf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q5, [r4, #254]! # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0] # CHECK: vldrw.u32 q1, [r0] @ encoding: [0x90,0xed,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q1, [r0] # CHECK: vldrw.u32 q0, [r11] @ encoding: [0x9b,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r11] # CHECK: vldrw.u32 q3, [r11] @ encoding: [0x9b,0xed,0x00,0x7f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q3, [r11] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r4, #56] # CHECK: vldrw.u32 q4, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x9f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q4, [r4, #56] # CHECK: vldrw.u32 q0, [r8, #56] @ encoding: [0x98,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r8, #56] # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4], #-28 @ encoding: [0x34,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4], #-28 # CHECK: vldrw.u32 q5, [r10], #-28 @ encoding: [0x3a,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r10], #-28 # CHECK: vldrw.u32 q5, [sp, #-28] @ encoding: [0x1d,0xed,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-28] # CHECK: vldrw.u32 q5, [sp, #-64] @ encoding: [0x1d,0xed,0x10,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-64] # CHECK: vldrw.u32 q5, [sp, #-508] @ encoding: [0x1d,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [sp, #-508] # CHECK: vldrw.u32 q5, [r4, #508]! @ encoding: [0xb4,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q5, [r4, #508]! # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0] # CHECK: vstrw.32 q1, [r0] @ encoding: [0x80,0xed,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q1, [r0] # CHECK: vstrw.32 q0, [r11] @ encoding: [0x8b,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r11] # CHECK: vstrw.32 q3, [r11] @ encoding: [0x8b,0xed,0x00,0x7f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r11] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r4, #56] # CHECK: vstrw.32 q4, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x9f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q4, [r4, #56] # CHECK: vstrw.32 q0, [r8, #56] @ encoding: [0x88,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r8, #56] # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4], #-28 @ encoding: [0x24,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4], #-28 # CHECK: vstrw.32 q5, [r10], #-28 @ encoding: [0x2a,0xec,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r10], #-28 # CHECK: vstrw.32 q5, [sp, #-28] @ encoding: [0x0d,0xed,0x07,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-28] # CHECK: vstrw.32 q5, [sp, #-64] @ encoding: [0x0d,0xed,0x10,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-64] # CHECK: vstrw.32 q5, [sp, #-508] @ encoding: [0x0d,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [sp, #-508] # CHECK: vstrw.32 q5, [r4, #508]! @ encoding: [0xa4,0xed,0x7f,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q5, [r4, #508]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -885,271 +885,271 @@ vstrw.32 q5, [sp, #-3] vstrw.32 q5, [sp, #512] # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0, q1] # CHECK: vldrb.u8 q3, [r10, q1] @ encoding: [0x9a,0xfc,0x02,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q3, [r10, q1] # CHECK: vldrb.u16 q0, [r0, q1] @ encoding: [0x90,0xfc,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0, q1] # CHECK: vldrb.u16 q3, [r9, q1] @ encoding: [0x99,0xfc,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q3, [r9, q1] # CHECK: vldrb.s16 q0, [r0, q1] @ encoding: [0x90,0xec,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0, q1] # CHECK: vldrb.s16 q3, [sp, q1] @ encoding: [0x9d,0xec,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q3, [sp, q1] # CHECK: vldrb.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0, q1] # CHECK: vldrb.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q3, [r0, q1] # CHECK: vldrb.s32 q0, [r0, q1] @ encoding: [0x90,0xec,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0, q1] # CHECK: vldrb.s32 q3, [r0, q1] @ encoding: [0x90,0xec,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q3, [r0, q1] # CHECK: vldrh.u16 q0, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q3, [r0, q1] # CHECK: vldrh.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q1] # CHECK: vldrh.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q3, [r0, q1] # CHECK: vldrh.s32 q0, [r0, q1] @ encoding: [0x90,0xec,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q1] # CHECK: vldrh.s32 q3, [r0, q1] @ encoding: [0x90,0xec,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q3, [r0, q1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u8 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u32 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s32 q0, [r0, q0, uxtw #1] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q0, uxtw #2] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q0] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector offset register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q0, uxtw #3] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.u16 q0, [r0, q1, uxtw #1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q1] # CHECK: vldrw.u32 q3, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q3, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [sp, q1, uxtw #2] @ encoding: [0x9d,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [sp, q1, uxtw #2] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q1] # CHECK: vldrd.u64 q3, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q3, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [sp, q1, uxtw #3] @ encoding: [0x9d,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [sp, q1, uxtw #3] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q0, [r0, q1] # CHECK: vstrb.8 q3, [r10, q1] @ encoding: [0x8a,0xec,0x02,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r10, q1] # CHECK: vstrb.8 q3, [r0, q3] @ encoding: [0x80,0xec,0x06,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.8 q3, [r0, q3] # CHECK: vstrb.16 q0, [r0, q1] @ encoding: [0x80,0xec,0x82,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q0, [r0, q1] # CHECK: vstrb.16 q3, [sp, q1] @ encoding: [0x8d,0xec,0x82,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [sp, q1] # CHECK: vstrb.16 q3, [r0, q3] @ encoding: [0x80,0xec,0x86,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.16 q3, [r0, q3] # CHECK: vstrb.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q0, [r0, q1] # CHECK: vstrb.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x02,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r0, q1] # CHECK: vstrb.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x06,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.32 q3, [r0, q3] # CHECK: vstrh.16 q0, [r0, q1] @ encoding: [0x80,0xec,0x92,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q3] @ encoding: [0x80,0xec,0x96,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q3, [r0, q3] # CHECK: vstrh.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x12,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q0, [r0, q1] # CHECK: vstrh.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x12,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r0, q1] # CHECK: vstrh.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x16,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r0, q3] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.32 q3, [r8, q3, uxtw #1] @ encoding: [0x88,0xec,0x17,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.32 q3, [r8, q3, uxtw #1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0, q1] # CHECK: vstrw.32 q3, [r0, q1] @ encoding: [0x80,0xec,0x42,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r0, q1] # CHECK: vstrw.32 q3, [r0, q3] @ encoding: [0x80,0xec,0x46,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q3, [r0, q3] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [sp, q1, uxtw #2] @ encoding: [0x8d,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [sp, q1, uxtw #2] # CHECK: vstrd.64 q0, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q3] @ encoding: [0x80,0xec,0xd6,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q3, [r0, q3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [sp, q1, uxtw #3] @ encoding: [0x8d,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [sp, q1, uxtw #3] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1189,79 +1189,79 @@ vstrh.16 q0, [r0, q1, uxtw #2] vstrb.32 q0, [r11, q1, uxtw #1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q0, [q1] # CHECK: vldrw.u32 q7, [q1] @ encoding: [0x92,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1] # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #-4] @ encoding: [0x12,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #-4] # CHECK: vldrw.u32 q7, [q1, #508] @ encoding: [0x92,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #508] # CHECK: vldrw.u32 q7, [q1, #-508] @ encoding: [0x12,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #-508] # CHECK: vldrw.u32 q7, [q1, #264] @ encoding: [0x92,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #264] # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4]! # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q0, [q1] # CHECK: vstrw.32 q1, [q1] @ encoding: [0x82,0xfd,0x00,0x3e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q1, [q1] # CHECK: vstrw.32 q7, [q1] @ encoding: [0x82,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1] # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1]! # CHECK: vstrw.32 q7, [q7] @ encoding: [0x8e,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q7] # CHECK: vstrw.32 q7, [q1, #4] @ encoding: [0x82,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #4] # CHECK: vstrw.32 q7, [q1, #-4] @ encoding: [0x02,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #-4] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #-508] @ encoding: [0x02,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #-508] # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.32 q7, [q1, #264]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1277,103 +1277,103 @@ vstrw.32 q4, [q1, #3]! vldrw.u32 q7, [q1, #512] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector pointer register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q1, [q1, #264] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q0, [q1] # CHECK: vldrd.u64 q7, [q1] @ encoding: [0x92,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1] # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #-8] @ encoding: [0x12,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-8] # CHECK: vldrd.u64 q7, [q1, #1016] @ encoding: [0x92,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #1016] # CHECK: vldrd.u64 q7, [q1, #-1016] @ encoding: [0x12,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-1016] # CHECK: vldrd.u64 q7, [q1, #264] @ encoding: [0x92,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #264] # CHECK: vldrd.u64 q7, [q1, #624] @ encoding: [0x92,0xfd,0x4e,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #624] # CHECK: vldrd.u64 q7, [q1, #264] @ encoding: [0x92,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #264] # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q7, [q1, #-1016]! # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: destination vector register and vector pointer register can't be identical -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.u64 q6, [q6] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q0, [q1] # CHECK: vstrd.64 q1, [q1] @ encoding: [0x82,0xfd,0x00,0x3f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q1, [q1] # CHECK: vstrd.64 q7, [q1] @ encoding: [0x82,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1] # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1]! # CHECK: vstrd.64 q7, [q7] @ encoding: [0x8e,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q7] # CHECK: vstrd.64 q7, [q1, #8] @ encoding: [0x82,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #8] # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #-1016] @ encoding: [0x02,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #-1016] # CHECK: vstrd.64 q7, [q1, #264] @ encoding: [0x82,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #264] # CHECK: vstrd.64 q7, [q1, #624] @ encoding: [0x82,0xfd,0x4e,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #624] # CHECK: vstrd.64 q7, [q1, #264] @ encoding: [0x82,0xfd,0x21,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.64 q7, [q1, #264] # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [q0, q7] @@ -1393,547 +1393,547 @@ vstrd.64 q4, [q1, #3] vstrd.64 q4, [q1, #4] # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r0] # CHECK: vldrb.u8 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r0] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r8, #56] # CHECK: vldrb.u8 q0, [r8, #56] @ encoding: [0x98,0xed,0x38,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r8, #56] # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q5, [r4, #56]! # CHECK: vldrb.u8 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q5, [r4, #56]! # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q0, [r0] # CHECK: vstrb.8 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q0, [r0] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q4, [r4, #56] # CHECK: vstrb.8 q4, [r4, #56] @ encoding: [0x84,0xed,0x38,0x9e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q4, [r4, #56] # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q5, [r4, #56]! # CHECK: vstrb.8 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x38,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q5, [r4, #56]! # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r0] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r0] # CHECK: vldrh.u16 q0, [r0] @ encoding: [0x90,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r0] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r4, #56] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r4, #56] # CHECK: vldrh.u16 q0, [r4, #56] @ encoding: [0x94,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r4, #56] # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q5, [r4, #56]! # CHECK: vldrh.u16 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q5, [r4, #56]! # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r0] # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r0] # CHECK: vstrh.16 q0, [r0] @ encoding: [0x80,0xed,0x80,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r0] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r4, #56] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r4, #56] # CHECK: vstrh.16 q0, [r4, #56] @ encoding: [0x84,0xed,0x9c,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r4, #56] # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q5, [r4, #56]! # CHECK: vstrh.16 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x9c,0xbe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q5, [r4, #56]! # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0] # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0] # CHECK: vldrw.u32 q0, [r0] @ encoding: [0x90,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r4, #56] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r4, #56] # CHECK: vldrw.u32 q0, [r4, #56] @ encoding: [0x94,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r4, #56] # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q5, [r4, #56]! # CHECK: vldrw.u32 q5, [r4, #56]! @ encoding: [0xb4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q5, [r4, #56]! # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0] # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0] # CHECK: vstrw.32 q0, [r0] @ encoding: [0x80,0xed,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r4, #56] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r4, #56] # CHECK: vstrw.32 q0, [r4, #56] @ encoding: [0x84,0xed,0x0e,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r4, #56] # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q5, [r4, #56]! # CHECK: vstrw.32 q5, [r4, #56]! @ encoding: [0xa4,0xed,0x0e,0xbf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q5, [r4, #56]! # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.s8 q0, [r0, q1] # CHECK: vldrb.u8 q0, [r0, q1] @ encoding: [0x90,0xfc,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrb.8 q0, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q3, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q3, [r0, q1] # CHECK: vldrh.u16 q3, [r0, q1] @ encoding: [0x90,0xfc,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q3, [r0, q1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.s16 q0, [r0, q1, uxtw #1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.f16 q0, [r0, q1, uxtw #1] # CHECK: vldrh.u16 q0, [r0, q1, uxtw #1] @ encoding: [0x90,0xfc,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrh.16 q0, [r0, q1, uxtw #1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1] @ encoding: [0x90,0xfc,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0, q1] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [r0, q1, uxtw #2] # CHECK: vldrw.u32 q0, [r0, q1, uxtw #2] @ encoding: [0x90,0xfc,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [r0, q1, uxtw #2] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1] @ encoding: [0x90,0xfc,0xd2,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [r0, q1] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [r0, q1, uxtw #3] # CHECK: vldrd.u64 q0, [r0, q1, uxtw #3] @ encoding: [0x90,0xfc,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [r0, q1, uxtw #3] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.u8 q0, [r0, q1] # CHECK: vstrb.8 q0, [r0, q1] @ encoding: [0x80,0xec,0x02,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrb.s8 q0, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q3, [r0, q1] # CHECK: vstrh.16 q3, [r0, q1] @ encoding: [0x80,0xec,0x92,0x6e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q3, [r0, q1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.u16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.s16 q0, [r0, q1, uxtw #1] # CHECK: vstrh.16 q0, [r0, q1, uxtw #1] @ encoding: [0x80,0xec,0x93,0x0e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrh.f16 q0, [r0, q1, uxtw #1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1] @ encoding: [0x80,0xec,0x42,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0, q1] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [r0, q1, uxtw #2] # CHECK: vstrw.32 q0, [r0, q1, uxtw #2] @ encoding: [0x80,0xec,0x43,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [r0, q1, uxtw #2] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q3, [r0, q1] # CHECK: vstrd.64 q3, [r0, q1] @ encoding: [0x80,0xec,0xd2,0x6f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q3, [r0, q1] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q0, [r0, q1, uxtw #3] # CHECK: vstrd.64 q0, [r0, q1, uxtw #3] @ encoding: [0x80,0xec,0xd3,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q0, [r0, q1, uxtw #3] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q0, [q1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q0, [q1] # CHECK: vldrw.u32 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q0, [q1] # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q7, [q1]! # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4] @ encoding: [0x92,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.32 q7, [q1, #4] # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.s32 q7, [q1, #4]! # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.f32 q7, [q1, #4]! # CHECK: vldrw.u32 q7, [q1, #4]! @ encoding: [0xb2,0xfd,0x01,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrw.u32 q7, [q1, #4]! # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q0, [q1] # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q0, [q1] # CHECK: vstrw.32 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1e] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q0, [q1] # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1]! # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1]! # CHECK: vstrw.32 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1]! # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #508] @ encoding: [0x82,0xfd,0x7f,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1, #508] # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.u32 q7, [q1, #264]! # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.s32 q7, [q1, #264]! # CHECK: vstrw.32 q7, [q1, #264]! @ encoding: [0xa2,0xfd,0x42,0xfe] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrw.f32 q7, [q1, #264]! # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q0, [q1] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q0, [q1] # CHECK: vldrd.u64 q0, [q1] @ encoding: [0x92,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q0, [q1] # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1]! @ encoding: [0xb2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1]! # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #8] @ encoding: [0x92,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1, #8] # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.s64 q7, [q1, #-1016]! # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.f64 q7, [q1, #-1016]! # CHECK: vldrd.u64 q7, [q1, #-1016]! @ encoding: [0x32,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vldrd.64 q7, [q1, #-1016]! # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q0, [q1] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q0, [q1] # CHECK: vstrd.64 q0, [q1] @ encoding: [0x82,0xfd,0x00,0x1f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q0, [q1] # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1]! # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1]! # CHECK: vstrd.64 q7, [q1]! @ encoding: [0xa2,0xfd,0x00,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1]! # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #1016] @ encoding: [0x82,0xfd,0x7f,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1, #1016] # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.u64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.s64 q7, [q1, #-8]! # CHECK: vstrd.64 q7, [q1, #-8]! @ encoding: [0x22,0xfd,0x01,0xff] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vstrd.f64 q7, [q1, #-8]! vpste diff --git a/llvm/test/MC/ARM/mve-misc.s b/llvm/test/MC/ARM/mve-misc.s index f3af9e0afe64f..251a77b4710dc 100644 --- a/llvm/test/MC/ARM/mve-misc.s +++ b/llvm/test/MC/ARM/mve-misc.s @@ -7,63 +7,63 @@ # RUN: FileCheck --check-prefix=ERROR-NOMVE < %t %s # CHECK: vpsel q0, q5, q2 @ encoding: [0x3b,0xfe,0x05,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpsel q0, q5, q2 # CHECK: vpnot @ encoding: [0x31,0xfe,0x4d,0x0f] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpnot # CHECK: wlstp.8 lr, r0, #1668 @ encoding: [0x00,0xf0,0x43,0xc3] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r0, #1668 # CHECK: wlstp.16 lr, r0, #1668 @ encoding: [0x10,0xf0,0x43,0xc3] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r0, #1668 # CHECK: wlstp.32 lr, r4, #2706 @ encoding: [0x24,0xf0,0x49,0xcd] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r4, #2706 # CHECK: wlstp.64 lr, lr, #3026 @ encoding: [0x3e,0xf0,0xe9,0xcd] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, lr, #3026 # CHECK: wlstp.8 lr, r5, #3436 @ encoding: [0x05,0xf0,0xb7,0xc6] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r5, #3436 # CHECK: wlstp.16 lr, r1, #1060 @ encoding: [0x11,0xf0,0x13,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r1, #1060 # CHECK: wlstp.32 lr, r7, #4036 @ encoding: [0x27,0xf0,0xe3,0xc7] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r7, #4036 # CHECK: wlstp.8 lr, r1, #538 @ encoding: [0x01,0xf0,0x0d,0xc9] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r1, #538 # CHECK: wlstp.8 lr, r10, #1404 @ encoding: [0x0a,0xf0,0xbf,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #1404 # CHECK: wlstp.8 lr, r10, #1408 @ encoding: [0x0a,0xf0,0xc1,0xc2] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #1408 # CHECK: wlstp.8 lr, r10, #2358 @ encoding: [0x0a,0xf0,0x9b,0xcc] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #2358 # CHECK: wlstp.8 lr, r10, #4086 @ encoding: [0x0a,0xf0,0xfb,0xcf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r10, #4086 # CHECK: wlstp.8 lr, r11, #1442 @ encoding: [0x0b,0xf0,0xd1,0xca] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r11, #1442 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: loop end is out of range or not a positive multiple of 2 @@ -87,39 +87,39 @@ wlstp.16 lr, sp, #1442 wlstp.32 r10, r11, #1442 # CHECK: wlstp.8 lr, r1, .Lendloop @ encoding: [0x01'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.8 lr, r1, .Lendloop # CHECK: wlstp.16 lr, r2, .Lendloop @ encoding: [0x12'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.16 lr, r2, .Lendloop # CHECK: wlstp.32 lr, r3, .Lendloop @ encoding: [0x23'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.32 lr, r3, .Lendloop # CHECK: wlstp.64 lr, r5, .Lendloop @ encoding: [0x35'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, r5, .Lendloop # CHECK: wlstp.64 lr, r5, #0 @ encoding: [0x35,0xf0,0x01,0xc0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve wlstp.64 lr, r5, #0 # CHECK: dlstp.8 lr, r5 @ encoding: [0x05,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.8 lr, r5 # CHECK: dlstp.16 lr, r5 @ encoding: [0x15,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.16 lr, r5 # CHECK: dlstp.32 lr, r7 @ encoding: [0x27,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.32 lr, r7 # CHECK: dlstp.64 lr, r2 @ encoding: [0x32,0xf0,0x01,0xe0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve dlstp.64 lr, r2 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: operand must be a register in range [r0, r12] or r14 @@ -135,15 +135,15 @@ dlstp.64 r10, r0 dlstp.64 lr, pc # CHECK: letp lr, #-2 @ encoding: [0x1f,0xf0,0x01,0xc8] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-2 # CHECK: letp lr, #-8 @ encoding: [0x1f,0xf0,0x05,0xc0] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-8 # CHECK: letp lr, #-4094 @ encoding: [0x1f,0xf0,0xff,0xcf] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, #-4094 # ERROR: [[@LINE+2]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction @@ -159,7 +159,7 @@ letp lr, #8 letp lr, #-4096 # CHECK: letp lr, .Lstartloop @ encoding: [0x1f'A',0xf0'A',0x01'A',0xc0'A'] -# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve letp lr, .Lstartloop # CHECK: lctp @ encoding: [0x0f,0xf0,0x01,0xe0] @@ -172,8 +172,11 @@ it eq # ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve lctpeq +# ERROR-NOMVE: [[@LINE+1]]:1: error: instruction requires: mve vpste +# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction vpselt.s16 q0, q1, q2 +# ERROR-NOMVE: [[@LINE+1]]:1: error: invalid instruction vpsele.i32 q0, q1, q2 # CHECK: vpste @ encoding: [0x71,0xfe,0x4d,0x8f] # CHECK: vpselt q0, q1, q2 @ encoding: [0x33,0xfe,0x05,0x0f] diff --git a/llvm/test/MC/ARM/neon-complex.s b/llvm/test/MC/ARM/neon-complex.s index 0d428b596c94c..6054a08dc82e8 100644 --- a/llvm/test/MC/ARM/neon-complex.s +++ b/llvm/test/MC/ARM/neon-complex.s @@ -29,8 +29,10 @@ // FP16-ARM: vcmla.f16 q0, q1, q2, #0 @ encoding: [0x44,0x08,0x22,0xfc] // FP16-THUMB: vcmla.f16 q0, q1, q2, #0 @ encoding: [0x22,0xfc,0x44,0x08] // NO-FP16-STDERR: :[[@LINE-3]]:{{[0-9]*}}: note: instruction requires: full half-float -// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-5]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-6]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-7]]:{{[0-9]*}}: error: instruction requires: NEON vcmla.f32 d0, d1, d2, #0 // ARM: vcmla.f32 d0, d1, d2, #0 @ encoding: [0x02,0x08,0x31,0xfc] // THUMB: vcmla.f32 d0, d1, d2, #0 @ encoding: [0x31,0xfc,0x02,0x08] @@ -39,8 +41,10 @@ vcmla.f32 q0, q1, q2, #0 // ARM: vcmla.f32 q0, q1, q2, #0 @ encoding: [0x44,0x08,0x32,0xfc] // THUMB: vcmla.f32 q0, q1, q2, #0 @ encoding: [0x32,0xfc,0x44,0x08] -// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-4]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-6]]:{{[0-9]*}}: error: instruction requires: NEON // Valid rotations vcmla.f32 d0, d1, d2, #90 @@ -83,8 +87,10 @@ // FP16-ARM: vcadd.f16 q0, q1, q2, #90 @ encoding: [0x44,0x08,0x82,0xfc] // FP16-THUMB: vcadd.f16 q0, q1, q2, #90 @ encoding: [0x82,0xfc,0x44,0x08] // NO-FP16-STDERR: :[[@LINE-3]]:{{[0-9]*}}: note: instruction requires: full half-float -// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-5]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-4]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-6]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-7]]:{{[0-9]*}}: error: instruction requires: NEON vcadd.f32 d0, d1, d2, #90 // ARM: vcadd.f32 d0, d1, d2, #90 @ encoding: [0x02,0x08,0x91,0xfc] // THUMB: vcadd.f32 d0, d1, d2, #90 @ encoding: [0x91,0xfc,0x02,0x08] @@ -93,8 +99,10 @@ vcadd.f32 q0, q1, q2, #90 // ARM: vcadd.f32 q0, q1, q2, #90 @ encoding: [0x44,0x08,0x92,0xfc] // THUMB: vcadd.f32 q0, q1, q2, #90 @ encoding: [0x92,0xfc,0x44,0x08] -// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a -// NO-NEON_STDERR: :[[@LINE-4]]:{{[0-9]*}}: error: instruction requires: NEON +// V82A: :[[@LINE-3]]:{{[0-9]*}}: error: invalid instruction, any one of the following would fix this: +// V82A: :[[@LINE-4]]:{{[0-9]*}}: note: instruction requires: mve.fp +// V82A: :[[@LINE-5]]:{{[0-9]*}}: note: instruction requires: armv8.3a +// NO-NEON_STDERR: :[[@LINE-6]]:{{[0-9]*}}: error: instruction requires: NEON // Valid rotations vcadd.f32 d0, d1, d2, #270 diff --git a/llvm/test/MC/ARM/no-mve.s b/llvm/test/MC/ARM/no-mve.s index 668db402dc66d..2435ced45a370 100644 --- a/llvm/test/MC/ARM/no-mve.s +++ b/llvm/test/MC/ARM/no-mve.s @@ -4,13 +4,13 @@ # RUN: FileCheck --check-prefix=CHECK-MVE < %t %s # CHECK-MVE: instruction requires: mve.fp -# CHECK: invalid instruction +# CHECK: instruction requires: mve.fp vcadd.f32 q1, q2, q3, #270 # CHECK-MVE: instruction requires: mve.fp -# CHECK: invalid instruction +# CHECK: instruction requires: mve.fp vadd.f32 q1, q2, q3 # CHECK-MVE: vadd.i16 q1, q2, q3 @ encoding: [0x14,0xef,0x46,0x28] -# CHECK: invalid instruction +# CHECK: instruction requires: mve vadd.i16 q1, q2, q3 diff --git a/llvm/test/MC/ARM/not-armv4.s b/llvm/test/MC/ARM/not-armv4.s index c62c50c26c31d..b65b12976f78a 100644 --- a/llvm/test/MC/ARM/not-armv4.s +++ b/llvm/test/MC/ARM/not-armv4.s @@ -1,13 +1,21 @@ @ RUN: not llvm-mc < %s -triple armv4-unknown-unknown -show-encoding 2>&1 | FileCheck %s @ PR18524 -@ CHECK: instruction requires: armv5t +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: instruction requires: armv5t +@ CHECK: note: instruction requires: thumb2 clz r4,r9 -@ CHECK: instruction requires: armv6t2 +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: instruction requires: armv6t2 +@ CHECK: note: instruction requires: thumb2 rbit r4,r9 @ CHECK: error: instruction requires: armv6t2 movw r4,#0x1234 -@ CHECK: error: instruction requires: armv6t2 + +@ CHECK: error: invalid instruction, any one of the following would fix this: +@ CHECK: note: invalid operand for instruction +@ CHECK: note: operand must be a register in range [r0, r15] +@ CHECK: note: instruction requires: armv6t2 mov r4,#0x1234 diff --git a/llvm/test/MC/ARM/register-token-source-loc.s b/llvm/test/MC/ARM/register-token-source-loc.s index afb6ba0c61a39..7560f95999e71 100644 --- a/llvm/test/MC/ARM/register-token-source-loc.s +++ b/llvm/test/MC/ARM/register-token-source-loc.s @@ -3,6 +3,9 @@ // CHECK: error: invalid instruction, any one of the following would fix this: // CHECK-NEXT: add sp, r0, #4 // CHECK-NEXT: ^ +// CHECK-NEXT: note: operand must be a register in range [r0, r7] +// CHECK-NEXT: add sp, r0, #4 +// CHECK-NEXT: ^ // CHECK-NEXT: note: operand must be a register sp // CHECK-NEXT: add sp, r0, #4 // CHECK-NEXT: ^ diff --git a/llvm/test/MC/ARM/tMOVSr.s b/llvm/test/MC/ARM/tMOVSr.s index 198c90aa5ceb4..09602fecd6851 100644 --- a/llvm/test/MC/ARM/tMOVSr.s +++ b/llvm/test/MC/ARM/tMOVSr.s @@ -1,6 +1,7 @@ @ REQUIRES: asserts -@ RUN: llvm-mc --triple=thumbv8 --debug %s 2>&1 | FileCheck %s --match-full-lines +@ RUN: llvm-mc --triple=thumbv8 %s --show-encoding 2>&1 | FileCheck %s --match-full-lines -@ CHECK: Changed to: > +// Note this makes sure the narrow instruciton is selected +@ CHECK: movs r2, r3 @ encoding: [0x1a,0x00] .text movs r2, r3 diff --git a/llvm/test/MC/ARM/thumb-diagnostics.s b/llvm/test/MC/ARM/thumb-diagnostics.s index cacd7f21cb9d3..171d60ac13f9a 100644 --- a/llvm/test/MC/ARM/thumb-diagnostics.s +++ b/llvm/test/MC/ARM/thumb-diagnostics.s @@ -28,9 +28,12 @@ @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction variant requires Thumb2 @ CHECK-ERRORS: note: operand must be a register sp -@ CHECK-ERRORS-V5: error: instruction variant requires ARMv6 or later +@ CHECK-ERRORS-V5: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS-V5: mov r2, r3 @ CHECK-ERRORS-V5: ^ +@ CHECK-ERRORS-V5: note: instruction requires: arm-mode +@ CHECK-ERRORS-V5: note: operand must be an immediate in the range [0,255] or a relocatable expression +@ CHECK-ERRORS-V5: note: instruction variant requires ARMv6 or later @ Immediates where registers were expected adds #0, r1, r2 @@ -225,10 +228,11 @@ @ Mismatched source/destination operands for MUL instruction. muls r1, r2, r3 -@ CHECK-ERRORS: error: destination register must match source register +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: muls r1, r2, r3 -@ CHECK-ERRORS: ^ - +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: destination register must match a source register +@ CHECK-ERRORS: note: too many operands for instruction @ Out of range immediates for STR instruction. str r2, [r7, #-1] @@ -274,30 +278,33 @@ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, #-1 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: invalid operand for instruction @ CHECK-ERRORS: add sp, #-1 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, #-1 -@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, #3 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: invalid operand for instruction @ CHECK-ERRORS: add sp, #3 @ CHECK-ERRORS: ^ -@ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, #3 -@ CHECK-ERRORS: ^ @ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ +@ CHECK-ERRORS: note: instruction requires: thumb2 +@ CHECK-ERRORS: add sp, sp, #512 +@ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: operand must be a register in range [r0, r15] @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ @@ -305,9 +312,6 @@ @ CHECK-ERRORS: add sp, sp, #512 @ CHECK-ERRORS: ^ @ CHECK-ERRORS: note: instruction requires: thumb2 -@ CHECK-ERRORS: add sp, sp, #512 -@ CHECK-ERRORS: ^ -@ CHECK-ERRORS: error: instruction requires: thumb2 @ CHECK-ERRORS: add r2, sp, #1024 @ CHECK-ERRORS: ^ add r2, sp, ip @@ -407,7 +411,8 @@ adds adds r0 @ CHECK-ERRORS: error: too few operands for instruction -@ CHECK-ERRORS: error: too few operands for instruction +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS: note: too few operands for instruction @------------------------------------------------------------------------------ @ Out of range width for SBFX/UBFX diff --git a/llvm/test/MC/ARM/thumb-mov.s b/llvm/test/MC/ARM/thumb-mov.s index 6f662f3ee2c72..e910722f2edf4 100644 --- a/llvm/test/MC/ARM/thumb-mov.s +++ b/llvm/test/MC/ARM/thumb-mov.s @@ -58,10 +58,16 @@ movs sp, r0 movs r0, sp movs sp, sp -// CHECK-V7: error: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs sp, r0 -// CHECK-V7: instruction variant requires ARMv8 or later +// CHECK-V7: note: instruction variant requires ARMv8 or later +// CHECK-V7: note: operand must be a register in range [r0, r7] +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs r0, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later +// CHECK-V7: note: invalid operand for instruction +// CHECK-V7: note: operand must be an immediate in the range [0,255] or a relocatable expression +// CHECK-V7: note: operand must be a register in range [r0, r7] // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs sp, sp // CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] @@ -69,8 +75,9 @@ // CHECK-V8: movs.w sp, sp @ encoding: [0x5f,0xea,0x0d,0x0d] mov.w sp, sp -// CHECK-V7: error: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: mov.w sp, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later // CHECK-V8: mov.w sp, sp @ encoding: [0x4f,0xea,0x0d,0x0d] movs.w sp, r0 @@ -78,8 +85,9 @@ movs.w sp, sp // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs.w sp, r0 -// CHECK-V7: instruction variant requires ARMv8 or later +// CHECK-V7: error: invalid instruction, any one of the following would fix this: // CHECK-V7-NEXT: movs.w r0, sp +// CHECK-V7: note: instruction variant requires ARMv8 or later // CHECK-V7: error: instruction variant requires ARMv8 or later // CHECK-V7-NEXT: movs.w sp, sp // CHECK-V8: movs.w sp, r0 @ encoding: [0x5f,0xea,0x00,0x0d] diff --git a/llvm/test/MC/ARM/thumb2-diagnostics.s b/llvm/test/MC/ARM/thumb2-diagnostics.s index 45efd3c62120c..afb12ce430981 100644 --- a/llvm/test/MC/ARM/thumb2-diagnostics.s +++ b/llvm/test/MC/ARM/thumb2-diagnostics.s @@ -156,7 +156,9 @@ foo2: adds adds r0 @ CHECK-ERRORS: error: too few operands for instruction -@ CHECK-ERRORS: error: too few operands for instruction +@ CHECK-ERRORS: error: invalid instruction, any one of the following would fix this: +@ CHECK-ERRORS: note: too few operands for instruction +@ CHECK-ERRORS: note: operand must be a register in range [r0, r15] tst sp, #3 tst sp, r5 diff --git a/llvm/test/MC/ARM/vfp4.s b/llvm/test/MC/ARM/vfp4.s index 37d03bb53de8e..f3bc5750f4312 100644 --- a/llvm/test/MC/ARM/vfp4.s +++ b/llvm/test/MC/ARM/vfp4.s @@ -23,7 +23,7 @@ vfma.f32 d16, d18, d17 @ ARM: vfma.f32 q2, q4, q0 @ encoding: [0x50,0x4c,0x08,0xf2] @ THUMB: vfma.f32 q2, q4, q0 @ encoding: [0x08,0xef,0x50,0x4c] -@ THUMB_V7EM-ERRORS: error: invalid instruction +@ THUMB_V7EM-ERRORS: error: instruction requires: mve.fp @ THUMB_V7EM-ERRORS-NEXT: vfma.f32 q2, q4, q0 vfma.f32 q2, q4, q0 @@ -57,7 +57,7 @@ vfms.f32 d16, d18, d17 @ ARM: vfms.f32 q2, q4, q0 @ encoding: [0x50,0x4c,0x28,0xf2] @ THUMB: vfms.f32 q2, q4, q0 @ encoding: [0x28,0xef,0x50,0x4c] -@ THUMB_V7EM-ERRORS: error: invalid instruction +@ THUMB_V7EM-ERRORS: error: instruction requires: mve.fp @ THUMB_V7EM-ERRORS-NEXT: vfms.f32 q2, q4, q0 vfms.f32 q2, q4, q0 diff --git a/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s b/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s index 2257e453e0a81..d686293c9b430 100644 --- a/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s +++ b/llvm/test/tools/llvm-mca/ARM/cortex-a57-basic-instructions.s @@ -1023,7 +1023,7 @@ # CHECK-NEXT: 2 2 1.00 blxne r2 # CHECK-NEXT: 2 1 1.00 U blx #32424576 # CHECK-NEXT: 2 1 1.00 U blx #16212288 -# CHECK-NEXT: 1 1 1.00 U bx r2 +# CHECK-NEXT: 1 1 1.00 bx r2 # CHECK-NEXT: 1 1 1.00 U bxne r2 # CHECK-NEXT: 1 1 1.00 U bxj r2 # CHECK-NEXT: 1 1 1.00 U bxjne r2 diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp index de273bd1a46cb..5267345ea80a4 100644 --- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp +++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp @@ -107,6 +107,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -3752,6 +3753,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " } else {\n"; OS << " DEBUG_WITH_TYPE(\"asm-matcher\", dbgs() << \"but formal " "operand not required\\n\");\n"; + OS << " if (isSubclass(Formal, OptionalMatchClass)) {\n"; + OS << " OptionalOperandsMask.set(FormalIdx);\n"; + OS << " }\n"; OS << " }\n"; OS << " continue;\n"; } else {