summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/ARM/ARMInstrMVE.td134
-rw-r--r--llvm/lib/Target/ARM/ARMInstrThumb2.td4
-rw-r--r--llvm/lib/Target/ARM/ARMRegisterInfo.td9
-rw-r--r--llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp105
-rw-r--r--llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp36
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp14
-rw-r--r--llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h3
-rw-r--r--llvm/test/MC/ARM/mve-interleave.s270
-rw-r--r--llvm/test/MC/Disassembler/ARM/mve-interleave.txt267
9 files changed, 809 insertions, 33 deletions
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index 85830077b98..d5c13205f60 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -126,6 +126,33 @@ def pred_basic_fp : VCMPPredicateOperand {
let EncoderMethod = "getRestrictedCondCodeOpValue";
}
+// Register list operands for interleaving load/stores
+def VecList2QAsmOperand : AsmOperandClass {
+ let Name = "VecListTwoMQ";
+ let ParserMethod = "parseVectorList";
+ let RenderMethod = "addMVEVecListOperands";
+ let DiagnosticString = "operand must be a list of two consecutive "#
+ "q-registers in range [q0,q7]";
+}
+
+def VecList2Q : RegisterOperand<QQPR, "printMVEVectorListTwoQ"> {
+ let ParserMatchClass = VecList2QAsmOperand;
+ let PrintMethod = "printMVEVectorList<2>";
+}
+
+def VecList4QAsmOperand : AsmOperandClass {
+ let Name = "VecListFourMQ";
+ let ParserMethod = "parseVectorList";
+ let RenderMethod = "addMVEVecListOperands";
+ let DiagnosticString = "operand must be a list of four consecutive "#
+ "q-registers in range [q0,q7]";
+}
+
+def VecList4Q : RegisterOperand<QQQQPR, "printMVEVectorListFourQ"> {
+ let ParserMatchClass = VecList4QAsmOperand;
+ let PrintMethod = "printMVEVectorList<4>";
+}
+
class MVE_MI<dag oops, dag iops, InstrItinClass itin, string asm,
string ops, string cstr, list<dag> pattern>
: Thumb2XI<oops, iops, AddrModeNone, 4, itin, !strconcat(asm, "\t", ops), cstr,
@@ -3111,6 +3138,113 @@ def MVE_VMOV_rr_q : MVE_VMOV_64bit<(outs rGPR:$Rt, rGPR:$Rt2), (ins MQPR:$Qd),
// end of coproc mov
+// start of MVE interleaving load/store
+
+// Base class for the family of interleaving/deinterleaving
+// load/stores with names like VLD20.8 and VST43.32.
+class MVE_vldst24_base<bit writeback, bit fourregs, bits<2> stage, bits<2> size,
+ bit load, dag Oops, dag loadIops, dag wbIops,
+ string iname, string ops,
+ string cstr, list<dag> pattern=[]>
+ : MVE_MI<Oops, !con(loadIops, wbIops), NoItinerary, iname, ops, cstr, pattern> {
+ bits<4> VQd;
+ bits<4> Rn;
+
+ let Inst{31-22} = 0b1111110010;
+ let Inst{21} = writeback;
+ let Inst{20} = load;
+ let Inst{19-16} = Rn;
+ let Inst{15-13} = VQd{2-0};
+ let Inst{12-9} = 0b1111;
+ let Inst{8-7} = size;
+ let Inst{6-5} = stage;
+ let Inst{4-1} = 0b0000;
+ let Inst{0} = fourregs;
+
+ let mayLoad = load;
+ let mayStore = !eq(load,0);
+}
+
+// A parameter class used to encapsulate all the ways the writeback
+// variants of VLD20 and friends differ from the non-writeback ones.
+class MVE_vldst24_writeback<bit b, dag Oo, dag Io,
+ string sy="", string c="", string n=""> {
+ bit writeback = b;
+ dag Oops = Oo;
+ dag Iops = Io;
+ string syntax = sy;
+ string cstr = c;
+ string id_suffix = n;
+}
+
+// Another parameter class that encapsulates the differences between VLD2x
+// and VLD4x.
+class MVE_vldst24_nvecs<int n, list<int> s, bit b, RegisterOperand vl> {
+ int nvecs = n;
+ list<int> stages = s;
+ bit bit0 = b;
+ RegisterOperand VecList = vl;
+}
+
+// A third parameter class that distinguishes VLDnn.8 from .16 from .32.
+class MVE_vldst24_lanesize<int i, bits<2> b> {
+ int lanesize = i;
+ bits<2> sizebits = b;
+}
+
+// A base class for each direction of transfer: one for load, one for
+// store. I can't make these a fourth independent parametric tuple
+// class, because they have to take the nvecs tuple class as a
+// parameter, in order to find the right VecList operand type.
+
+class MVE_vld24_base<MVE_vldst24_nvecs n, bits<2> pat, bits<2> size,
+ MVE_vldst24_writeback wb, string iname,
+ list<dag> pattern=[]>
+ : MVE_vldst24_base<wb.writeback, n.bit0, pat, size, 1,
+ !con((outs n.VecList:$VQd), wb.Oops),
+ (ins n.VecList:$VQdSrc), wb.Iops,
+ iname, "$VQd, $Rn" # wb.syntax,
+ wb.cstr # ",$VQdSrc = $VQd", pattern>;
+
+class MVE_vst24_base<MVE_vldst24_nvecs n, bits<2> pat, bits<2> size,
+ MVE_vldst24_writeback wb, string iname,
+ list<dag> pattern=[]>
+ : MVE_vldst24_base<wb.writeback, n.bit0, pat, size, 0,
+ wb.Oops, (ins n.VecList:$VQd), wb.Iops,
+ iname, "$VQd, $Rn" # wb.syntax,
+ wb.cstr, pattern>;
+
+// Actually define all the interleaving loads and stores, by a series
+// of nested foreaches over number of vectors (VLD2/VLD4); stage
+// within one of those series (VLDx0/VLDx1/VLDx2/VLDx3); size of
+// vector lane; writeback or no writeback.
+foreach n = [MVE_vldst24_nvecs<2, [0,1], 0, VecList2Q>,
+ MVE_vldst24_nvecs<4, [0,1,2,3], 1, VecList4Q>] in
+foreach stage = n.stages in
+foreach s = [MVE_vldst24_lanesize< 8, 0b00>,
+ MVE_vldst24_lanesize<16, 0b01>,
+ MVE_vldst24_lanesize<32, 0b10>] in
+foreach wb = [MVE_vldst24_writeback<
+ 1, (outs rGPR:$wb), (ins t2_nosp_addr_offset_none:$Rn),
+ "!", "$Rn.base = $wb", "_wb">,
+ MVE_vldst24_writeback<0, (outs), (ins t2_addr_offset_none:$Rn)>] in {
+
+ // For each case within all of those foreaches, define the actual
+ // instructions. The def names are made by gluing together pieces
+ // from all the parameter classes, and will end up being things like
+ // MVE_VLD20_8 and MVE_VST43_16_wb.
+
+ def "MVE_VLD" # n.nvecs # stage # "_" # s.lanesize # wb.id_suffix
+ : MVE_vld24_base<n, stage, s.sizebits, wb,
+ "vld" # n.nvecs # stage # "." # s.lanesize>;
+
+ def "MVE_VST" # n.nvecs # stage # "_" # s.lanesize # wb.id_suffix
+ : MVE_vst24_base<n, stage, s.sizebits, wb,
+ "vst" # n.nvecs # stage # "." # s.lanesize>;
+}
+
+// end of MVE interleaving load/store
+
class MVE_VPT<string suffix, bits<2> size, dag iops, string asm, list<dag> pattern=[]>
: MVE_MI<(outs ), iops, NoItinerary, !strconcat("vpt", "${Mk}", ".", suffix), asm, "", pattern> {
bits<3> fc;
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb2.td b/llvm/lib/Target/ARM/ARMInstrThumb2.td
index 61e157ba986..8ca710cb468 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb2.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb2.td
@@ -176,9 +176,9 @@ def MemNoOffsetT2NoSpAsmOperand
: AsmOperandClass { let Name = "MemNoOffsetT2NoSp"; }
def t2_nosp_addr_offset_none : MemOperand {
let PrintMethod = "printAddrMode7Operand";
- let DecoderMethod = "Decodet2rGPRRegisterClass";
+ let DecoderMethod = "DecoderGPRRegisterClass";
let ParserMatchClass = MemNoOffsetT2NoSpAsmOperand;
- let MIOperandInfo = (ops t2rGPR:$base);
+ let MIOperandInfo = (ops rGPR:$base);
}
// t2addrmode_imm12 := reg + imm12
diff --git a/llvm/lib/Target/ARM/ARMRegisterInfo.td b/llvm/lib/Target/ARM/ARMRegisterInfo.td
index 1322ed5577b..fc0286e724d 100644
--- a/llvm/lib/Target/ARM/ARMRegisterInfo.td
+++ b/llvm/lib/Target/ARM/ARMRegisterInfo.td
@@ -296,15 +296,6 @@ def rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
let DiagnosticType = "rGPR";
}
-// t2rGPR : All Thumb 2 registers with the exception of SP and PC.
-def t2rGPR : RegisterClass<"ARM", [i32], 32, (sub GPR, SP, PC)> {
- let AltOrders = [(add LR, t2rGPR), (trunc t2rGPR, 8)];
- let AltOrderSelect = [{
- return 1 + MF.getSubtarget<ARMSubtarget>().isThumb1Only();
- }];
- let DiagnosticType = "rGPR";
-}
-
// Thumb registers are R0-R7 normally. Some instructions can still use
// the general GPR register class above (MOV, e.g.)
def tGPR : RegisterClass<"ARM", [i32], 32, (trunc GPR, 8)> {
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 8ecdb139a04..6b5e77f81ce 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -1759,6 +1759,12 @@ public:
return VectorList.Count == 1;
}
+ bool isVecListTwoMQ() const {
+ return isSingleSpacedVectorList() && VectorList.Count == 2 &&
+ ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(
+ VectorList.RegNum);
+ }
+
bool isVecListDPair() const {
if (!isSingleSpacedVectorList()) return false;
return (ARMMCRegisterClasses[ARM::DPairRegClassID]
@@ -1792,6 +1798,12 @@ public:
return VectorList.Count == 4;
}
+ bool isVecListFourMQ() const {
+ return isSingleSpacedVectorList() && VectorList.Count == 4 &&
+ ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(
+ VectorList.RegNum);
+ }
+
bool isSingleSpacedVectorAllLanes() const {
return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
}
@@ -2550,6 +2562,11 @@ public:
Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
}
+ void addMemNoOffsetT2NoSpOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::createReg(Memory.BaseRegNum));
+ }
+
void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
int32_t Imm = Memory.OffsetImm->getValue();
@@ -2973,6 +2990,37 @@ public:
Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
}
+ void addMVEVecListOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+
+ // When we come here, the VectorList field will identify a range
+ // of q-registers by its base register and length, and it will
+ // have already been error-checked to be the expected length of
+ // range and contain only q-regs in the range q0-q7. So we can
+ // count on the base register being in the range q0-q6 (for 2
+ // regs) or q0-q4 (for 4)
+ //
+ // The MVE instructions taking a register range of this kind will
+ // need an operand in the QQPR or QQQQPR class, representing the
+ // entire range as a unit. So we must translate into that class,
+ // by finding the index of the base register in the MQPR reg
+ // class, and returning the super-register at the corresponding
+ // index in the target class.
+
+ const MCRegisterClass *RC_in = &ARMMCRegisterClasses[ARM::MQPRRegClassID];
+ const MCRegisterClass *RC_out = (VectorList.Count == 2) ?
+ &ARMMCRegisterClasses[ARM::QQPRRegClassID] :
+ &ARMMCRegisterClasses[ARM::QQQQPRRegClassID];
+
+ unsigned I, E = RC_out->getNumRegs();
+ for (I = 0; I < E; I++)
+ if (RC_in->getRegister(I) == VectorList.RegNum)
+ break;
+ assert(I < E && "Invalid vector list start register!");
+
+ Inst.addOperand(MCOperand::createReg(RC_out->getRegister(I)));
+ }
+
void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
Inst.addOperand(MCOperand::createReg(VectorList.RegNum));
@@ -4257,7 +4305,7 @@ 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 (Parser.getTok().is(AsmToken::Identifier)) {
+ if (!hasMVE() && Parser.getTok().is(AsmToken::Identifier)) {
SMLoc E = Parser.getTok().getEndLoc();
int Reg = tryParseRegister();
if (Reg == -1)
@@ -4325,9 +4373,14 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) {
unsigned Count = 1;
int Spacing = 0;
unsigned FirstReg = Reg;
+
+ if (hasMVE() && !ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) {
+ Error(Parser.getTok().getLoc(), "vector register in range Q0-Q7 expected");
+ return MatchOperand_ParseFail;
+ }
// The list is of D registers, but we also allow Q regs and just interpret
// them as the two D sub-registers.
- if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
+ else if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
FirstReg = Reg = getDRegFromQReg(Reg);
Spacing = 1; // double-spacing requires explicit D registers, otherwise
// it's ambiguous with four-register single spaced.
@@ -4357,14 +4410,17 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) {
return MatchOperand_ParseFail;
}
// Allow Q regs and just interpret them as the two D sub-registers.
- if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
+ if (!hasMVE() && ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
EndReg = getDRegFromQReg(EndReg) + 1;
// If the register is the same as the start reg, there's nothing
// more to do.
if (Reg == EndReg)
continue;
// The register must be in the same register class as the first.
- if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
+ if ((hasMVE() &&
+ !ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(EndReg)) ||
+ (!hasMVE() &&
+ !ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg))) {
Error(AfterMinusLoc, "invalid register in register list");
return MatchOperand_ParseFail;
}
@@ -4397,13 +4453,21 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) {
Error(RegLoc, "register expected");
return MatchOperand_ParseFail;
}
+
+ if (hasMVE()) {
+ if (!ARMMCRegisterClasses[ARM::MQPRRegClassID].contains(Reg)) {
+ Error(RegLoc, "vector register in range Q0-Q7 expected");
+ return MatchOperand_ParseFail;
+ }
+ Spacing = 1;
+ }
// vector register lists must be contiguous.
// It's OK to use the enumeration values directly here rather, as the
// VFP register classes have the enum sorted properly.
//
// The list is of D registers, but we also allow Q regs and just interpret
// them as the two D sub-registers.
- if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
+ else if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
if (!Spacing)
Spacing = 1; // Register range implies a single spaced list.
else if (Spacing == 2) {
@@ -4464,30 +4528,20 @@ ARMAsmParser::parseVectorList(OperandVector &Operands) {
switch (LaneKind) {
case NoLanes:
+ case AllLanes: {
// Two-register operands have been converted to the
// composite register classes.
- if (Count == 2) {
- const MCRegisterClass *RC = (Spacing == 1) ?
- &ARMMCRegisterClasses[ARM::DPairRegClassID] :
- &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
- FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
- }
- Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
- (Spacing == 2), S, E));
- break;
- case AllLanes:
- // Two-register operands have been converted to the
- // composite register classes.
- if (Count == 2) {
+ if (Count == 2 && !hasMVE()) {
const MCRegisterClass *RC = (Spacing == 1) ?
&ARMMCRegisterClasses[ARM::DPairRegClassID] :
&ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
}
- Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
- (Spacing == 2),
- S, E));
+ auto Create = (LaneKind == NoLanes ? ARMOperand::CreateVectorList :
+ ARMOperand::CreateVectorListAllLanes);
+ Operands.push_back(Create(FirstReg, Count, (Spacing == 2), S, E));
break;
+ }
case IndexedLane:
Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
LaneIndex,
@@ -6127,7 +6181,10 @@ void ARMAsmParser::getMnemonicAcceptInfo(StringRef Mnemonic,
Mnemonic == "csinc" || Mnemonic == "csinv" || Mnemonic == "csneg" ||
Mnemonic == "cinc" || Mnemonic == "cinv" || Mnemonic == "cneg" ||
Mnemonic == "cset" || Mnemonic == "csetm" ||
- Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst")) {
+ Mnemonic.startswith("vpt") || Mnemonic.startswith("vpst") ||
+ (hasMVE() &&
+ (Mnemonic.startswith("vst2") || Mnemonic.startswith("vld2") ||
+ Mnemonic.startswith("vst4") || Mnemonic.startswith("vld4")))) {
// These mnemonics are never predicable
CanAcceptPredicationCode = false;
} else if (!isThumb()) {
@@ -6385,6 +6442,10 @@ bool ARMAsmParser::shouldOmitVectorPredicateOperand(StringRef Mnemonic,
if (!hasMVE() || Operands.size() < 3)
return true;
+ if (Mnemonic.startswith("vld2") || Mnemonic.startswith("vld4") ||
+ Mnemonic.startswith("vst2") || Mnemonic.startswith("vst4"))
+ return true;
+
if (Mnemonic.startswith("vctp"))
return false;
diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
index acabfd32cd7..7ccf37ef0e6 100644
--- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
+++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
@@ -220,6 +220,10 @@ static DecodeStatus DecodeQPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeMQPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeQQPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
+static DecodeStatus DecodeQQQQPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPairRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder);
static DecodeStatus DecodeDPairSpacedRegisterClass(MCInst &Inst,
@@ -5940,6 +5944,38 @@ static DecodeStatus DecodeMQPRRegisterClass(MCInst &Inst, unsigned RegNo,
return MCDisassembler::Success;
}
+static const uint16_t QQPRDecoderTable[] = {
+ ARM::Q0_Q1, ARM::Q1_Q2, ARM::Q2_Q3, ARM::Q3_Q4,
+ ARM::Q4_Q5, ARM::Q5_Q6, ARM::Q6_Q7
+};
+
+static DecodeStatus DecodeQQPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 6)
+ return MCDisassembler::Fail;
+
+ unsigned Register = QQPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return MCDisassembler::Success;
+}
+
+static const uint16_t QQQQPRDecoderTable[] = {
+ ARM::Q0_Q1_Q2_Q3, ARM::Q1_Q2_Q3_Q4, ARM::Q2_Q3_Q4_Q5,
+ ARM::Q3_Q4_Q5_Q6, ARM::Q4_Q5_Q6_Q7
+};
+
+static DecodeStatus DecodeQQQQPRRegisterClass(MCInst &Inst, unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 4)
+ return MCDisassembler::Fail;
+
+ unsigned Register = QQQQPRDecoderTable[RegNo];
+ Inst.addOperand(MCOperand::createReg(Register));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeVPTMaskOperand(MCInst &Inst, unsigned Val,
uint64_t Address,
const void *Decoder) {
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
index f85c8ee774e..72600c9209a 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.cpp
@@ -1588,6 +1588,20 @@ void ARMInstPrinter::printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
O << "}";
}
+template<unsigned NumRegs>
+void ARMInstPrinter::printMVEVectorList(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI,
+ raw_ostream &O) {
+ unsigned Reg = MI->getOperand(OpNum).getReg();
+ const char *Prefix = "{";
+ for (unsigned i = 0; i < NumRegs; i++) {
+ O << Prefix;
+ printRegName(O, MRI.getSubReg(Reg, ARM::qsub_0 + i));
+ Prefix = ", ";
+ }
+ O << "}";
+}
+
template<int64_t Angle, int64_t Remainder>
void ARMInstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
const MCSubtargetInfo &STI,
diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
index 2805f7b58d1..4230ee975e7 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMInstPrinter.h
@@ -243,6 +243,9 @@ public:
const MCSubtargetInfo &STI, raw_ostream &O);
void printVectorListFourSpaced(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
+ template<unsigned NumRegs>
+ void printMVEVectorList(const MCInst *MI, unsigned OpNum,
+ const MCSubtargetInfo &STI, raw_ostream &O);
template<int64_t Angle, int64_t Remainder>
void printComplexRotationOp(const MCInst *MI, unsigned OpNum,
const MCSubtargetInfo &STI, raw_ostream &O);
diff --git a/llvm/test/MC/ARM/mve-interleave.s b/llvm/test/MC/ARM/mve-interleave.s
new file mode 100644
index 00000000000..a2f7d054419
--- /dev/null
+++ b/llvm/test/MC/ARM/mve-interleave.s
@@ -0,0 +1,270 @@
+# RUN: not llvm-mc -triple=thumbv8.1m.main-none-eabi -mattr=+mve -show-encoding < %s 2> %t \
+# RUN: | FileCheck --check-prefix=CHECK %s
+# RUN: FileCheck --check-prefix=ERROR < %t %s
+
+# CHECK: vld20.8 {q0, q1}, [sp] @ encoding: [0x9d,0xfc,0x00,0x1e]
+vld20.8 {q0, q1}, [sp]
+
+# CHECK: vld20.8 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x00,0x1e]
+vld20.8 {q0, q1}, [r0]
+
+# CHECK: vld20.8 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x00,0x1e]
+vld20.8 {q0, q1}, [r0]!
+
+# CHECK: vld20.8 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x00,0x1e]
+vld20.8 {q0, q1}, [r11]
+
+# CHECK: vld20.8 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x00,0xbe]
+vld20.8 {q5, q6}, [r0]!
+
+# CHECK: vld21.8 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x20,0x1e]
+vld21.8 {q0, q1}, [r0]
+
+# CHECK: vld21.8 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0x20,0x7e]
+vld21.8 {q3, q4}, [r0]!
+
+# CHECK: vld20.16 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x80,0x1e]
+vld20.16 {q0, q1}, [r0]
+
+# CHECK: vld20.16 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x80,0x1e]
+vld20.16 {q0, q1}, [r0]!
+
+# CHECK: vld20.16 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x80,0x1e]
+vld20.16 {q0, q1}, [r11]
+
+# CHECK: vld20.16 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x80,0xbe]
+vld20.16 {q5, q6}, [r0]!
+
+# CHECK: vld21.16 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0xa0,0x1e]
+vld21.16 {q0, q1}, [r0]
+
+# CHECK: vld21.16 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0xa0,0x7e]
+vld21.16 {q3, q4}, [r0]!
+
+# CHECK: vld20.32 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x00,0x1f]
+vld20.32 {q0, q1}, [r0]
+
+# CHECK: vld20.32 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x00,0x1f]
+vld20.32 {q0, q1}, [r0]!
+
+# CHECK: vld20.32 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x00,0x1f]
+vld20.32 {q0, q1}, [r11]
+
+# CHECK: vld20.32 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x00,0xbf]
+vld20.32 {q5, q6}, [r0]!
+
+# CHECK: vld21.32 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x20,0x1f]
+vld21.32 {q0, q1}, [r0]
+
+# CHECK: vld21.32 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0x20,0x7f]
+vld21.32 {q3, q4}, [r0]!
+
+# CHECK: vst20.8 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x00,0x1e]
+vst20.8 {q0, q1}, [r0]
+
+# CHECK: vst20.8 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x00,0x1e]
+vst20.8 {q0, q1}, [r0]!
+
+# CHECK: vst20.8 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x00,0x1e]
+vst20.8 {q0, q1}, [r11]
+
+# CHECK: vst20.8 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x00,0xbe]
+vst20.8 {q5, q6}, [r0]!
+
+# CHECK: vst21.8 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x20,0x1e]
+vst21.8 {q0, q1}, [r0]
+
+# CHECK: vst21.8 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0x20,0x7e]
+vst21.8 {q3, q4}, [r0]!
+
+# CHECK: vst20.16 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x80,0x1e]
+vst20.16 {q0, q1}, [r0]
+
+# CHECK: vst20.16 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x80,0x1e]
+vst20.16 {q0, q1}, [r0]!
+
+# CHECK: vst20.16 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x80,0x1e]
+vst20.16 {q0, q1}, [r11]
+
+# CHECK: vst20.16 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x80,0xbe]
+vst20.16 {q5, q6}, [r0]!
+
+# CHECK: vst21.16 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0xa0,0x1e]
+vst21.16 {q0, q1}, [r0]
+
+# CHECK: vst21.16 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0xa0,0x7e]
+vst21.16 {q3, q4}, [r0]!
+
+# CHECK: vst20.32 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x00,0x1f]
+vst20.32 {q0, q1}, [r0]
+
+# CHECK: vst20.32 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x00,0x1f]
+vst20.32 {q0, q1}, [r0]!
+
+# CHECK: vst20.32 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x00,0x1f]
+vst20.32 {q0, q1}, [r11]
+
+# CHECK: vst20.32 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x00,0xbf]
+vst20.32 {q5, q6}, [r0]!
+
+# CHECK: vst21.32 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x20,0x1f]
+vst21.32 {q0, q1}, [r0]
+
+# CHECK: vst21.32 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0x20,0x7f]
+vst21.32 {q3, q4}, [r0]!
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld20.8 {q0, q1}, [sp]!
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld20.64 {q0, q1}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: non-contiguous register range
+vld20.32 {q0, q2}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a list of two consecutive q-registers in range [q0,q7]
+vld20.32 {q0, q1, q2}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a list of two consecutive q-registers in range [q0,q7]
+vld20.32 {q0}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid instruction
+vld20.32 q0, q1, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: vector register in range Q0-Q7 expected
+vld20.32 {q7, q8}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: vector register in range Q0-Q7 expected
+vld20.32 {d0, d1}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid instruction
+vld22.32 {q0, q1}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld20.32 {q0, q1}, [pc]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld20.32 {q0, q1}, [r0, #4]
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x01,0x1e]
+vld40.8 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x1e]
+vld40.8 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x01,0x1e]
+vld40.8 {q0, q1, q2, q3}, [r11]
+
+# CHECK: vld40.8 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x7e]
+vld40.8 {q3, q4, q5, q6}, [r0]!
+
+# CHECK: vld41.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x21,0x1e]
+vld41.8 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld41.8 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x21,0x9e]
+vld41.8 {q4, q5, q6, q7}, [r0]!
+
+# CHECK: vld42.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x41,0x1e]
+vld42.8 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld42.8 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x41,0x1e]
+vld42.8 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld43.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x61,0x1e]
+vld43.8 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld43.8 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x61,0x9e]
+vld43.8 {q4, q5, q6, q7}, [r0]!
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x81,0x1e]
+vld40.16 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x81,0x1e]
+vld40.16 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x81,0x1e]
+vld40.16 {q0, q1, q2, q3}, [r11]
+
+# CHECK: vld40.16 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x81,0x7e]
+vld40.16 {q3, q4, q5, q6}, [r0]!
+
+# CHECK: vld41.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xa1,0x1e]
+vld41.16 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld41.16 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0xa1,0x9e]
+vld41.16 {q4, q5, q6, q7}, [r0]!
+
+# CHECK: vld42.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xc1,0x1e]
+vld42.16 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld42.16 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0xc1,0x1e]
+vld42.16 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld43.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xe1,0x1e]
+vld43.16 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld43.16 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0xe1,0x9e]
+vld43.16 {q4, q5, q6, q7}, [r0]!
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x01,0x1f]
+vld40.32 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x1f]
+vld40.32 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x01,0x1f]
+vld40.32 {q0, q1, q2, q3}, [r11]
+
+# CHECK: vld40.32 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x7f]
+vld40.32 {q3, q4, q5, q6}, [r0]!
+
+# CHECK: vld41.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x21,0x1f]
+vld41.32 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld41.32 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x21,0x9f]
+vld41.32 {q4, q5, q6, q7}, [r0]!
+
+# CHECK: vld42.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x41,0x1f]
+vld42.32 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld42.32 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x41,0x1f]
+vld42.32 {q0, q1, q2, q3}, [r0]!
+
+# CHECK: vld43.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x61,0x1f]
+vld43.32 {q0, q1, q2, q3}, [r0]
+
+# CHECK: vld43.32 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x61,0x9f]
+vld43.32 {q4, q5, q6, q7}, [r0]!
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld40.64 {q0, q1, q2, q3}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: non-contiguous register range
+vld40.32 {q0, q2, q3, q4}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a list of four consecutive q-registers in range [q0,q7]
+vld40.32 {q0, q1, q2, q3, q4}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a list of four consecutive q-registers in range [q0,q7]
+vld40.32 {q0, q1}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: operand must be a list of four consecutive q-registers in range [q0,q7]
+vld40.32 {q0, q1, q2}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid instruction
+vld40.32 q0, q1, q2, q3, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: vector register in range Q0-Q7 expected
+vld40.32 {q5, q6, q7, q8}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: vector register in range Q0-Q7 expected
+vld40.32 {d0, d1, d2, d3}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid instruction
+vld44.32 {q0, q1, q2, q3}, [r0]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld40.32 {q0, q1, q2, q3}, [pc]
+
+# ERROR: [[@LINE+1]]:{{[0-9]+}}: {{error|note}}: invalid operand for instruction
+vld40.32 {q0, q1, q2, q3}, [r0, #4]
diff --git a/llvm/test/MC/Disassembler/ARM/mve-interleave.txt b/llvm/test/MC/Disassembler/ARM/mve-interleave.txt
new file mode 100644
index 00000000000..1d4232c3b38
--- /dev/null
+++ b/llvm/test/MC/Disassembler/ARM/mve-interleave.txt
@@ -0,0 +1,267 @@
+# RUN: llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -mattr=+mve -show-encoding %s | FileCheck %s
+# RUN: not llvm-mc -disassemble -triple=thumbv8.1m.main-none-eabi -show-encoding %s &> %t
+# RUN: FileCheck --check-prefix=CHECK-NOMVE < %t %s
+
+# CHECK: vld20.8 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x00,0x1e]
+
+# CHECK: vld20.8 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x00,0x1e]
+
+# CHECK: vld20.8 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x00,0x1e]
+
+# CHECK: vld20.8 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x00,0xbe]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x00,0xbe]
+
+# CHECK: vld21.8 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x20,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x20,0x1e]
+
+# CHECK: vld21.8 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0x20,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x20,0x7e]
+
+# CHECK: vld20.16 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x80,0x1e]
+
+# CHECK: vld20.16 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x80,0x1e]
+
+# CHECK: vld20.16 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x80,0x1e]
+
+# CHECK: vld20.16 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x80,0xbe]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x80,0xbe]
+
+# CHECK: vld21.16 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0xa0,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0xa0,0x1e]
+
+# CHECK: vld21.16 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0xa0,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0xa0,0x7e]
+
+# CHECK: vld20.32 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x00,0x1f]
+
+# CHECK: vld20.32 {q0, q1}, [r0]! @ encoding: [0xb0,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x00,0x1f]
+
+# CHECK: vld20.32 {q0, q1}, [r11] @ encoding: [0x9b,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x00,0x1f]
+
+# CHECK: vld20.32 {q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x00,0xbf]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x00,0xbf]
+
+# CHECK: vld21.32 {q0, q1}, [r0] @ encoding: [0x90,0xfc,0x20,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x20,0x1f]
+
+# CHECK: vld21.32 {q3, q4}, [r0]! @ encoding: [0xb0,0xfc,0x20,0x7f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x20,0x7f]
+
+# CHECK: vst20.8 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0x00,0x1e]
+
+# CHECK: vst20.8 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x00,0x1e]
+
+# CHECK: vst20.8 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x00,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x8b,0xfc,0x00,0x1e]
+
+# CHECK: vst20.8 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x00,0xbe]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x00,0xbe]
+
+# CHECK: vst21.8 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x20,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0x20,0x1e]
+
+# CHECK: vst21.8 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0x20,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x20,0x7e]
+
+# CHECK: vst20.16 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0x80,0x1e]
+
+# CHECK: vst20.16 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x80,0x1e]
+
+# CHECK: vst20.16 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x80,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x8b,0xfc,0x80,0x1e]
+
+# CHECK: vst20.16 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x80,0xbe]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x80,0xbe]
+
+# CHECK: vst21.16 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0xa0,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0xa0,0x1e]
+
+# CHECK: vst21.16 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0xa0,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0xa0,0x7e]
+
+# CHECK: vst20.32 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0x00,0x1f]
+
+# CHECK: vst20.32 {q0, q1}, [r0]! @ encoding: [0xa0,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x00,0x1f]
+
+# CHECK: vst20.32 {q0, q1}, [r11] @ encoding: [0x8b,0xfc,0x00,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x8b,0xfc,0x00,0x1f]
+
+# CHECK: vst20.32 {q5, q6}, [r0]! @ encoding: [0xa0,0xfc,0x00,0xbf]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x00,0xbf]
+
+# CHECK: vst21.32 {q0, q1}, [r0] @ encoding: [0x80,0xfc,0x20,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x80,0xfc,0x20,0x1f]
+
+# CHECK: vst21.32 {q3, q4}, [r0]! @ encoding: [0xa0,0xfc,0x20,0x7f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xa0,0xfc,0x20,0x7f]
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x01,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x01,0x1e]
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x01,0x1e]
+
+# CHECK: vld40.8 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x01,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x01,0x1e]
+
+# CHECK: vld40.8 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x01,0x7e]
+
+# CHECK: vld41.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x21,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x21,0x1e]
+
+# CHECK: vld41.8 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x21,0x9e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x21,0x9e]
+
+# CHECK: vld42.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x41,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x41,0x1e]
+
+# CHECK: vld42.8 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x41,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x41,0x1e]
+
+# CHECK: vld43.8 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x61,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x61,0x1e]
+
+# CHECK: vld43.8 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x61,0x9e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x61,0x9e]
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x81,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x81,0x1e]
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x81,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x81,0x1e]
+
+# CHECK: vld40.16 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x81,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x81,0x1e]
+
+# CHECK: vld40.16 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x81,0x7e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x81,0x7e]
+
+# CHECK: vld41.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xa1,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0xa1,0x1e]
+
+# CHECK: vld41.16 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0xa1,0x9e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0xa1,0x9e]
+
+# CHECK: vld42.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xc1,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0xc1,0x1e]
+
+# CHECK: vld42.16 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0xc1,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0xc1,0x1e]
+
+# CHECK: vld43.16 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0xe1,0x1e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0xe1,0x1e]
+
+# CHECK: vld43.16 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0xe1,0x9e]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0xe1,0x9e]
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x01,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x01,0x1f]
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x01,0x1f]
+
+# CHECK: vld40.32 {q0, q1, q2, q3}, [r11] @ encoding: [0x9b,0xfc,0x01,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x9b,0xfc,0x01,0x1f]
+
+# CHECK: vld40.32 {q3, q4, q5, q6}, [r0]! @ encoding: [0xb0,0xfc,0x01,0x7f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x01,0x7f]
+
+# CHECK: vld41.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x21,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x21,0x1f]
+
+# CHECK: vld41.32 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x21,0x9f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x21,0x9f]
+
+# CHECK: vld42.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x41,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x41,0x1f]
+
+# CHECK: vld42.32 {q0, q1, q2, q3}, [r0]! @ encoding: [0xb0,0xfc,0x41,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x41,0x1f]
+
+# CHECK: vld43.32 {q0, q1, q2, q3}, [r0] @ encoding: [0x90,0xfc,0x61,0x1f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0x90,0xfc,0x61,0x1f]
+
+# CHECK: vld43.32 {q4, q5, q6, q7}, [r0]! @ encoding: [0xb0,0xfc,0x61,0x9f]
+# CHECK-NOMVE: [[@LINE+1]]:2: warning: invalid instruction encoding
+[0xb0,0xfc,0x61,0x9f]
OpenPOWER on IntegriCloud