1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[AArch64][SME] Add zero instruction

This patch adds the zero instruction for zeroing a list of 64-bit
element ZA tiles. The instruction takes a list of up to eight tiles
ZA0.D-ZA7.D, which must be in order, e.g.

  zero {za0.d,za1.d,za2.d,za3.d,za4.d,za5.d,za6.d,za7.d}
  zero {za1.d,za3.d,za5.d,za7.d}

The assembler also accepts 32-bit, 16-bit and 8-bit element tiles which
are mapped to corresponding 64-bit element tiles in accordance with the
architecturally defined mapping between different element size tiles,
e.g.

  * Zeroing ZA0.B, or the entire array name ZA, is equivalent to zeroing
    all eight 64-bit element tiles ZA0.D to ZA7.D.
  * Zeroing ZA0.S is equivalent to zeroing ZA0.D and ZA4.D.

The preferred disassembly of this instruction uses the shortest list of
tile names that represent the encoded immediate mask, e.g.

  * An immediate which encodes 64-bit element tiles ZA0.D, ZA1.D, ZA4.D and
    ZA5.D is disassembled as {ZA0.S, ZA1.S}.
  * An immediate which encodes 64-bit element tiles ZA0.D, ZA2.D, ZA4.D and
    ZA6.D is disassembled as {ZA0.H}.
  * An all-ones immediate is disassembled as {ZA}.
  * An all-zeros immediate is disassembled as an empty list {}.

This patch adds the MatrixTileList asm operand and related parsing to support
this.

Depends on D105570.

The reference can be found here:
https://developer.arm.com/documentation/ddi0602/2021-06

Reviewed By: david-arm

Differential Revision: https://reviews.llvm.org/D105575
This commit is contained in:
Cullen Rhodes 2021-07-27 08:00:49 +00:00
parent b7fc1f8c1c
commit 1ae2c0fb16
10 changed files with 650 additions and 0 deletions

View File

