diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td --- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -1352,6 +1352,22 @@ def MatrixOp : MatrixOperand; +class MatrixTileListAsmOperand : AsmOperandClass { + let Name = "MatrixTileList"; + let ParserMethod = "tryParseMatrixTileList"; + let RenderMethod = "addMatrixTileListOperands"; + let PredicateMethod = "isMatrixTileList"; +} + +class MatrixTileListOperand : Operand { + let ParserMatchClass = MatrixTileListAsmOperand<>; + let DecoderMethod = "DecodeMatrixTileListRegisterClass"; + let EncoderMethod = "EncodeMatrixTileListRegisterClass"; + let PrintMethod = "printMatrixTileList"; +} + +def MatrixTileList : MatrixTileListOperand<>; + def MatrixIndexGPR32_12_15 : RegisterClass<"AArch64", [i32], 32, (sequence "W%u", 12, 15)> { let DiagnosticType = "InvalidMatrixIndexGPR32_12_15"; } diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -88,6 +88,12 @@ defm INSERT_MXIPZ : sme_vector_to_tile<"mova">; defm EXTRACT_ZPMXI : sme_tile_to_vector<"mova">; +//===----------------------------------------------------------------------===// +// Zero instruction +//===----------------------------------------------------------------------===// + +defm ZERO_M : sme_zero<"zero">; + //===----------------------------------------------------------------------===// // Mode selection and state access instructions //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" @@ -262,6 +263,7 @@ template OperandMatchResultTy tryParseVectorList(OperandVector &Operands, bool ExpectMatch = false); + OperandMatchResultTy tryParseMatrixTileList(OperandVector &Operands); OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands); OperandMatchResultTy tryParseGPR64x8(OperandVector &Operands); @@ -322,6 +324,7 @@ k_CondCode, k_Register, k_MatrixRegister, + k_MatrixTileList, k_SVCR, k_VectorList, k_VectorIndex, @@ -383,6 +386,10 @@ MatrixKind Kind; }; + struct MatrixTileListOp { + unsigned RegMask = 0; + }; + struct VectorListOp { unsigned RegNum; unsigned Count; @@ -460,6 +467,7 @@ struct TokOp Tok; struct RegOp Reg; struct MatrixRegOp MatrixReg; + struct MatrixTileListOp MatrixTileList; struct VectorListOp VectorList; struct VectorIndexOp VectorIndex; struct ImmOp Imm; @@ -512,6 +520,9 @@ case k_MatrixRegister: MatrixReg = o.MatrixReg; break; + case k_MatrixTileList: + MatrixTileList = o.MatrixTileList; + break; case k_VectorList: VectorList = o.VectorList; break; @@ -622,6 +633,11 @@ return MatrixReg.Kind; } + unsigned getMatrixTileListRegMask() const { + assert(isMatrixTileList() && "Invalid access!"); + return MatrixTileList.RegMask; + } + RegConstraintEqualityTy getRegEqualityTy() const { assert(Kind == k_Register && "Invalid access!"); return Reg.EqualityTy; @@ -1143,6 +1159,7 @@ } bool isMatrix() const { return Kind == k_MatrixRegister; } + bool isMatrixTileList() const { return Kind == k_MatrixTileList; } template bool isSVEVectorReg() const { RegKind RK; @@ -1643,6 +1660,13 @@ FirstRegs[(unsigned)RegTy][0])); } + void addMatrixTileListOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + unsigned RegMask = getMatrixTileListRegMask(); + assert(RegMask <= 0xFF && "Invalid mask!"); + Inst.addOperand(MCOperand::createImm(RegMask)); + } + void addVectorIndexOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createImm(getVectorIndex())); @@ -2012,6 +2036,45 @@ return Op; } + static std::unique_ptr + CreateMatrixTileList(unsigned RegMask, SMLoc S, SMLoc E, MCContext &Ctx) { + auto Op = std::make_unique(k_MatrixTileList, Ctx); + Op->MatrixTileList.RegMask = RegMask; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static void ComputeRegsForAlias(unsigned Reg, SmallSet &OutRegs, + const unsigned ElementWidth) { + static std::map, std::vector> + RegMap = { + {{0, AArch64::ZAB0}, + {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3, + AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}}, + {{8, AArch64::ZAB0}, + {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3, + AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}}, + {{16, AArch64::ZAH0}, + {AArch64::ZAD0, AArch64::ZAD2, AArch64::ZAD4, AArch64::ZAD6}}, + {{16, AArch64::ZAH1}, + {AArch64::ZAD1, AArch64::ZAD3, AArch64::ZAD5, AArch64::ZAD7}}, + {{32, AArch64::ZAS0}, {AArch64::ZAD0, AArch64::ZAD4}}, + {{32, AArch64::ZAS1}, {AArch64::ZAD1, AArch64::ZAD5}}, + {{32, AArch64::ZAS2}, {AArch64::ZAD2, AArch64::ZAD6}}, + {{32, AArch64::ZAS3}, {AArch64::ZAD3, AArch64::ZAD7}}, + }; + + if (ElementWidth == 64) + OutRegs.insert(Reg); + else { + std::vector Regs = RegMap[std::make_pair(ElementWidth, Reg)]; + assert(!Regs.empty() && "Invalid tile or element width!"); + for (auto OutReg : Regs) + OutRegs.insert(OutReg); + } + } + static std::unique_ptr CreateImm(const MCExpr *Val, SMLoc S, SMLoc E, MCContext &Ctx) { auto Op = std::make_unique(k_Immediate, Ctx); @@ -2235,6 +2298,15 @@ case k_MatrixRegister: OS << ""; break; + case k_MatrixTileList: { + OS << " 0; --I) + OS << ((RegMask & (1 << (I - 1))) >> (I - 1)); + OS << '>'; + break; + } case k_SVCR: { OS << getSVCR(); break; @@ -2418,6 +2490,26 @@ .Default(0); } +static unsigned matchMatrixTileListRegName(StringRef Name) { + return StringSwitch(Name.lower()) + .Case("za0.d", AArch64::ZAD0) + .Case("za1.d", AArch64::ZAD1) + .Case("za2.d", AArch64::ZAD2) + .Case("za3.d", AArch64::ZAD3) + .Case("za4.d", AArch64::ZAD4) + .Case("za5.d", AArch64::ZAD5) + .Case("za6.d", AArch64::ZAD6) + .Case("za7.d", AArch64::ZAD7) + .Case("za0.s", AArch64::ZAS0) + .Case("za1.s", AArch64::ZAS1) + .Case("za2.s", AArch64::ZAS2) + .Case("za3.s", AArch64::ZAS3) + .Case("za0.h", AArch64::ZAH0) + .Case("za1.h", AArch64::ZAH1) + .Case("za0.b", AArch64::ZAB0) + .Default(0); +} + static unsigned matchMatrixRegName(StringRef Name) { return StringSwitch(Name.lower()) .Case("za", AArch64::ZA) @@ -3763,6 +3855,120 @@ return false; } +OperandMatchResultTy +AArch64AsmParser::tryParseMatrixTileList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + + if (Parser.getTok().isNot(AsmToken::LCurly)) + return MatchOperand_NoMatch; + + auto ParseMatrixTile = [this, &Parser](unsigned &Reg, + unsigned &ElementWidth) { + StringRef Name = Parser.getTok().getString(); + size_t DotPosition = Name.find('.'); + if (DotPosition == StringRef::npos) + return MatchOperand_NoMatch; + + unsigned RegNum = matchMatrixTileListRegName(Name); + if (!RegNum) + return MatchOperand_NoMatch; + + StringRef Tail = Name.drop_front(DotPosition); + const Optional> &KindRes = + parseVectorKind(Tail, RegKind::Matrix); + if (!KindRes) { + TokError("Expected the register to be followed by element width suffix"); + return MatchOperand_ParseFail; + } + ElementWidth = KindRes->second; + Reg = RegNum; + Parser.Lex(); // Eat the register. + return MatchOperand_Success; + }; + + SMLoc S = getLoc(); + auto LCurly = Parser.getTok(); + Parser.Lex(); // Eat left bracket token. + + // Empty matrix list + if (parseOptionalToken(AsmToken::RCurly)) { + Operands.push_back(AArch64Operand::CreateMatrixTileList( + /*RegMask=*/0, S, getLoc(), getContext())); + return MatchOperand_Success; + } + + // Try parse {za} alias early + if (Parser.getTok().getString().equals_insensitive("za")) { + Parser.Lex(); // Eat 'za' + + if (parseToken(AsmToken::RCurly, "'}' expected")) + return MatchOperand_ParseFail; + + Operands.push_back(AArch64Operand::CreateMatrixTileList( + /*RegMask=*/0xFF, S, getLoc(), getContext())); + return MatchOperand_Success; + } + + SMLoc TileLoc = getLoc(); + + unsigned FirstReg, ElementWidth; + auto ParseRes = ParseMatrixTile(FirstReg, ElementWidth); + if (ParseRes != MatchOperand_Success) { + Parser.getLexer().UnLex(LCurly); + return ParseRes; + } + + const MCRegisterInfo *RI = getContext().getRegisterInfo(); + + unsigned PrevReg = FirstReg; + unsigned Count = 1; + + SmallSet DRegs; + AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth); + + SmallSet SeenRegs; + SeenRegs.insert(FirstReg); + + while (parseOptionalToken(AsmToken::Comma)) { + TileLoc = getLoc(); + unsigned Reg, NextElementWidth; + ParseRes = ParseMatrixTile(Reg, NextElementWidth); + if (ParseRes != MatchOperand_Success) + return ParseRes; + + // Element size must match on all regs in the list. + if (ElementWidth != NextElementWidth) { + Error(TileLoc, "mismatched register size suffix"); + return MatchOperand_ParseFail; + } + + if (RI->getEncodingValue(Reg) <= (RI->getEncodingValue(PrevReg))) + Warning(TileLoc, "tile list not in ascending order"); + + if (SeenRegs.contains(Reg)) + Warning(TileLoc, "duplicate tile in list"); + else { + SeenRegs.insert(Reg); + AArch64Operand::ComputeRegsForAlias(Reg, DRegs, ElementWidth); + } + + PrevReg = Reg; + ++Count; + } + + if (parseToken(AsmToken::RCurly, "'}' expected")) + return MatchOperand_ParseFail; + + unsigned RegMask = 0; + for (auto Reg : DRegs) + RegMask |= 0x1 << (RI->getEncodingValue(Reg) - + RI->getEncodingValue(AArch64::ZAD0)); + Operands.push_back( + AArch64Operand::CreateMatrixTileList(RegMask, S, getLoc(), getContext())); + + return MatchOperand_Success; +} + template OperandMatchResultTy AArch64AsmParser::tryParseVectorList(OperandVector &Operands, diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -118,6 +118,10 @@ template static DecodeStatus DecodeMatrixTile(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst &Inst, + unsigned RegMask, + uint64_t Address, + const void *Decoder); static DecodeStatus DecodePPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); @@ -704,6 +708,16 @@ return Success; } +static DecodeStatus DecodeMatrixTileListRegisterClass(MCInst &Inst, + unsigned RegMask, + uint64_t Address, + const void *Decoder) { + if (RegMask > 0xFF) + return Fail; + Inst.addOperand(MCOperand::createImm(RegMask)); + return Success; +} + static const SmallVector, 5> MatrixZATileDecoderTable = { {AArch64::ZAB0}, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h @@ -146,6 +146,9 @@ const MCSubtargetInfo &STI, raw_ostream &O, StringRef LayoutSuffix); + void printMatrixTileList(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, raw_ostream &O); + /// Print a list of vector registers where the type suffix is implicit /// (i.e. attached to the instruction rather than the registers). void printImplicitlyTypedVectorList(const MCInst *MI, unsigned OpNum, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp @@ -1340,6 +1340,36 @@ O << getRegisterName(Even) << ", " << getRegisterName(Odd); } +static const unsigned MatrixZADRegisterTable[] = { + AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3, + AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7 +}; + +void AArch64InstPrinter::printMatrixTileList(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned MaxRegs = 8; + unsigned RegMask = MI->getOperand(OpNum).getImm(); + + unsigned NumRegs = 0; + for (unsigned I = 0; I < MaxRegs; ++I) + if ((RegMask & (1 << I)) != 0) + ++NumRegs; + + O << "{"; + unsigned Printed = 0; + for (unsigned I = 0; I < MaxRegs; ++I) { + unsigned Reg = RegMask & (1 << I); + if (Reg == 0) + continue; + O << getRegisterName(MatrixZADRegisterTable[I]); + if (Printed + 1 != NumRegs) + O << ", "; + ++Printed; + } + O << "}"; +} + void AArch64InstPrinter::printVectorList(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O, diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -186,6 +186,9 @@ unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const; + uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; @@ -520,6 +523,14 @@ return MO.getImm() - 8; } +uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass( + const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + unsigned RegMask = MI.getOperand(OpIdx).getImm(); + assert(RegMask <= 0xFF && "Invalid register mask!"); + return RegMask; +} + uint32_t AArch64MCCodeEmitter::encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, diff --git a/llvm/lib/Target/AArch64/SMEInstrFormats.td b/llvm/lib/Target/AArch64/SMEInstrFormats.td --- a/llvm/lib/Target/AArch64/SMEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SMEInstrFormats.td @@ -653,6 +653,38 @@ defm _V : sme_tile_to_vector_v; } +//===----------------------------------------------------------------------===// +// SME Zero +//===----------------------------------------------------------------------===// + +class sme_zero_inst + : I<(outs MatrixTileList:$imm), (ins), + mnemonic, "\t$imm", "", []>, Sched<[]> { + bits<8> imm; + let Inst{31-8} = 0b110000000000100000000000; + let Inst{7-0} = imm; +} + +multiclass sme_zero { + def NAME : sme_zero_inst; + + def : InstAlias<"zero\t\\{za\\}", (!cast(NAME) 0b11111111), 1>; + def : InstAlias<"zero\t\\{za0.h\\}", (!cast(NAME) 0b01010101), 1>; + def : InstAlias<"zero\t\\{za1.h\\}", (!cast(NAME) 0b10101010), 1>; + def : InstAlias<"zero\t\\{za0.s\\}", (!cast(NAME) 0b00010001), 1>; + def : InstAlias<"zero\t\\{za1.s\\}", (!cast(NAME) 0b00100010), 1>; + def : InstAlias<"zero\t\\{za2.s\\}", (!cast(NAME) 0b01000100), 1>; + def : InstAlias<"zero\t\\{za3.s\\}", (!cast(NAME) 0b10001000), 1>; + def : InstAlias<"zero\t\\{za0.s,za1.s\\}", (!cast(NAME) 0b00110011), 1>; + def : InstAlias<"zero\t\\{za0.s,za3.s\\}", (!cast(NAME) 0b10011001), 1>; + def : InstAlias<"zero\t\\{za1.s,za2.s\\}", (!cast(NAME) 0b01100110), 1>; + def : InstAlias<"zero\t\\{za2.s,za3.s\\}", (!cast(NAME) 0b11001100), 1>; + def : InstAlias<"zero\t\\{za0.s,za1.s,za2.s\\}", (!cast(NAME) 0b01110111), 1>; + def : InstAlias<"zero\t\\{za0.s,za1.s,za3.s\\}", (!cast(NAME) 0b10111011), 1>; + def : InstAlias<"zero\t\\{za0.s,za2.s,za3.s\\}", (!cast(NAME) 0b11011101), 1>; + def : InstAlias<"zero\t\\{za1.s,za2.s,za3.s\\}", (!cast(NAME) 0b11101110), 1>; +} + //===----------------------------------------------------------------------===// // SVE2 Instructions //===----------------------------------------------------------------------===// diff --git a/llvm/test/MC/AArch64/SME/zero-diagnostics.s b/llvm/test/MC/AArch64/SME/zero-diagnostics.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SME/zero-diagnostics.s @@ -0,0 +1,82 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Registers list not in ascending order + +zero {za1.s, za0.s} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: tile list not in ascending order +// CHECK-NEXT: zero {za1.s, za0.s} +// CHECK-NEXT: ^ + +zero {za0.d, za1.d, za4.d, za3.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: tile list not in ascending order +// CHECK-NEXT: zero {za0.d, za1.d, za4.d, za3.d} +// CHECK-NEXT: ^ + +// --------------------------------------------------------------------------// +// Duplicate tile + +zero {za0.s, za0.s} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: duplicate tile in list +// CHECK-NEXT: zero {za0.s, za0.s} +// CHECK-NEXT: ^ + +zero {za0.d, za1.d, za2.d, za2.d, za3.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: warning: duplicate tile in list +// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za2.d, za3.d} +// CHECK-NEXT: ^ + +// --------------------------------------------------------------------------// +// Mismatched register size suffix + +zero {za0.b, za5.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: mismatched register size suffix +// CHECK-NEXT: zero {za0.b, za5.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Missing '}' + +zero {za +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: '}' expected +// CHECK-NEXT: zero {za +// CHECK-NEXT: ^ +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Invalid matrix tile + +zero {za0.b, za1.b} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za0.b, za1.b} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za2.h} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za2.h} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0.s, za1.s, za2.s, za3.s, za4.s} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za0.s, za1.s, za2.s, za3.s, za4.s} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d, za8.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d, za8.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0h.b} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za0h.b} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0.s, za1h.s} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za0.s, za1h.s} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za15.q} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid operand for instruction +// CHECK-NEXT: zero {za15.q} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SME/zero.s b/llvm/test/MC/AArch64/SME/zero.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SME/zero.s @@ -0,0 +1,250 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \ +// RUN: | llvm-objdump -d --mattr=+sme - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sme < %s \ +// RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// Disassemble encoding and check the re-encoding (-show-encoding) matches. +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sme -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + +zero {} +// CHECK-INST: zero {} +// CHECK-ENCODING: [0x00,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 00 00 08 c0 + +zero {za0.d, za2.d, za4.d, za6.d} +// CHECK-INST: zero {za0.h} +// CHECK-ENCODING: [0x55,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 55 00 08 c0 + +zero {za0.d, za1.d, za2.d, za4.d, za5.d, za7.d} +// CHECK-INST: zero {za0.d, za1.d, za2.d, za4.d, za5.d, za7.d} +// CHECK-ENCODING: [0xb7,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: b7 00 08 c0 + +zero {za0.d, za1.d, za2.d, za3.d, za4.d, za5.d, za6.d, za7.d} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +// --------------------------------------------------------------------------// +// Aliases + +zero {za} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +zero {za0.b} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +zero {za0.h} +// CHECK-INST: zero {za0.h} +// CHECK-ENCODING: [0x55,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 55 00 08 c0 + +zero {za1.h} +// CHECK-INST: zero {za1.h} +// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: aa 00 08 c0 + +zero {za0.h,za1.h} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +zero {za0.s} +// CHECK-INST: zero {za0.s} +// CHECK-ENCODING: [0x11,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 11 00 08 c0 + +zero {za1.s} +// CHECK-INST: zero {za1.s} +// CHECK-ENCODING: [0x22,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 22 00 08 c0 + +zero {za2.s} +// CHECK-INST: zero {za2.s} +// CHECK-ENCODING: [0x44,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 44 00 08 c0 + +zero {za3.s} +// CHECK-INST: zero {za3.s} +// CHECK-ENCODING: [0x88,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 88 00 08 c0 + +zero {za0.s,za1.s} +// CHECK-INST: zero {za0.s,za1.s} +// CHECK-ENCODING: [0x33,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 33 00 08 c0 + +zero {za0.s,za2.s} +// CHECK-INST: zero {za0.h} +// CHECK-ENCODING: [0x55,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 55 00 08 c0 + +zero {za0.s,za3.s} +// CHECK-INST: zero {za0.s,za3.s} +// CHECK-ENCODING: [0x99,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 99 00 08 c0 + +zero {za1.s,za2.s} +// CHECK-INST: zero {za1.s,za2.s} +// CHECK-ENCODING: [0x66,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 66 00 08 c0 + +zero {za1.s,za3.s} +// CHECK-INST: zero {za1.h} +// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: aa 00 08 c0 + +zero {za2.s,za3.s} +// CHECK-INST: zero {za2.s,za3.s} +// CHECK-ENCODING: [0xcc,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: cc 00 08 c0 + +zero {za0.s,za1.s,za2.s} +// CHECK-INST: zero {za0.s,za1.s,za2.s} +// CHECK-ENCODING: [0x77,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 77 00 08 c0 + +zero {za0.s,za1.s,za3.s} +// CHECK-INST: zero {za0.s,za1.s,za3.s} +// CHECK-ENCODING: [0xbb,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: bb 00 08 c0 + +zero {za0.s,za2.s,za3.s} +// CHECK-INST: zero {za0.s,za2.s,za3.s} +// CHECK-ENCODING: [0xdd,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: dd 00 08 c0 + +zero {za1.s,za2.s,za3.s} +// CHECK-INST: zero {za1.s,za2.s,za3.s} +// CHECK-ENCODING: [0xee,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ee 00 08 c0 + +zero {za0.s,za1.s,za2.s,za3.s} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +zero {za0.d,za1.d,za2.d,za3.d,za4.d,za5.d,za6.d,za7.d} +// CHECK-INST: zero {za} +// CHECK-ENCODING: [0xff,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ff 00 08 c0 + +zero {za0.d,za2.d,za4.d,za6.d} +// CHECK-INST: zero {za0.h} +// CHECK-ENCODING: [0x55,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 55 00 08 c0 + +zero {za1.d,za3.d,za5.d,za7.d} +// CHECK-INST: zero {za1.h} +// CHECK-ENCODING: [0xaa,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: aa 00 08 c0 + +zero {za0.d,za4.d} +// CHECK-INST: zero {za0.s} +// CHECK-ENCODING: [0x11,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 11 00 08 c0 + +zero {za1.d,za5.d} +// CHECK-INST: zero {za1.s} +// CHECK-ENCODING: [0x22,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 22 00 08 c0 + +zero {za2.d,za6.d} +// CHECK-INST: zero {za2.s} +// CHECK-ENCODING: [0x44,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 44 00 08 c0 + +zero {za3.d,za7.d} +// CHECK-INST: zero {za3.s} +// CHECK-ENCODING: [0x88,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 88 00 08 c0 + +zero {za0.d,za1.d,za4.d,za5.d} +// CHECK-INST: zero {za0.s,za1.s} +// CHECK-ENCODING: [0x33,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 33 00 08 c0 + +zero {za0.d,za3.d,za4.d,za7.d} +// CHECK-INST: zero {za0.s,za3.s} +// CHECK-ENCODING: [0x99,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 99 00 08 c0 + +zero {za1.d,za2.d,za5.d,za6.d} +// CHECK-INST: zero {za1.s,za2.s} +// CHECK-ENCODING: [0x66,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 66 00 08 c0 + +zero {za2.d,za3.d,za6.d,za7.d} +// CHECK-INST: zero {za2.s,za3.s} +// CHECK-ENCODING: [0xcc,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: cc 00 08 c0 + +zero {za0.d,za1.d,za2.d,za4.d,za5.d,za6.d} +// CHECK-INST: zero {za0.s,za1.s,za2.s} +// CHECK-ENCODING: [0x77,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: 77 00 08 c0 + +zero {za0.d,za1.d,za3.d,za4.d,za5.d,za7.d} +// CHECK-INST: zero {za0.s,za1.s,za3.s} +// CHECK-ENCODING: [0xbb,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: bb 00 08 c0 + +zero {za0.d,za2.d,za3.d,za4.d,za6.d,za7.d} +// CHECK-INST: zero {za0.s,za2.s,za3.s} +// CHECK-ENCODING: [0xdd,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: dd 00 08 c0 + +zero {za1.d,za2.d,za3.d,za5.d,za6.d,za7.d} +// CHECK-INST: zero {za1.s,za2.s,za3.s} +// CHECK-ENCODING: [0xee,0x00,0x08,0xc0] +// CHECK-ERROR: instruction requires: sme +// CHECK-UNKNOWN: ee 00 08 c0