Skip to content

Commit 91f11e5

Browse files
committedNov 7, 2017
[AArch64][SVE] Asm: Add SVE (Z) Register definitions and parsing support
Patch [3/5] in a series to add assembler/disassembler support for AArch64 SVE unpredicated ADD/SUB instructions. To summarise, this patch adds: * SVE register definitions * Methods to parse SVE register operands * Methods to print SVE register operands * RegKind SVEDataVector to distinguish it from other data types like scalar register or Neon vector. * k_SVEDataRegister and SVEDataRegOp to describe SVE registers (which will be extended by further patches with e.g. ElementWidth and the shift-extend type). Patch by Sander De Smalen. Reviewed by: rengolin Differential Revision: https://reviews.llvm.org/D39089 llvm-svn: 317590
1 parent 612d693 commit 91f11e5

File tree

5 files changed

+330
-1
lines changed

5 files changed

+330
-1
lines changed
 

‎llvm/lib/Target/AArch64/AArch64RegisterInfo.td

+122
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ let Namespace = "AArch64" in {
3232
def qsub : SubRegIndex<64>;
3333
def sube64 : SubRegIndex<64>;
3434
def subo64 : SubRegIndex<64>;
35+
// SVE
36+
def zsub : SubRegIndex<128>;
37+
// Note: zsub_hi should never be used directly because it represents
38+
// the scalable part of the SVE vector and cannot be manipulated as a
39+
// subvector in the same way the lower 128bits can.
40+
def zsub_hi : SubRegIndex<128>;
3541
// Note: Code depends on these having consecutive numbers
3642
def dsub0 : SubRegIndex<64>;
3743
def dsub1 : SubRegIndex<64>;
@@ -645,3 +651,119 @@ def XSeqPairClassOperand :
645651

646652

647653
//===----- END: v8.1a atomic CASP register operands -----------------------===//
654+
655+
// The part of SVE registers that don't overlap Neon registers.
656+
// These are only used as part of clobber lists.
657+
def Z0_HI : AArch64Reg<0, "z0_hi">;
658+
def Z1_HI : AArch64Reg<1, "z1_hi">;
659+
def Z2_HI : AArch64Reg<2, "z2_hi">;
660+
def Z3_HI : AArch64Reg<3, "z3_hi">;
661+
def Z4_HI : AArch64Reg<4, "z4_hi">;
662+
def Z5_HI : AArch64Reg<5, "z5_hi">;
663+
def Z6_HI : AArch64Reg<6, "z6_hi">;
664+
def Z7_HI : AArch64Reg<7, "z7_hi">;
665+
def Z8_HI : AArch64Reg<8, "z8_hi">;
666+
def Z9_HI : AArch64Reg<9, "z9_hi">;
667+
def Z10_HI : AArch64Reg<10, "z10_hi">;
668+
def Z11_HI : AArch64Reg<11, "z11_hi">;
669+
def Z12_HI : AArch64Reg<12, "z12_hi">;
670+
def Z13_HI : AArch64Reg<13, "z13_hi">;
671+
def Z14_HI : AArch64Reg<14, "z14_hi">;
672+
def Z15_HI : AArch64Reg<15, "z15_hi">;
673+
def Z16_HI : AArch64Reg<16, "z16_hi">;
674+
def Z17_HI : AArch64Reg<17, "z17_hi">;
675+
def Z18_HI : AArch64Reg<18, "z18_hi">;
676+
def Z19_HI : AArch64Reg<19, "z19_hi">;
677+
def Z20_HI : AArch64Reg<20, "z20_hi">;
678+
def Z21_HI : AArch64Reg<21, "z21_hi">;
679+
def Z22_HI : AArch64Reg<22, "z22_hi">;
680+
def Z23_HI : AArch64Reg<23, "z23_hi">;
681+
def Z24_HI : AArch64Reg<24, "z24_hi">;
682+
def Z25_HI : AArch64Reg<25, "z25_hi">;
683+
def Z26_HI : AArch64Reg<26, "z26_hi">;
684+
def Z27_HI : AArch64Reg<27, "z27_hi">;
685+
def Z28_HI : AArch64Reg<28, "z28_hi">;
686+
def Z29_HI : AArch64Reg<29, "z29_hi">;
687+
def Z30_HI : AArch64Reg<30, "z30_hi">;
688+
def Z31_HI : AArch64Reg<31, "z31_hi">;
689+
690+
// SVE variable-size vector registers
691+
let SubRegIndices = [zsub,zsub_hi] in {
692+
def Z0 : AArch64Reg<0, "z0", [Q0, Z0_HI]>, DwarfRegNum<[96]>;
693+
def Z1 : AArch64Reg<1, "z1", [Q1, Z1_HI]>, DwarfRegNum<[97]>;
694+
def Z2 : AArch64Reg<2, "z2", [Q2, Z2_HI]>, DwarfRegNum<[98]>;
695+
def Z3 : AArch64Reg<3, "z3", [Q3, Z3_HI]>, DwarfRegNum<[99]>;
696+
def Z4 : AArch64Reg<4, "z4", [Q4, Z4_HI]>, DwarfRegNum<[100]>;
697+
def Z5 : AArch64Reg<5, "z5", [Q5, Z5_HI]>, DwarfRegNum<[101]>;
698+
def Z6 : AArch64Reg<6, "z6", [Q6, Z6_HI]>, DwarfRegNum<[102]>;
699+
def Z7 : AArch64Reg<7, "z7", [Q7, Z7_HI]>, DwarfRegNum<[103]>;
700+
def Z8 : AArch64Reg<8, "z8", [Q8, Z8_HI]>, DwarfRegNum<[104]>;
701+
def Z9 : AArch64Reg<9, "z9", [Q9, Z9_HI]>, DwarfRegNum<[105]>;
702+
def Z10 : AArch64Reg<10, "z10", [Q10, Z10_HI]>, DwarfRegNum<[106]>;
703+
def Z11 : AArch64Reg<11, "z11", [Q11, Z11_HI]>, DwarfRegNum<[107]>;
704+
def Z12 : AArch64Reg<12, "z12", [Q12, Z12_HI]>, DwarfRegNum<[108]>;
705+
def Z13 : AArch64Reg<13, "z13", [Q13, Z13_HI]>, DwarfRegNum<[109]>;
706+
def Z14 : AArch64Reg<14, "z14", [Q14, Z14_HI]>, DwarfRegNum<[110]>;
707+
def Z15 : AArch64Reg<15, "z15", [Q15, Z15_HI]>, DwarfRegNum<[111]>;
708+
def Z16 : AArch64Reg<16, "z16", [Q16, Z16_HI]>, DwarfRegNum<[112]>;
709+
def Z17 : AArch64Reg<17, "z17", [Q17, Z17_HI]>, DwarfRegNum<[113]>;
710+
def Z18 : AArch64Reg<18, "z18", [Q18, Z18_HI]>, DwarfRegNum<[114]>;
711+
def Z19 : AArch64Reg<19, "z19", [Q19, Z19_HI]>, DwarfRegNum<[115]>;
712+
def Z20 : AArch64Reg<20, "z20", [Q20, Z20_HI]>, DwarfRegNum<[116]>;
713+
def Z21 : AArch64Reg<21, "z21", [Q21, Z21_HI]>, DwarfRegNum<[117]>;
714+
def Z22 : AArch64Reg<22, "z22", [Q22, Z22_HI]>, DwarfRegNum<[118]>;
715+
def Z23 : AArch64Reg<23, "z23", [Q23, Z23_HI]>, DwarfRegNum<[119]>;
716+
def Z24 : AArch64Reg<24, "z24", [Q24, Z24_HI]>, DwarfRegNum<[120]>;
717+
def Z25 : AArch64Reg<25, "z25", [Q25, Z25_HI]>, DwarfRegNum<[121]>;
718+
def Z26 : AArch64Reg<26, "z26", [Q26, Z26_HI]>, DwarfRegNum<[122]>;
719+
def Z27 : AArch64Reg<27, "z27", [Q27, Z27_HI]>, DwarfRegNum<[123]>;
720+
def Z28 : AArch64Reg<28, "z28", [Q28, Z28_HI]>, DwarfRegNum<[124]>;
721+
def Z29 : AArch64Reg<29, "z29", [Q29, Z29_HI]>, DwarfRegNum<[125]>;
722+
def Z30 : AArch64Reg<30, "z30", [Q30, Z30_HI]>, DwarfRegNum<[126]>;
723+
def Z31 : AArch64Reg<31, "z31", [Q31, Z31_HI]>, DwarfRegNum<[127]>;
724+
}
725+
726+
class SVERegOp <string Suffix, AsmOperandClass C,
727+
RegisterClass RC> : RegisterOperand<RC> {
728+
let PrintMethod = !if(!eq(Suffix, ""),
729+
"printSVERegOp<>",
730+
"printSVERegOp<'" # Suffix # "'>");
731+
let ParserMatchClass = C;
732+
}
733+
734+
class ZPRRegOp <string Suffix, AsmOperandClass C,
735+
RegisterClass RC> : SVERegOp<Suffix, C, RC> {}
736+
737+
//******************************************************************************
738+
739+
// SVE vector register class
740+
def ZPR : RegisterClass<"AArch64",
741+
[nxv16i8, nxv8i16, nxv4i32, nxv2i64,
742+
nxv2f16, nxv4f16, nxv8f16,
743+
nxv1f32, nxv2f32, nxv4f32,
744+
nxv1f64, nxv2f64],
745+
128, (sequence "Z%u", 0, 31)> {
746+
let Size = 128;
747+
}
748+
749+
class ZPRAsmOperand <string name, int Width>: AsmOperandClass {
750+
let Name = "SVE" # name # "Reg";
751+
let PredicateMethod = "isSVEDataVectorRegOfWidth<" # Width # ">";
752+
let RenderMethod = "addRegOperands";
753+
let ParserMethod = "tryParseSVEDataVector<"
754+
# !if(!eq(Width, -1), "false", "true") # ">";
755+
}
756+
757+
def ZPRAsmOpAny : ZPRAsmOperand<"VectorAny", -1>;
758+
def ZPRAsmOp8 : ZPRAsmOperand<"VectorB", 8>;
759+
def ZPRAsmOp16 : ZPRAsmOperand<"VectorH", 16>;
760+
def ZPRAsmOp32 : ZPRAsmOperand<"VectorS", 32>;
761+
def ZPRAsmOp64 : ZPRAsmOperand<"VectorD", 64>;
762+
def ZPRAsmOp128 : ZPRAsmOperand<"VectorQ", 128>;
763+
764+
def ZPRAny : ZPRRegOp<"", ZPRAsmOpAny, ZPR>;
765+
def ZPR8 : ZPRRegOp<"b", ZPRAsmOp8, ZPR>;
766+
def ZPR16 : ZPRRegOp<"h", ZPRAsmOp16, ZPR>;
767+
def ZPR32 : ZPRRegOp<"s", ZPRAsmOp32, ZPR>;
768+
def ZPR64 : ZPRRegOp<"d", ZPRAsmOp64, ZPR>;
769+
def ZPR128 : ZPRRegOp<"q", ZPRAsmOp128, ZPR>;

‎llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

+161-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ using namespace llvm;
5959

6060
namespace {
6161

62-
enum class RegKind {Scalar, NeonVector};
62+
enum class RegKind {Scalar, NeonVector, SVEDataVector};
6363

6464
class AArch64AsmParser : public MCTargetAsmParser {
6565
private:
@@ -82,6 +82,7 @@ class AArch64AsmParser : public MCTargetAsmParser {
8282
unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
8383
int tryParseRegister();
8484
int tryMatchVectorRegister(StringRef &Kind, bool expected);
85+
int tryParseSVEDataVectorRegister(const AsmToken &Tok, StringRef &Kind);
8586
bool parseRegister(OperandVector &Operands);
8687
bool parseSymbolicImmVal(const MCExpr *&ImmVal);
8788
bool parseVectorList(OperandVector &Operands);
@@ -130,6 +131,8 @@ class AArch64AsmParser : public MCTargetAsmParser {
130131
OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
131132
bool tryParseNeonVectorRegister(OperandVector &Operands);
132133
OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
134+
template <bool ParseSuffix>
135+
OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
133136

134137
public:
135138
enum AArch64MatchResultTy {
@@ -197,6 +200,8 @@ class AArch64Operand : public MCParsedAsmOperand {
197200
struct RegOp {
198201
unsigned RegNum;
199202
RegKind Kind;
203+
204+
int ElementWidth;
200205
};
201206

202207
struct VectorListOp {
@@ -820,6 +825,17 @@ class AArch64Operand : public MCParsedAsmOperand {
820825
Reg.RegNum);
821826
}
822827

828+
template <unsigned Class = AArch64::ZPRRegClassID>
829+
bool isSVEDataVectorReg() const {
830+
return (Kind == k_Register && Reg.Kind == RegKind::SVEDataVector) &&
831+
AArch64MCRegisterClasses[Class].contains(getReg());
832+
}
833+
834+
template <int ElementWidth> bool isSVEDataVectorRegOfWidth() const {
835+
return isSVEDataVectorReg() &&
836+
(ElementWidth == -1 || Reg.ElementWidth == ElementWidth);
837+
}
838+
823839
bool isGPR32as64() const {
824840
return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
825841
AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
@@ -1580,6 +1596,18 @@ class AArch64Operand : public MCParsedAsmOperand {
15801596
return Op;
15811597
}
15821598

1599+
static std::unique_ptr<AArch64Operand>
1600+
CreateReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1601+
SMLoc S, SMLoc E, MCContext &Ctx) {
1602+
auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1603+
Op->Reg.RegNum = RegNum;
1604+
Op->Reg.ElementWidth = ElementWidth;
1605+
Op->Reg.Kind = Kind;
1606+
Op->StartLoc = S;
1607+
Op->EndLoc = E;
1608+
return Op;
1609+
}
1610+
15831611
static std::unique_ptr<AArch64Operand>
15841612
CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
15851613
char ElementKind, SMLoc S, SMLoc E, MCContext &Ctx) {
@@ -1860,6 +1888,57 @@ static bool isValidVectorKind(StringRef Name) {
18601888
.Default(false);
18611889
}
18621890

1891+
static unsigned matchSVEDataVectorRegName(StringRef Name) {
1892+
return StringSwitch<unsigned>(Name.lower())
1893+
.Case("z0", AArch64::Z0)
1894+
.Case("z1", AArch64::Z1)
1895+
.Case("z2", AArch64::Z2)
1896+
.Case("z3", AArch64::Z3)
1897+
.Case("z4", AArch64::Z4)
1898+
.Case("z5", AArch64::Z5)
1899+
.Case("z6", AArch64::Z6)
1900+
.Case("z7", AArch64::Z7)
1901+
.Case("z8", AArch64::Z8)
1902+
.Case("z9", AArch64::Z9)
1903+
.Case("z10", AArch64::Z10)
1904+
.Case("z11", AArch64::Z11)
1905+
.Case("z12", AArch64::Z12)
1906+
.Case("z13", AArch64::Z13)
1907+
.Case("z14", AArch64::Z14)
1908+
.Case("z15", AArch64::Z15)
1909+
.Case("z16", AArch64::Z16)
1910+
.Case("z17", AArch64::Z17)
1911+
.Case("z18", AArch64::Z18)
1912+
.Case("z19", AArch64::Z19)
1913+
.Case("z20", AArch64::Z20)
1914+
.Case("z21", AArch64::Z21)
1915+
.Case("z22", AArch64::Z22)
1916+
.Case("z23", AArch64::Z23)
1917+
.Case("z24", AArch64::Z24)
1918+
.Case("z25", AArch64::Z25)
1919+
.Case("z26", AArch64::Z26)
1920+
.Case("z27", AArch64::Z27)
1921+
.Case("z28", AArch64::Z28)
1922+
.Case("z29", AArch64::Z29)
1923+
.Case("z30", AArch64::Z30)
1924+
.Case("z31", AArch64::Z31)
1925+
.Default(0);
1926+
}
1927+
1928+
static bool isValidSVEKind(StringRef Name) {
1929+
return StringSwitch<bool>(Name.lower())
1930+
.Case(".b", true)
1931+
.Case(".h", true)
1932+
.Case(".s", true)
1933+
.Case(".d", true)
1934+
.Case(".q", true)
1935+
.Default(false);
1936+
}
1937+
1938+
static bool isSVEDataVectorRegister(StringRef Name) {
1939+
return Name[0] == 'z';
1940+
}
1941+
18631942
static void parseValidVectorKind(StringRef Name, unsigned &NumElements,
18641943
char &ElementKind) {
18651944
assert(isValidVectorKind(Name));
@@ -1897,6 +1976,9 @@ unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
18971976
case RegKind::NeonVector:
18981977
RegNum = MatchNeonVectorRegName(Name);
18991978
break;
1979+
case RegKind::SVEDataVector:
1980+
RegNum = matchSVEDataVectorRegName(Name);
1981+
break;
19001982
}
19011983

19021984
if (!RegNum) {
@@ -1924,6 +2006,9 @@ int AArch64AsmParser::tryParseRegister() {
19242006
return -1;
19252007

19262008
std::string lowerCase = Tok.getString().lower();
2009+
if (isSVEDataVectorRegister(lowerCase))
2010+
return -1;
2011+
19272012
unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
19282013
// Also handle a few aliases of registers.
19292014
if (RegNum == 0)
@@ -2620,6 +2705,35 @@ bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
26202705
return false;
26212706
}
26222707

2708+
// tryParseSVEDataVectorRegister - Try to parse a SVE vector register name with
2709+
// optional kind specifier. If it is a register specifier, eat the token
2710+
// and return it.
2711+
int AArch64AsmParser::tryParseSVEDataVectorRegister(const AsmToken &Tok,
2712+
StringRef &Kind) {
2713+
if (Tok.isNot(AsmToken::Identifier))
2714+
return -1;
2715+
2716+
StringRef Name = Tok.getString();
2717+
// If there is a kind specifier, it's separated from the register name by
2718+
// a '.'.
2719+
size_t Start = 0, Next = Name.find('.');
2720+
StringRef Head = Name.slice(Start, Next);
2721+
unsigned RegNum = matchRegisterNameAlias(Head, RegKind::SVEDataVector);
2722+
2723+
if (RegNum) {
2724+
if (Next != StringRef::npos) {
2725+
Kind = Name.slice(Next, StringRef::npos);
2726+
if (!isValidSVEKind(Kind)) {
2727+
TokError("invalid sve vector kind qualifier");
2728+
return -1;
2729+
}
2730+
}
2731+
return RegNum;
2732+
}
2733+
2734+
return -1;
2735+
}
2736+
26232737
/// parseRegister - Parse a non-vector register operand.
26242738
bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
26252739
SMLoc S = getLoc();
@@ -4188,6 +4302,17 @@ bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
41884302
return Error(SRegLoc, "vector register without type specifier expected");
41894303
}
41904304

4305+
if (RegNum == static_cast<unsigned>(-1)) {
4306+
StringRef Kind;
4307+
RegisterKind = RegKind::SVEDataVector;
4308+
int RegNumTmp = tryParseSVEDataVectorRegister(Parser.getTok(), Kind);
4309+
if (RegNumTmp != -1)
4310+
Parser.Lex();
4311+
RegNum = RegNumTmp;
4312+
if (!Kind.empty())
4313+
return Error(SRegLoc, "sve vector register without type specifier expected");
4314+
}
4315+
41914316
if (RegNum == static_cast<unsigned>(-1))
41924317
return Error(SRegLoc, "register name or alias expected");
41934318

@@ -4413,3 +4538,38 @@ AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
44134538

44144539
return MatchOperand_Success;
44154540
}
4541+
4542+
template <bool ParseSuffix>
4543+
OperandMatchResultTy
4544+
AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
4545+
MCAsmParser &Parser = getParser();
4546+
const SMLoc S = getLoc();
4547+
// Check for a SVE vector register specifier first.
4548+
StringRef Kind;
4549+
int RegNum = tryParseSVEDataVectorRegister(Parser.getTok(), Kind);
4550+
if (RegNum == -1)
4551+
return MatchOperand_NoMatch;
4552+
4553+
// Eat the SVE Register Token
4554+
Parser.Lex();
4555+
4556+
if (ParseSuffix && Kind.empty())
4557+
return MatchOperand_NoMatch;
4558+
4559+
unsigned ElementWidth = StringSwitch<unsigned>(Kind.lower())
4560+
.Case("", -1)
4561+
.Case(".b", 8)
4562+
.Case(".h", 16)
4563+
.Case(".s", 32)
4564+
.Case(".d", 64)
4565+
.Case(".q", 128)
4566+
.Default(0);
4567+
if (!ElementWidth)
4568+
return MatchOperand_NoMatch;
4569+
4570+
Operands.push_back(
4571+
AArch64Operand::CreateReg(RegNum, RegKind::SVEDataVector, ElementWidth,
4572+
S, S, getContext()));
4573+
4574+
return MatchOperand_Success;
4575+
}

‎llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ static DecodeStatus DecodeDDDRegisterClass(MCInst &Inst, unsigned RegNo,
8585
static DecodeStatus DecodeDDDDRegisterClass(MCInst &Inst, unsigned RegNo,
8686
uint64_t Address,
8787
const void *Decoder);
88+
static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
89+
uint64_t Address,
90+
const void *Decode);
8891

8992
static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm,
9093
uint64_t Address,
@@ -436,6 +439,27 @@ static DecodeStatus DecodeGPR32spRegisterClass(MCInst &Inst, unsigned RegNo,
436439
Inst.addOperand(MCOperand::createReg(Register));
437440
return Success;
438441
}
442+
static const unsigned ZPRDecoderTable[] = {
443+
AArch64::Z0, AArch64::Z1, AArch64::Z2, AArch64::Z3,
444+
AArch64::Z4, AArch64::Z5, AArch64::Z6, AArch64::Z7,
445+
AArch64::Z8, AArch64::Z9, AArch64::Z10, AArch64::Z11,
446+
AArch64::Z12, AArch64::Z13, AArch64::Z14, AArch64::Z15,
447+
AArch64::Z16, AArch64::Z17, AArch64::Z18, AArch64::Z19,
448+
AArch64::Z20, AArch64::Z21, AArch64::Z22, AArch64::Z23,
449+
AArch64::Z24, AArch64::Z25, AArch64::Z26, AArch64::Z27,
450+
AArch64::Z28, AArch64::Z29, AArch64::Z30, AArch64::Z31
451+
};
452+
453+
static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo,
454+
uint64_t Address,
455+
const void* Decoder) {
456+
if (RegNo > 31)
457+
return Fail;
458+
459+
unsigned Register = ZPRDecoderTable[RegNo];
460+
Inst.addOperand(MCOperand::createReg(Register));
461+
return Success;
462+
}
439463

440464
static const unsigned VectorDecoderTable[] = {
441465
AArch64::Q0, AArch64::Q1, AArch64::Q2, AArch64::Q3, AArch64::Q4,

‎llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -1340,3 +1340,23 @@ void AArch64InstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo,
13401340
O << "#" << (Val * Angle) + Remainder;
13411341
}
13421342

1343+
template <char suffix>
1344+
void AArch64InstPrinter::printSVERegOp(const MCInst *MI, unsigned OpNum,
1345+
const MCSubtargetInfo &STI,
1346+
raw_ostream &O) {
1347+
switch (suffix) {
1348+
case 0:
1349+
case 'b':
1350+
case 'h':
1351+
case 's':
1352+
case 'd':
1353+
case 'q':
1354+
break;
1355+
default: llvm_unreachable("Invalid kind specifier.");
1356+
}
1357+
1358+
unsigned Reg = MI->getOperand(OpNum).getReg();
1359+
O << getRegisterName(Reg);
1360+
if (suffix != 0)
1361+
O << '.' << suffix;
1362+
}

‎llvm/lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h

+3
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ class AArch64InstPrinter : public MCInstPrinter {
165165
void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum,
166166
const MCSubtargetInfo &STI,
167167
raw_ostream &O);
168+
template <char = 0>
169+
void printSVERegOp(const MCInst *MI, unsigned OpNum,
170+
const MCSubtargetInfo &STI, raw_ostream &O);
168171
};
169172

170173
class AArch64AppleInstPrinter : public AArch64InstPrinter {

0 commit comments

Comments
 (0)
Please sign in to comment.