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:
parent
b7fc1f8c1c
commit
1ae2c0fb16
@ -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";
|
||||
}
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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,
|
||||
|
@ -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},
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
82
test/MC/AArch64/SME/zero-diagnostics.s
Normal file
82
test/MC/AArch64/SME/zero-diagnostics.s
Normal 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
250
test/MC/AArch64/SME/zero.s
Normal 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>
|
Loading…
Reference in New Issue
Block a user