Index: llvm/lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64RegisterInfo.td +++ llvm/lib/Target/AArch64/AArch64RegisterInfo.td @@ -1352,6 +1352,26 @@ def MatrixOp : MatrixOperand; +class MatrixTileListAsmOperand : AsmOperandClass { + let Name = "MatrixTileList" # EltSize; + let ParserMethod = "tryParseMatrixTileList"; + let RenderMethod = "addMatrixTileListOperands"; + let PredicateMethod = "isMatrixTileListOperand<" # EltSize # ">"; +} + +class MatrixTileListOperand : Operand { + let ParserMatchClass = MatrixTileListAsmOperand; + let DecoderMethod = "DecodeMatrixTileListRegisterClass"; + let EncoderMethod = "EncodeMatrixTileListRegisterClass"; + let PrintMethod = "printMatrixTileList<" # EltSize # ">"; + let MIOperandInfo = ops; +} + +def MatrixTileList8 : MatrixTileListOperand<"MPR8", 8, (ops MPR8)>; +def MatrixTileList16 : MatrixTileListOperand<"MPR16", 16, (ops MPR16)>; +def MatrixTileList32 : MatrixTileListOperand<"MPR32", 32, (ops MPR32)>; +def MatrixTileList64 : MatrixTileListOperand<"MPR64", 64, (ops MPR64)>; + def MatrixIndexGPR32_12_15 : RegisterClass<"AArch64", [i32], 32, (sequence "W%u", 12, 15)>; def MatrixIndexGPR32Op12_15 : RegisterOperand { let EncoderMethod = "EncodeMatrixIndexGPR32"; Index: llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -88,4 +88,10 @@ defm INSERT_MXIPZ : sme_vector_to_tile<"mova">; defm EXTRACT_ZPMXI : sme_tile_to_vector<"mova">; +//===----------------------------------------------------------------------===// +// Zero instruction +//===----------------------------------------------------------------------===// + +defm ZERO_M : sme_zero<"zero">; + } // End let Predicates = [HasSME] Index: llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ 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" @@ -261,6 +262,7 @@ template OperandMatchResultTy tryParseVectorList(OperandVector &Operands, bool ExpectMatch = false); + OperandMatchResultTy tryParseMatrixTileList(OperandVector &Operands); OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands); OperandMatchResultTy tryParseGPR64x8(OperandVector &Operands); @@ -321,6 +323,7 @@ k_CondCode, k_Register, k_MatrixRegister, + k_MatrixTileList, k_VectorList, k_VectorIndex, k_Token, @@ -381,6 +384,11 @@ MatrixKind Kind; }; + struct MatrixTileListOp { + unsigned RegMask = 0; + unsigned ElementWidth; + }; + struct VectorListOp { unsigned RegNum; unsigned Count; @@ -452,6 +460,7 @@ struct TokOp Tok; struct RegOp Reg; struct MatrixRegOp MatrixReg; + struct MatrixTileListOp MatrixTileList; struct VectorListOp VectorList; struct VectorIndexOp VectorIndex; struct ImmOp Imm; @@ -503,6 +512,9 @@ case k_MatrixRegister: MatrixReg = o.MatrixReg; break; + case k_MatrixTileList: + MatrixTileList = o.MatrixTileList; + break; case k_VectorList: VectorList = o.VectorList; break; @@ -610,6 +622,16 @@ return MatrixReg.Kind; } + unsigned getMatrixTileListRegMask() const { + assert(isMatrixTileList() && "Invalid access!"); + return MatrixTileList.RegMask; + } + + unsigned getMatrixTileListElementWidth() const { + assert(isMatrixTileList() && "Invalid access!"); + return MatrixTileList.ElementWidth; + } + RegConstraintEqualityTy getRegEqualityTy() const { assert(Kind == k_Register && "Invalid access!"); return Reg.EqualityTy; @@ -1120,6 +1142,7 @@ } bool isMatrix() const { return Kind == k_MatrixRegister; } + bool isMatrixTileList() const { return Kind == k_MatrixTileList; } template bool isSVEVectorReg() const { RegKind RK; @@ -1502,6 +1525,14 @@ return true; } + template + DiagnosticPredicate isMatrixTileListOperand() const { + if (!isMatrixTileList() || + EltSize != getMatrixTileListElementWidth()) + return DiagnosticPredicateTy::NoMatch; + return DiagnosticPredicateTy::Match; + } + template DiagnosticPredicate isMatrixRegOperand() const { if (!isMatrix()) @@ -1620,6 +1651,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())); @@ -1983,6 +2021,49 @@ return Op; } + static std::unique_ptr + CreateMatrixTileList(SmallSet DRegs, unsigned ElementWidth, + SMLoc S, SMLoc E, MCContext &Ctx) { + auto Op = std::make_unique(k_MatrixTileList, Ctx); + const MCRegisterInfo *RI = Ctx.getRegisterInfo(); + unsigned RegMask = 0; + for (auto Reg : DRegs) + RegMask |= 0x1 << (RI->getEncodingValue(Reg) - + RI->getEncodingValue(AArch64::ZAD0)); + Op->MatrixTileList.RegMask = RegMask; + Op->MatrixTileList.ElementWidth = ElementWidth; + 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 + for (auto OutReg : RegMap[std::make_pair(ElementWidth, Reg)]) + 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); @@ -2195,6 +2276,14 @@ case k_MatrixRegister: OS << ""; break; + case k_MatrixTileList: { + OS << " 0; --I) + OS << ((RegMask & (1 << (I - 1))) >> (I - 1)); + break; + } case k_Register: OS << ""; if (!getShiftExtendAmount() && !hasShiftExtendAmount()) @@ -2374,9 +2463,8 @@ .Default(0); } -static unsigned matchMatrixRegName(StringRef Name) { +static unsigned matchMatrixTileRegName(StringRef Name) { return StringSwitch(Name.lower()) - .Case("za", AArch64::ZA) .Case("za0.q", AArch64::ZAQ0) .Case("za1.q", AArch64::ZAQ1) .Case("za2.q", AArch64::ZAQ2) @@ -2408,6 +2496,15 @@ .Case("za0.h", AArch64::ZAH0) .Case("za1.h", AArch64::ZAH1) .Case("za0.b", AArch64::ZAB0) + .Default(0); +} + +static unsigned matchMatrixRegName(StringRef Name) { + if (unsigned RegNum = matchMatrixTileRegName(Name)) + return RegNum; + + return StringSwitch(Name.lower()) + .Case("za", AArch64::ZA) .Case("za0h.q", AArch64::ZAQ0) .Case("za1h.q", AArch64::ZAQ1) .Case("za2h.q", AArch64::ZAQ2) @@ -3692,6 +3789,114 @@ return false; } +OperandMatchResultTy +AArch64AsmParser::tryParseMatrixTileList(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + + if (!Parser.getTok().is(AsmToken::LCurly)) + return MatchOperand_NoMatch; + + auto ParseMatrixTile = [&Parser](unsigned &Reg, unsigned &ElementWidth) { + std::string NameStr = Parser.getTok().getString().lower(); + StringRef Name = NameStr; + size_t DotPosition = Name.find('.'); + if (DotPosition == StringRef::npos) + return MatchOperand_NoMatch; + + unsigned RegNum = matchMatrixTileRegName(Name); + if (!RegNum) + return MatchOperand_NoMatch; + + StringRef Tail = Name.drop_front(DotPosition); + const auto &KindRes = parseVectorKind(Tail, RegKind::Matrix); + 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. + + SmallSet DRegs; + // Empty matrix list + if (Parser.getTok().is(AsmToken::RCurly)) { + Operands.push_back(AArch64Operand::CreateMatrixTileList( + DRegs, /*ElementWidth=*/64, S, getLoc(), getContext())); + Parser.Lex(); // Eat right bracket token. + return MatchOperand_Success; + } + + // Try parse {za} alias early + auto RegTok = Parser.getTok(); + auto Reg = RegTok.getString().lower(); + if (Reg == "za") { + Parser.Lex(); // Eat register + + if (parseToken(AsmToken::RCurly, "'}' expected")) + return MatchOperand_ParseFail; + + AArch64Operand::ComputeRegsForAlias(AArch64::ZAB0, DRegs, + /*ElementWidth=*/0); + Operands.push_back(AArch64Operand::CreateMatrixTileList( + DRegs, /*ElementWidth=*/64, S, getLoc(), getContext())); + return MatchOperand_Success; + } + + 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; + + AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth); + + while (parseOptionalToken(AsmToken::Comma)) { + SMLoc Loc = 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(Loc, "mismatched register size suffix"); + return MatchOperand_ParseFail; + } + + // Registers must be sequential + if (RI->getEncodingValue(Reg) <= (RI->getEncodingValue(PrevReg))) { + Error(Loc, "registers must be sequential"); + return MatchOperand_ParseFail; + } + + AArch64Operand::ComputeRegsForAlias(Reg, DRegs, ElementWidth); + + PrevReg = Reg; + ++Count; + } + + if (parseToken(AsmToken::RCurly, "'}' expected")) + return MatchOperand_ParseFail; + + if (Count > 8) { + Error(S, "invalid number of matrix registers"); + return MatchOperand_ParseFail; + } + + Operands.push_back(AArch64Operand::CreateMatrixTileList( + DRegs, ElementWidth, S, getLoc(), getContext())); + + return MatchOperand_Success; +} + template OperandMatchResultTy AArch64AsmParser::tryParseVectorList(OperandVector &Operands, Index: llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ 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); @@ -697,6 +701,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}, Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.h @@ -146,6 +146,10 @@ const MCSubtargetInfo &STI, raw_ostream &O, StringRef LayoutSuffix); + template + 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, Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp +++ llvm/lib/Target/AArch64/MCTargetDesc/AArch64InstPrinter.cpp @@ -1329,6 +1329,44 @@ 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 +}; + +template +void AArch64InstPrinter::printMatrixTileList(const MCInst *MI, unsigned OpNum, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned MaxRegs = 8; + + StringRef TypeSuffix; + if (EltSize == 64) + TypeSuffix = ".d"; + else + llvm_unreachable("Unsupported element size"); + + 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, Index: llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ 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, const MCSubtargetInfo &STI) const { Index: llvm/lib/Target/AArch64/SMEInstrFormats.td =================================================================== --- llvm/lib/Target/AArch64/SMEInstrFormats.td +++ llvm/lib/Target/AArch64/SMEInstrFormats.td @@ -653,3 +653,42 @@ defm _V : sme_tile_to_vector_v; } +//===----------------------------------------------------------------------===// +// SME Zero +//===----------------------------------------------------------------------===// + +class sme_zero_inst + : I<(outs MatrixTileList64:$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$imm", + (!cast(NAME) MatrixTileList8:$imm), 0>; + def : InstAlias<"zero\t$imm", + (!cast(NAME) MatrixTileList16:$imm), 0>; + def : InstAlias<"zero\t$imm", + (!cast(NAME) MatrixTileList32:$imm), 0>; + + 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>; +} + Index: llvm/test/MC/AArch64/SME/zero-diagnostics.s =================================================================== --- /dev/null +++ llvm/test/MC/AArch64/SME/zero-diagnostics.s @@ -0,0 +1,86 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sme 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Registers must be sequential + +zero {za0.d, za0.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: zero {za0.d, za0.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za1.d, za0.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: zero {za1.d, za0.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0.d, za1.d, za2.d, za1.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za1.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za0.d, za1.d, za2.d, za2.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: zero {za0.d, za1.d, za2.d, za2.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +zero {za7.d, za6.d} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: registers must be sequential +// CHECK-NEXT: zero {za7.d, za6.d} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// 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]+}}: + +// --------------------------------------------------------------------------// +// Invalid element width + +zero {za, za} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: '}' expected +// CHECK-NEXT: zero {za, za} +// 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 {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]+}}: + +// --------------------------------------------------------------------------// +// Invalid matrix list operand + +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 {za0.q, za1.q, za2.q, za3.q, za4.q, za5.q, za6.q, za7.q, za8.q, za9.q, za10.q, za11.q, za12.q, za13.q, za14.q, za15.q} +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid number of matrix registers +// CHECK-NEXT: zero {za0.q, za1.q, za2.q, za3.q, za4.q, za5.q, za6.q, za7.q, za8.q, za9.q, za10.q, za11.q, za12.q, za13.q, za14.q, za15.q} +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: llvm/test/MC/AArch64/SME/zero.s =================================================================== --- /dev/null +++ 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