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 {