@ -1352,6 +1352,22 @@ class MatrixOperand<RegisterClass RC, int EltSize> : RegisterOperand<RC> {
def MatrixOp : MatrixOperand<MPR, 0>;
class MatrixTileListAsmOperand : AsmOperandClass {
let Name = "MatrixTileList";
let ParserMethod = "tryParseMatrixTileList";
let RenderMethod = "addMatrixTileListOperands";
let PredicateMethod = "isMatrixTileList";
}
class MatrixTileListOperand : Operand<i8> {
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";
}

View File

@ -88,6 +88,12 @@ defm STR_ZA : sme_spill<"str">;
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
//===----------------------------------------------------------------------===//

View File

@ -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 @@ private:
template <RegKind VectorKind>
OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
bool ExpectMatch = false);
OperandMatchResultTy tryParseMatrixTileList(OperandVector &Operands);
OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
OperandMatchResultTy tryParseGPR64x8(OperandVector &Operands);
@ -322,6 +324,7 @@ private:
k_CondCode,
k_Register,
k_MatrixRegister,
k_MatrixTileList,
k_SVCR,
k_VectorList,
k_VectorIndex,
@ -383,6 +386,10 @@ private:
MatrixKind Kind;
};
struct MatrixTileListOp {
unsigned RegMask = 0;
};
struct VectorListOp {
unsigned RegNum;
unsigned Count;
@ -460,6 +467,7 @@ private:
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 @@ public:
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 @@ public:
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 @@ public:
}
bool isMatrix() const { return Kind == k_MatrixRegister; }
bool isMatrixTileList() const { return Kind == k_MatrixTileList; }
template <unsigned Class> bool isSVEVectorReg() const {
RegKind RK;
@ -1643,6 +1660,13 @@ public:
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 @@ public:
return Op;
}
static std::unique_ptr<AArch64Operand>
CreateMatrixTileList(unsigned RegMask, SMLoc S, SMLoc E, MCContext &Ctx) {
auto Op = std::make_unique<AArch64Operand>(k_MatrixTileList, Ctx);
Op->MatrixTileList.RegMask = RegMask;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
}
static void ComputeRegsForAlias(unsigned Reg, SmallSet<unsigned, 8> &OutRegs,
const unsigned ElementWidth) {
static std::map<std::pair<unsigned, unsigned>, std::vector<unsigned>>
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<unsigned> 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<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
SMLoc E, MCContext &Ctx) {
auto Op = std::make_unique<AArch64Operand>(k_Immediate, Ctx);
@ -2235,6 +2298,15 @@ void AArch64Operand::print(raw_ostream &OS) const {
case k_MatrixRegister:
OS << "<matrix " << getMatrixReg() << ">";
break;
case k_MatrixTileList: {
OS << "<matrixlist ";
unsigned RegMask = getMatrixTileListRegMask();
unsigned MaxBits = 8;
for (unsigned I = MaxBits; I > 0; --I)
OS << ((RegMask & (1 << (I - 1))) >> (I - 1));
OS << '>';
break;
}
case k_SVCR: {
OS << getSVCR();
break;
@ -2418,6 +2490,26 @@ static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
.Default(0);
}
static unsigned matchMatrixTileListRegName(StringRef Name) {
return StringSwitch<unsigned>(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<unsigned>(Name.lower())
.Case("za", AArch64::ZA)
@ -3763,6 +3855,120 @@ bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
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<std::pair<int, int>> &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<unsigned, 8> DRegs;
AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth);
SmallSet<unsigned, 8> 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 <RegKind VectorKind>
OperandMatchResultTy
AArch64AsmParser::tryParseVectorList(OperandVector &Operands,

View File

@ -118,6 +118,10 @@ static DecodeStatus DecodeZPR4RegisterClass(MCInst &Inst, unsigned RegNo,
template <unsigned NumBitsForTile>
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 @@ static DecodeStatus DecodeZPR4RegisterClass(MCInst &Inst, unsigned RegNo,
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<SmallVector<unsigned, 16>, 5>
MatrixZATileDecoderTable = {
{AArch64::ZAB0},

View File

@ -1340,6 +1340,36 @@ void AArch64InstPrinter::printGPRSeqPairsClassOperand(const MCInst *MI,
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,

View File

@ -146,6 +146,9 @@ protected:
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,

View File

@ -186,6 +186,9 @@ public:
unsigned fixOneOperandFPComparison(const MCInst &MI, unsigned EncodedValue,
const MCSubtargetInfo &STI) const;
uint32_t EncodeMatrixTileListRegisterClass(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
uint32_t encodeMatrixIndexGPR32(const MCInst &MI, unsigned OpIdx,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@ -520,6 +523,14 @@ AArch64MCCodeEmitter::getVecShiftL8OpValue(const MCInst &MI, unsigned OpIdx,
return MO.getImm() - 8;
}
uint32_t AArch64MCCodeEmitter::EncodeMatrixTileListRegisterClass(
const MCInst &MI, unsigned OpIdx, SmallVectorImpl<MCFixup> &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<MCFixup> &Fixups,

View File

@ -653,6 +653,38 @@ multiclass sme_tile_to_vector<string mnemonic> {
defm _V : sme_tile_to_vector_v<mnemonic, /*is_col=*/0b1>;
}
//===----------------------------------------------------------------------===//
// SME Zero
//===----------------------------------------------------------------------===//
class sme_zero_inst<string mnemonic>
: 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<string mnemonic> {
def NAME : sme_zero_inst<mnemonic>;
def : InstAlias<"zero\t\\{za\\}", (!cast<Instruction>(NAME) 0b11111111), 1>;
def : InstAlias<"zero\t\\{za0.h\\}", (!cast<Instruction>(NAME) 0b01010101), 1>;
def : InstAlias<"zero\t\\{za1.h\\}", (!cast<Instruction>(NAME) 0b10101010), 1>;
def : InstAlias<"zero\t\\{za0.s\\}", (!cast<Instruction>(NAME) 0b00010001), 1>;
def : InstAlias<"zero\t\\{za1.s\\}", (!cast<Instruction>(NAME) 0b00100010), 1>;
def : InstAlias<"zero\t\\{za2.s\\}", (!cast<Instruction>(NAME) 0b01000100), 1>;
def : InstAlias<"zero\t\\{za3.s\\}", (!cast<Instruction>(NAME) 0b10001000), 1>;
def : InstAlias<"zero\t\\{za0.s,za1.s\\}", (!cast<Instruction>(NAME) 0b00110011), 1>;
def : InstAlias<"zero\t\\{za0.s,za3.s\\}", (!cast<Instruction>(NAME) 0b10011001), 1>;
def : InstAlias<"zero\t\\{za1.s,za2.s\\}", (!cast<Instruction>(NAME) 0b01100110), 1>;
def : InstAlias<"zero\t\\{za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11001100), 1>;
def : InstAlias<"zero\t\\{za0.s,za1.s,za2.s\\}", (!cast<Instruction>(NAME) 0b01110111), 1>;
def : InstAlias<"zero\t\\{za0.s,za1.s,za3.s\\}", (!cast<Instruction>(NAME) 0b10111011), 1>;
def : InstAlias<"zero\t\\{za0.s,za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11011101), 1>;
def : InstAlias<"zero\t\\{za1.s,za2.s,za3.s\\}", (!cast<Instruction>(NAME) 0b11101110), 1>;
}
//===----------------------------------------------------------------------===//
// SVE2 Instructions
//===----------------------------------------------------------------------===//

View File

@ -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]+}}:

250
test/MC/AArch64/SME/zero.s Normal file
View File

@ -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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
// --------------------------------------------------------------------------//
// Aliases
zero {za}
// CHECK-INST: zero {za}
// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
// CHECK-ERROR: instruction requires: sme
// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
zero {za0.b}
// CHECK-INST: zero {za}
// CHECK-ENCODING: [0xff,0x00,0x08,0xc0]
// CHECK-ERROR: instruction requires: sme
// CHECK-UNKNOWN: ff 00 08 c0 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>
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 <unknown>