71 SVEPredicateAsCounter,
77enum class MatrixKind {
Array, Tile, Row, Col };
79enum RegConstraintEqualityTy {
97 case AArch64::MOVPRFX_ZZ:
101 case AArch64::MOVPRFX_ZPmZ_B:
102 case AArch64::MOVPRFX_ZPmZ_H:
103 case AArch64::MOVPRFX_ZPmZ_S:
104 case AArch64::MOVPRFX_ZPmZ_D:
109 "No destructive element size set for movprfx");
113 case AArch64::MOVPRFX_ZPzZ_B:
114 case AArch64::MOVPRFX_ZPzZ_H:
115 case AArch64::MOVPRFX_ZPzZ_S:
116 case AArch64::MOVPRFX_ZPzZ_D:
121 "No destructive element size set for movprfx");
132 PrefixInfo() =
default;
133 bool isActive()
const {
return Active; }
135 unsigned getElementSize()
const {
139 unsigned getDstReg()
const {
return Dst; }
140 unsigned getPgReg()
const {
147 bool Predicated =
false;
148 unsigned ElementSize;
164 std::string &Suggestion);
166 unsigned matchRegisterNameAlias(
StringRef Name, RegKind Kind);
168 bool parseSymbolicImmVal(
const MCExpr *&ImmVal);
174 bool invertCondCode);
175 bool parseImmExpr(int64_t &Out);
177 bool parseRegisterInRange(
unsigned &Out,
unsigned Base,
unsigned First,
183 bool parseAuthExpr(
const MCExpr *&Res,
SMLoc &EndLoc);
185 bool parseDirectiveArch(
SMLoc L);
186 bool parseDirectiveArchExtension(
SMLoc L);
187 bool parseDirectiveCPU(
SMLoc L);
188 bool parseDirectiveInst(
SMLoc L);
190 bool parseDirectiveTLSDescCall(
SMLoc L);
193 bool parseDirectiveLtorg(
SMLoc L);
196 bool parseDirectiveUnreq(
SMLoc L);
197 bool parseDirectiveCFINegateRAState();
198 bool parseDirectiveCFIBKeyFrame();
199 bool parseDirectiveCFIMTETaggedFrame();
201 bool parseDirectiveVariantPCS(
SMLoc L);
203 bool parseDirectiveSEHAllocStack(
SMLoc L);
204 bool parseDirectiveSEHPrologEnd(
SMLoc L);
205 bool parseDirectiveSEHSaveR19R20X(
SMLoc L);
206 bool parseDirectiveSEHSaveFPLR(
SMLoc L);
207 bool parseDirectiveSEHSaveFPLRX(
SMLoc L);
208 bool parseDirectiveSEHSaveReg(
SMLoc L);
209 bool parseDirectiveSEHSaveRegX(
SMLoc L);
210 bool parseDirectiveSEHSaveRegP(
SMLoc L);
211 bool parseDirectiveSEHSaveRegPX(
SMLoc L);
212 bool parseDirectiveSEHSaveLRPair(
SMLoc L);
213 bool parseDirectiveSEHSaveFReg(
SMLoc L);
214 bool parseDirectiveSEHSaveFRegX(
SMLoc L);
215 bool parseDirectiveSEHSaveFRegP(
SMLoc L);
216 bool parseDirectiveSEHSaveFRegPX(
SMLoc L);
217 bool parseDirectiveSEHSetFP(
SMLoc L);
218 bool parseDirectiveSEHAddFP(
SMLoc L);
219 bool parseDirectiveSEHNop(
SMLoc L);
220 bool parseDirectiveSEHSaveNext(
SMLoc L);
221 bool parseDirectiveSEHEpilogStart(
SMLoc L);
222 bool parseDirectiveSEHEpilogEnd(
SMLoc L);
223 bool parseDirectiveSEHTrapFrame(
SMLoc L);
224 bool parseDirectiveSEHMachineFrame(
SMLoc L);
225 bool parseDirectiveSEHContext(
SMLoc L);
226 bool parseDirectiveSEHECContext(
SMLoc L);
227 bool parseDirectiveSEHClearUnwoundToCall(
SMLoc L);
228 bool parseDirectiveSEHPACSignLR(
SMLoc L);
229 bool parseDirectiveSEHSaveAnyReg(
SMLoc L,
bool Paired,
bool Writeback);
231 bool validateInstruction(
MCInst &Inst,
SMLoc &IDLoc,
233 unsigned getNumRegsForRegKind(RegKind K);
237 bool MatchingInlineAsm)
override;
241#define GET_ASSEMBLER_HEADER
242#include "AArch64GenAsmMatcher.inc"
256 template <
bool IsSVEPrefetch = false>
263 template <
bool AddFPZeroAsLiteral>
271 template <
bool ParseShiftExtend,
272 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
275 template <
bool ParseShiftExtend,
bool ParseSuffix>
277 template <RegKind RK>
279 template <RegKind VectorKind>
281 bool ExpectMatch =
false);
289 enum AArch64MatchResultTy {
291#define GET_OPERAND_DIAGNOSTIC_TYPES
292#include "AArch64GenAsmMatcher.inc"
324 SMLoc &EndLoc)
override;
327 unsigned Kind)
override;
331 static bool classifySymbolRef(
const MCExpr *Expr,
363 SMLoc StartLoc, EndLoc;
372 struct ShiftExtendOp {
375 bool HasExplicitAmount;
385 RegConstraintEqualityTy EqualityTy;
401 ShiftExtendOp ShiftExtend;
406 unsigned ElementWidth;
410 struct MatrixTileListOp {
411 unsigned RegMask = 0;
414 struct VectorListOp {
418 unsigned NumElements;
419 unsigned ElementWidth;
420 RegKind RegisterKind;
423 struct VectorIndexOp {
431 struct ShiftedImmOp {
433 unsigned ShiftAmount;
490 unsigned PStateField;
496 struct MatrixRegOp MatrixReg;
497 struct MatrixTileListOp MatrixTileList;
498 struct VectorListOp VectorList;
499 struct VectorIndexOp VectorIndex;
501 struct ShiftedImmOp ShiftedImm;
502 struct ImmRangeOp ImmRange;
504 struct FPImmOp FPImm;
506 struct SysRegOp SysReg;
507 struct SysCRImmOp SysCRImm;
509 struct PSBHintOp PSBHint;
510 struct BTIHintOp BTIHint;
511 struct ShiftExtendOp ShiftExtend;
524 StartLoc =
o.StartLoc;
534 ShiftedImm =
o.ShiftedImm;
537 ImmRange =
o.ImmRange;
551 case k_MatrixRegister:
552 MatrixReg =
o.MatrixReg;
554 case k_MatrixTileList:
555 MatrixTileList =
o.MatrixTileList;
558 VectorList =
o.VectorList;
561 VectorIndex =
o.VectorIndex;
567 SysCRImm =
o.SysCRImm;
579 ShiftExtend =
o.ShiftExtend;
588 SMLoc getStartLoc()
const override {
return StartLoc; }
590 SMLoc getEndLoc()
const override {
return EndLoc; }
593 assert(Kind == k_Token &&
"Invalid access!");
597 bool isTokenSuffix()
const {
598 assert(Kind == k_Token &&
"Invalid access!");
602 const MCExpr *getImm()
const {
603 assert(Kind == k_Immediate &&
"Invalid access!");
607 const MCExpr *getShiftedImmVal()
const {
608 assert(Kind == k_ShiftedImm &&
"Invalid access!");
609 return ShiftedImm.Val;
612 unsigned getShiftedImmShift()
const {
613 assert(Kind == k_ShiftedImm &&
"Invalid access!");
614 return ShiftedImm.ShiftAmount;
617 unsigned getFirstImmVal()
const {
618 assert(Kind == k_ImmRange &&
"Invalid access!");
619 return ImmRange.First;
622 unsigned getLastImmVal()
const {
623 assert(Kind == k_ImmRange &&
"Invalid access!");
624 return ImmRange.Last;
628 assert(Kind == k_CondCode &&
"Invalid access!");
633 assert (Kind == k_FPImm &&
"Invalid access!");
634 return APFloat(APFloat::IEEEdouble(),
APInt(64, FPImm.Val,
true));
637 bool getFPImmIsExact()
const {
638 assert (Kind == k_FPImm &&
"Invalid access!");
639 return FPImm.IsExact;
642 unsigned getBarrier()
const {
643 assert(Kind == k_Barrier &&
"Invalid access!");
648 assert(Kind == k_Barrier &&
"Invalid access!");
652 bool getBarriernXSModifier()
const {
653 assert(Kind == k_Barrier &&
"Invalid access!");
657 unsigned getReg()
const override {
658 assert(Kind == k_Register &&
"Invalid access!");
662 unsigned getMatrixReg()
const {
663 assert(Kind == k_MatrixRegister &&
"Invalid access!");
664 return MatrixReg.RegNum;
667 unsigned getMatrixElementWidth()
const {
668 assert(Kind == k_MatrixRegister &&
"Invalid access!");
669 return MatrixReg.ElementWidth;
672 MatrixKind getMatrixKind()
const {
673 assert(Kind == k_MatrixRegister &&
"Invalid access!");
674 return MatrixReg.Kind;
677 unsigned getMatrixTileListRegMask()
const {
678 assert(isMatrixTileList() &&
"Invalid access!");
679 return MatrixTileList.RegMask;
682 RegConstraintEqualityTy getRegEqualityTy()
const {
683 assert(Kind == k_Register &&
"Invalid access!");
684 return Reg.EqualityTy;
687 unsigned getVectorListStart()
const {
688 assert(Kind == k_VectorList &&
"Invalid access!");
689 return VectorList.RegNum;
692 unsigned getVectorListCount()
const {
693 assert(Kind == k_VectorList &&
"Invalid access!");
694 return VectorList.Count;
697 unsigned getVectorListStride()
const {
698 assert(Kind == k_VectorList &&
"Invalid access!");
699 return VectorList.Stride;
702 int getVectorIndex()
const {
703 assert(Kind == k_VectorIndex &&
"Invalid access!");
704 return VectorIndex.Val;
708 assert(Kind == k_SysReg &&
"Invalid access!");
709 return StringRef(SysReg.Data, SysReg.Length);
712 unsigned getSysCR()
const {
713 assert(Kind == k_SysCR &&
"Invalid access!");
717 unsigned getPrefetch()
const {
718 assert(Kind == k_Prefetch &&
"Invalid access!");
722 unsigned getPSBHint()
const {
723 assert(Kind == k_PSBHint &&
"Invalid access!");
728 assert(Kind == k_PSBHint &&
"Invalid access!");
729 return StringRef(PSBHint.Data, PSBHint.Length);
732 unsigned getBTIHint()
const {
733 assert(Kind == k_BTIHint &&
"Invalid access!");
738 assert(Kind == k_BTIHint &&
"Invalid access!");
739 return StringRef(BTIHint.Data, BTIHint.Length);
743 assert(Kind == k_SVCR &&
"Invalid access!");
744 return StringRef(SVCR.Data, SVCR.Length);
748 assert(Kind == k_Prefetch &&
"Invalid access!");
753 if (Kind == k_ShiftExtend)
754 return ShiftExtend.Type;
755 if (Kind == k_Register)
756 return Reg.ShiftExtend.Type;
760 unsigned getShiftExtendAmount()
const {
761 if (Kind == k_ShiftExtend)
762 return ShiftExtend.Amount;
763 if (Kind == k_Register)
764 return Reg.ShiftExtend.Amount;
768 bool hasShiftExtendAmount()
const {
769 if (Kind == k_ShiftExtend)
770 return ShiftExtend.HasExplicitAmount;
771 if (Kind == k_Register)
772 return Reg.ShiftExtend.HasExplicitAmount;
776 bool isImm()
const override {
return Kind == k_Immediate; }
777 bool isMem()
const override {
return false; }
779 bool isUImm6()
const {
786 return (Val >= 0 && Val < 64);
789 template <
int W
idth>
bool isSImm()
const {
return isSImmScaled<Width, 1>(); }
792 return isImmScaled<Bits, Scale>(
true);
795 template <
int Bits,
int Scale,
int Offset = 0,
bool IsRange = false>
797 if (IsRange && isImmRange() &&
798 (getLastImmVal() != getFirstImmVal() +
Offset))
799 return DiagnosticPredicateTy::NoMatch;
801 return isImmScaled<Bits, Scale, IsRange>(
false);
804 template <
int Bits,
int Scale,
bool IsRange = false>
806 if ((!
isImm() && !isImmRange()) || (
isImm() && IsRange) ||
807 (isImmRange() && !IsRange))
808 return DiagnosticPredicateTy::NoMatch;
812 Val = getFirstImmVal();
816 return DiagnosticPredicateTy::NoMatch;
820 int64_t MinVal, MaxVal;
822 int64_t Shift =
Bits - 1;
823 MinVal = (int64_t(1) << Shift) * -Scale;
824 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
827 MaxVal = ((int64_t(1) <<
Bits) - 1) * Scale;
830 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
831 return DiagnosticPredicateTy::Match;
833 return DiagnosticPredicateTy::NearMatch;
838 return DiagnosticPredicateTy::NoMatch;
839 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
841 return DiagnosticPredicateTy::NoMatch;
843 if (Val >= 0 && Val < 32)
844 return DiagnosticPredicateTy::Match;
845 return DiagnosticPredicateTy::NearMatch;
850 return DiagnosticPredicateTy::NoMatch;
851 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
853 return DiagnosticPredicateTy::NoMatch;
855 if (Val >= 0 && Val <= 1)
856 return DiagnosticPredicateTy::Match;
857 return DiagnosticPredicateTy::NearMatch;
860 bool isSymbolicUImm12Offset(
const MCExpr *Expr)
const {
864 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
896 template <
int Scale>
bool isUImm12Offset()
const {
902 return isSymbolicUImm12Offset(getImm());
905 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
908 template <
int N,
int M>
909 bool isImmInRange()
const {
916 return (Val >=
N && Val <= M);
921 template <
typename T>
922 bool isLogicalImm()
const {
939 bool isShiftedImm()
const {
return Kind == k_ShiftedImm; }
941 bool isImmRange()
const {
return Kind == k_ImmRange; }
946 template <
unsigned W
idth>
947 std::optional<std::pair<int64_t, unsigned>> getShiftedVal()
const {
948 if (isShiftedImm() && Width == getShiftedImmShift())
949 if (
auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
950 return std::make_pair(
CE->getValue(), Width);
953 if (
auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
954 int64_t Val =
CE->getValue();
956 return std::make_pair(Val >> Width, Width);
958 return std::make_pair(Val, 0u);
964 bool isAddSubImm()
const {
965 if (!isShiftedImm() && !
isImm())
971 if (isShiftedImm()) {
972 unsigned Shift = ShiftedImm.ShiftAmount;
973 Expr = ShiftedImm.Val;
974 if (Shift != 0 && Shift != 12)
983 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
984 DarwinRefKind, Addend)) {
1001 if (
auto ShiftedVal = getShiftedVal<12>())
1002 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
1009 bool isAddSubImmNeg()
const {
1010 if (!isShiftedImm() && !
isImm())
1014 if (
auto ShiftedVal = getShiftedVal<12>())
1015 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
1025 template <
typename T>
1027 if (!isShiftedImm() && (!
isImm() || !isa<MCConstantExpr>(getImm())))
1028 return DiagnosticPredicateTy::NoMatch;
1030 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>
::value ||
1031 std::is_same<int8_t, T>::value;
1032 if (
auto ShiftedImm = getShiftedVal<8>())
1033 if (!(IsByte && ShiftedImm->second) &&
1034 AArch64_AM::isSVECpyImm<T>(
uint64_t(ShiftedImm->first)
1035 << ShiftedImm->second))
1036 return DiagnosticPredicateTy::Match;
1038 return DiagnosticPredicateTy::NearMatch;
1045 if (!isShiftedImm() && (!
isImm() || !isa<MCConstantExpr>(getImm())))
1046 return DiagnosticPredicateTy::NoMatch;
1048 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>
::value ||
1049 std::is_same<int8_t, T>::value;
1050 if (
auto ShiftedImm = getShiftedVal<8>())
1051 if (!(IsByte && ShiftedImm->second) &&
1052 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
1053 << ShiftedImm->second))
1054 return DiagnosticPredicateTy::Match;
1056 return DiagnosticPredicateTy::NearMatch;
1060 if (isLogicalImm<T>() && !isSVECpyImm<T>())
1061 return DiagnosticPredicateTy::Match;
1062 return DiagnosticPredicateTy::NoMatch;
1065 bool isCondCode()
const {
return Kind == k_CondCode; }
1067 bool isSIMDImmType10()
const {
1077 bool isBranchTarget()
const {
1086 assert(
N > 0 &&
"Branch target immediate cannot be 0 bits!");
1087 return (Val >= -((1<<(
N-1)) << 2) && Val <= (((1<<(
N-1))-1) << 2));
1098 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
1099 DarwinRefKind, Addend)) {
1108 bool isMovWSymbolG3()
const {
1112 bool isMovWSymbolG2()
const {
1113 return isMovWSymbol(
1120 bool isMovWSymbolG1()
const {
1121 return isMovWSymbol(
1129 bool isMovWSymbolG0()
const {
1130 return isMovWSymbol(
1138 template<
int RegW
idth,
int Shift>
1139 bool isMOVZMovAlias()
const {
1140 if (!
isImm())
return false;
1153 template<
int RegW
idth,
int Shift>
1154 bool isMOVNMovAlias()
const {
1155 if (!
isImm())
return false;
1158 if (!CE)
return false;
1164 bool isFPImm()
const {
1165 return Kind == k_FPImm &&
1169 bool isBarrier()
const {
1170 return Kind == k_Barrier && !getBarriernXSModifier();
1172 bool isBarriernXS()
const {
1173 return Kind == k_Barrier && getBarriernXSModifier();
1175 bool isSysReg()
const {
return Kind == k_SysReg; }
1177 bool isMRSSystemRegister()
const {
1178 if (!isSysReg())
return false;
1180 return SysReg.MRSReg != -1U;
1183 bool isMSRSystemRegister()
const {
1184 if (!isSysReg())
return false;
1185 return SysReg.MSRReg != -1U;
1188 bool isSystemPStateFieldWithImm0_1()
const {
1189 if (!isSysReg())
return false;
1190 return AArch64PState::lookupPStateImm0_1ByEncoding(SysReg.PStateField);
1193 bool isSystemPStateFieldWithImm0_15()
const {
1196 return AArch64PState::lookupPStateImm0_15ByEncoding(SysReg.PStateField);
1199 bool isSVCR()
const {
1202 return SVCR.PStateField != -1U;
1205 bool isReg()
const override {
1206 return Kind == k_Register;
1209 bool isVectorList()
const {
return Kind == k_VectorList; }
1211 bool isScalarReg()
const {
1212 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar;
1215 bool isNeonVectorReg()
const {
1216 return Kind == k_Register &&
Reg.Kind == RegKind::NeonVector;
1219 bool isNeonVectorRegLo()
const {
1220 return Kind == k_Register &&
Reg.Kind == RegKind::NeonVector &&
1221 (AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1223 AArch64MCRegisterClasses[AArch64::FPR64_loRegClassID].contains(
1227 bool isNeonVectorReg0to7()
const {
1228 return Kind == k_Register &&
Reg.Kind == RegKind::NeonVector &&
1229 (AArch64MCRegisterClasses[AArch64::FPR128_0to7RegClassID].contains(
1233 bool isMatrix()
const {
return Kind == k_MatrixRegister; }
1234 bool isMatrixTileList()
const {
return Kind == k_MatrixTileList; }
1236 template <
unsigned Class>
bool isSVEPredicateAsCounterReg()
const {
1239 case AArch64::PPRRegClassID:
1240 case AArch64::PPR_3bRegClassID:
1241 case AArch64::PPR_p8to15RegClassID:
1242 case AArch64::PNRRegClassID:
1243 case AArch64::PNR_p8to15RegClassID:
1244 RK = RegKind::SVEPredicateAsCounter;
1250 return (Kind == k_Register &&
Reg.Kind == RK) &&
1251 AArch64MCRegisterClasses[
Class].contains(
getReg());
1254 template <
unsigned Class>
bool isSVEVectorReg()
const {
1257 case AArch64::ZPRRegClassID:
1258 case AArch64::ZPR_3bRegClassID:
1259 case AArch64::ZPR_4bRegClassID:
1260 RK = RegKind::SVEDataVector;
1262 case AArch64::PPRRegClassID:
1263 case AArch64::PPR_3bRegClassID:
1264 case AArch64::PPR_p8to15RegClassID:
1265 case AArch64::PNRRegClassID:
1266 case AArch64::PNR_p8to15RegClassID:
1267 RK = RegKind::SVEPredicateVector;
1273 return (Kind == k_Register &&
Reg.Kind == RK) &&
1274 AArch64MCRegisterClasses[
Class].contains(
getReg());
1277 template <
unsigned Class>
bool isFPRasZPR()
const {
1278 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1279 AArch64MCRegisterClasses[
Class].contains(
getReg());
1282 template <
int ElementW
idth,
unsigned Class>
1284 if (Kind != k_Register ||
Reg.Kind != RegKind::SVEPredicateVector)
1285 return DiagnosticPredicateTy::NoMatch;
1287 if (isSVEVectorReg<Class>() && (
Reg.ElementWidth == ElementWidth))
1288 return DiagnosticPredicateTy::Match;
1290 return DiagnosticPredicateTy::NearMatch;
1293 template <
int ElementW
idth,
unsigned Class>
1295 if (Kind != k_Register ||
Reg.Kind != RegKind::SVEPredicateAsCounter)
1296 return DiagnosticPredicateTy::NoMatch;
1298 if (isSVEPredicateAsCounterReg<Class>() && (
Reg.ElementWidth == ElementWidth))
1299 return DiagnosticPredicateTy::Match;
1301 return DiagnosticPredicateTy::NearMatch;
1304 template <
int ElementW
idth,
unsigned Class>
1306 if (Kind != k_Register ||
Reg.Kind != RegKind::SVEDataVector)
1307 return DiagnosticPredicateTy::NoMatch;
1309 if (isSVEVectorReg<Class>() &&
Reg.ElementWidth == ElementWidth)
1310 return DiagnosticPredicateTy::Match;
1312 return DiagnosticPredicateTy::NearMatch;
1315 template <
int ElementWidth,
unsigned Class,
1317 bool ShiftWidthAlwaysSame>
1319 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1320 if (!VectorMatch.isMatch())
1321 return DiagnosticPredicateTy::NoMatch;
1326 bool MatchShift = getShiftExtendAmount() ==
Log2_32(ShiftWidth / 8);
1329 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1330 return DiagnosticPredicateTy::NoMatch;
1332 if (MatchShift && ShiftExtendTy == getShiftExtendType())
1333 return DiagnosticPredicateTy::Match;
1335 return DiagnosticPredicateTy::NearMatch;
1338 bool isGPR32as64()
const {
1339 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1340 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(
Reg.RegNum);
1343 bool isGPR64as32()
const {
1344 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1345 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(
Reg.RegNum);
1348 bool isGPR64x8()
const {
1349 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1350 AArch64MCRegisterClasses[AArch64::GPR64x8ClassRegClassID].contains(
1354 bool isWSeqPair()
const {
1355 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1356 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1360 bool isXSeqPair()
const {
1361 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1362 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1366 bool isSyspXzrPair()
const {
1367 return isGPR64<AArch64::GPR64RegClassID>() &&
Reg.RegNum == AArch64::XZR;
1370 template<
int64_t Angle,
int64_t Remainder>
1372 if (!
isImm())
return DiagnosticPredicateTy::NoMatch;
1375 if (!CE)
return DiagnosticPredicateTy::NoMatch;
1378 if (
Value % Angle == Remainder &&
Value <= 270)
1379 return DiagnosticPredicateTy::Match;
1380 return DiagnosticPredicateTy::NearMatch;
1383 template <
unsigned RegClassID>
bool isGPR64()
const {
1384 return Kind == k_Register &&
Reg.Kind == RegKind::Scalar &&
1385 AArch64MCRegisterClasses[RegClassID].contains(
getReg());
1388 template <
unsigned RegClassID,
int ExtW
idth>
1390 if (Kind != k_Register ||
Reg.Kind != RegKind::Scalar)
1391 return DiagnosticPredicateTy::NoMatch;
1393 if (isGPR64<RegClassID>() && getShiftExtendType() ==
AArch64_AM::LSL &&
1394 getShiftExtendAmount() ==
Log2_32(ExtWidth / 8))
1395 return DiagnosticPredicateTy::Match;
1396 return DiagnosticPredicateTy::NearMatch;
1401 template <RegKind VectorKind,
unsigned NumRegs>
1402 bool isImplicitlyTypedVectorList()
const {
1403 return Kind == k_VectorList && VectorList.Count == NumRegs &&
1404 VectorList.NumElements == 0 &&
1405 VectorList.RegisterKind == VectorKind;
1408 template <RegKind VectorKind,
unsigned NumRegs,
unsigned NumElements,
1409 unsigned ElementWidth,
unsigned Stride = 1>
1410 bool isTypedVectorList()
const {
1411 if (Kind != k_VectorList)
1413 if (VectorList.Count != NumRegs)
1415 if (VectorList.RegisterKind != VectorKind)
1417 if (VectorList.ElementWidth != ElementWidth)
1419 if (VectorList.Stride != Stride)
1421 return VectorList.NumElements == NumElements;
1424 template <RegKind VectorKind,
unsigned NumRegs,
unsigned NumElements,
1425 unsigned ElementWidth>
1428 isTypedVectorList<VectorKind, NumRegs, NumElements, ElementWidth>();
1430 return DiagnosticPredicateTy::NoMatch;
1431 if (((VectorList.RegNum - AArch64::Z0) % NumRegs) != 0)
1432 return DiagnosticPredicateTy::NearMatch;
1433 return DiagnosticPredicateTy::Match;
1436 template <RegKind VectorKind,
unsigned NumRegs,
unsigned Stride,
1437 unsigned ElementWidth>
1439 bool Res = isTypedVectorList<VectorKind, NumRegs, 0,
1440 ElementWidth, Stride>();
1442 return DiagnosticPredicateTy::NoMatch;
1443 if ((VectorList.RegNum < (AArch64::Z0 + Stride)) ||
1444 ((VectorList.RegNum >= AArch64::Z16) &&
1445 (VectorList.RegNum < (AArch64::Z16 + Stride))))
1446 return DiagnosticPredicateTy::Match;
1447 return DiagnosticPredicateTy::NoMatch;
1450 template <
int Min,
int Max>
1452 if (Kind != k_VectorIndex)
1453 return DiagnosticPredicateTy::NoMatch;
1454 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1455 return DiagnosticPredicateTy::Match;
1456 return DiagnosticPredicateTy::NearMatch;
1459 bool isToken()
const override {
return Kind == k_Token; }
1461 bool isTokenEqual(
StringRef Str)
const {
1462 return Kind == k_Token && getToken() == Str;
1464 bool isSysCR()
const {
return Kind == k_SysCR; }
1465 bool isPrefetch()
const {
return Kind == k_Prefetch; }
1466 bool isPSBHint()
const {
return Kind == k_PSBHint; }
1467 bool isBTIHint()
const {
return Kind == k_BTIHint; }
1468 bool isShiftExtend()
const {
return Kind == k_ShiftExtend; }
1469 bool isShifter()
const {
1470 if (!isShiftExtend())
1480 if (Kind != k_FPImm)
1481 return DiagnosticPredicateTy::NoMatch;
1483 if (getFPImmIsExact()) {
1485 auto *
Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1489 APFloat RealVal(APFloat::IEEEdouble());
1491 RealVal.convertFromString(
Desc->Repr, APFloat::rmTowardZero);
1492 if (
errorToBool(StatusOrErr.takeError()) || *StatusOrErr != APFloat::opOK)
1495 if (
getFPImm().bitwiseIsEqual(RealVal))
1496 return DiagnosticPredicateTy::Match;
1499 return DiagnosticPredicateTy::NearMatch;
1502 template <
unsigned ImmA,
unsigned ImmB>
1505 if ((Res = isExactFPImm<ImmA>()))
1506 return DiagnosticPredicateTy::Match;
1507 if ((Res = isExactFPImm<ImmB>()))
1508 return DiagnosticPredicateTy::Match;
1512 bool isExtend()
const {
1513 if (!isShiftExtend())
1522 getShiftExtendAmount() <= 4;
1525 bool isExtend64()
const {
1535 bool isExtendLSL64()
const {
1541 getShiftExtendAmount() <= 4;
1544 bool isLSLImm3Shift()
const {
1545 if (!isShiftExtend())
1551 template<
int W
idth>
bool isMemXExtend()
const {
1556 (getShiftExtendAmount() ==
Log2_32(Width / 8) ||
1557 getShiftExtendAmount() == 0);
1560 template<
int W
idth>
bool isMemWExtend()
const {
1565 (getShiftExtendAmount() ==
Log2_32(Width / 8) ||
1566 getShiftExtendAmount() == 0);
1569 template <
unsigned w
idth>
1570 bool isArithmeticShifter()
const {
1580 template <
unsigned w
idth>
1581 bool isLogicalShifter()
const {
1589 getShiftExtendAmount() < width;
1592 bool isMovImm32Shifter()
const {
1600 uint64_t Val = getShiftExtendAmount();
1601 return (Val == 0 || Val == 16);
1604 bool isMovImm64Shifter()
const {
1612 uint64_t Val = getShiftExtendAmount();
1613 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1616 bool isLogicalVecShifter()
const {
1621 unsigned Shift = getShiftExtendAmount();
1623 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1626 bool isLogicalVecHalfWordShifter()
const {
1627 if (!isLogicalVecShifter())
1631 unsigned Shift = getShiftExtendAmount();
1633 (Shift == 0 || Shift == 8);
1636 bool isMoveVecShifter()
const {
1637 if (!isShiftExtend())
1641 unsigned Shift = getShiftExtendAmount();
1643 (Shift == 8 || Shift == 16);
1652 bool isSImm9OffsetFB()
const {
1653 return isSImm<9>() && !isUImm12Offset<
Width / 8>();
1656 bool isAdrpLabel()
const {
1663 int64_t Val =
CE->getValue();
1664 int64_t Min = - (4096 * (1LL << (21 - 1)));
1665 int64_t
Max = 4096 * ((1LL << (21 - 1)) - 1);
1666 return (Val % 4096) == 0 && Val >= Min && Val <=
Max;
1672 bool isAdrLabel()
const {
1679 int64_t Val =
CE->getValue();
1680 int64_t Min = - (1LL << (21 - 1));
1681 int64_t
Max = ((1LL << (21 - 1)) - 1);
1682 return Val >= Min && Val <=
Max;
1688 template <MatrixKind Kind,
unsigned EltSize,
unsigned RegClass>
1691 return DiagnosticPredicateTy::NoMatch;
1692 if (getMatrixKind() != Kind ||
1693 !AArch64MCRegisterClasses[RegClass].
contains(getMatrixReg()) ||
1694 EltSize != getMatrixElementWidth())
1695 return DiagnosticPredicateTy::NearMatch;
1696 return DiagnosticPredicateTy::Match;
1703 else if (
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1709 void addRegOperands(
MCInst &Inst,
unsigned N)
const {
1710 assert(
N == 1 &&
"Invalid number of operands!");
1714 void addMatrixOperands(
MCInst &Inst,
unsigned N)
const {
1715 assert(
N == 1 &&
"Invalid number of operands!");
1719 void addGPR32as64Operands(
MCInst &Inst,
unsigned N)
const {
1720 assert(
N == 1 &&
"Invalid number of operands!");
1722 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].
contains(
getReg()));
1731 void addGPR64as32Operands(
MCInst &Inst,
unsigned N)
const {
1732 assert(
N == 1 &&
"Invalid number of operands!");
1734 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].
contains(
getReg()));
1743 template <
int W
idth>
1744 void addFPRasZPRRegOperands(
MCInst &Inst,
unsigned N)
const {
1747 case 8:
Base = AArch64::B0;
break;
1748 case 16:
Base = AArch64::H0;
break;
1749 case 32:
Base = AArch64::S0;
break;
1750 case 64:
Base = AArch64::D0;
break;
1751 case 128:
Base = AArch64::Q0;
break;
1758 void addPNRasPPRRegOperands(
MCInst &Inst,
unsigned N)
const {
1759 assert(
N == 1 &&
"Invalid number of operands!");
1764 void addVectorReg64Operands(
MCInst &Inst,
unsigned N)
const {
1765 assert(
N == 1 &&
"Invalid number of operands!");
1767 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].
contains(
getReg()));
1771 void addVectorReg128Operands(
MCInst &Inst,
unsigned N)
const {
1772 assert(
N == 1 &&
"Invalid number of operands!");
1774 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].
contains(
getReg()));
1778 void addVectorRegLoOperands(
MCInst &Inst,
unsigned N)
const {
1779 assert(
N == 1 &&
"Invalid number of operands!");
1783 void addVectorReg0to7Operands(
MCInst &Inst,
unsigned N)
const {
1784 assert(
N == 1 &&
"Invalid number of operands!");
1788 enum VecListIndexType {
1789 VecListIdx_DReg = 0,
1790 VecListIdx_QReg = 1,
1791 VecListIdx_ZReg = 2,
1792 VecListIdx_PReg = 3,
1795 template <VecListIndexType RegTy,
unsigned NumRegs>
1796 void addVectorListOperands(
MCInst &Inst,
unsigned N)
const {
1797 assert(
N == 1 &&
"Invalid number of operands!");
1798 static const unsigned FirstRegs[][5] = {
1800 AArch64::D0, AArch64::D0_D1,
1801 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1803 AArch64::Q0, AArch64::Q0_Q1,
1804 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1806 AArch64::Z0, AArch64::Z0_Z1,
1807 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 },
1809 AArch64::P0, AArch64::P0_P1 }
1812 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1813 " NumRegs must be <= 4 for ZRegs");
1815 assert((RegTy != VecListIdx_PReg || NumRegs <= 2) &&
1816 " NumRegs must be <= 2 for PRegs");
1818 unsigned FirstReg = FirstRegs[(
unsigned)RegTy][NumRegs];
1820 FirstRegs[(
unsigned)RegTy][0]));
1823 template <
unsigned NumRegs>
1824 void addStridedVectorListOperands(
MCInst &Inst,
unsigned N)
const {
1825 assert(
N == 1 &&
"Invalid number of operands!");
1826 assert((NumRegs == 2 || NumRegs == 4) &&
" NumRegs must be 2 or 4");
1830 if (getVectorListStart() < AArch64::Z16) {
1831 assert((getVectorListStart() < AArch64::Z8) &&
1832 (getVectorListStart() >= AArch64::Z0) &&
"Invalid Register");
1834 AArch64::Z0_Z8 + getVectorListStart() - AArch64::Z0));
1836 assert((getVectorListStart() < AArch64::Z24) &&
1837 (getVectorListStart() >= AArch64::Z16) &&
"Invalid Register");
1839 AArch64::Z16_Z24 + getVectorListStart() - AArch64::Z16));
1843 if (getVectorListStart() < AArch64::Z16) {
1844 assert((getVectorListStart() < AArch64::Z4) &&
1845 (getVectorListStart() >= AArch64::Z0) &&
"Invalid Register");
1847 AArch64::Z0_Z4_Z8_Z12 + getVectorListStart() - AArch64::Z0));
1849 assert((getVectorListStart() < AArch64::Z20) &&
1850 (getVectorListStart() >= AArch64::Z16) &&
"Invalid Register");
1852 AArch64::Z16_Z20_Z24_Z28 + getVectorListStart() - AArch64::Z16));
1860 void addMatrixTileListOperands(
MCInst &Inst,
unsigned N)
const {
1861 assert(
N == 1 &&
"Invalid number of operands!");
1862 unsigned RegMask = getMatrixTileListRegMask();
1867 void addVectorIndexOperands(
MCInst &Inst,
unsigned N)
const {
1868 assert(
N == 1 &&
"Invalid number of operands!");
1872 template <
unsigned ImmIs0,
unsigned ImmIs1>
1873 void addExactFPImmOperands(
MCInst &Inst,
unsigned N)
const {
1874 assert(
N == 1 &&
"Invalid number of operands!");
1875 assert(
bool(isExactFPImm<ImmIs0, ImmIs1>()) &&
"Invalid operand");
1879 void addImmOperands(
MCInst &Inst,
unsigned N)
const {
1880 assert(
N == 1 &&
"Invalid number of operands!");
1884 addExpr(Inst, getImm());
1887 template <
int Shift>
1888 void addImmWithOptionalShiftOperands(
MCInst &Inst,
unsigned N)
const {
1889 assert(
N == 2 &&
"Invalid number of operands!");
1890 if (
auto ShiftedVal = getShiftedVal<Shift>()) {
1893 }
else if (isShiftedImm()) {
1894 addExpr(Inst, getShiftedImmVal());
1897 addExpr(Inst, getImm());
1902 template <
int Shift>
1903 void addImmNegWithOptionalShiftOperands(
MCInst &Inst,
unsigned N)
const {
1904 assert(
N == 2 &&
"Invalid number of operands!");
1905 if (
auto ShiftedVal = getShiftedVal<Shift>()) {
1912 void addCondCodeOperands(
MCInst &Inst,
unsigned N)
const {
1913 assert(
N == 1 &&
"Invalid number of operands!");
1917 void addAdrpLabelOperands(
MCInst &Inst,
unsigned N)
const {
1918 assert(
N == 1 &&
"Invalid number of operands!");
1921 addExpr(Inst, getImm());
1926 void addAdrLabelOperands(
MCInst &Inst,
unsigned N)
const {
1927 addImmOperands(Inst,
N);
1931 void addUImm12OffsetOperands(
MCInst &Inst,
unsigned N)
const {
1932 assert(
N == 1 &&
"Invalid number of operands!");
1942 void addUImm6Operands(
MCInst &Inst,
unsigned N)
const {
1943 assert(
N == 1 &&
"Invalid number of operands!");
1948 template <
int Scale>
1949 void addImmScaledOperands(
MCInst &Inst,
unsigned N)
const {
1950 assert(
N == 1 &&
"Invalid number of operands!");
1955 template <
int Scale>
1956 void addImmScaledRangeOperands(
MCInst &Inst,
unsigned N)
const {
1957 assert(
N == 1 &&
"Invalid number of operands!");
1961 template <
typename T>
1962 void addLogicalImmOperands(
MCInst &Inst,
unsigned N)
const {
1963 assert(
N == 1 &&
"Invalid number of operands!");
1965 std::make_unsigned_t<T> Val = MCE->
getValue();
1970 template <
typename T>
1971 void addLogicalImmNotOperands(
MCInst &Inst,
unsigned N)
const {
1972 assert(
N == 1 &&
"Invalid number of operands!");
1974 std::make_unsigned_t<T> Val = ~MCE->getValue();
1979 void addSIMDImmType10Operands(
MCInst &Inst,
unsigned N)
const {
1980 assert(
N == 1 &&
"Invalid number of operands!");
1986 void addBranchTarget26Operands(
MCInst &Inst,
unsigned N)
const {
1990 assert(
N == 1 &&
"Invalid number of operands!");
1993 addExpr(Inst, getImm());
1996 assert(MCE &&
"Invalid constant immediate operand!");
2000 void addPCRelLabel19Operands(
MCInst &Inst,
unsigned N)
const {
2004 assert(
N == 1 &&
"Invalid number of operands!");
2007 addExpr(Inst, getImm());
2010 assert(MCE &&
"Invalid constant immediate operand!");
2014 void addBranchTarget14Operands(
MCInst &Inst,
unsigned N)
const {
2018 assert(
N == 1 &&
"Invalid number of operands!");
2021 addExpr(Inst, getImm());
2024 assert(MCE &&
"Invalid constant immediate operand!");
2028 void addFPImmOperands(
MCInst &Inst,
unsigned N)
const {
2029 assert(
N == 1 &&
"Invalid number of operands!");
2034 void addBarrierOperands(
MCInst &Inst,
unsigned N)
const {
2035 assert(
N == 1 &&
"Invalid number of operands!");
2039 void addBarriernXSOperands(
MCInst &Inst,
unsigned N)
const {
2040 assert(
N == 1 &&
"Invalid number of operands!");
2044 void addMRSSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
2045 assert(
N == 1 &&
"Invalid number of operands!");
2050 void addMSRSystemRegisterOperands(
MCInst &Inst,
unsigned N)
const {
2051 assert(
N == 1 &&
"Invalid number of operands!");
2056 void addSystemPStateFieldWithImm0_1Operands(
MCInst &Inst,
unsigned N)
const {
2057 assert(
N == 1 &&
"Invalid number of operands!");
2062 void addSVCROperands(
MCInst &Inst,
unsigned N)
const {
2063 assert(
N == 1 &&
"Invalid number of operands!");
2068 void addSystemPStateFieldWithImm0_15Operands(
MCInst &Inst,
unsigned N)
const {
2069 assert(
N == 1 &&
"Invalid number of operands!");
2074 void addSysCROperands(
MCInst &Inst,
unsigned N)
const {
2075 assert(
N == 1 &&
"Invalid number of operands!");
2079 void addPrefetchOperands(
MCInst &Inst,
unsigned N)
const {
2080 assert(
N == 1 &&
"Invalid number of operands!");
2084 void addPSBHintOperands(
MCInst &Inst,
unsigned N)
const {
2085 assert(
N == 1 &&
"Invalid number of operands!");
2089 void addBTIHintOperands(
MCInst &Inst,
unsigned N)
const {
2090 assert(
N == 1 &&
"Invalid number of operands!");
2094 void addShifterOperands(
MCInst &Inst,
unsigned N)
const {
2095 assert(
N == 1 &&
"Invalid number of operands!");
2101 void addLSLImm3ShifterOperands(
MCInst &Inst,
unsigned N)
const {
2102 assert(
N == 1 &&
"Invalid number of operands!");
2103 unsigned Imm = getShiftExtendAmount();
2107 void addSyspXzrPairOperand(
MCInst &Inst,
unsigned N)
const {
2108 assert(
N == 1 &&
"Invalid number of operands!");
2116 if (
Reg != AArch64::XZR)
2122 void addExtendOperands(
MCInst &Inst,
unsigned N)
const {
2123 assert(
N == 1 &&
"Invalid number of operands!");
2130 void addExtend64Operands(
MCInst &Inst,
unsigned N)
const {
2131 assert(
N == 1 &&
"Invalid number of operands!");
2138 void addMemExtendOperands(
MCInst &Inst,
unsigned N)
const {
2139 assert(
N == 2 &&
"Invalid number of operands!");
2150 void addMemExtend8Operands(
MCInst &Inst,
unsigned N)
const {
2151 assert(
N == 2 &&
"Invalid number of operands!");
2159 void addMOVZMovAliasOperands(
MCInst &Inst,
unsigned N)
const {
2160 assert(
N == 1 &&
"Invalid number of operands!");
2167 addExpr(Inst, getImm());
2172 void addMOVNMovAliasOperands(
MCInst &Inst,
unsigned N)
const {
2173 assert(
N == 1 &&
"Invalid number of operands!");
2180 void addComplexRotationEvenOperands(
MCInst &Inst,
unsigned N)
const {
2181 assert(
N == 1 &&
"Invalid number of operands!");
2186 void addComplexRotationOddOperands(
MCInst &Inst,
unsigned N)
const {
2187 assert(
N == 1 &&
"Invalid number of operands!");
2194 static std::unique_ptr<AArch64Operand>
2196 auto Op = std::make_unique<AArch64Operand>(k_Token, Ctx);
2197 Op->Tok.Data = Str.data();
2198 Op->Tok.Length = Str.size();
2199 Op->Tok.IsSuffix = IsSuffix;
2205 static std::unique_ptr<AArch64Operand>
2207 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
2209 unsigned ShiftAmount = 0,
2210 unsigned HasExplicitAmount =
false) {
2211 auto Op = std::make_unique<AArch64Operand>(k_Register, Ctx);
2212 Op->Reg.RegNum = RegNum;
2214 Op->Reg.ElementWidth = 0;
2215 Op->Reg.EqualityTy = EqTy;
2216 Op->Reg.ShiftExtend.Type = ExtTy;
2217 Op->Reg.ShiftExtend.Amount = ShiftAmount;
2218 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2224 static std::unique_ptr<AArch64Operand>
2225 CreateVectorReg(
unsigned RegNum, RegKind Kind,
unsigned ElementWidth,
2228 unsigned ShiftAmount = 0,
2229 unsigned HasExplicitAmount =
false) {
2230 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
2231 Kind == RegKind::SVEPredicateVector ||
2232 Kind == RegKind::SVEPredicateAsCounter) &&
2233 "Invalid vector kind");
2234 auto Op = CreateReg(RegNum, Kind, S,
E, Ctx, EqualsReg, ExtTy, ShiftAmount,
2236 Op->Reg.ElementWidth = ElementWidth;
2240 static std::unique_ptr<AArch64Operand>
2241 CreateVectorList(
unsigned RegNum,
unsigned Count,
unsigned Stride,
2242 unsigned NumElements,
unsigned ElementWidth,
2244 auto Op = std::make_unique<AArch64Operand>(k_VectorList, Ctx);
2245 Op->VectorList.RegNum = RegNum;
2246 Op->VectorList.Count = Count;
2247 Op->VectorList.Stride = Stride;
2248 Op->VectorList.NumElements = NumElements;
2249 Op->VectorList.ElementWidth = ElementWidth;
2250 Op->VectorList.RegisterKind = RegisterKind;
2256 static std::unique_ptr<AArch64Operand>
2258 auto Op = std::make_unique<AArch64Operand>(k_VectorIndex, Ctx);
2259 Op->VectorIndex.Val =
Idx;
2265 static std::unique_ptr<AArch64Operand>
2267 auto Op = std::make_unique<AArch64Operand>(k_MatrixTileList, Ctx);
2275 const unsigned ElementWidth) {
2276 static std::map<std::pair<unsigned, unsigned>, std::vector<unsigned>>
2278 {{0, AArch64::ZAB0},
2279 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2280 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2281 {{8, AArch64::ZAB0},
2282 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2283 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2284 {{16, AArch64::ZAH0},
2285 {AArch64::ZAD0, AArch64::ZAD2, AArch64::ZAD4, AArch64::ZAD6}},
2286 {{16, AArch64::ZAH1},
2287 {AArch64::ZAD1, AArch64::ZAD3, AArch64::ZAD5, AArch64::ZAD7}},
2288 {{32, AArch64::ZAS0}, {AArch64::ZAD0, AArch64::ZAD4}},
2289 {{32, AArch64::ZAS1}, {AArch64::ZAD1, AArch64::ZAD5}},
2290 {{32, AArch64::ZAS2}, {AArch64::ZAD2, AArch64::ZAD6}},
2291 {{32, AArch64::ZAS3}, {AArch64::ZAD3, AArch64::ZAD7}},
2294 if (ElementWidth == 64)
2297 std::vector<unsigned> Regs = RegMap[std::make_pair(ElementWidth,
Reg)];
2298 assert(!Regs.empty() &&
"Invalid tile or element width!");
2299 for (
auto OutReg : Regs)
2304 static std::unique_ptr<AArch64Operand> CreateImm(
const MCExpr *Val,
SMLoc S,
2306 auto Op = std::make_unique<AArch64Operand>(k_Immediate, Ctx);
2313 static std::unique_ptr<AArch64Operand> CreateShiftedImm(
const MCExpr *Val,
2314 unsigned ShiftAmount,
2317 auto Op = std::make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
2318 Op->ShiftedImm .Val = Val;
2319 Op->ShiftedImm.ShiftAmount = ShiftAmount;
2325 static std::unique_ptr<AArch64Operand> CreateImmRange(
unsigned First,
2329 auto Op = std::make_unique<AArch64Operand>(k_ImmRange, Ctx);
2331 Op->ImmRange.Last =
Last;
2336 static std::unique_ptr<AArch64Operand>
2338 auto Op = std::make_unique<AArch64Operand>(k_CondCode, Ctx);
2339 Op->CondCode.Code =
Code;
2345 static std::unique_ptr<AArch64Operand>
2347 auto Op = std::make_unique<AArch64Operand>(k_FPImm, Ctx);
2349 Op->FPImm.IsExact = IsExact;
2355 static std::unique_ptr<AArch64Operand> CreateBarrier(
unsigned Val,
2359 bool HasnXSModifier) {
2360 auto Op = std::make_unique<AArch64Operand>(k_Barrier, Ctx);
2361 Op->Barrier.Val = Val;
2362 Op->Barrier.Data = Str.data();
2363 Op->Barrier.Length = Str.size();
2364 Op->Barrier.HasnXSModifier = HasnXSModifier;
2370 static std::unique_ptr<AArch64Operand> CreateSysReg(
StringRef Str,
SMLoc S,
2375 auto Op = std::make_unique<AArch64Operand>(k_SysReg, Ctx);
2376 Op->SysReg.Data = Str.data();
2377 Op->SysReg.Length = Str.size();
2378 Op->SysReg.MRSReg = MRSReg;
2379 Op->SysReg.MSRReg = MSRReg;
2380 Op->SysReg.PStateField = PStateField;
2386 static std::unique_ptr<AArch64Operand> CreateSysCR(
unsigned Val,
SMLoc S,
2388 auto Op = std::make_unique<AArch64Operand>(k_SysCR, Ctx);
2389 Op->SysCRImm.Val = Val;
2395 static std::unique_ptr<AArch64Operand> CreatePrefetch(
unsigned Val,
2399 auto Op = std::make_unique<AArch64Operand>(k_Prefetch, Ctx);
2400 Op->Prefetch.Val = Val;
2401 Op->Barrier.Data = Str.data();
2402 Op->Barrier.Length = Str.size();
2408 static std::unique_ptr<AArch64Operand> CreatePSBHint(
unsigned Val,
2412 auto Op = std::make_unique<AArch64Operand>(k_PSBHint, Ctx);
2413 Op->PSBHint.Val = Val;
2414 Op->PSBHint.Data = Str.data();
2415 Op->PSBHint.Length = Str.size();
2421 static std::unique_ptr<AArch64Operand> CreateBTIHint(
unsigned Val,
2425 auto Op = std::make_unique<AArch64Operand>(k_BTIHint, Ctx);
2426 Op->BTIHint.Val = Val | 32;
2427 Op->BTIHint.Data = Str.data();
2428 Op->BTIHint.Length = Str.size();
2434 static std::unique_ptr<AArch64Operand>
2435 CreateMatrixRegister(
unsigned RegNum,
unsigned ElementWidth, MatrixKind Kind,
2437 auto Op = std::make_unique<AArch64Operand>(k_MatrixRegister, Ctx);
2438 Op->MatrixReg.RegNum = RegNum;
2439 Op->MatrixReg.ElementWidth = ElementWidth;
2440 Op->MatrixReg.Kind =
Kind;
2446 static std::unique_ptr<AArch64Operand>
2448 auto Op = std::make_unique<AArch64Operand>(k_SVCR, Ctx);
2449 Op->SVCR.PStateField = PStateField;
2450 Op->SVCR.Data = Str.data();
2451 Op->SVCR.Length = Str.size();
2457 static std::unique_ptr<AArch64Operand>
2460 auto Op = std::make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
2461 Op->ShiftExtend.Type = ShOp;
2462 Op->ShiftExtend.Amount = Val;
2463 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2475 OS <<
"<fpimm " <<
getFPImm().bitcastToAPInt().getZExtValue();
2476 if (!getFPImmIsExact())
2483 OS <<
"<barrier " <<
Name <<
">";
2485 OS <<
"<barrier invalid #" << getBarrier() <<
">";
2491 case k_ShiftedImm: {
2492 unsigned Shift = getShiftedImmShift();
2493 OS <<
"<shiftedimm ";
2494 OS << *getShiftedImmVal();
2500 OS << getFirstImmVal();
2501 OS <<
":" << getLastImmVal() <<
">";
2507 case k_VectorList: {
2508 OS <<
"<vectorlist ";
2509 unsigned Reg = getVectorListStart();
2510 for (
unsigned i = 0, e = getVectorListCount(); i !=
e; ++i)
2511 OS <<
Reg + i * getVectorListStride() <<
" ";
2516 OS <<
"<vectorindex " << getVectorIndex() <<
">";
2519 OS <<
"<sysreg: " << getSysReg() <<
'>';
2522 OS <<
"'" << getToken() <<
"'";
2525 OS <<
"c" << getSysCR();
2530 OS <<
"<prfop " <<
Name <<
">";
2532 OS <<
"<prfop invalid #" << getPrefetch() <<
">";
2536 OS << getPSBHintName();
2539 OS << getBTIHintName();
2541 case k_MatrixRegister:
2542 OS <<
"<matrix " << getMatrixReg() <<
">";
2544 case k_MatrixTileList: {
2545 OS <<
"<matrixlist ";
2546 unsigned RegMask = getMatrixTileListRegMask();
2547 unsigned MaxBits = 8;
2548 for (
unsigned I = MaxBits;
I > 0; --
I)
2558 OS <<
"<register " <<
getReg() <<
">";
2559 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2564 << getShiftExtendAmount();
2565 if (!hasShiftExtendAmount())
2581 .
Case(
"v0", AArch64::Q0)
2582 .
Case(
"v1", AArch64::Q1)
2583 .
Case(
"v2", AArch64::Q2)
2584 .
Case(
"v3", AArch64::Q3)
2585 .
Case(
"v4", AArch64::Q4)
2586 .
Case(
"v5", AArch64::Q5)
2587 .
Case(
"v6", AArch64::Q6)
2588 .
Case(
"v7", AArch64::Q7)
2589 .
Case(
"v8", AArch64::Q8)
2590 .
Case(
"v9", AArch64::Q9)
2591 .
Case(
"v10", AArch64::Q10)
2592 .
Case(
"v11", AArch64::Q11)
2593 .
Case(
"v12", AArch64::Q12)
2594 .
Case(
"v13", AArch64::Q13)
2595 .
Case(
"v14", AArch64::Q14)
2596 .
Case(
"v15", AArch64::Q15)
2597 .
Case(
"v16", AArch64::Q16)
2598 .
Case(
"v17", AArch64::Q17)
2599 .
Case(
"v18", AArch64::Q18)
2600 .
Case(
"v19", AArch64::Q19)
2601 .
Case(
"v20", AArch64::Q20)
2602 .
Case(
"v21", AArch64::Q21)
2603 .
Case(
"v22", AArch64::Q22)
2604 .
Case(
"v23", AArch64::Q23)
2605 .
Case(
"v24", AArch64::Q24)
2606 .
Case(
"v25", AArch64::Q25)
2607 .
Case(
"v26", AArch64::Q26)
2608 .
Case(
"v27", AArch64::Q27)
2609 .
Case(
"v28", AArch64::Q28)
2610 .
Case(
"v29", AArch64::Q29)
2611 .
Case(
"v30", AArch64::Q30)
2612 .
Case(
"v31", AArch64::Q31)
2621 RegKind VectorKind) {
2622 std::pair<int, int> Res = {-1, -1};
2624 switch (VectorKind) {
2625 case RegKind::NeonVector:
2628 .Case(
".1d", {1, 64})
2629 .Case(
".1q", {1, 128})
2631 .Case(
".2h", {2, 16})
2632 .Case(
".2b", {2, 8})
2633 .Case(
".2s", {2, 32})
2634 .Case(
".2d", {2, 64})
2637 .Case(
".4b", {4, 8})
2638 .Case(
".4h", {4, 16})
2639 .Case(
".4s", {4, 32})
2640 .Case(
".8b", {8, 8})
2641 .Case(
".8h", {8, 16})
2642 .Case(
".16b", {16, 8})
2647 .Case(
".h", {0, 16})
2648 .Case(
".s", {0, 32})
2649 .Case(
".d", {0, 64})
2652 case RegKind::SVEPredicateAsCounter:
2653 case RegKind::SVEPredicateVector:
2654 case RegKind::SVEDataVector:
2655 case RegKind::Matrix:
2659 .Case(
".h", {0, 16})
2660 .Case(
".s", {0, 32})
2661 .Case(
".d", {0, 64})
2662 .Case(
".q", {0, 128})
2669 if (Res == std::make_pair(-1, -1))
2670 return std::nullopt;
2672 return std::optional<std::pair<int, int>>(Res);
2681 .
Case(
"z0", AArch64::Z0)
2682 .
Case(
"z1", AArch64::Z1)
2683 .
Case(
"z2", AArch64::Z2)
2684 .
Case(
"z3", AArch64::Z3)
2685 .
Case(
"z4", AArch64::Z4)
2686 .
Case(
"z5", AArch64::Z5)
2687 .
Case(
"z6", AArch64::Z6)
2688 .
Case(
"z7", AArch64::Z7)
2689 .
Case(
"z8", AArch64::Z8)
2690 .
Case(
"z9", AArch64::Z9)
2691 .
Case(
"z10", AArch64::Z10)
2692 .
Case(
"z11", AArch64::Z11)
2693 .
Case(
"z12", AArch64::Z12)
2694 .
Case(
"z13", AArch64::Z13)
2695 .
Case(
"z14", AArch64::Z14)
2696 .
Case(
"z15", AArch64::Z15)
2697 .
Case(
"z16", AArch64::Z16)
2698 .
Case(
"z17", AArch64::Z17)
2699 .
Case(
"z18", AArch64::Z18)
2700 .
Case(
"z19", AArch64::Z19)
2701 .
Case(
"z20", AArch64::Z20)
2702 .
Case(
"z21", AArch64::Z21)
2703 .
Case(
"z22", AArch64::Z22)
2704 .
Case(
"z23", AArch64::Z23)
2705 .
Case(
"z24", AArch64::Z24)
2706 .
Case(
"z25", AArch64::Z25)
2707 .
Case(
"z26", AArch64::Z26)
2708 .
Case(
"z27", AArch64::Z27)
2709 .
Case(
"z28", AArch64::Z28)
2710 .
Case(
"z29", AArch64::Z29)
2711 .
Case(
"z30", AArch64::Z30)
2712 .
Case(
"z31", AArch64::Z31)
2718 .
Case(
"p0", AArch64::P0)
2719 .
Case(
"p1", AArch64::P1)
2720 .
Case(
"p2", AArch64::P2)
2721 .
Case(
"p3", AArch64::P3)
2722 .
Case(
"p4", AArch64::P4)
2723 .
Case(
"p5", AArch64::P5)
2724 .
Case(
"p6", AArch64::P6)
2725 .
Case(
"p7", AArch64::P7)
2726 .
Case(
"p8", AArch64::P8)
2727 .
Case(
"p9", AArch64::P9)
2728 .
Case(
"p10", AArch64::P10)
2729 .
Case(
"p11", AArch64::P11)
2730 .
Case(
"p12", AArch64::P12)
2731 .
Case(
"p13", AArch64::P13)
2732 .
Case(
"p14", AArch64::P14)
2733 .
Case(
"p15", AArch64::P15)
2739 .
Case(
"pn0", AArch64::PN0)
2740 .
Case(
"pn1", AArch64::PN1)
2741 .
Case(
"pn2", AArch64::PN2)
2742 .
Case(
"pn3", AArch64::PN3)
2743 .
Case(
"pn4", AArch64::PN4)
2744 .
Case(
"pn5", AArch64::PN5)
2745 .
Case(
"pn6", AArch64::PN6)
2746 .
Case(
"pn7", AArch64::PN7)
2747 .
Case(
"pn8", AArch64::PN8)
2748 .
Case(
"pn9", AArch64::PN9)
2749 .
Case(
"pn10", AArch64::PN10)
2750 .
Case(
"pn11", AArch64::PN11)
2751 .
Case(
"pn12", AArch64::PN12)
2752 .
Case(
"pn13", AArch64::PN13)
2753 .
Case(
"pn14", AArch64::PN14)
2754 .
Case(
"pn15", AArch64::PN15)
2760 .
Case(
"za0.d", AArch64::ZAD0)
2761 .
Case(
"za1.d", AArch64::ZAD1)
2762 .
Case(
"za2.d", AArch64::ZAD2)
2763 .
Case(
"za3.d", AArch64::ZAD3)
2764 .
Case(
"za4.d", AArch64::ZAD4)
2765 .
Case(
"za5.d", AArch64::ZAD5)
2766 .
Case(
"za6.d", AArch64::ZAD6)
2767 .
Case(
"za7.d", AArch64::ZAD7)
2768 .
Case(
"za0.s", AArch64::ZAS0)
2769 .
Case(
"za1.s", AArch64::ZAS1)
2770 .
Case(
"za2.s", AArch64::ZAS2)
2771 .
Case(
"za3.s", AArch64::ZAS3)
2772 .
Case(
"za0.h", AArch64::ZAH0)
2773 .
Case(
"za1.h", AArch64::ZAH1)
2774 .
Case(
"za0.b", AArch64::ZAB0)
2780 .
Case(
"za", AArch64::ZA)
2781 .
Case(
"za0.q", AArch64::ZAQ0)
2782 .
Case(
"za1.q", AArch64::ZAQ1)
2783 .
Case(
"za2.q", AArch64::ZAQ2)
2784 .
Case(
"za3.q", AArch64::ZAQ3)
2785 .
Case(
"za4.q", AArch64::ZAQ4)
2786 .
Case(
"za5.q", AArch64::ZAQ5)
2787 .
Case(
"za6.q", AArch64::ZAQ6)
2788 .
Case(
"za7.q", AArch64::ZAQ7)
2789 .
Case(
"za8.q", AArch64::ZAQ8)
2790 .
Case(
"za9.q", AArch64::ZAQ9)
2791 .
Case(
"za10.q", AArch64::ZAQ10)
2792 .
Case(
"za11.q", AArch64::ZAQ11)
2793 .
Case(
"za12.q", AArch64::ZAQ12)
2794 .
Case(
"za13.q", AArch64::ZAQ13)
2795 .
Case(
"za14.q", AArch64::ZAQ14)
2796 .
Case(
"za15.q", AArch64::ZAQ15)
2797 .
Case(
"za0.d", AArch64::ZAD0)
2798 .
Case(
"za1.d", AArch64::ZAD1)
2799 .
Case(
"za2.d", AArch64::ZAD2)
2800 .
Case(
"za3.d", AArch64::ZAD3)
2801 .
Case(
"za4.d", AArch64::ZAD4)
2802 .
Case(
"za5.d", AArch64::ZAD5)
2803 .
Case(
"za6.d", AArch64::ZAD6)
2804 .
Case(
"za7.d", AArch64::ZAD7)
2805 .
Case(
"za0.s", AArch64::ZAS0)
2806 .
Case(
"za1.s", AArch64::ZAS1)
2807 .
Case(
"za2.s", AArch64::ZAS2)
2808 .
Case(
"za3.s", AArch64::ZAS3)
2809 .
Case(
"za0.h", AArch64::ZAH0)
2810 .
Case(
"za1.h", AArch64::ZAH1)
2811 .
Case(
"za0.b", AArch64::ZAB0)
2812 .
Case(
"za0h.q", AArch64::ZAQ0)
2813 .
Case(
"za1h.q", AArch64::ZAQ1)
2814 .
Case(
"za2h.q", AArch64::ZAQ2)
2815 .
Case(
"za3h.q", AArch64::ZAQ3)
2816 .
Case(
"za4h.q", AArch64::ZAQ4)
2817 .
Case(
"za5h.q", AArch64::ZAQ5)
2818 .
Case(
"za6h.q", AArch64::ZAQ6)
2819 .
Case(
"za7h.q", AArch64::ZAQ7)
2820 .
Case(
"za8h.q", AArch64::ZAQ8)
2821 .
Case(
"za9h.q", AArch64::ZAQ9)
2822 .
Case(
"za10h.q", AArch64::ZAQ10)
2823 .
Case(
"za11h.q", AArch64::ZAQ11)
2824 .
Case(
"za12h.q", AArch64::ZAQ12)
2825 .
Case(
"za13h.q", AArch64::ZAQ13)
2826 .
Case(
"za14h.q", AArch64::ZAQ14)
2827 .
Case(
"za15h.q", AArch64::ZAQ15)
2828 .
Case(
"za0h.d", AArch64::ZAD0)
2829 .
Case(
"za1h.d", AArch64::ZAD1)
2830 .
Case(
"za2h.d", AArch64::ZAD2)
2831 .
Case(
"za3h.d", AArch64::ZAD3)
2832 .
Case(
"za4h.d", AArch64::ZAD4)
2833 .
Case(
"za5h.d", AArch64::ZAD5)
2834 .
Case(
"za6h.d", AArch64::ZAD6)
2835 .
Case(
"za7h.d", AArch64::ZAD7)
2836 .
Case(
"za0h.s", AArch64::ZAS0)
2837 .
Case(
"za1h.s", AArch64::ZAS1)
2838 .
Case(
"za2h.s", AArch64::ZAS2)
2839 .
Case(
"za3h.s", AArch64::ZAS3)
2840 .
Case(
"za0h.h", AArch64::ZAH0)
2841 .
Case(
"za1h.h", AArch64::ZAH1)
2842 .
Case(
"za0h.b", AArch64::ZAB0)
2843 .
Case(
"za0v.q", AArch64::ZAQ0)
2844 .
Case(
"za1v.q", AArch64::ZAQ1)
2845 .
Case(
"za2v.q", AArch64::ZAQ2)
2846 .
Case(
"za3v.q", AArch64::ZAQ3)
2847 .
Case(
"za4v.q", AArch64::ZAQ4)
2848 .
Case(
"za5v.q", AArch64::ZAQ5)
2849 .
Case(
"za6v.q", AArch64::ZAQ6)
2850 .
Case(
"za7v.q", AArch64::ZAQ7)
2851 .
Case(
"za8v.q", AArch64::ZAQ8)
2852 .
Case(
"za9v.q", AArch64::ZAQ9)
2853 .
Case(
"za10v.q", AArch64::ZAQ10)
2854 .
Case(
"za11v.q", AArch64::ZAQ11)
2855 .
Case(
"za12v.q", AArch64::ZAQ12)
2856 .
Case(
"za13v.q", AArch64::ZAQ13)
2857 .
Case(
"za14v.q", AArch64::ZAQ14)
2858 .
Case(
"za15v.q", AArch64::ZAQ15)
2859 .
Case(
"za0v.d", AArch64::ZAD0)
2860 .
Case(
"za1v.d", AArch64::ZAD1)
2861 .
Case(
"za2v.d", AArch64::ZAD2)
2862 .
Case(
"za3v.d", AArch64::ZAD3)
2863 .
Case(
"za4v.d", AArch64::ZAD4)
2864 .
Case(
"za5v.d", AArch64::ZAD5)
2865 .
Case(
"za6v.d", AArch64::ZAD6)
2866 .
Case(
"za7v.d", AArch64::ZAD7)
2867 .
Case(
"za0v.s", AArch64::ZAS0)
2868 .
Case(
"za1v.s", AArch64::ZAS1)
2869 .
Case(
"za2v.s", AArch64::ZAS2)
2870 .
Case(
"za3v.s", AArch64::ZAS3)
2871 .
Case(
"za0v.h", AArch64::ZAH0)
2872 .
Case(
"za1v.h", AArch64::ZAH1)
2873 .
Case(
"za0v.b", AArch64::ZAB0)
2879 return !tryParseRegister(
Reg, StartLoc, EndLoc).isSuccess();
2884 StartLoc = getLoc();
2891unsigned AArch64AsmParser::matchRegisterNameAlias(
StringRef Name,
2893 unsigned RegNum = 0;
2895 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2898 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2901 return Kind == RegKind::SVEPredicateAsCounter ? RegNum : 0;
2904 return Kind == RegKind::NeonVector ? RegNum : 0;
2907 return Kind == RegKind::Matrix ? RegNum : 0;
2909 if (
Name.equals_insensitive(
"zt0"))
2910 return Kind == RegKind::LookupTable ? AArch64::ZT0 : 0;
2914 return (Kind == RegKind::Scalar) ? RegNum : 0;
2919 .
Case(
"fp", AArch64::FP)
2920 .
Case(
"lr", AArch64::LR)
2921 .
Case(
"x31", AArch64::XZR)
2922 .
Case(
"w31", AArch64::WZR)
2924 return Kind == RegKind::Scalar ? RegNum : 0;
2929 auto Entry = RegisterReqs.
find(
Name.lower());
2930 if (Entry == RegisterReqs.
end())
2934 if (Kind == Entry->getValue().first)
2935 RegNum = Entry->getValue().second;
2940unsigned AArch64AsmParser::getNumRegsForRegKind(RegKind K) {
2942 case RegKind::Scalar:
2943 case RegKind::NeonVector:
2944 case RegKind::SVEDataVector:
2946 case RegKind::Matrix:
2947 case RegKind::SVEPredicateVector:
2948 case RegKind::SVEPredicateAsCounter:
2950 case RegKind::LookupTable:
2965 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2979 return Error(S,
"Expected cN operand where 0 <= N <= 15");
2982 if (Tok[0] !=
'c' && Tok[0] !=
'C')
2983 return Error(S,
"Expected cN operand where 0 <= N <= 15");
2987 if (BadNum || CRNum > 15)
2988 return Error(S,
"Expected cN operand where 0 <= N <= 15");
2992 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
3001 unsigned MaxVal = 63;
3007 if (getParser().parseExpression(ImmVal))
3012 return TokError(
"immediate value expected for prefetch operand");
3015 return TokError(
"prefetch operand out of range, [0," + utostr(MaxVal) +
3018 auto RPRFM = AArch64RPRFM::lookupRPRFMByEncoding(MCE->
getValue());
3019 Operands.push_back(AArch64Operand::CreatePrefetch(
3020 prfop, RPRFM ? RPRFM->Name :
"", S, getContext()));
3025 return TokError(
"prefetch hint expected");
3027 auto RPRFM = AArch64RPRFM::lookupRPRFMByName(Tok.
getString());
3029 return TokError(
"prefetch hint expected");
3031 Operands.push_back(AArch64Operand::CreatePrefetch(
3032 RPRFM->Encoding, Tok.
getString(), S, getContext()));
3038template <
bool IsSVEPrefetch>
3044 if (IsSVEPrefetch) {
3045 if (
auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(
N))
3046 return std::optional<unsigned>(Res->Encoding);
3047 }
else if (
auto Res = AArch64PRFM::lookupPRFMByName(
N))
3048 return std::optional<unsigned>(Res->Encoding);
3049 return std::optional<unsigned>();
3052 auto LookupByEncoding = [](
unsigned E) {
3053 if (IsSVEPrefetch) {
3054 if (
auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(
E))
3055 return std::optional<StringRef>(Res->Name);
3056 }
else if (
auto Res = AArch64PRFM::lookupPRFMByEncoding(
E))
3057 return std::optional<StringRef>(Res->Name);
3058 return std::optional<StringRef>();
3060 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
3067 if (getParser().parseExpression(ImmVal))
3072 return TokError(
"immediate value expected for prefetch operand");
3075 return TokError(
"prefetch operand out of range, [0," + utostr(MaxVal) +
3078 auto PRFM = LookupByEncoding(MCE->
getValue());
3079 Operands.push_back(AArch64Operand::CreatePrefetch(prfop, PRFM.value_or(
""),
3085 return TokError(
"prefetch hint expected");
3087 auto PRFM = LookupByName(Tok.
getString());
3089 return TokError(
"prefetch hint expected");
3091 Operands.push_back(AArch64Operand::CreatePrefetch(
3092 *PRFM, Tok.
getString(), S, getContext()));
3102 return TokError(
"invalid operand for instruction");
3104 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.
getString());
3106 return TokError(
"invalid operand for instruction");
3108 Operands.push_back(AArch64Operand::CreatePSBHint(
3109 PSB->Encoding, Tok.
getString(), S, getContext()));
3115 SMLoc StartLoc = getLoc();
3121 auto RegTok = getTok();
3122 if (!tryParseScalarRegister(RegNum).isSuccess())
3125 if (RegNum != AArch64::XZR) {
3126 getLexer().UnLex(RegTok);
3133 if (!tryParseScalarRegister(RegNum).isSuccess())
3134 return TokError(
"expected register operand");
3136 if (RegNum != AArch64::XZR)
3137 return TokError(
"xzr must be followed by xzr");
3141 Operands.push_back(AArch64Operand::CreateReg(
3142 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3152 return TokError(
"invalid operand for instruction");
3154 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.
getString());
3156 return TokError(
"invalid operand for instruction");
3158 Operands.push_back(AArch64Operand::CreateBTIHint(
3159 BTI->Encoding, Tok.
getString(), S, getContext()));
3168 const MCExpr *Expr =
nullptr;
3174 if (parseSymbolicImmVal(Expr))
3180 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3190 return Error(S,
"gotpage label reference not allowed an addend");
3200 return Error(S,
"page or gotpage label reference expected");
3208 Operands.push_back(AArch64Operand::CreateImm(Expr, S,
E, getContext()));
3217 const MCExpr *Expr =
nullptr;
3226 if (parseSymbolicImmVal(Expr))
3232 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3239 return Error(S,
"unexpected adr label");
3244 Operands.push_back(AArch64Operand::CreateImm(Expr, S,
E, getContext()));
3249template <
bool AddFPZeroAsLiteral>
3262 return TokError(
"invalid floating point immediate");
3267 if (Tok.
getIntVal() > 255 || isNegative)
3268 return TokError(
"encoded floating point value out of range");
3272 AArch64Operand::CreateFPImm(
F,
true, S, getContext()));
3275 APFloat RealVal(APFloat::IEEEdouble());
3277 RealVal.convertFromString(Tok.
getString(), APFloat::rmTowardZero);
3279 return TokError(
"invalid floating point representation");
3282 RealVal.changeSign();
3284 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
3285 Operands.push_back(AArch64Operand::CreateToken(
"#0", S, getContext()));
3286 Operands.push_back(AArch64Operand::CreateToken(
".0", S, getContext()));
3288 Operands.push_back(AArch64Operand::CreateFPImm(
3289 RealVal, *StatusOrErr == APFloat::opOK, S, getContext()));
3314 if (parseSymbolicImmVal(Imm))
3318 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3325 if (!parseOptionalVGOperand(
Operands, VecGroup)) {
3327 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3329 AArch64Operand::CreateToken(VecGroup, getLoc(), getContext()));
3335 !getTok().getIdentifier().equals_insensitive(
"lsl"))
3336 return Error(getLoc(),
"only 'lsl #+N' valid after immediate");
3344 return Error(getLoc(),
"only 'lsl #+N' valid after immediate");
3346 int64_t ShiftAmount = getTok().getIntVal();
3348 if (ShiftAmount < 0)
3349 return Error(getLoc(),
"positive shift amount required");
3353 if (ShiftAmount == 0 && Imm !=
nullptr) {
3355 AArch64Operand::CreateImm(Imm, S, getLoc(), getContext()));
3359 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S,
3360 getLoc(), getContext()));
3367AArch64AsmParser::parseCondCodeString(
StringRef Cond, std::string &Suggestion) {
3404 Suggestion =
"nfrst";
3411 bool invertCondCode) {
3417 std::string Suggestion;
3420 std::string
Msg =
"invalid condition code";
3421 if (!Suggestion.empty())
3422 Msg +=
", did you mean " + Suggestion +
"?";
3423 return TokError(Msg);
3427 if (invertCondCode) {
3429 return TokError(
"condition codes AL and NV are invalid for this instruction");
3434 AArch64Operand::CreateCondCode(
CC, S, getLoc(), getContext()));
3443 return TokError(
"invalid operand for instruction");
3445 unsigned PStateImm = -1;
3446 const auto *SVCR = AArch64SVCR::lookupSVCRByName(Tok.
getString());
3449 if (SVCR->haveFeatures(getSTI().getFeatureBits()))
3450 PStateImm = SVCR->Encoding;
3453 AArch64Operand::CreateSVCR(PStateImm, Tok.
getString(), S, getContext()));
3464 if (
Name.equals_insensitive(
"za") ||
Name.starts_with_insensitive(
"za.")) {
3466 unsigned ElementWidth = 0;
3467 auto DotPosition =
Name.find(
'.');
3469 const auto &KindRes =
3473 "Expected the register to be followed by element width suffix");
3474 ElementWidth = KindRes->second;
3476 Operands.push_back(AArch64Operand::CreateMatrixRegister(
3477 AArch64::ZA, ElementWidth, MatrixKind::Array, S, getLoc(),
3482 if (parseOperand(
Operands,
false,
false))
3489 unsigned Reg = matchRegisterNameAlias(
Name, RegKind::Matrix);
3493 size_t DotPosition =
Name.find(
'.');
3501 .
Case(
"h", MatrixKind::Row)
3502 .
Case(
"v", MatrixKind::Col)
3509 "Expected the register to be followed by element width suffix");
3510 unsigned ElementWidth = KindRes->second;
3514 Operands.push_back(AArch64Operand::CreateMatrixRegister(
3515 Reg, ElementWidth, Kind, S, getLoc(), getContext()));
3520 if (parseOperand(
Operands,
false,
false))
3562 return TokError(
"expected #imm after shift specifier");
3568 AArch64Operand::CreateShiftExtend(ShOp, 0,
false, S,
E, getContext()));
3577 return Error(
E,
"expected integer shift amount");
3580 if (getParser().parseExpression(ImmVal))
3585 return Error(
E,
"expected constant '#imm' after shift specifier");
3588 Operands.push_back(AArch64Operand::CreateShiftExtend(
3589 ShOp, MCE->
getValue(),
true, S,
E, getContext()));
3597 {
"crc", {AArch64::FeatureCRC}},
3598 {
"sm4", {AArch64::FeatureSM4}},
3599 {
"sha3", {AArch64::FeatureSHA3}},
3600 {
"sha2", {AArch64::FeatureSHA2}},
3601 {
"aes", {AArch64::FeatureAES}},
3602 {
"crypto", {AArch64::FeatureCrypto}},
3603 {
"fp", {AArch64::FeatureFPARMv8}},
3604 {
"simd", {AArch64::FeatureNEON}},
3605 {
"ras", {AArch64::FeatureRAS}},
3606 {
"rasv2", {AArch64::FeatureRASv2}},
3607 {
"lse", {AArch64::FeatureLSE}},
3608 {
"predres", {AArch64::FeaturePredRes}},
3609 {
"predres2", {AArch64::FeatureSPECRES2}},
3610 {
"ccdp", {AArch64::FeatureCacheDeepPersist}},
3611 {
"mte", {AArch64::FeatureMTE}},
3612 {
"memtag", {AArch64::FeatureMTE}},
3613 {
"tlb-rmi", {AArch64::FeatureTLB_RMI}},
3614 {
"pan", {AArch64::FeaturePAN}},
3615 {
"pan-rwv", {AArch64::FeaturePAN_RWV}},
3616 {
"ccpp", {AArch64::FeatureCCPP}},
3617 {
"rcpc", {AArch64::FeatureRCPC}},
3618 {
"rng", {AArch64::FeatureRandGen}},
3619 {
"sve", {AArch64::FeatureSVE}},
3620 {
"sve2", {AArch64::FeatureSVE2}},
3621 {
"sve2-aes", {AArch64::FeatureSVE2AES}},
3622 {
"sve2-sm4", {AArch64::FeatureSVE2SM4}},
3623 {
"sve2-sha3", {AArch64::FeatureSVE2SHA3}},
3624 {
"sve2-bitperm", {AArch64::FeatureSVE2BitPerm}},
3625 {
"sve2p1", {AArch64::FeatureSVE2p1}},
3626 {
"b16b16", {AArch64::FeatureB16B16}},
3627 {
"ls64", {AArch64::FeatureLS64}},
3628 {
"xs", {AArch64::FeatureXS}},
3629 {
"pauth", {AArch64::FeaturePAuth}},
3630 {
"flagm", {AArch64::FeatureFlagM}},
3631 {
"rme", {AArch64::FeatureRME}},
3632 {
"sme", {AArch64::FeatureSME}},
3633 {
"sme-f64f64", {AArch64::FeatureSMEF64F64}},
3634 {
"sme-f16f16", {AArch64::FeatureSMEF16F16}},
3635 {
"sme-i16i64", {AArch64::FeatureSMEI16I64}},
3636 {
"sme2", {AArch64::FeatureSME2}},
3637 {
"sme2p1", {AArch64::FeatureSME2p1}},
3638 {
"hbc", {AArch64::FeatureHBC}},
3639 {
"mops", {AArch64::FeatureMOPS}},
3640 {
"mec", {AArch64::FeatureMEC}},
3641 {
"the", {AArch64::FeatureTHE}},
3642 {
"d128", {AArch64::FeatureD128}},
3643 {
"lse128", {AArch64::FeatureLSE128}},
3644 {
"ite", {AArch64::FeatureITE}},
3645 {
"cssc", {AArch64::FeatureCSSC}},
3646 {
"rcpc3", {AArch64::FeatureRCPC3}},
3647 {
"gcs", {AArch64::FeatureGCS}},
3648 {
"bf16", {AArch64::FeatureBF16}},
3649 {
"compnum", {AArch64::FeatureComplxNum}},
3650 {
"dotprod", {AArch64::FeatureDotProd}},
3651 {
"f32mm", {AArch64::FeatureMatMulFP32}},
3652 {
"f64mm", {AArch64::FeatureMatMulFP64}},
3653 {
"fp16", {AArch64::FeatureFullFP16}},
3654 {
"fp16fml", {AArch64::FeatureFP16FML}},
3655 {
"i8mm", {AArch64::FeatureMatMulInt8}},
3656 {
"lor", {AArch64::FeatureLOR}},
3657 {
"profile", {AArch64::FeatureSPE}},
3661 {
"rdm", {AArch64::FeatureRDM}},
3662 {
"rdma", {AArch64::FeatureRDM}},
3663 {
"sb", {AArch64::FeatureSB}},
3664 {
"ssbs", {AArch64::FeatureSSBS}},
3665 {
"tme", {AArch64::FeatureTME}},
3666 {
"fpmr", {AArch64::FeatureFPMR}},
3667 {
"fp8", {AArch64::FeatureFP8}},
3668 {
"faminmax", {AArch64::FeatureFAMINMAX}},
3669 {
"fp8fma", {AArch64::FeatureFP8FMA}},
3670 {
"ssve-fp8fma", {AArch64::FeatureSSVE_FP8FMA}},
3671 {
"fp8dot2", {AArch64::FeatureFP8DOT2}},
3672 {
"ssve-fp8dot2", {AArch64::FeatureSSVE_FP8DOT2}},
3673 {
"fp8dot4", {AArch64::FeatureFP8DOT4}},
3674 {
"ssve-fp8dot4", {AArch64::FeatureSSVE_FP8DOT4}},
3675 {
"lut", {AArch64::FeatureLUT}},
3676 {
"sme-lutv2", {AArch64::FeatureSME_LUTv2}},
3677 {
"sme-f8f16", {AArch64::FeatureSMEF8F16}},
3678 {
"sme-f8f32", {AArch64::FeatureSMEF8F32}},
3679 {
"sme-fa64", {AArch64::FeatureSMEFA64}},
3680 {
"cpa", {AArch64::FeatureCPA}},
3684 if (FBS[AArch64::HasV8_0aOps])
3686 if (FBS[AArch64::HasV8_1aOps])
3688 else if (FBS[AArch64::HasV8_2aOps])
3690 else if (FBS[AArch64::HasV8_3aOps])
3692 else if (FBS[AArch64::HasV8_4aOps])
3694 else if (FBS[AArch64::HasV8_5aOps])
3696 else if (FBS[AArch64::HasV8_6aOps])
3698 else if (FBS[AArch64::HasV8_7aOps])
3700 else if (FBS[AArch64::HasV8_8aOps])
3702 else if (FBS[AArch64::HasV8_9aOps])
3704 else if (FBS[AArch64::HasV9_0aOps])
3706 else if (FBS[AArch64::HasV9_1aOps])
3708 else if (FBS[AArch64::HasV9_2aOps])
3710 else if (FBS[AArch64::HasV9_3aOps])
3712 else if (FBS[AArch64::HasV9_4aOps])
3714 else if (FBS[AArch64::HasV9_5aOps])
3716 else if (FBS[AArch64::HasV8_0rOps])
3725 Str += !ExtMatches.
empty() ? llvm::join(ExtMatches,
", ") :
"(unknown)";
3732 const uint16_t Cm = (Encoding & 0x78) >> 3;
3733 const uint16_t Cn = (Encoding & 0x780) >> 7;
3734 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
3739 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
3741 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
3743 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
3746 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
3753 if (
Name.contains(
'.'))
3754 return TokError(
"invalid operand");
3757 Operands.push_back(AArch64Operand::CreateToken(
"sys", NameLoc, getContext()));
3763 if (Mnemonic ==
"ic") {
3766 return TokError(
"invalid operand for IC instruction");
3767 else if (!IC->
haveFeatures(getSTI().getFeatureBits())) {
3768 std::string Str(
"IC " + std::string(IC->
Name) +
" requires: ");
3770 return TokError(Str);
3773 }
else if (Mnemonic ==
"dc") {
3776 return TokError(
"invalid operand for DC instruction");
3777 else if (!DC->
haveFeatures(getSTI().getFeatureBits())) {
3778 std::string Str(
"DC " + std::string(DC->
Name) +
" requires: ");
3780 return TokError(Str);
3783 }
else if (Mnemonic ==
"at") {
3786 return TokError(
"invalid operand for AT instruction");
3787 else if (!AT->
haveFeatures(getSTI().getFeatureBits())) {
3788 std::string Str(
"AT " + std::string(AT->
Name) +
" requires: ");
3790 return TokError(Str);
3793 }
else if (Mnemonic ==
"tlbi") {
3796 return TokError(
"invalid operand for TLBI instruction");
3797 else if (!TLBI->
haveFeatures(getSTI().getFeatureBits())) {
3798 std::string Str(
"TLBI " + std::string(TLBI->
Name) +
" requires: ");
3800 return TokError(Str);
3803 }
else if (Mnemonic ==
"cfp" || Mnemonic ==
"dvp" || Mnemonic ==
"cpp" || Mnemonic ==
"cosp") {
3805 if (
Op.lower() !=
"rctx")
3806 return TokError(
"invalid operand for prediction restriction instruction");
3808 bool hasAll = getSTI().hasFeature(AArch64::FeatureAll);
3809 bool hasPredres = hasAll || getSTI().hasFeature(AArch64::FeaturePredRes);
3810 bool hasSpecres2 = hasAll || getSTI().hasFeature(AArch64::FeatureSPECRES2);
3812 if (Mnemonic ==
"cosp" && !hasSpecres2)
3813 return TokError(
"COSP requires: predres2");
3815 return TokError(Mnemonic.
upper() +
"RCTX requires: predres");
3817 uint16_t PRCTX_Op2 = Mnemonic ==
"cfp" ? 0b100
3818 : Mnemonic ==
"dvp" ? 0b101
3819 : Mnemonic ==
"cosp" ? 0b110
3820 : Mnemonic ==
"cpp" ? 0b111
3823 "Invalid mnemonic for prediction restriction instruction");
3824 const auto SYS_3_7_3 = 0b01101110011;
3825 const auto Encoding = SYS_3_7_3 << 3 | PRCTX_Op2;
3827 createSysAlias(Encoding,
Operands, S);
3833 bool HasRegister =
false;
3838 return TokError(
"expected register operand");
3842 if (ExpectRegister && !HasRegister)
3843 return TokError(
"specified " + Mnemonic +
" op requires a register");
3844 else if (!ExpectRegister && HasRegister)
3845 return TokError(
"specified " + Mnemonic +
" op does not use a register");
3857 if (
Name.contains(
'.'))
3858 return TokError(
"invalid operand");
3862 AArch64Operand::CreateToken(
"sysp", NameLoc, getContext()));
3868 if (Mnemonic ==
"tlbip") {
3869 bool HasnXSQualifier =
Op.ends_with_insensitive(
"nXS");
3870 if (HasnXSQualifier) {
3871 Op =
Op.drop_back(3);
3875 return TokError(
"invalid operand for TLBIP instruction");
3877 TLBIorig->
Name, TLBIorig->
Encoding | (HasnXSQualifier ? (1 << 7) : 0),
3884 std::string(TLBI.
Name) + (HasnXSQualifier ?
"nXS" :
"");
3885 std::string Str(
"TLBIP " +
Name +
" requires: ");
3887 return TokError(Str);
3898 return TokError(
"expected register identifier");
3903 return TokError(
"specified " + Mnemonic +
3904 " op requires a pair of registers");
3917 return TokError(
"'csync' operand expected");
3921 SMLoc ExprLoc = getLoc();
3923 if (getParser().parseExpression(ImmVal))
3927 return Error(ExprLoc,
"immediate value expected for barrier operand");
3929 if (Mnemonic ==
"dsb" &&
Value > 15) {
3936 if (Value < 0 || Value > 15)
3937 return Error(ExprLoc,
"barrier operand out of range");
3938 auto DB = AArch64DB::lookupDBByEncoding(
Value);
3939 Operands.push_back(AArch64Operand::CreateBarrier(
Value, DB ?
DB->Name :
"",
3940 ExprLoc, getContext(),
3946 return TokError(
"invalid operand for instruction");
3949 auto TSB = AArch64TSB::lookupTSBByName(Operand);
3950 auto DB = AArch64DB::lookupDBByName(Operand);
3952 if (Mnemonic ==
"isb" && (!DB ||
DB->Encoding != AArch64DB::sy))
3953 return TokError(
"'sy' or #imm operand expected");
3955 if (Mnemonic ==
"tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync))
3956 return TokError(
"'csync' operand expected");
3958 if (Mnemonic ==
"dsb") {
3963 return TokError(
"invalid barrier option name");
3966 Operands.push_back(AArch64Operand::CreateBarrier(
3967 DB ?
DB->Encoding : TSB->Encoding, Tok.
getString(), getLoc(),
3968 getContext(),
false ));
3978 assert(Mnemonic ==
"dsb" &&
"Instruction does not accept nXS operands");
3979 if (Mnemonic !=
"dsb")
3985 SMLoc ExprLoc = getLoc();
3986 if (getParser().parseExpression(ImmVal))
3990 return Error(ExprLoc,
"immediate value expected for barrier operand");
3995 return Error(ExprLoc,
"barrier operand out of range");
3996 auto DB = AArch64DBnXS::lookupDBnXSByImmValue(
Value);
3997 Operands.push_back(AArch64Operand::CreateBarrier(
DB->Encoding,
DB->Name,
3998 ExprLoc, getContext(),
4004 return TokError(
"invalid operand for instruction");
4007 auto DB = AArch64DBnXS::lookupDBnXSByName(Operand);
4010 return TokError(
"invalid barrier option name");
4013 AArch64Operand::CreateBarrier(
DB->Encoding, Tok.
getString(), getLoc(),
4014 getContext(),
true ));
4026 if (AArch64SVCR::lookupSVCRByName(Tok.
getString()))
4031 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
4032 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
4033 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
4037 unsigned PStateImm = -1;
4038 auto PState15 = AArch64PState::lookupPStateImm0_15ByName(Tok.
getString());
4039 if (PState15 && PState15->haveFeatures(getSTI().getFeatureBits()))
4040 PStateImm = PState15->Encoding;
4042 auto PState1 = AArch64PState::lookupPStateImm0_1ByName(Tok.
getString());
4043 if (PState1 && PState1->haveFeatures(getSTI().getFeatureBits()))
4044 PStateImm = PState1->Encoding;
4048 AArch64Operand::CreateSysReg(Tok.
getString(), getLoc(), MRSReg, MSRReg,
4049 PStateImm, getContext()));
4064 ParseStatus Res = tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
4072 unsigned ElementWidth = KindRes->second;
4074 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
4075 S, getLoc(), getContext()));
4080 Operands.push_back(AArch64Operand::CreateToken(Kind, S, getContext()));
4082 return tryParseVectorIndex(
Operands).isFailure();
4086 SMLoc SIdx = getLoc();
4089 if (getParser().parseExpression(ImmVal))
4093 return TokError(
"immediate value expected for vector index");
4100 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->
getValue(), SIdx,
4113 RegKind MatchKind) {
4122 size_t Start = 0, Next =
Name.find(
'.');
4124 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
4130 return TokError(
"invalid vector kind qualifier");
4142template <RegKind RK>
4146 const SMLoc S = getLoc();
4149 auto Res = tryParseVectorRegister(RegNum, Kind, RK);
4157 unsigned ElementWidth = KindRes->second;
4158 Operands.push_back(AArch64Operand::CreateVectorReg(
4159 RegNum, RK, ElementWidth, S,
4160 getLoc(), getContext()));
4163 if (RK == RegKind::SVEPredicateAsCounter) {
4170 if (parseOperand(
Operands,
false,
false))
4181 return Error(S,
"not expecting size suffix");
4184 Operands.push_back(AArch64Operand::CreateToken(
"/", getLoc(), getContext()));
4189 auto Pred = getTok().getString().lower();
4190 if (RK == RegKind::SVEPredicateAsCounter && Pred !=
"z")
4191 return Error(getLoc(),
"expecting 'z' predication");
4193 if (RK == RegKind::SVEPredicateVector && Pred !=
"z" && Pred !=
"m")
4194 return Error(getLoc(),
"expecting 'm' or 'z' predication");
4197 const char *ZM = Pred ==
"z" ?
"z" :
"m";
4198 Operands.push_back(AArch64Operand::CreateToken(ZM, getLoc(), getContext()));
4207 if (!tryParseNeonVectorRegister(
Operands))
4210 if (tryParseZTOperand(
Operands).isSuccess())
4214 if (tryParseGPROperand<false>(
Operands).isSuccess())
4220bool AArch64AsmParser::parseSymbolicImmVal(
const MCExpr *&ImmVal) {
4221 bool HasELFModifier =
false;
4225 HasELFModifier =
true;
4228 return TokError(
"expect relocation specifier in operand after ':'");
4230 std::string LowerCase = getTok().getIdentifier().lower();
4281 return TokError(
"expect relocation specifier in operand after ':'");
4285 if (parseToken(
AsmToken::Colon,
"expect ':' after relocation specifier"))
4289 if (getParser().parseExpression(ImmVal))
4302 auto ParseMatrixTile = [
this](
unsigned &
Reg,
4305 size_t DotPosition =
Name.find(
'.');
4314 const std::optional<std::pair<int, int>> &KindRes =
4318 "Expected the register to be followed by element width suffix");
4319 ElementWidth = KindRes->second;
4326 auto LCurly = getTok();
4331 Operands.push_back(AArch64Operand::CreateMatrixTileList(
4332 0, S, getLoc(), getContext()));
4337 if (getTok().getString().equals_insensitive(
"za")) {
4343 Operands.push_back(AArch64Operand::CreateMatrixTileList(
4344 0xFF, S, getLoc(), getContext()));
4348 SMLoc TileLoc = getLoc();
4350 unsigned FirstReg, ElementWidth;
4351 auto ParseRes = ParseMatrixTile(FirstReg, ElementWidth);
4352 if (!ParseRes.isSuccess()) {
4353 getLexer().UnLex(LCurly);
4359 unsigned PrevReg = FirstReg;
4362 AArch64Operand::ComputeRegsForAlias(FirstReg, DRegs, ElementWidth);
4365 SeenRegs.
insert(FirstReg);
4369 unsigned Reg, NextElementWidth;
4370 ParseRes = ParseMatrixTile(Reg, NextElementWidth);
4371 if (!ParseRes.isSuccess())
4375 if (ElementWidth != NextElementWidth)
4376 return Error(TileLoc,
"mismatched register size suffix");
4379 Warning(TileLoc,
"tile list not in ascending order");
4382 Warning(TileLoc,
"duplicate tile in list");
4385 AArch64Operand::ComputeRegsForAlias(Reg, DRegs, ElementWidth);
4395 for (
auto Reg : DRegs)
4399 AArch64Operand::CreateMatrixTileList(
RegMask, S, getLoc(), getContext()));
4404template <RegKind VectorKind>
4414 auto RegTok = getTok();
4415 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
4416 if (ParseRes.isSuccess()) {
4423 RegTok.getString().equals_insensitive(
"zt0"))
4427 (ParseRes.isNoMatch() && NoMatchIsError &&
4428 !RegTok.getString().starts_with_insensitive(
"za")))
4429 return Error(Loc,
"vector register expected");
4434 int NumRegs = getNumRegsForRegKind(VectorKind);
4436 auto LCurly = getTok();
4441 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
4445 if (ParseRes.isNoMatch())
4448 if (!ParseRes.isSuccess())
4451 int64_t PrevReg = FirstReg;
4456 SMLoc Loc = getLoc();
4460 ParseRes = ParseVector(Reg, NextKind, getLoc(),
true);
4461 if (!ParseRes.isSuccess())
4465 if (Kind != NextKind)
4466 return Error(Loc,
"mismatched register size suffix");
4469 (PrevReg <
Reg) ? (Reg - PrevReg) : (
Reg + NumRegs - PrevReg);
4471 if (Space == 0 || Space > 3)
4472 return Error(Loc,
"invalid number of vectors");
4477 bool HasCalculatedStride =
false;
4479 SMLoc Loc = getLoc();
4482 ParseRes = ParseVector(Reg, NextKind, getLoc(),
true);
4483 if (!ParseRes.isSuccess())
4487 if (Kind != NextKind)
4488 return Error(Loc,
"mismatched register size suffix");
4490 unsigned RegVal = getContext().getRegisterInfo()->getEncodingValue(Reg);
4491 unsigned PrevRegVal =
4492 getContext().getRegisterInfo()->getEncodingValue(PrevReg);
4493 if (!HasCalculatedStride) {
4494 Stride = (PrevRegVal < RegVal) ? (RegVal - PrevRegVal)
4495 : (RegVal + NumRegs - PrevRegVal);
4496 HasCalculatedStride =
true;
4500 if (Stride == 0 || RegVal != ((PrevRegVal + Stride) % NumRegs))
4501 return Error(Loc,
"registers must have the same sequential stride");
4512 return Error(S,
"invalid number of vectors");
4514 unsigned NumElements = 0;
4515 unsigned ElementWidth = 0;
4516 if (!
Kind.empty()) {
4518 std::tie(NumElements, ElementWidth) = *VK;
4521 Operands.push_back(AArch64Operand::CreateVectorList(
4522 FirstReg, Count, Stride, NumElements, ElementWidth, VectorKind, S,
4523 getLoc(), getContext()));
4530 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(
Operands,
true);
4531 if (!ParseRes.isSuccess())
4534 return tryParseVectorIndex(
Operands).isFailure();
4538 SMLoc StartLoc = getLoc();
4546 Operands.push_back(AArch64Operand::CreateReg(
4547 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
4554 return Error(getLoc(),
"index must be absent or #0");
4557 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
4558 cast<MCConstantExpr>(ImmVal)->getValue() != 0)
4559 return Error(getLoc(),
"index must be absent or #0");
4561 Operands.push_back(AArch64Operand::CreateReg(
4562 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
4567 SMLoc StartLoc = getLoc();
4571 unsigned RegNum = matchRegisterNameAlias(
Name, RegKind::LookupTable);
4576 Operands.push_back(AArch64Operand::CreateReg(
4577 RegNum, RegKind::LookupTable, StartLoc, getLoc(), getContext()));
4583 AArch64Operand::CreateToken(
"[", getLoc(), getContext()));
4585 if (getParser().parseExpression(ImmVal))
4589 return TokError(
"immediate value expected for vector index");
4590 Operands.push_back(AArch64Operand::CreateImm(
4592 getLoc(), getContext()));
4594 if (parseOptionalMulOperand(
Operands))
4599 AArch64Operand::CreateToken(
"]", getLoc(), getContext()));
4604template <
bool ParseShiftExtend, RegConstra
intEqualityTy EqTy>
4606 SMLoc StartLoc = getLoc();
4615 Operands.push_back(AArch64Operand::CreateReg(
4616 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
4625 Res = tryParseOptionalShiftExtend(ExtOpnd);
4629 auto Ext =
static_cast<AArch64Operand*
>(ExtOpnd.
back().get());
4630 Operands.push_back(AArch64Operand::CreateReg(
4631 RegNum, RegKind::Scalar, StartLoc,
Ext->getEndLoc(), getContext(), EqTy,
4632 Ext->getShiftExtendType(),
Ext->getShiftExtendAmount(),
4633 Ext->hasShiftExtendAmount()));
4647 if (!getTok().getString().equals_insensitive(
"mul") ||
4648 !(NextIsVL || NextIsHash))
4652 AArch64Operand::CreateToken(
"mul", getLoc(), getContext()));
4657 AArch64Operand::CreateToken(
"vl", getLoc(), getContext()));
4669 if (
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
4670 Operands.push_back(AArch64Operand::CreateImm(
4677 return Error(getLoc(),
"expected 'vl' or '#<imm>'");
4683 auto Tok = Parser.
getTok();
4688 .
Case(
"vgx2",
"vgx2")
4689 .
Case(
"vgx4",
"vgx4")
4701 auto Tok = getTok();
4711 AArch64Operand::CreateToken(Keyword, Tok.
getLoc(), getContext()));
4720 bool invertCondCode) {
4724 MatchOperandParserImpl(
Operands, Mnemonic,
true);
4738 switch (getLexer().getKind()) {
4742 if (parseSymbolicImmVal(Expr))
4743 return Error(S,
"invalid operand");
4746 Operands.push_back(AArch64Operand::CreateImm(Expr, S,
E, getContext()));
4751 AArch64Operand::CreateToken(
"[", getLoc(), getContext()));
4756 return parseOperand(
Operands,
false,
false);
4759 if (!parseNeonVectorList(
Operands))
4763 AArch64Operand::CreateToken(
"{", getLoc(), getContext()));
4768 return parseOperand(
Operands,
false,
false);
4773 if (!parseOptionalVGOperand(
Operands, VecGroup)) {
4775 AArch64Operand::CreateToken(VecGroup, getLoc(), getContext()));
4780 return parseCondCode(
Operands, invertCondCode);
4788 if (!parseOptionalMulOperand(
Operands))
4799 if (Mnemonic ==
"brb" || Mnemonic ==
"smstart" || Mnemonic ==
"smstop" ||
4801 return parseKeywordOperand(
Operands);
4807 if (getParser().parseExpression(IdVal))
4810 Operands.push_back(AArch64Operand::CreateImm(IdVal, S,
E, getContext()));
4822 bool isNegative =
false;
4838 if (Mnemonic !=
"fcmp" && Mnemonic !=
"fcmpe" && Mnemonic !=
"fcmeq" &&
4839 Mnemonic !=
"fcmge" && Mnemonic !=
"fcmgt" && Mnemonic !=
"fcmle" &&
4840 Mnemonic !=
"fcmlt" && Mnemonic !=
"fcmne")
4841 return TokError(
"unexpected floating point literal");
4842 else if (IntVal != 0 || isNegative)
4843 return TokError(
"expected floating-point constant #0.0");
4846 Operands.push_back(AArch64Operand::CreateToken(
"#0", S, getContext()));
4847 Operands.push_back(AArch64Operand::CreateToken(
".0", S, getContext()));
4852 if (parseSymbolicImmVal(ImmVal))
4856 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S,
E, getContext()));
4860 SMLoc Loc = getLoc();
4861 if (Mnemonic !=
"ldr")
4862 return TokError(
"unexpected token in operand");
4864 const MCExpr *SubExprVal;
4865 if (getParser().parseExpression(SubExprVal))
4869 !
static_cast<AArch64Operand &
>(*
Operands[1]).isScalarReg())
4870 return Error(Loc,
"Only valid when first operand is register");
4873 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4879 if (isa<MCConstantExpr>(SubExprVal)) {
4880 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
4881 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
4886 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
4887 Operands[0] = AArch64Operand::CreateToken(
"movz", Loc, Ctx);
4888 Operands.push_back(AArch64Operand::CreateImm(
4892 ShiftAmt,
true, S,
E, Ctx));