1//==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AArch64InstrInfo.h"
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64InstPrinter.h"
12#include "MCTargetDesc/AArch64MCAsmInfo.h"
13#include "MCTargetDesc/AArch64MCTargetDesc.h"
14#include "MCTargetDesc/AArch64TargetStreamer.h"
15#include "TargetInfo/AArch64TargetInfo.h"
16#include "Utils/AArch64BaseInfo.h"
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/APInt.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/Enum.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallSet.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringExtras.h"
25#include "llvm/ADT/StringMap.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/ADT/StringSwitch.h"
28#include "llvm/ADT/Twine.h"
29#include "llvm/MC/MCAsmInfo.h"
30#include "llvm/MC/MCContext.h"
31#include "llvm/MC/MCExpr.h"
32#include "llvm/MC/MCInst.h"
33#include "llvm/MC/MCLinkerOptimizationHint.h"
34#include "llvm/MC/MCObjectFileInfo.h"
35#include "llvm/MC/MCParser/AsmLexer.h"
36#include "llvm/MC/MCParser/MCAsmParser.h"
37#include "llvm/MC/MCParser/MCAsmParserExtension.h"
38#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
39#include "llvm/MC/MCParser/MCTargetAsmParser.h"
40#include "llvm/MC/MCRegisterInfo.h"
41#include "llvm/MC/MCStreamer.h"
42#include "llvm/MC/MCSubtargetInfo.h"
43#include "llvm/MC/MCSymbol.h"
44#include "llvm/MC/MCTargetOptions.h"
45#include "llvm/MC/MCValue.h"
46#include "llvm/MC/TargetRegistry.h"
47#include "llvm/Support/AArch64BuildAttributes.h"
48#include "llvm/Support/Compiler.h"
49#include "llvm/Support/ErrorHandling.h"
50#include "llvm/Support/MathExtras.h"
51#include "llvm/Support/SMLoc.h"
52#include "llvm/Support/raw_ostream.h"
53#include "llvm/TargetParser/AArch64TargetParser.h"
54#include "llvm/TargetParser/SubtargetFeature.h"
55#include <cassert>
56#include <cstdint>
57#include <cstdio>
58#include <optional>
59#include <string>
60#include <tuple>
61#include <utility>
62#include <vector>
63
64using namespace llvm;
65
66namespace {
67
68enum class RegKind {
69 Scalar,
70 NeonVector,
71 SVEDataVector,
72 SVEPredicateAsCounter,
73 SVEPredicateVector,
74 Matrix,
75 LookupTable
76};
77
78enum class MatrixKind { Array, Tile, Row, Col };
79
80enum RegConstraintEqualityTy {
81 EqualsReg,
82 EqualsSuperReg,
83 EqualsSubReg
84};
85
86class AArch64AsmParser : public MCTargetAsmParser {
87private:
88 StringRef Mnemonic; ///< Instruction mnemonic.
89
90 // Map of register aliases registers via the .req directive.
91 StringMap<std::pair<RegKind, MCRegister>> RegisterReqs;
92
93 class PrefixInfo {
94 public:
95 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
96 PrefixInfo Prefix;
97 switch (Inst.getOpcode()) {
98 case AArch64::MOVPRFX_ZZ:
99 Prefix.Active = true;
100 Prefix.Dst = Inst.getOperand(i: 0).getReg();
101 break;
102 case AArch64::MOVPRFX_ZPmZ_B:
103 case AArch64::MOVPRFX_ZPmZ_H:
104 case AArch64::MOVPRFX_ZPmZ_S:
105 case AArch64::MOVPRFX_ZPmZ_D:
106 Prefix.Active = true;
107 Prefix.Predicated = true;
108 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
109 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
110 "No destructive element size set for movprfx");
111 Prefix.Dst = Inst.getOperand(i: 0).getReg();
112 Prefix.Pg = Inst.getOperand(i: 2).getReg();
113 break;
114 case AArch64::MOVPRFX_ZPzZ_B:
115 case AArch64::MOVPRFX_ZPzZ_H:
116 case AArch64::MOVPRFX_ZPzZ_S:
117 case AArch64::MOVPRFX_ZPzZ_D:
118 Prefix.Active = true;
119 Prefix.Predicated = true;
120 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
121 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
122 "No destructive element size set for movprfx");
123 Prefix.Dst = Inst.getOperand(i: 0).getReg();
124 Prefix.Pg = Inst.getOperand(i: 1).getReg();
125 break;
126 default:
127 break;
128 }
129
130 return Prefix;
131 }
132
133 PrefixInfo() = default;
134 bool isActive() const { return Active; }
135 bool isPredicated() const { return Predicated; }
136 unsigned getElementSize() const {
137 assert(Predicated);
138 return ElementSize;
139 }
140 MCRegister getDstReg() const { return Dst; }
141 MCRegister getPgReg() const {
142 assert(Predicated);
143 return Pg;
144 }
145
146 private:
147 bool Active = false;
148 bool Predicated = false;
149 unsigned ElementSize;
150 MCRegister Dst;
151 MCRegister Pg;
152 } NextPrefix;
153
154 AArch64TargetStreamer &getTargetStreamer() {
155 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
156 return static_cast<AArch64TargetStreamer &>(TS);
157 }
158
159 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
160
161 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
162 bool parseSyslAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
163 bool parseSyspAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
164 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
165 AArch64CC::CondCode parseCondCodeString(StringRef Cond,
166 std::string &Suggestion);
167 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
168 MCRegister matchRegisterNameAlias(StringRef Name, RegKind Kind);
169 bool parseRegister(OperandVector &Operands);
170 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
171 bool parseNeonVectorList(OperandVector &Operands);
172 bool parseOptionalMulOperand(OperandVector &Operands);
173 bool parseOptionalVGOperand(OperandVector &Operands, StringRef &VecGroup);
174 bool parseKeywordOperand(OperandVector &Operands);
175 bool parseOperand(OperandVector &Operands, bool isCondCode,
176 bool invertCondCode);
177 bool parseImmExpr(int64_t &Out);
178 bool parseComma();
179 bool parseRegisterInRange(unsigned &Out, unsigned Base, unsigned First,
180 unsigned Last);
181
182 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
183 OperandVector &Operands);
184
185 bool parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E);
186 bool parseDataExpr(const MCExpr *&Res) override;
187 bool parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc);
188
189 bool parseDirectiveArch(SMLoc L);
190 bool parseDirectiveArchExtension(SMLoc L);
191 bool parseDirectiveCPU(SMLoc L);
192 bool parseDirectiveInst(SMLoc L);
193
194 bool parseDirectiveTLSDescCall(SMLoc L, bool IsAuth);
195
196 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
197 bool parseDirectiveLtorg(SMLoc L);
198
199 bool parseDirectiveReq(StringRef Name, SMLoc L);
200 bool parseDirectiveUnreq(SMLoc L);
201 bool parseDirectiveCFINegateRAState();
202 bool parseDirectiveCFINegateRAStateWithPC();
203 bool parseDirectiveCFILLVMSetRAState();
204 bool parseDirectiveCFIBKeyFrame();
205 bool parseDirectiveCFIMTETaggedFrame();
206
207 bool parseDirectiveVariantPCS(SMLoc L);
208
209 bool parseDirectiveSEHAllocStack(SMLoc L);
210 bool parseDirectiveSEHPrologEnd(SMLoc L);
211 bool parseDirectiveSEHEndC(SMLoc L);
212 bool parseDirectiveSEHSaveR19R20X(SMLoc L);
213 bool parseDirectiveSEHSaveFPLR(SMLoc L);
214 bool parseDirectiveSEHSaveFPLRX(SMLoc L);
215 bool parseDirectiveSEHSaveReg(SMLoc L);
216 bool parseDirectiveSEHSaveRegX(SMLoc L);
217 bool parseDirectiveSEHSaveRegP(SMLoc L);
218 bool parseDirectiveSEHSaveRegPX(SMLoc L);
219 bool parseDirectiveSEHSaveLRPair(SMLoc L);
220 bool parseDirectiveSEHSaveFReg(SMLoc L);
221 bool parseDirectiveSEHSaveFRegX(SMLoc L);
222 bool parseDirectiveSEHSaveFRegP(SMLoc L);
223 bool parseDirectiveSEHSaveFRegPX(SMLoc L);
224 bool parseDirectiveSEHSetFP(SMLoc L);
225 bool parseDirectiveSEHAddFP(SMLoc L);
226 bool parseDirectiveSEHNop(SMLoc L);
227 bool parseDirectiveSEHSaveNext(SMLoc L);
228 bool parseDirectiveSEHEpilogStart(SMLoc L);
229 bool parseDirectiveSEHEpilogEnd(SMLoc L);
230 bool parseDirectiveSEHTrapFrame(SMLoc L);
231 bool parseDirectiveSEHMachineFrame(SMLoc L);
232 bool parseDirectiveSEHContext(SMLoc L);
233 bool parseDirectiveSEHECContext(SMLoc L);
234 bool parseDirectiveSEHClearUnwoundToCall(SMLoc L);
235 bool parseDirectiveSEHPACSignLR(SMLoc L);
236 bool parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired, bool Writeback);
237 bool parseDirectiveSEHAllocZ(SMLoc L);
238 bool parseDirectiveSEHSaveZReg(SMLoc L);
239 bool parseDirectiveSEHSavePReg(SMLoc L);
240 bool parseDirectiveAeabiSubSectionHeader(SMLoc L);
241 bool parseDirectiveAeabiAArch64Attr(SMLoc L);
242
243 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
244 SmallVectorImpl<SMLoc> &Loc);
245 unsigned getNumRegsForRegKind(RegKind K);
246 bool matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
247 OperandVector &Operands, MCStreamer &Out,
248 uint64_t &ErrorInfo,
249 bool MatchingInlineAsm) override;
250 /// @name Auto-generated Match Functions
251 /// {
252
253#define GET_ASSEMBLER_HEADER
254#include "AArch64GenAsmMatcher.inc"
255
256 /// }
257
258 ParseStatus tryParseScalarRegister(MCRegister &Reg);
259 ParseStatus tryParseVectorRegister(MCRegister &Reg, StringRef &Kind,
260 RegKind MatchKind);
261 ParseStatus tryParseMatrixRegister(OperandVector &Operands);
262 ParseStatus tryParseSVCR(OperandVector &Operands);
263 ParseStatus tryParseOptionalShiftExtend(OperandVector &Operands);
264 ParseStatus tryParseBarrierOperand(OperandVector &Operands);
265 ParseStatus tryParseBarriernXSOperand(OperandVector &Operands);
266 ParseStatus tryParseSysReg(OperandVector &Operands);
267 ParseStatus tryParseSysCROperand(OperandVector &Operands);
268 template <bool IsSVEPrefetch = false>
269 ParseStatus tryParsePrefetch(OperandVector &Operands);
270 ParseStatus tryParseRPRFMOperand(OperandVector &Operands);
271 ParseStatus tryParseTIndexHint(OperandVector &Operands);
272 ParseStatus tryParseAdrpLabel(OperandVector &Operands);
273 ParseStatus tryParseAdrLabel(OperandVector &Operands);
274 template <bool AddFPZeroAsLiteral>
275 ParseStatus tryParseFPImm(OperandVector &Operands);
276 ParseStatus tryParseImmWithOptionalShift(OperandVector &Operands);
277 ParseStatus tryParseGPR64sp0Operand(OperandVector &Operands);
278 bool tryParseNeonVectorRegister(OperandVector &Operands);
279 ParseStatus tryParseVectorIndex(OperandVector &Operands);
280 ParseStatus tryParseGPRSeqPair(OperandVector &Operands);
281 ParseStatus tryParseSyspXzrPair(OperandVector &Operands);
282 template <bool ParseShiftExtend,
283 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
284 ParseStatus tryParseGPROperand(OperandVector &Operands);
285 ParseStatus tryParseZTOperand(OperandVector &Operands);
286 template <bool ParseShiftExtend, bool ParseSuffix>
287 ParseStatus tryParseSVEDataVector(OperandVector &Operands);
288 template <RegKind RK>
289 ParseStatus tryParseSVEPredicateVector(OperandVector &Operands);
290 ParseStatus
291 tryParseSVEPredicateOrPredicateAsCounterVector(OperandVector &Operands);
292 template <RegKind VectorKind>
293 ParseStatus tryParseVectorList(OperandVector &Operands,
294 bool ExpectMatch = false);
295 ParseStatus tryParseMatrixTileList(OperandVector &Operands);
296 ParseStatus tryParseSVEPattern(OperandVector &Operands);
297 ParseStatus tryParseSVEVecLenSpecifier(OperandVector &Operands);
298 ParseStatus tryParseGPR64x8(OperandVector &Operands);
299 ParseStatus tryParseImmRange(OperandVector &Operands);
300
301public:
302 enum AArch64MatchResultTy {
303 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
304#define GET_OPERAND_DIAGNOSTIC_TYPES
305#include "AArch64GenAsmMatcher.inc"
306 };
307 bool IsILP32;
308 bool IsWindowsArm64EC;
309
310 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
311 const MCInstrInfo &MII)
312 : MCTargetAsmParser(STI, MII) {
313 IsILP32 = STI.getTargetTriple().getEnvironment() == Triple::GNUILP32;
314 IsWindowsArm64EC = STI.getTargetTriple().isWindowsArm64EC();
315 MCAsmParserExtension::Initialize(Parser);
316 MCStreamer &S = getParser().getStreamer();
317 if (S.getTargetStreamer() == nullptr)
318 new AArch64TargetStreamer(S);
319
320 // Alias .hword/.word/.[dx]word to the target-independent
321 // .2byte/.4byte/.8byte directives as they have the same form and
322 // semantics:
323 /// ::= (.hword | .word | .dword | .xword ) [ expression (, expression)* ]
324 Parser.addAliasForDirective(Directive: ".hword", Alias: ".2byte");
325 Parser.addAliasForDirective(Directive: ".word", Alias: ".4byte");
326 Parser.addAliasForDirective(Directive: ".dword", Alias: ".8byte");
327 Parser.addAliasForDirective(Directive: ".xword", Alias: ".8byte");
328
329 // Initialize the set of available features.
330 setAvailableFeatures(ComputeAvailableFeatures(FB: getSTI().getFeatureBits()));
331 }
332
333 bool areEqualRegs(const MCParsedAsmOperand &Op1,
334 const MCParsedAsmOperand &Op2) const override;
335 bool parseInstruction(ParseInstructionInfo &Info, StringRef Name,
336 SMLoc NameLoc, OperandVector &Operands) override;
337 bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
338 ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
339 SMLoc &EndLoc) override;
340 bool ParseDirective(AsmToken DirectiveID) override;
341 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
342 unsigned Kind) override;
343
344 static bool classifySymbolRef(const MCExpr *Expr, AArch64::Specifier &ELFSpec,
345 AArch64::Specifier &DarwinSpec,
346 int64_t &Addend);
347};
348
349/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
350/// instruction.
351class AArch64Operand : public MCParsedAsmOperand {
352private:
353 enum KindTy {
354 k_Immediate,
355 k_ShiftedImm,
356 k_ImmRange,
357 k_CondCode,
358 k_Register,
359 k_MatrixRegister,
360 k_MatrixTileList,
361 k_SVCR,
362 k_VectorList,
363 k_VectorIndex,
364 k_Token,
365 k_SysReg,
366 k_SysCR,
367 k_Prefetch,
368 k_ShiftExtend,
369 k_FPImm,
370 k_Barrier,
371 k_TIndexHint,
372 } Kind;
373
374 SMLoc StartLoc, EndLoc;
375
376 struct TokOp {
377 const char *Data;
378 unsigned Length;
379 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
380 };
381
382 // Separate shift/extend operand.
383 struct ShiftExtendOp {
384 AArch64_AM::ShiftExtendType Type;
385 unsigned Amount;
386 bool HasExplicitAmount;
387 };
388
389 struct RegOp {
390 MCRegister Reg;
391 RegKind Kind;
392 int ElementWidth;
393
394 // The register may be allowed as a different register class,
395 // e.g. for GPR64as32 or GPR32as64.
396 RegConstraintEqualityTy EqualityTy;
397
398 // In some cases the shift/extend needs to be explicitly parsed together
399 // with the register, rather than as a separate operand. This is needed
400 // for addressing modes where the instruction as a whole dictates the
401 // scaling/extend, rather than specific bits in the instruction.
402 // By parsing them as a single operand, we avoid the need to pass an
403 // extra operand in all CodeGen patterns (because all operands need to
404 // have an associated value), and we avoid the need to update TableGen to
405 // accept operands that have no associated bits in the instruction.
406 //
407 // An added benefit of parsing them together is that the assembler
408 // can give a sensible diagnostic if the scaling is not correct.
409 //
410 // The default is 'lsl #0' (HasExplicitAmount = false) if no
411 // ShiftExtend is specified.
412 ShiftExtendOp ShiftExtend;
413 };
414
415 struct MatrixRegOp {
416 MCRegister Reg;
417 unsigned ElementWidth;
418 MatrixKind Kind;
419 };
420
421 struct MatrixTileListOp {
422 unsigned RegMask = 0;
423 };
424
425 struct VectorListOp {
426 MCRegister Reg;
427 unsigned Count;
428 unsigned Stride;
429 unsigned NumElements;
430 unsigned ElementWidth;
431 RegKind RegisterKind;
432 };
433
434 struct VectorIndexOp {
435 int Val;
436 };
437
438 struct ImmOp {
439 const MCExpr *Val;
440 };
441
442 struct ShiftedImmOp {
443 const MCExpr *Val;
444 unsigned ShiftAmount;
445 };
446
447 struct ImmRangeOp {
448 unsigned First;
449 unsigned Last;
450 };
451
452 struct CondCodeOp {
453 AArch64CC::CondCode Code;
454 };
455
456 struct FPImmOp {
457 uint64_t Val; // APFloat value bitcasted to uint64_t.
458 bool IsExact; // describes whether parsed value was exact.
459 };
460
461 struct BarrierOp {
462 const char *Data;
463 unsigned Length;
464 unsigned Val; // Not the enum since not all values have names.
465 bool HasnXSModifier;
466 };
467
468 struct SysRegOp {
469 const char *Data;
470 unsigned Length;
471 uint32_t MRSReg;
472 uint32_t MSRReg;
473 uint32_t PStateField;
474 };
475
476 struct SysCRImmOp {
477 unsigned Val;
478 };
479
480 struct PrefetchOp {
481 const char *Data;
482 unsigned Length;
483 unsigned Val;
484 };
485
486 struct TIndexHintOp {
487 const char *Data;
488 unsigned Length;
489 unsigned Val;
490 };
491
492 struct SVCROp {
493 const char *Data;
494 unsigned Length;
495 unsigned PStateField;
496 };
497
498 union {
499 struct TokOp Tok;
500 struct RegOp Reg;
501 struct MatrixRegOp MatrixReg;
502 struct MatrixTileListOp MatrixTileList;
503 struct VectorListOp VectorList;
504 struct VectorIndexOp VectorIndex;
505 struct ImmOp Imm;
506 struct ShiftedImmOp ShiftedImm;
507 struct ImmRangeOp ImmRange;
508 struct CondCodeOp CondCode;
509 struct FPImmOp FPImm;
510 struct BarrierOp Barrier;
511 struct SysRegOp SysReg;
512 struct SysCRImmOp SysCRImm;
513 struct PrefetchOp Prefetch;
514 struct TIndexHintOp TIndexHint;
515 struct ShiftExtendOp ShiftExtend;
516 struct SVCROp SVCR;
517 };
518
519 // Keep the MCContext around as the MCExprs may need manipulated during
520 // the add<>Operands() calls.
521 MCContext &Ctx;
522
523public:
524 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
525
526 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
527 Kind = o.Kind;
528 StartLoc = o.StartLoc;
529 EndLoc = o.EndLoc;
530 switch (Kind) {
531 case k_Token:
532 Tok = o.Tok;
533 break;
534 case k_Immediate:
535 Imm = o.Imm;
536 break;
537 case k_ShiftedImm:
538 ShiftedImm = o.ShiftedImm;
539 break;
540 case k_ImmRange:
541 ImmRange = o.ImmRange;
542 break;
543 case k_CondCode:
544 CondCode = o.CondCode;
545 break;
546 case k_FPImm:
547 FPImm = o.FPImm;
548 break;
549 case k_Barrier:
550 Barrier = o.Barrier;
551 break;
552 case k_Register:
553 Reg = o.Reg;
554 break;
555 case k_MatrixRegister:
556 MatrixReg = o.MatrixReg;
557 break;
558 case k_MatrixTileList:
559 MatrixTileList = o.MatrixTileList;
560 break;
561 case k_VectorList:
562 VectorList = o.VectorList;
563 break;
564 case k_VectorIndex:
565 VectorIndex = o.VectorIndex;
566 break;
567 case k_SysReg:
568 SysReg = o.SysReg;
569 break;
570 case k_SysCR:
571 SysCRImm = o.SysCRImm;
572 break;
573 case k_Prefetch:
574 Prefetch = o.Prefetch;
575 break;
576 case k_TIndexHint:
577 TIndexHint = o.TIndexHint;
578 break;
579 case k_ShiftExtend:
580 ShiftExtend = o.ShiftExtend;
581 break;
582 case k_SVCR:
583 SVCR = o.SVCR;
584 break;
585 }
586 }
587
588 /// getStartLoc - Get the location of the first token of this operand.
589 SMLoc getStartLoc() const override { return StartLoc; }
590 /// getEndLoc - Get the location of the last token of this operand.
591 SMLoc getEndLoc() const override { return EndLoc; }
592
593 StringRef getToken() const {
594 assert(Kind == k_Token && "Invalid access!");
595 return StringRef(Tok.Data, Tok.Length);
596 }
597
598 bool isTokenSuffix() const {
599 assert(Kind == k_Token && "Invalid access!");
600 return Tok.IsSuffix;
601 }
602
603 const MCExpr *getImm() const {
604 assert(Kind == k_Immediate && "Invalid access!");
605 return Imm.Val;
606 }
607
608 const MCExpr *getShiftedImmVal() const {
609 assert(Kind == k_ShiftedImm && "Invalid access!");
610 return ShiftedImm.Val;
611 }
612
613 unsigned getShiftedImmShift() const {
614 assert(Kind == k_ShiftedImm && "Invalid access!");
615 return ShiftedImm.ShiftAmount;
616 }
617
618 unsigned getFirstImmVal() const {
619 assert(Kind == k_ImmRange && "Invalid access!");
620 return ImmRange.First;
621 }
622
623 unsigned getLastImmVal() const {
624 assert(Kind == k_ImmRange && "Invalid access!");
625 return ImmRange.Last;
626 }
627
628 AArch64CC::CondCode getCondCode() const {
629 assert(Kind == k_CondCode && "Invalid access!");
630 return CondCode.Code;
631 }
632
633 APFloat getFPImm() const {
634 assert (Kind == k_FPImm && "Invalid access!");
635 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
636 }
637
638 bool getFPImmIsExact() const {
639 assert (Kind == k_FPImm && "Invalid access!");
640 return FPImm.IsExact;
641 }
642
643 unsigned getBarrier() const {
644 assert(Kind == k_Barrier && "Invalid access!");
645 return Barrier.Val;
646 }
647
648 StringRef getBarrierName() const {
649 assert(Kind == k_Barrier && "Invalid access!");
650 return StringRef(Barrier.Data, Barrier.Length);
651 }
652
653 bool getBarriernXSModifier() const {
654 assert(Kind == k_Barrier && "Invalid access!");
655 return Barrier.HasnXSModifier;
656 }
657
658 MCRegister getReg() const override {
659 assert(Kind == k_Register && "Invalid access!");
660 return Reg.Reg;
661 }
662
663 MCRegister getMatrixReg() const {
664 assert(Kind == k_MatrixRegister && "Invalid access!");
665 return MatrixReg.Reg;
666 }
667
668 unsigned getMatrixElementWidth() const {
669 assert(Kind == k_MatrixRegister && "Invalid access!");
670 return MatrixReg.ElementWidth;
671 }
672
673 MatrixKind getMatrixKind() const {
674 assert(Kind == k_MatrixRegister && "Invalid access!");
675 return MatrixReg.Kind;
676 }
677
678 unsigned getMatrixTileListRegMask() const {
679 assert(isMatrixTileList() && "Invalid access!");
680 return MatrixTileList.RegMask;
681 }
682
683 RegConstraintEqualityTy getRegEqualityTy() const {
684 assert(Kind == k_Register && "Invalid access!");
685 return Reg.EqualityTy;
686 }
687
688 MCRegister getVectorListStart() const {
689 assert(Kind == k_VectorList && "Invalid access!");
690 return VectorList.Reg;
691 }
692
693 unsigned getVectorListCount() const {
694 assert(Kind == k_VectorList && "Invalid access!");
695 return VectorList.Count;
696 }
697
698 unsigned getVectorListStride() const {
699 assert(Kind == k_VectorList && "Invalid access!");
700 return VectorList.Stride;
701 }
702
703 int getVectorIndex() const {
704 assert(Kind == k_VectorIndex && "Invalid access!");
705 return VectorIndex.Val;
706 }
707
708 StringRef getSysReg() const {
709 assert(Kind == k_SysReg && "Invalid access!");
710 return StringRef(SysReg.Data, SysReg.Length);
711 }
712
713 unsigned getSysCR() const {
714 assert(Kind == k_SysCR && "Invalid access!");
715 return SysCRImm.Val;
716 }
717
718 unsigned getPrefetch() const {
719 assert(Kind == k_Prefetch && "Invalid access!");
720 return Prefetch.Val;
721 }
722
723 unsigned getTIndexHint() const {
724 assert(Kind == k_TIndexHint && "Invalid access!");
725 return TIndexHint.Val;
726 }
727
728 StringRef getTIndexHintName() const {
729 assert(Kind == k_TIndexHint && "Invalid access!");
730 return StringRef(TIndexHint.Data, TIndexHint.Length);
731 }
732
733 StringRef getSVCR() const {
734 assert(Kind == k_SVCR && "Invalid access!");
735 return StringRef(SVCR.Data, SVCR.Length);
736 }
737
738 StringRef getPrefetchName() const {
739 assert(Kind == k_Prefetch && "Invalid access!");
740 return StringRef(Prefetch.Data, Prefetch.Length);
741 }
742
743 AArch64_AM::ShiftExtendType getShiftExtendType() const {
744 if (Kind == k_ShiftExtend)
745 return ShiftExtend.Type;
746 if (Kind == k_Register)
747 return Reg.ShiftExtend.Type;
748 llvm_unreachable("Invalid access!");
749 }
750
751 unsigned getShiftExtendAmount() const {
752 if (Kind == k_ShiftExtend)
753 return ShiftExtend.Amount;
754 if (Kind == k_Register)
755 return Reg.ShiftExtend.Amount;
756 llvm_unreachable("Invalid access!");
757 }
758
759 bool hasShiftExtendAmount() const {
760 if (Kind == k_ShiftExtend)
761 return ShiftExtend.HasExplicitAmount;
762 if (Kind == k_Register)
763 return Reg.ShiftExtend.HasExplicitAmount;
764 llvm_unreachable("Invalid access!");
765 }
766
767 bool isImm() const override { return Kind == k_Immediate; }
768 bool isMem() const override { return false; }
769
770 bool isUImm6() const {
771 if (!isImm())
772 return false;
773 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
774 if (!MCE)
775 return false;
776 int64_t Val = MCE->getValue();
777 return (Val >= 0 && Val < 64);
778 }
779
780 template <int Width> DiagnosticPredicate isSImm() const {
781 return isSImmScaled<Width, 1>();
782 }
783
784 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
785 return isImmScaled<Bits, Scale>(true);
786 }
787
788 template <int Bits, int Scale, int Offset = 0, bool IsRange = false>
789 DiagnosticPredicate isUImmScaled() const {
790 if (IsRange && isImmRange() &&
791 (getLastImmVal() != getFirstImmVal() + Offset))
792 return DiagnosticPredicate::NoMatch;
793
794 return isImmScaled<Bits, Scale, IsRange>(false);
795 }
796
797 template <int Bits, int Scale, bool IsRange = false>
798 DiagnosticPredicate isImmScaled(bool Signed) const {
799 if ((!isImm() && !isImmRange()) || (isImm() && IsRange) ||
800 (isImmRange() && !IsRange))
801 return DiagnosticPredicate::NoMatch;
802
803 int64_t Val;
804 if (isImmRange())
805 Val = getFirstImmVal();
806 else {
807 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
808 if (!MCE)
809 return DiagnosticPredicate::NoMatch;
810 Val = MCE->getValue();
811 }
812
813 int64_t MinVal, MaxVal;
814 if (Signed) {
815 int64_t Shift = Bits - 1;
816 MinVal = (int64_t(1) << Shift) * -Scale;
817 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
818 } else {
819 MinVal = 0;
820 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
821 }
822
823 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
824 return DiagnosticPredicate::Match;
825
826 return DiagnosticPredicate::NearMatch;
827 }
828
829 DiagnosticPredicate isSVEPattern() const {
830 if (!isImm())
831 return DiagnosticPredicate::NoMatch;
832 auto *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
833 if (!MCE)
834 return DiagnosticPredicate::NoMatch;
835 int64_t Val = MCE->getValue();
836 if (Val >= 0 && Val < 32)
837 return DiagnosticPredicate::Match;
838 return DiagnosticPredicate::NearMatch;
839 }
840
841 DiagnosticPredicate isSVEVecLenSpecifier() const {
842 if (!isImm())
843 return DiagnosticPredicate::NoMatch;
844 auto *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
845 if (!MCE)
846 return DiagnosticPredicate::NoMatch;
847 int64_t Val = MCE->getValue();
848 if (Val >= 0 && Val <= 1)
849 return DiagnosticPredicate::Match;
850 return DiagnosticPredicate::NearMatch;
851 }
852
853 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
854 AArch64::Specifier ELFSpec;
855 AArch64::Specifier DarwinSpec;
856 int64_t Addend;
857 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
858 Addend)) {
859 // If we don't understand the expression, assume the best and
860 // let the fixup and relocation code deal with it.
861 return true;
862 }
863
864 if (DarwinSpec == AArch64::S_MACHO_PAGEOFF ||
865 llvm::is_contained(
866 Set: {AArch64::S_LO12, AArch64::S_GOT_LO12, AArch64::S_GOT_AUTH_LO12,
867 AArch64::S_DTPREL_LO12, AArch64::S_DTPREL_LO12_NC,
868 AArch64::S_TPREL_LO12, AArch64::S_TPREL_LO12_NC,
869 AArch64::S_GOTTPREL_LO12_NC, AArch64::S_TLSDESC_LO12,
870 AArch64::S_TLSDESC_AUTH_LO12, AArch64::S_SECREL_LO12,
871 AArch64::S_SECREL_HI12, AArch64::S_GOT_PAGE_LO15},
872 Element: ELFSpec)) {
873 // Note that we don't range-check the addend. It's adjusted modulo page
874 // size when converted, so there is no "out of range" condition when using
875 // @pageoff.
876 return true;
877 } else if (DarwinSpec == AArch64::S_MACHO_GOTPAGEOFF ||
878 DarwinSpec == AArch64::S_MACHO_TLVPPAGEOFF) {
879 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
880 return Addend == 0;
881 }
882
883 return false;
884 }
885
886 template <int Scale> DiagnosticPredicate isUImm12Offset() const {
887 if (!isImm())
888 return DiagnosticPredicate::NoMatch;
889
890 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
891 if (!MCE)
892 return DiagnosticPredicate(isSymbolicUImm12Offset(Expr: getImm()));
893
894 int64_t Val = MCE->getValue();
895 if ((Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000)
896 return DiagnosticPredicate::Match;
897 return DiagnosticPredicate::NearMatch;
898 }
899
900 template <int N, int M> DiagnosticPredicate isImmInRange() const {
901 if (!isImm())
902 return DiagnosticPredicate::NoMatch;
903 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
904 if (!MCE)
905 return DiagnosticPredicate::NoMatch;
906 int64_t Val = MCE->getValue();
907 if (Val >= N && Val <= M)
908 return DiagnosticPredicate::Match;
909 return DiagnosticPredicate::NearMatch;
910 }
911
912 bool isHinteUImm16() const {
913 if (!isImm())
914 return false;
915 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
916 if (!MCE)
917 return false;
918 int64_t Val = MCE->getValue();
919 return Val >= 0 && Val <= 65535 &&
920 !(Val >= 12319 && Val <= 16383 && ((Val - 12319) % 32) == 0);
921 }
922
923 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
924 // a logical immediate can always be represented when inverted.
925 template <typename T>
926 bool isLogicalImm() const {
927 if (!isImm())
928 return false;
929 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
930 if (!MCE)
931 return false;
932
933 int64_t Val = MCE->getValue();
934 // Avoid left shift by 64 directly.
935 uint64_t Upper = UINT64_C(-1) << (sizeof(T) * 4) << (sizeof(T) * 4);
936 // Allow all-0 or all-1 in top bits to permit bitwise NOT.
937 if ((Val & Upper) && (Val & Upper) != Upper)
938 return false;
939
940 return AArch64_AM::isLogicalImmediate(imm: Val & ~Upper, regSize: sizeof(T) * 8);
941 }
942
943 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
944
945 bool isImmRange() const { return Kind == k_ImmRange; }
946
947 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
948 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
949 /// immediate that can be shifted by 'Shift'.
950 template <unsigned Width>
951 std::optional<std::pair<int64_t, unsigned>> getShiftedVal() const {
952 if (isShiftedImm() && Width == getShiftedImmShift())
953 if (auto *CE = dyn_cast<MCConstantExpr>(Val: getShiftedImmVal()))
954 return std::make_pair(x: CE->getValue(), y: Width);
955
956 if (isImm())
957 if (auto *CE = dyn_cast<MCConstantExpr>(Val: getImm())) {
958 int64_t Val = CE->getValue();
959 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
960 return std::make_pair(x: Val >> Width, y: Width);
961 else
962 return std::make_pair(x&: Val, y: 0u);
963 }
964
965 return {};
966 }
967
968 bool isAddSubImm() const {
969 if (!isShiftedImm() && !isImm())
970 return false;
971
972 const MCExpr *Expr;
973
974 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
975 if (isShiftedImm()) {
976 unsigned Shift = ShiftedImm.ShiftAmount;
977 Expr = ShiftedImm.Val;
978 if (Shift != 0 && Shift != 12)
979 return false;
980 } else {
981 Expr = getImm();
982 }
983
984 AArch64::Specifier ELFSpec;
985 AArch64::Specifier DarwinSpec;
986 int64_t Addend;
987 if (AArch64AsmParser::classifySymbolRef(Expr, ELFSpec, DarwinSpec,
988 Addend)) {
989 return DarwinSpec == AArch64::S_MACHO_PAGEOFF ||
990 DarwinSpec == AArch64::S_MACHO_TLVPPAGEOFF ||
991 (DarwinSpec == AArch64::S_MACHO_GOTPAGEOFF && Addend == 0) ||
992 llvm::is_contained(
993 Set: {AArch64::S_LO12, AArch64::S_GOT_AUTH_LO12,
994 AArch64::S_DTPREL_HI12, AArch64::S_DTPREL_LO12,
995 AArch64::S_DTPREL_LO12_NC, AArch64::S_TPREL_HI12,
996 AArch64::S_TPREL_LO12, AArch64::S_TPREL_LO12_NC,
997 AArch64::S_TLSDESC_LO12, AArch64::S_TLSDESC_AUTH_LO12,
998 AArch64::S_SECREL_HI12, AArch64::S_SECREL_LO12},
999 Element: ELFSpec);
1000 }
1001
1002 // If it's a constant, it should be a real immediate in range.
1003 if (auto ShiftedVal = getShiftedVal<12>())
1004 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
1005
1006 // If it's an expression, we hope for the best and let the fixup/relocation
1007 // code deal with it.
1008 return true;
1009 }
1010
1011 bool isAddSubImmNeg() const {
1012 if (!isShiftedImm() && !isImm())
1013 return false;
1014
1015 // Otherwise it should be a real negative immediate in range.
1016 if (auto ShiftedVal = getShiftedVal<12>())
1017 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
1018
1019 return false;
1020 }
1021
1022 // Signed value in the range -128 to +127. For element widths of
1023 // 16 bits or higher it may also be a signed multiple of 256 in the
1024 // range -32768 to +32512.
1025 // For element-width of 8 bits a range of -128 to 255 is accepted,
1026 // since a copy of a byte can be either signed/unsigned.
1027 template <typename T>
1028 DiagnosticPredicate isSVECpyImm() const {
1029 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(Val: getImm())))
1030 return DiagnosticPredicate::NoMatch;
1031
1032 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
1033 std::is_same<int8_t, T>::value;
1034 if (auto ShiftedImm = getShiftedVal<8>())
1035 if (!(IsByte && ShiftedImm->second) &&
1036 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
1037 << ShiftedImm->second))
1038 return DiagnosticPredicate::Match;
1039
1040 return DiagnosticPredicate::NearMatch;
1041 }
1042
1043 // Unsigned value in the range 0 to 255. For element widths of
1044 // 16 bits or higher it may also be a signed multiple of 256 in the
1045 // range 0 to 65280.
1046 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
1047 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(Val: getImm())))
1048 return DiagnosticPredicate::NoMatch;
1049
1050 bool IsByte = std::is_same<int8_t, std::make_signed_t<T>>::value ||
1051 std::is_same<int8_t, T>::value;
1052 if (auto ShiftedImm = getShiftedVal<8>())
1053 if (!(IsByte && ShiftedImm->second) &&
1054 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
1055 << ShiftedImm->second))
1056 return DiagnosticPredicate::Match;
1057
1058 return DiagnosticPredicate::NearMatch;
1059 }
1060
1061 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
1062 if (isLogicalImm<T>() && !isSVECpyImm<T>())
1063 return DiagnosticPredicate::Match;
1064 return DiagnosticPredicate::NoMatch;
1065 }
1066
1067 bool isCondCode() const { return Kind == k_CondCode; }
1068
1069 bool isSIMDImmType10() const {
1070 if (!isImm())
1071 return false;
1072 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
1073 if (!MCE)
1074 return false;
1075 return AArch64_AM::isAdvSIMDModImmType10(Imm: MCE->getValue());
1076 }
1077
1078 template<int N>
1079 bool isBranchTarget() const {
1080 if (!isImm())
1081 return false;
1082 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
1083 if (!MCE)
1084 return true;
1085 int64_t Val = MCE->getValue();
1086 if (Val & 0x3)
1087 return false;
1088 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
1089 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
1090 }
1091
1092 bool isMovWSymbol(ArrayRef<AArch64::Specifier> AllowedModifiers) const {
1093 if (!isImm())
1094 return false;
1095
1096 AArch64::Specifier ELFSpec;
1097 AArch64::Specifier DarwinSpec;
1098 int64_t Addend;
1099 if (!AArch64AsmParser::classifySymbolRef(Expr: getImm(), ELFSpec, DarwinSpec,
1100 Addend)) {
1101 return false;
1102 }
1103 if (DarwinSpec != AArch64::S_None)
1104 return false;
1105
1106 return llvm::is_contained(Range&: AllowedModifiers, Element: ELFSpec);
1107 }
1108
1109 bool isMovWSymbolG3() const {
1110 return isMovWSymbol(AllowedModifiers: {AArch64::S_ABS_G3, AArch64::S_PREL_G3});
1111 }
1112
1113 bool isMovWSymbolG2() const {
1114 return isMovWSymbol(AllowedModifiers: {AArch64::S_ABS_G2, AArch64::S_ABS_G2_S,
1115 AArch64::S_ABS_G2_NC, AArch64::S_PREL_G2,
1116 AArch64::S_PREL_G2_NC, AArch64::S_TPREL_G2,
1117 AArch64::S_DTPREL_G2});
1118 }
1119
1120 bool isMovWSymbolG1() const {
1121 return isMovWSymbol(AllowedModifiers: {AArch64::S_ABS_G1, AArch64::S_ABS_G1_S,
1122 AArch64::S_ABS_G1_NC, AArch64::S_PREL_G1,
1123 AArch64::S_PREL_G1_NC, AArch64::S_GOTTPREL_G1,
1124 AArch64::S_TPREL_G1, AArch64::S_TPREL_G1_NC,
1125 AArch64::S_DTPREL_G1, AArch64::S_DTPREL_G1_NC});
1126 }
1127
1128 bool isMovWSymbolG0() const {
1129 return isMovWSymbol(AllowedModifiers: {AArch64::S_ABS_G0, AArch64::S_ABS_G0_S,
1130 AArch64::S_ABS_G0_NC, AArch64::S_PREL_G0,
1131 AArch64::S_PREL_G0_NC, AArch64::S_GOTTPREL_G0_NC,
1132 AArch64::S_TPREL_G0, AArch64::S_TPREL_G0_NC,
1133 AArch64::S_DTPREL_G0, AArch64::S_DTPREL_G0_NC});
1134 }
1135
1136 template<int RegWidth, int Shift>
1137 bool isMOVZMovAlias() const {
1138 if (!isImm()) return false;
1139
1140 const MCExpr *E = getImm();
1141 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: E)) {
1142 uint64_t Value = CE->getValue();
1143
1144 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
1145 }
1146 // Only supports the case of Shift being 0 if an expression is used as an
1147 // operand
1148 return !Shift && E;
1149 }
1150
1151 template<int RegWidth, int Shift>
1152 bool isMOVNMovAlias() const {
1153 if (!isImm()) return false;
1154
1155 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
1156 if (!CE) return false;
1157 uint64_t Value = CE->getValue();
1158
1159 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
1160 }
1161
1162 bool isFPImm() const {
1163 return Kind == k_FPImm &&
1164 AArch64_AM::getFP64Imm(Imm: getFPImm().bitcastToAPInt()) != -1;
1165 }
1166
1167 bool isBarrier() const {
1168 return Kind == k_Barrier && !getBarriernXSModifier();
1169 }
1170 bool isBarriernXS() const {
1171 return Kind == k_Barrier && getBarriernXSModifier();
1172 }
1173 bool isSysReg() const { return Kind == k_SysReg; }
1174
1175 bool isMRSSystemRegister() const {
1176 if (!isSysReg()) return false;
1177
1178 return SysReg.MRSReg != -1U;
1179 }
1180
1181 bool isMSRSystemRegister() const {
1182 if (!isSysReg()) return false;
1183 return SysReg.MSRReg != -1U;
1184 }
1185
1186 bool isSystemPStateFieldWithImm0_1() const {
1187 if (!isSysReg()) return false;
1188 return AArch64PState::lookupPStateImm0_1ByEncoding(Encoding: SysReg.PStateField);
1189 }
1190
1191 bool isSystemPStateFieldWithImm0_15() const {
1192 if (!isSysReg())
1193 return false;
1194 return AArch64PState::lookupPStateImm0_15ByEncoding(Encoding: SysReg.PStateField);
1195 }
1196
1197 bool isSVCR() const {
1198 if (Kind != k_SVCR)
1199 return false;
1200 return SVCR.PStateField != -1U;
1201 }
1202
1203 bool isReg() const override {
1204 return Kind == k_Register;
1205 }
1206
1207 bool isVectorList() const { return Kind == k_VectorList; }
1208
1209 bool isScalarReg() const {
1210 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1211 }
1212
1213 bool isNeonVectorReg() const {
1214 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1215 }
1216
1217 bool isNeonVectorRegLo() const {
1218 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
1219 (getAArch64MCRegisterClass(RC: AArch64::FPR128_loRegClassID)
1220 .contains(Reg: Reg.Reg) ||
1221 getAArch64MCRegisterClass(RC: AArch64::FPR64_loRegClassID)
1222 .contains(Reg: Reg.Reg));
1223 }
1224
1225 bool isNeonVectorReg0to7() const {
1226 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
1227 (getAArch64MCRegisterClass(RC: AArch64::FPR128_0to7RegClassID)
1228 .contains(Reg: Reg.Reg));
1229 }
1230
1231 bool isMatrix() const { return Kind == k_MatrixRegister; }
1232 bool isMatrixTileList() const { return Kind == k_MatrixTileList; }
1233
1234 template <unsigned Class> bool isSVEPredicateAsCounterReg() const {
1235 RegKind RK;
1236 switch (Class) {
1237 case AArch64::PPRRegClassID:
1238 case AArch64::PPR_3bRegClassID:
1239 case AArch64::PPR_p8to15RegClassID:
1240 case AArch64::PNRRegClassID:
1241 case AArch64::PNR_p8to15RegClassID:
1242 case AArch64::PPRorPNRRegClassID:
1243 RK = RegKind::SVEPredicateAsCounter;
1244 break;
1245 default:
1246 llvm_unreachable("Unsupported register class");
1247 }
1248
1249 return (Kind == k_Register && Reg.Kind == RK) &&
1250 getAArch64MCRegisterClass(RC: Class).contains(Reg: getReg());
1251 }
1252
1253 template <unsigned Class> bool isSVEVectorReg() const {
1254 RegKind RK;
1255 switch (Class) {
1256 case AArch64::ZPRRegClassID:
1257 case AArch64::ZPR_3bRegClassID:
1258 case AArch64::ZPR_4bRegClassID:
1259 case AArch64::ZPRMul2_LoRegClassID:
1260 case AArch64::ZPRMul2_HiRegClassID:
1261 case AArch64::ZPR_KRegClassID:
1262 RK = RegKind::SVEDataVector;
1263 break;
1264 case AArch64::PPRRegClassID:
1265 case AArch64::PPR_3bRegClassID:
1266 case AArch64::PPR_p8to15RegClassID:
1267 case AArch64::PNRRegClassID:
1268 case AArch64::PNR_p8to15RegClassID:
1269 case AArch64::PPRorPNRRegClassID:
1270 RK = RegKind::SVEPredicateVector;
1271 break;
1272 default:
1273 llvm_unreachable("Unsupported register class");
1274 }
1275
1276 return (Kind == k_Register && Reg.Kind == RK) &&
1277 getAArch64MCRegisterClass(RC: Class).contains(Reg: getReg());
1278 }
1279
1280 template <unsigned Class> bool isFPRasZPR() const {
1281 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1282 getAArch64MCRegisterClass(RC: Class).contains(Reg: getReg());
1283 }
1284
1285 template <int ElementWidth, unsigned Class>
1286 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1287 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1288 return DiagnosticPredicate::NoMatch;
1289
1290 if (isSVEVectorReg<Class>() && (Reg.ElementWidth == ElementWidth))
1291 return DiagnosticPredicate::Match;
1292
1293 return DiagnosticPredicate::NearMatch;
1294 }
1295
1296 template <int ElementWidth, unsigned Class>
1297 DiagnosticPredicate isSVEPredicateOrPredicateAsCounterRegOfWidth() const {
1298 if (Kind != k_Register || (Reg.Kind != RegKind::SVEPredicateAsCounter &&
1299 Reg.Kind != RegKind::SVEPredicateVector))
1300 return DiagnosticPredicate::NoMatch;
1301
1302 if ((isSVEPredicateAsCounterReg<Class>() ||
1303 isSVEPredicateVectorRegOfWidth<ElementWidth, Class>()) &&
1304 Reg.ElementWidth == ElementWidth)
1305 return DiagnosticPredicate::Match;
1306
1307 return DiagnosticPredicate::NearMatch;
1308 }
1309
1310 template <int ElementWidth, unsigned Class>
1311 DiagnosticPredicate isSVEPredicateAsCounterRegOfWidth() const {
1312 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateAsCounter)
1313 return DiagnosticPredicate::NoMatch;
1314
1315 if (isSVEPredicateAsCounterReg<Class>() && (Reg.ElementWidth == ElementWidth))
1316 return DiagnosticPredicate::Match;
1317
1318 return DiagnosticPredicate::NearMatch;
1319 }
1320
1321 template <int ElementWidth, unsigned Class>
1322 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1323 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1324 return DiagnosticPredicate::NoMatch;
1325
1326 if (isSVEVectorReg<Class>() && Reg.ElementWidth == ElementWidth)
1327 return DiagnosticPredicate::Match;
1328
1329 return DiagnosticPredicate::NearMatch;
1330 }
1331
1332 template <int ElementWidth, unsigned Class,
1333 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1334 bool ShiftWidthAlwaysSame>
1335 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1336 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1337 if (!VectorMatch.isMatch())
1338 return DiagnosticPredicate::NoMatch;
1339
1340 // Give a more specific diagnostic when the user has explicitly typed in
1341 // a shift-amount that does not match what is expected, but for which
1342 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1343 bool MatchShift = getShiftExtendAmount() == Log2_32(Value: ShiftWidth / 8);
1344 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1345 ShiftExtendTy == AArch64_AM::SXTW) &&
1346 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1347 return DiagnosticPredicate::NoMatch;
1348
1349 if (MatchShift && ShiftExtendTy == getShiftExtendType())
1350 return DiagnosticPredicate::Match;
1351
1352 return DiagnosticPredicate::NearMatch;
1353 }
1354
1355 bool isGPR32as64() const {
1356 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1357 getAArch64MCRegisterClass(RC: AArch64::GPR64RegClassID)
1358 .contains(Reg: Reg.Reg);
1359 }
1360
1361 bool isGPR64as32() const {
1362 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1363 getAArch64MCRegisterClass(RC: AArch64::GPR32RegClassID)
1364 .contains(Reg: Reg.Reg);
1365 }
1366
1367 bool isGPR64x8() const {
1368 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1369 getAArch64MCRegisterClass(RC: AArch64::GPR64x8ClassRegClassID)
1370 .contains(Reg: Reg.Reg);
1371 }
1372
1373 bool isWSeqPair() const {
1374 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1375 getAArch64MCRegisterClass(RC: AArch64::WSeqPairsClassRegClassID)
1376 .contains(Reg: Reg.Reg);
1377 }
1378
1379 bool isXSeqPair() const {
1380 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1381 getAArch64MCRegisterClass(RC: AArch64::XSeqPairsClassRegClassID)
1382 .contains(Reg: Reg.Reg);
1383 }
1384
1385 bool isSyspXzrPair() const {
1386 return isGPR64<AArch64::GPR64RegClassID>() && Reg.Reg == AArch64::XZR;
1387 }
1388
1389 template<int64_t Angle, int64_t Remainder>
1390 DiagnosticPredicate isComplexRotation() const {
1391 if (!isImm())
1392 return DiagnosticPredicate::NoMatch;
1393
1394 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
1395 if (!CE)
1396 return DiagnosticPredicate::NoMatch;
1397 uint64_t Value = CE->getValue();
1398
1399 if (Value % Angle == Remainder && Value <= 270)
1400 return DiagnosticPredicate::Match;
1401 return DiagnosticPredicate::NearMatch;
1402 }
1403
1404 template <unsigned RegClassID> bool isGPR64() const {
1405 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1406 getAArch64MCRegisterClass(RC: RegClassID).contains(Reg: getReg());
1407 }
1408
1409 template <unsigned RegClassID, int ExtWidth>
1410 DiagnosticPredicate isGPR64WithShiftExtend() const {
1411 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1412 return DiagnosticPredicate::NoMatch;
1413
1414 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1415 getShiftExtendAmount() == Log2_32(Value: ExtWidth / 8))
1416 return DiagnosticPredicate::Match;
1417 return DiagnosticPredicate::NearMatch;
1418 }
1419
1420 /// Is this a vector list with the type implicit (presumably attached to the
1421 /// instruction itself)?
1422 template <RegKind VectorKind, unsigned NumRegs, bool IsConsecutive = false>
1423 bool isImplicitlyTypedVectorList() const {
1424 return Kind == k_VectorList && VectorList.Count == NumRegs &&
1425 VectorList.NumElements == 0 &&
1426 VectorList.RegisterKind == VectorKind &&
1427 (!IsConsecutive || (VectorList.Stride == 1));
1428 }
1429
1430 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1431 unsigned ElementWidth, unsigned Stride = 1>
1432 bool isTypedVectorList() const {
1433 if (Kind != k_VectorList)
1434 return false;
1435 if (VectorList.Count != NumRegs)
1436 return false;
1437 if (VectorList.RegisterKind != VectorKind)
1438 return false;
1439 if (VectorList.ElementWidth != ElementWidth)
1440 return false;
1441 if (VectorList.Stride != Stride)
1442 return false;
1443 return VectorList.NumElements == NumElements;
1444 }
1445
1446 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1447 unsigned ElementWidth, unsigned FirstReg, unsigned LastReg,
1448 unsigned Multiple>
1449 DiagnosticPredicate isTypedVectorListInRange() const {
1450 bool Res =
1451 isTypedVectorList<VectorKind, NumRegs, NumElements, ElementWidth>();
1452 if (!Res)
1453 return DiagnosticPredicate::NoMatch;
1454 if (VectorList.Reg < FirstReg || VectorList.Reg > LastReg ||
1455 (VectorList.Reg - FirstReg) % Multiple != 0)
1456 return DiagnosticPredicate::NearMatch;
1457 return DiagnosticPredicate::Match;
1458 }
1459
1460 template <RegKind VectorKind, unsigned NumRegs, unsigned Stride,
1461 unsigned ElementWidth>
1462 DiagnosticPredicate isTypedVectorListStrided() const {
1463 bool Res = isTypedVectorList<VectorKind, NumRegs, /*NumElements*/ 0,
1464 ElementWidth, Stride>();
1465 if (!Res)
1466 return DiagnosticPredicate::NoMatch;
1467 if ((VectorList.Reg < (AArch64::Z0 + Stride)) ||
1468 ((VectorList.Reg >= AArch64::Z16) &&
1469 (VectorList.Reg < (AArch64::Z16 + Stride))))
1470 return DiagnosticPredicate::Match;
1471 return DiagnosticPredicate::NoMatch;
1472 }
1473
1474 template <int Min, int Max>
1475 DiagnosticPredicate isVectorIndex() const {
1476 if (Kind != k_VectorIndex)
1477 return DiagnosticPredicate::NoMatch;
1478 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1479 return DiagnosticPredicate::Match;
1480 return DiagnosticPredicate::NearMatch;
1481 }
1482
1483 bool isToken() const override { return Kind == k_Token; }
1484
1485 bool isTokenEqual(StringRef Str) const {
1486 return Kind == k_Token && getToken() == Str;
1487 }
1488 bool isSysCR() const { return Kind == k_SysCR; }
1489 bool isPrefetch() const { return Kind == k_Prefetch; }
1490 bool isTIndexHint() const { return Kind == k_TIndexHint; }
1491 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1492 bool isShifter() const {
1493 if (!isShiftExtend())
1494 return false;
1495
1496 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1497 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1498 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1499 ST == AArch64_AM::MSL);
1500 }
1501
1502 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1503 if (Kind != k_FPImm)
1504 return DiagnosticPredicate::NoMatch;
1505
1506 if (getFPImmIsExact()) {
1507 // Lookup the immediate from table of supported immediates.
1508 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(Enum: ImmEnum);
1509 assert(Desc && "Unknown enum value");
1510 StringRef DescRepr = AArch64ExactFPImm::getExactFPImmStr(Desc->Repr);
1511
1512 // Calculate its FP value.
1513 APFloat RealVal(APFloat::IEEEdouble());
1514 auto StatusOrErr =
1515 RealVal.convertFromString(DescRepr, APFloat::rmTowardZero);
1516 if (errorToBool(Err: StatusOrErr.takeError()) || *StatusOrErr != APFloat::opOK)
1517 llvm_unreachable("FP immediate is not exact");
1518
1519 if (getFPImm().bitwiseIsEqual(RHS: RealVal))
1520 return DiagnosticPredicate::Match;
1521 }
1522
1523 return DiagnosticPredicate::NearMatch;
1524 }
1525
1526 template <unsigned ImmA, unsigned ImmB>
1527 DiagnosticPredicate isExactFPImm() const {
1528 DiagnosticPredicate Res = DiagnosticPredicate::NoMatch;
1529 if ((Res = isExactFPImm<ImmA>()))
1530 return DiagnosticPredicate::Match;
1531 if ((Res = isExactFPImm<ImmB>()))
1532 return DiagnosticPredicate::Match;
1533 return Res;
1534 }
1535
1536 bool isExtend() const {
1537 if (!isShiftExtend())
1538 return false;
1539
1540 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1541 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1542 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1543 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1544 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1545 ET == AArch64_AM::LSL) &&
1546 getShiftExtendAmount() <= 4;
1547 }
1548
1549 bool isExtend64() const {
1550 if (!isExtend())
1551 return false;
1552 // Make sure the extend expects a 32-bit source register.
1553 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1554 return ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1555 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1556 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW;
1557 }
1558
1559 bool isExtendLSL64() const {
1560 if (!isExtend())
1561 return false;
1562 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1563 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1564 ET == AArch64_AM::LSL) &&
1565 getShiftExtendAmount() <= 4;
1566 }
1567
1568 bool isLSLImm3Shift() const {
1569 if (!isShiftExtend())
1570 return false;
1571 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1572 return ET == AArch64_AM::LSL && getShiftExtendAmount() <= 7;
1573 }
1574
1575 template<int Width> bool isMemXExtend() const {
1576 if (!isExtend())
1577 return false;
1578 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1579 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1580 (getShiftExtendAmount() == Log2_32(Value: Width / 8) ||
1581 getShiftExtendAmount() == 0);
1582 }
1583
1584 template<int Width> bool isMemWExtend() const {
1585 if (!isExtend())
1586 return false;
1587 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1588 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1589 (getShiftExtendAmount() == Log2_32(Value: Width / 8) ||
1590 getShiftExtendAmount() == 0);
1591 }
1592
1593 template <unsigned width>
1594 bool isArithmeticShifter() const {
1595 if (!isShifter())
1596 return false;
1597
1598 // An arithmetic shifter is LSL, LSR, or ASR.
1599 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1600 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1601 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1602 }
1603
1604 template <unsigned width>
1605 bool isLogicalShifter() const {
1606 if (!isShifter())
1607 return false;
1608
1609 // A logical shifter is LSL, LSR, ASR or ROR.
1610 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1611 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1612 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1613 getShiftExtendAmount() < width;
1614 }
1615
1616 bool isMovImm32Shifter() const {
1617 if (!isShifter())
1618 return false;
1619
1620 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1621 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1622 if (ST != AArch64_AM::LSL)
1623 return false;
1624 uint64_t Val = getShiftExtendAmount();
1625 return (Val == 0 || Val == 16);
1626 }
1627
1628 bool isMovImm64Shifter() const {
1629 if (!isShifter())
1630 return false;
1631
1632 // A MOVi shifter is LSL of 0 or 16.
1633 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1634 if (ST != AArch64_AM::LSL)
1635 return false;
1636 uint64_t Val = getShiftExtendAmount();
1637 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1638 }
1639
1640 bool isLogicalVecShifter() const {
1641 if (!isShifter())
1642 return false;
1643
1644 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1645 unsigned Shift = getShiftExtendAmount();
1646 return getShiftExtendType() == AArch64_AM::LSL &&
1647 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1648 }
1649
1650 bool isLogicalVecHalfWordShifter() const {
1651 if (!isLogicalVecShifter())
1652 return false;
1653
1654 // A logical vector shifter is a left shift by 0 or 8.
1655 unsigned Shift = getShiftExtendAmount();
1656 return getShiftExtendType() == AArch64_AM::LSL &&
1657 (Shift == 0 || Shift == 8);
1658 }
1659
1660 bool isMoveVecShifter() const {
1661 if (!isShiftExtend())
1662 return false;
1663
1664 // A logical vector shifter is a left shift by 8 or 16.
1665 unsigned Shift = getShiftExtendAmount();
1666 return getShiftExtendType() == AArch64_AM::MSL &&
1667 (Shift == 8 || Shift == 16);
1668 }
1669
1670 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1671 // to LDUR/STUR when the offset is not legal for the former but is for
1672 // the latter. As such, in addition to checking for being a legal unscaled
1673 // address, also check that it is not a legal scaled address. This avoids
1674 // ambiguity in the matcher.
1675 template<int Width>
1676 bool isSImm9OffsetFB() const {
1677 return isSImm<9>() && !isUImm12Offset<Width / 8>();
1678 }
1679
1680 bool isAdrpLabel() const {
1681 // Validation was handled during parsing, so we just verify that
1682 // something didn't go haywire.
1683 if (!isImm())
1684 return false;
1685
1686 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Imm.Val)) {
1687 int64_t Val = CE->getValue();
1688 int64_t Min = - (4096 * (1LL << (21 - 1)));
1689 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1690 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1691 }
1692
1693 return true;
1694 }
1695
1696 bool isAdrLabel() const {
1697 // Validation was handled during parsing, so we just verify that
1698 // something didn't go haywire.
1699 if (!isImm())
1700 return false;
1701
1702 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Imm.Val)) {
1703 int64_t Val = CE->getValue();
1704 int64_t Min = - (1LL << (21 - 1));
1705 int64_t Max = ((1LL << (21 - 1)) - 1);
1706 return Val >= Min && Val <= Max;
1707 }
1708
1709 return true;
1710 }
1711
1712 template <MatrixKind Kind, unsigned EltSize, unsigned RegClass>
1713 DiagnosticPredicate isMatrixRegOperand() const {
1714 if (!isMatrix())
1715 return DiagnosticPredicate::NoMatch;
1716 if (getMatrixKind() != Kind ||
1717 !getAArch64MCRegisterClass(RC: RegClass).contains(Reg: getMatrixReg()) ||
1718 EltSize != getMatrixElementWidth())
1719 return DiagnosticPredicate::NearMatch;
1720 return DiagnosticPredicate::Match;
1721 }
1722
1723 bool isPAuthPCRelLabel16Operand() const {
1724 // PAuth PCRel16 operands are similar to regular branch targets, but only
1725 // negative values are allowed for concrete immediates as signing instr
1726 // should be in a lower address.
1727 if (!isImm())
1728 return false;
1729 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
1730 if (!MCE)
1731 return true;
1732 int64_t Val = MCE->getValue();
1733 if (Val & 0b11)
1734 return false;
1735 return (Val <= 0) && (Val > -(1 << 18));
1736 }
1737
1738 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1739 // Add as immediates when possible. Null MCExpr = 0.
1740 if (!Expr)
1741 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
1742 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
1743 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
1744 else
1745 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
1746 }
1747
1748 void addRegOperands(MCInst &Inst, unsigned N) const {
1749 assert(N == 1 && "Invalid number of operands!");
1750 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1751 }
1752
1753 void addMatrixOperands(MCInst &Inst, unsigned N) const {
1754 assert(N == 1 && "Invalid number of operands!");
1755 Inst.addOperand(Op: MCOperand::createReg(Reg: getMatrixReg()));
1756 }
1757
1758 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1759 assert(N == 1 && "Invalid number of operands!");
1760 assert(
1761 getAArch64MCRegisterClass(AArch64::GPR64RegClassID).contains(getReg()));
1762
1763 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1764 MCRegister Reg = RI->getRegClass(i: AArch64::GPR32RegClassID)
1765 .getRegister(i: RI->getEncodingValue(Reg: getReg()));
1766
1767 Inst.addOperand(Op: MCOperand::createReg(Reg));
1768 }
1769
1770 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1771 assert(N == 1 && "Invalid number of operands!");
1772 assert(
1773 getAArch64MCRegisterClass(AArch64::GPR32RegClassID).contains(getReg()));
1774
1775 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1776 MCRegister Reg = RI->getRegClass(i: AArch64::GPR64RegClassID)
1777 .getRegister(i: RI->getEncodingValue(Reg: getReg()));
1778
1779 Inst.addOperand(Op: MCOperand::createReg(Reg));
1780 }
1781
1782 template <int Width>
1783 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1784 unsigned Base;
1785 switch (Width) {
1786 case 8: Base = AArch64::B0; break;
1787 case 16: Base = AArch64::H0; break;
1788 case 32: Base = AArch64::S0; break;
1789 case 64: Base = AArch64::D0; break;
1790 case 128: Base = AArch64::Q0; break;
1791 default:
1792 llvm_unreachable("Unsupported width");
1793 }
1794 Inst.addOperand(Op: MCOperand::createReg(Reg: AArch64::Z0 + getReg() - Base));
1795 }
1796
1797 void addPPRorPNRRegOperands(MCInst &Inst, unsigned N) const {
1798 assert(N == 1 && "Invalid number of operands!");
1799 MCRegister Reg = getReg();
1800 // Normalise to PPR
1801 if (Reg >= AArch64::PN0 && Reg <= AArch64::PN15)
1802 Reg = Reg - AArch64::PN0 + AArch64::P0;
1803 Inst.addOperand(Op: MCOperand::createReg(Reg));
1804 }
1805
1806 void addPNRasPPRRegOperands(MCInst &Inst, unsigned N) const {
1807 assert(N == 1 && "Invalid number of operands!");
1808 Inst.addOperand(
1809 Op: MCOperand::createReg(Reg: (getReg() - AArch64::PN0) + AArch64::P0));
1810 }
1811
1812 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1813 assert(N == 1 && "Invalid number of operands!");
1814 assert(getAArch64MCRegisterClass(AArch64::FPR128RegClassID)
1815 .contains(getReg()));
1816 Inst.addOperand(Op: MCOperand::createReg(Reg: AArch64::D0 + getReg() - AArch64::Q0));
1817 }
1818
1819 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1820 assert(N == 1 && "Invalid number of operands!");
1821 assert(getAArch64MCRegisterClass(AArch64::FPR128RegClassID)
1822 .contains(getReg()));
1823 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1824 }
1825
1826 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1827 assert(N == 1 && "Invalid number of operands!");
1828 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1829 }
1830
1831 void addVectorReg0to7Operands(MCInst &Inst, unsigned N) const {
1832 assert(N == 1 && "Invalid number of operands!");
1833 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
1834 }
1835
1836 enum VecListIndexType {
1837 VecListIdx_DReg = 0,
1838 VecListIdx_QReg = 1,
1839 VecListIdx_ZReg = 2,
1840 VecListIdx_PReg = 3,
1841 };
1842
1843 template <VecListIndexType RegTy, unsigned NumRegs,
1844 bool IsConsecutive = false>
1845 void addVectorListOperands(MCInst &Inst, unsigned N) const {
1846 assert(N == 1 && "Invalid number of operands!");
1847 assert((!IsConsecutive || (getVectorListStride() == 1)) &&
1848 "Expected consecutive registers");
1849 static const unsigned FirstRegs[][5] = {
1850 /* DReg */ { AArch64::Q0,
1851 AArch64::D0, AArch64::D0_D1,
1852 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1853 /* QReg */ { AArch64::Q0,
1854 AArch64::Q0, AArch64::Q0_Q1,
1855 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1856 /* ZReg */ { AArch64::Z0,
1857 AArch64::Z0, AArch64::Z0_Z1,
1858 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 },
1859 /* PReg */ { AArch64::P0,
1860 AArch64::P0, AArch64::P0_P1 }
1861 };
1862
1863 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1864 " NumRegs must be <= 4 for ZRegs");
1865
1866 assert((RegTy != VecListIdx_PReg || NumRegs <= 2) &&
1867 " NumRegs must be <= 2 for PRegs");
1868
1869 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1870 Inst.addOperand(Op: MCOperand::createReg(Reg: FirstReg + getVectorListStart() -
1871 FirstRegs[(unsigned)RegTy][0]));
1872 }
1873
1874 template <unsigned NumRegs>
1875 void addStridedVectorListOperands(MCInst &Inst, unsigned N) const {
1876 assert(N == 1 && "Invalid number of operands!");
1877 assert((NumRegs == 2 || NumRegs == 4) && " NumRegs must be 2 or 4");
1878
1879 switch (NumRegs) {
1880 case 2:
1881 if (getVectorListStart() < AArch64::Z16) {
1882 assert((getVectorListStart() < AArch64::Z8) &&
1883 (getVectorListStart() >= AArch64::Z0) && "Invalid Register");
1884 Inst.addOperand(Op: MCOperand::createReg(
1885 Reg: AArch64::Z0_Z8 + getVectorListStart() - AArch64::Z0));
1886 } else {
1887 assert((getVectorListStart() < AArch64::Z24) &&
1888 (getVectorListStart() >= AArch64::Z16) && "Invalid Register");
1889 Inst.addOperand(Op: MCOperand::createReg(
1890 Reg: AArch64::Z16_Z24 + getVectorListStart() - AArch64::Z16));
1891 }
1892 break;
1893 case 4:
1894 if (getVectorListStart() < AArch64::Z16) {
1895 assert((getVectorListStart() < AArch64::Z4) &&
1896 (getVectorListStart() >= AArch64::Z0) && "Invalid Register");
1897 Inst.addOperand(Op: MCOperand::createReg(
1898 Reg: AArch64::Z0_Z4_Z8_Z12 + getVectorListStart() - AArch64::Z0));
1899 } else {
1900 assert((getVectorListStart() < AArch64::Z20) &&
1901 (getVectorListStart() >= AArch64::Z16) && "Invalid Register");
1902 Inst.addOperand(Op: MCOperand::createReg(
1903 Reg: AArch64::Z16_Z20_Z24_Z28 + getVectorListStart() - AArch64::Z16));
1904 }
1905 break;
1906 default:
1907 llvm_unreachable("Unsupported number of registers for strided vec list");
1908 }
1909 }
1910
1911 void addMatrixTileListOperands(MCInst &Inst, unsigned N) const {
1912 assert(N == 1 && "Invalid number of operands!");
1913 unsigned RegMask = getMatrixTileListRegMask();
1914 assert(RegMask <= 0xFF && "Invalid mask!");
1915 Inst.addOperand(Op: MCOperand::createImm(Val: RegMask));
1916 }
1917
1918 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
1919 assert(N == 1 && "Invalid number of operands!");
1920 Inst.addOperand(Op: MCOperand::createImm(Val: getVectorIndex()));
1921 }
1922
1923 template <unsigned ImmIs0, unsigned ImmIs1>
1924 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1925 assert(N == 1 && "Invalid number of operands!");
1926 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1927 Inst.addOperand(Op: MCOperand::createImm(Val: bool(isExactFPImm<ImmIs1>())));
1928 }
1929
1930 void addImmOperands(MCInst &Inst, unsigned N) const {
1931 assert(N == 1 && "Invalid number of operands!");
1932 // If this is a pageoff symrefexpr with an addend, adjust the addend
1933 // to be only the page-offset portion. Otherwise, just add the expr
1934 // as-is.
1935 addExpr(Inst, Expr: getImm());
1936 }
1937
1938 template <int Adj> void addAdjImmOperands(MCInst &Inst, unsigned N) const {
1939 assert(N == 1 && "Invalid number of operands!");
1940 int64_t Imm = cast<MCConstantExpr>(Val: getImm())->getValue();
1941 Inst.addOperand(Op: MCOperand::createImm(Val: Imm + Adj));
1942 }
1943
1944 template <int Shift>
1945 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1946 assert(N == 2 && "Invalid number of operands!");
1947 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1948 Inst.addOperand(Op: MCOperand::createImm(Val: ShiftedVal->first));
1949 Inst.addOperand(Op: MCOperand::createImm(Val: ShiftedVal->second));
1950 } else if (isShiftedImm()) {
1951 addExpr(Inst, Expr: getShiftedImmVal());
1952 Inst.addOperand(Op: MCOperand::createImm(Val: getShiftedImmShift()));
1953 } else {
1954 addExpr(Inst, Expr: getImm());
1955 Inst.addOperand(Op: MCOperand::createImm(Val: 0));
1956 }
1957 }
1958
1959 template <int Shift>
1960 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1961 assert(N == 2 && "Invalid number of operands!");
1962 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1963 Inst.addOperand(Op: MCOperand::createImm(Val: -ShiftedVal->first));
1964 Inst.addOperand(Op: MCOperand::createImm(Val: ShiftedVal->second));
1965 } else
1966 llvm_unreachable("Not a shifted negative immediate");
1967 }
1968
1969 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1970 assert(N == 1 && "Invalid number of operands!");
1971 Inst.addOperand(Op: MCOperand::createImm(Val: getCondCode()));
1972 }
1973
1974 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1975 assert(N == 1 && "Invalid number of operands!");
1976 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
1977 if (!MCE)
1978 addExpr(Inst, Expr: getImm());
1979 else
1980 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 12));
1981 }
1982
1983 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1984 addImmOperands(Inst, N);
1985 }
1986
1987 template<int Scale>
1988 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1989 assert(N == 1 && "Invalid number of operands!");
1990 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
1991
1992 if (!MCE) {
1993 Inst.addOperand(Op: MCOperand::createExpr(Val: getImm()));
1994 return;
1995 }
1996 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() / Scale));
1997 }
1998
1999 void addUImm6Operands(MCInst &Inst, unsigned N) const {
2000 assert(N == 1 && "Invalid number of operands!");
2001 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2002 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue()));
2003 }
2004
2005 template <int Scale>
2006 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
2007 assert(N == 1 && "Invalid number of operands!");
2008 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2009 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() / Scale));
2010 }
2011
2012 template <int Scale>
2013 void addImmScaledRangeOperands(MCInst &Inst, unsigned N) const {
2014 assert(N == 1 && "Invalid number of operands!");
2015 Inst.addOperand(Op: MCOperand::createImm(Val: getFirstImmVal() / Scale));
2016 }
2017
2018 template <typename T>
2019 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
2020 assert(N == 1 && "Invalid number of operands!");
2021 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2022 std::make_unsigned_t<T> Val = MCE->getValue();
2023 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(imm: Val, regSize: sizeof(T) * 8);
2024 Inst.addOperand(Op: MCOperand::createImm(Val: encoding));
2025 }
2026
2027 template <typename T>
2028 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
2029 assert(N == 1 && "Invalid number of operands!");
2030 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2031 std::make_unsigned_t<T> Val = ~MCE->getValue();
2032 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(imm: Val, regSize: sizeof(T) * 8);
2033 Inst.addOperand(Op: MCOperand::createImm(Val: encoding));
2034 }
2035
2036 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
2037 assert(N == 1 && "Invalid number of operands!");
2038 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2039 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(Imm: MCE->getValue());
2040 Inst.addOperand(Op: MCOperand::createImm(Val: encoding));
2041 }
2042
2043 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
2044 // Branch operands don't encode the low bits, so shift them off
2045 // here. If it's a label, however, just put it on directly as there's
2046 // not enough information now to do anything.
2047 assert(N == 1 && "Invalid number of operands!");
2048 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
2049 if (!MCE) {
2050 addExpr(Inst, Expr: getImm());
2051 return;
2052 }
2053 assert(MCE && "Invalid constant immediate operand!");
2054 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 2));
2055 }
2056
2057 void addPAuthPCRelLabel16Operands(MCInst &Inst, unsigned N) const {
2058 // PC-relative operands don't encode the low bits, so shift them off
2059 // here. If it's a label, however, just put it on directly as there's
2060 // not enough information now to do anything.
2061 assert(N == 1 && "Invalid number of operands!");
2062 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
2063 if (!MCE) {
2064 addExpr(Inst, Expr: getImm());
2065 return;
2066 }
2067 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 2));
2068 }
2069
2070 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
2071 // Branch operands don't encode the low bits, so shift them off
2072 // here. If it's a label, however, just put it on directly as there's
2073 // not enough information now to do anything.
2074 assert(N == 1 && "Invalid number of operands!");
2075 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
2076 if (!MCE) {
2077 addExpr(Inst, Expr: getImm());
2078 return;
2079 }
2080 assert(MCE && "Invalid constant immediate operand!");
2081 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 2));
2082 }
2083
2084 void addPCRelLabel9Operands(MCInst &Inst, unsigned N) const {
2085 // Branch operands don't encode the low bits, so shift them off
2086 // here. If it's a label, however, just put it on directly as there's
2087 // not enough information now to do anything.
2088 assert(N == 1 && "Invalid number of operands!");
2089 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
2090 if (!MCE) {
2091 addExpr(Inst, Expr: getImm());
2092 return;
2093 }
2094 assert(MCE && "Invalid constant immediate operand!");
2095 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 2));
2096 }
2097
2098 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
2099 // Branch operands don't encode the low bits, so shift them off
2100 // here. If it's a label, however, just put it on directly as there's
2101 // not enough information now to do anything.
2102 assert(N == 1 && "Invalid number of operands!");
2103 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: getImm());
2104 if (!MCE) {
2105 addExpr(Inst, Expr: getImm());
2106 return;
2107 }
2108 assert(MCE && "Invalid constant immediate operand!");
2109 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() >> 2));
2110 }
2111
2112 void addFPImmOperands(MCInst &Inst, unsigned N) const {
2113 assert(N == 1 && "Invalid number of operands!");
2114 Inst.addOperand(Op: MCOperand::createImm(
2115 Val: AArch64_AM::getFP64Imm(Imm: getFPImm().bitcastToAPInt())));
2116 }
2117
2118 void addBarrierOperands(MCInst &Inst, unsigned N) const {
2119 assert(N == 1 && "Invalid number of operands!");
2120 Inst.addOperand(Op: MCOperand::createImm(Val: getBarrier()));
2121 }
2122
2123 void addBarriernXSOperands(MCInst &Inst, unsigned N) const {
2124 assert(N == 1 && "Invalid number of operands!");
2125 Inst.addOperand(Op: MCOperand::createImm(Val: getBarrier()));
2126 }
2127
2128 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
2129 assert(N == 1 && "Invalid number of operands!");
2130
2131 Inst.addOperand(Op: MCOperand::createImm(Val: SysReg.MRSReg));
2132 }
2133
2134 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
2135 assert(N == 1 && "Invalid number of operands!");
2136
2137 Inst.addOperand(Op: MCOperand::createImm(Val: SysReg.MSRReg));
2138 }
2139
2140 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
2141 assert(N == 1 && "Invalid number of operands!");
2142
2143 Inst.addOperand(Op: MCOperand::createImm(Val: SysReg.PStateField));
2144 }
2145
2146 void addSVCROperands(MCInst &Inst, unsigned N) const {
2147 assert(N == 1 && "Invalid number of operands!");
2148
2149 Inst.addOperand(Op: MCOperand::createImm(Val: SVCR.PStateField));
2150 }
2151
2152 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
2153 assert(N == 1 && "Invalid number of operands!");
2154
2155 Inst.addOperand(Op: MCOperand::createImm(Val: SysReg.PStateField));
2156 }
2157
2158 void addSysCROperands(MCInst &Inst, unsigned N) const {
2159 assert(N == 1 && "Invalid number of operands!");
2160 Inst.addOperand(Op: MCOperand::createImm(Val: getSysCR()));
2161 }
2162
2163 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
2164 assert(N == 1 && "Invalid number of operands!");
2165 Inst.addOperand(Op: MCOperand::createImm(Val: getPrefetch()));
2166 }
2167
2168 void addTIndexHintOperands(MCInst &Inst, unsigned N) const {
2169 assert(N == 1 && "Invalid number of operands!");
2170 Inst.addOperand(Op: MCOperand::createImm(Val: getTIndexHint()));
2171 }
2172
2173 void addShifterOperands(MCInst &Inst, unsigned N) const {
2174 assert(N == 1 && "Invalid number of operands!");
2175 unsigned Imm =
2176 AArch64_AM::getShifterImm(ST: getShiftExtendType(), Imm: getShiftExtendAmount());
2177 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
2178 }
2179
2180 void addLSLImm3ShifterOperands(MCInst &Inst, unsigned N) const {
2181 assert(N == 1 && "Invalid number of operands!");
2182 unsigned Imm = getShiftExtendAmount();
2183 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
2184 }
2185
2186 void addSyspXzrPairOperand(MCInst &Inst, unsigned N) const {
2187 assert(N == 1 && "Invalid number of operands!");
2188
2189 if (!isScalarReg())
2190 return;
2191
2192 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
2193 MCRegister Reg = RI->getRegClass(i: AArch64::GPR64RegClassID)
2194 .getRegister(i: RI->getEncodingValue(Reg: getReg()));
2195 if (Reg != AArch64::XZR)
2196 llvm_unreachable("wrong register");
2197
2198 Inst.addOperand(Op: MCOperand::createReg(Reg: AArch64::XZR));
2199 }
2200
2201 void addExtendOperands(MCInst &Inst, unsigned N) const {
2202 assert(N == 1 && "Invalid number of operands!");
2203 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2204 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
2205 unsigned Imm = AArch64_AM::getArithExtendImm(ET, Imm: getShiftExtendAmount());
2206 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
2207 }
2208
2209 void addExtend64Operands(MCInst &Inst, unsigned N) const {
2210 assert(N == 1 && "Invalid number of operands!");
2211 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2212 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
2213 unsigned Imm = AArch64_AM::getArithExtendImm(ET, Imm: getShiftExtendAmount());
2214 Inst.addOperand(Op: MCOperand::createImm(Val: Imm));
2215 }
2216
2217 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
2218 assert(N == 2 && "Invalid number of operands!");
2219 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2220 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
2221 Inst.addOperand(Op: MCOperand::createImm(Val: IsSigned));
2222 Inst.addOperand(Op: MCOperand::createImm(Val: getShiftExtendAmount() != 0));
2223 }
2224
2225 // For 8-bit load/store instructions with a register offset, both the
2226 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
2227 // they're disambiguated by whether the shift was explicit or implicit rather
2228 // than its size.
2229 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
2230 assert(N == 2 && "Invalid number of operands!");
2231 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
2232 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
2233 Inst.addOperand(Op: MCOperand::createImm(Val: IsSigned));
2234 Inst.addOperand(Op: MCOperand::createImm(Val: hasShiftExtendAmount()));
2235 }
2236
2237 template<int Shift>
2238 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
2239 assert(N == 1 && "Invalid number of operands!");
2240
2241 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
2242 if (CE) {
2243 uint64_t Value = CE->getValue();
2244 Inst.addOperand(Op: MCOperand::createImm(Val: (Value >> Shift) & 0xffff));
2245 } else {
2246 addExpr(Inst, Expr: getImm());
2247 }
2248 }
2249
2250 template<int Shift>
2251 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
2252 assert(N == 1 && "Invalid number of operands!");
2253
2254 const MCConstantExpr *CE = cast<MCConstantExpr>(Val: getImm());
2255 uint64_t Value = CE->getValue();
2256 Inst.addOperand(Op: MCOperand::createImm(Val: (~Value >> Shift) & 0xffff));
2257 }
2258
2259 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
2260 assert(N == 1 && "Invalid number of operands!");
2261 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2262 Inst.addOperand(Op: MCOperand::createImm(Val: MCE->getValue() / 90));
2263 }
2264
2265 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
2266 assert(N == 1 && "Invalid number of operands!");
2267 const MCConstantExpr *MCE = cast<MCConstantExpr>(Val: getImm());
2268 Inst.addOperand(Op: MCOperand::createImm(Val: (MCE->getValue() - 90) / 180));
2269 }
2270
2271 void print(raw_ostream &OS, const MCAsmInfo &MAI) const override;
2272
2273 static std::unique_ptr<AArch64Operand>
2274 CreateToken(StringRef Str, SMLoc S, MCContext &Ctx, bool IsSuffix = false) {
2275 auto Op = std::make_unique<AArch64Operand>(args: k_Token, args&: Ctx);
2276 Op->Tok.Data = Str.data();
2277 Op->Tok.Length = Str.size();
2278 Op->Tok.IsSuffix = IsSuffix;
2279 Op->StartLoc = S;
2280 Op->EndLoc = S;
2281 return Op;
2282 }
2283
2284 static std::unique_ptr<AArch64Operand>
2285 CreateReg(MCRegister Reg, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
2286 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
2287 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
2288 unsigned ShiftAmount = 0, unsigned HasExplicitAmount = false) {
2289 auto Op = std::make_unique<AArch64Operand>(args: k_Register, args&: Ctx);
2290 Op->Reg.Reg = Reg;
2291 Op->Reg.Kind = Kind;
2292 Op->Reg.ElementWidth = 0;
2293 Op->Reg.EqualityTy = EqTy;
2294 Op->Reg.ShiftExtend.Type = ExtTy;
2295 Op->Reg.ShiftExtend.Amount = ShiftAmount;
2296 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2297 Op->StartLoc = S;
2298 Op->EndLoc = E;
2299 return Op;
2300 }
2301
2302 static std::unique_ptr<AArch64Operand> CreateVectorReg(
2303 MCRegister Reg, RegKind Kind, unsigned ElementWidth, SMLoc S, SMLoc E,
2304 MCContext &Ctx, AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
2305 unsigned ShiftAmount = 0, unsigned HasExplicitAmount = false) {
2306 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
2307 Kind == RegKind::SVEPredicateVector ||
2308 Kind == RegKind::SVEPredicateAsCounter) &&
2309 "Invalid vector kind");
2310 auto Op = CreateReg(Reg, Kind, S, E, Ctx, EqTy: EqualsReg, ExtTy, ShiftAmount,
2311 HasExplicitAmount);
2312 Op->Reg.ElementWidth = ElementWidth;
2313 return Op;
2314 }
2315
2316 static std::unique_ptr<AArch64Operand>
2317 CreateVectorList(MCRegister Reg, unsigned Count, unsigned Stride,
2318 unsigned NumElements, unsigned ElementWidth,
2319 RegKind RegisterKind, SMLoc S, SMLoc E, MCContext &Ctx) {
2320 auto Op = std::make_unique<AArch64Operand>(args: k_VectorList, args&: Ctx);
2321 Op->VectorList.Reg = Reg;
2322 Op->VectorList.Count = Count;
2323 Op->VectorList.Stride = Stride;
2324 Op->VectorList.NumElements = NumElements;
2325 Op->VectorList.ElementWidth = ElementWidth;
2326 Op->VectorList.RegisterKind = RegisterKind;
2327 Op->StartLoc = S;
2328 Op->EndLoc = E;
2329 return Op;
2330 }
2331
2332 static std::unique_ptr<AArch64Operand>
2333 CreateVectorIndex(int Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
2334 auto Op = std::make_unique<AArch64Operand>(args: k_VectorIndex, args&: Ctx);
2335 Op->VectorIndex.Val = Idx;
2336 Op->StartLoc = S;
2337 Op->EndLoc = E;
2338 return Op;
2339 }
2340
2341 static std::unique_ptr<AArch64Operand>
2342 CreateMatrixTileList(unsigned RegMask, SMLoc S, SMLoc E, MCContext &Ctx) {
2343 auto Op = std::make_unique<AArch64Operand>(args: k_MatrixTileList, args&: Ctx);
2344 Op->MatrixTileList.RegMask = RegMask;
2345 Op->StartLoc = S;
2346 Op->EndLoc = E;
2347 return Op;
2348 }
2349
2350 static void ComputeRegsForAlias(unsigned Reg, SmallSet<unsigned, 8> &OutRegs,
2351 const unsigned ElementWidth) {
2352 static std::map<std::pair<unsigned, unsigned>, std::vector<unsigned>>
2353 RegMap = {
2354 {{0, AArch64::ZAB0},
2355 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2356 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2357 {{8, AArch64::ZAB0},
2358 {AArch64::ZAD0, AArch64::ZAD1, AArch64::ZAD2, AArch64::ZAD3,
2359 AArch64::ZAD4, AArch64::ZAD5, AArch64::ZAD6, AArch64::ZAD7}},
2360 {{16, AArch64::ZAH0},
2361 {AArch64::ZAD0, AArch64::ZAD2, AArch64::ZAD4, AArch64::ZAD6}},
2362 {{16, AArch64::ZAH1},
2363 {AArch64::ZAD1, AArch64::ZAD3, AArch64::ZAD5, AArch64::ZAD7}},
2364 {{32, AArch64::ZAS0}, {AArch64::ZAD0, AArch64::ZAD4}},
2365 {{32, AArch64::ZAS1}, {AArch64::ZAD1, AArch64::ZAD5}},
2366 {{32, AArch64::ZAS2}, {AArch64::ZAD2, AArch64::ZAD6}},
2367 {{32, AArch64::ZAS3}, {AArch64::ZAD3, AArch64::ZAD7}},
2368 };
2369
2370 if (ElementWidth == 64)
2371 OutRegs.insert(V: Reg);
2372 else {
2373 std::vector<unsigned> Regs = RegMap[std::make_pair(x: ElementWidth, y&: Reg)];
2374 assert(!Regs.empty() && "Invalid tile or element width!");
2375 OutRegs.insert_range(R&: Regs);
2376 }
2377 }
2378
2379 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
2380 SMLoc E, MCContext &Ctx) {
2381 auto Op = std::make_unique<AArch64Operand>(args: k_Immediate, args&: Ctx);
2382 Op->Imm.Val = Val;
2383 Op->StartLoc = S;
2384 Op->EndLoc = E;
2385 return Op;
2386 }
2387
2388 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
2389 unsigned ShiftAmount,
2390 SMLoc S, SMLoc E,
2391 MCContext &Ctx) {
2392 auto Op = std::make_unique<AArch64Operand>(args: k_ShiftedImm, args&: Ctx);
2393 Op->ShiftedImm .Val = Val;
2394 Op->ShiftedImm.ShiftAmount = ShiftAmount;
2395 Op->StartLoc = S;
2396 Op->EndLoc = E;
2397 return Op;
2398 }
2399
2400 static std::unique_ptr<AArch64Operand> CreateImmRange(unsigned First,
2401 unsigned Last, SMLoc S,
2402 SMLoc E,
2403 MCContext &Ctx) {
2404 auto Op = std::make_unique<AArch64Operand>(args: k_ImmRange, args&: Ctx);
2405 Op->ImmRange.First = First;
2406 Op->ImmRange.Last = Last;
2407 Op->EndLoc = E;
2408 return Op;
2409 }
2410
2411 static std::unique_ptr<AArch64Operand>
2412 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
2413 auto Op = std::make_unique<AArch64Operand>(args: k_CondCode, args&: Ctx);
2414 Op->CondCode.Code = Code;
2415 Op->StartLoc = S;
2416 Op->EndLoc = E;
2417 return Op;
2418 }
2419
2420 static std::unique_ptr<AArch64Operand>
2421 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
2422 auto Op = std::make_unique<AArch64Operand>(args: k_FPImm, args&: Ctx);
2423 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
2424 Op->FPImm.IsExact = IsExact;
2425 Op->StartLoc = S;
2426 Op->EndLoc = S;
2427 return Op;
2428 }
2429
2430 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
2431 StringRef Str,
2432 SMLoc S,
2433 MCContext &Ctx,
2434 bool HasnXSModifier) {
2435 auto Op = std::make_unique<AArch64Operand>(args: k_Barrier, args&: Ctx);
2436 Op->Barrier.Val = Val;
2437 Op->Barrier.Data = Str.data();
2438 Op->Barrier.Length = Str.size();
2439 Op->Barrier.HasnXSModifier = HasnXSModifier;
2440 Op->StartLoc = S;
2441 Op->EndLoc = S;
2442 return Op;
2443 }
2444
2445 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
2446 uint32_t MRSReg,
2447 uint32_t MSRReg,
2448 uint32_t PStateField,
2449 MCContext &Ctx) {
2450 auto Op = std::make_unique<AArch64Operand>(args: k_SysReg, args&: Ctx);
2451 Op->SysReg.Data = Str.data();
2452 Op->SysReg.Length = Str.size();
2453 Op->SysReg.MRSReg = MRSReg;
2454 Op->SysReg.MSRReg = MSRReg;
2455 Op->SysReg.PStateField = PStateField;
2456 Op->StartLoc = S;
2457 Op->EndLoc = S;
2458 return Op;
2459 }
2460
2461 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
2462 SMLoc E, MCContext &Ctx) {
2463 auto Op = std::make_unique<AArch64Operand>(args: k_SysCR, args&: Ctx);
2464 Op->SysCRImm.Val = Val;
2465 Op->StartLoc = S;
2466 Op->EndLoc = E;
2467 return Op;
2468 }
2469
2470 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
2471 StringRef Str,
2472 SMLoc S,
2473 MCContext &Ctx) {
2474 auto Op = std::make_unique<AArch64Operand>(args: k_Prefetch, args&: Ctx);
2475 Op->Prefetch.Val = Val;
2476 Op->Barrier.Data = Str.data();
2477 Op->Barrier.Length = Str.size();
2478 Op->StartLoc = S;
2479 Op->EndLoc = S;
2480 return Op;
2481 }
2482
2483 static std::unique_ptr<AArch64Operand>
2484 CreateTIndexHint(unsigned Val, StringRef Str, SMLoc S, MCContext &Ctx) {
2485 auto Op = std::make_unique<AArch64Operand>(args: k_TIndexHint, args&: Ctx);
2486 Op->TIndexHint.Val = Val;
2487 Op->TIndexHint.Data = Str.data();
2488 Op->TIndexHint.Length = Str.size();
2489 Op->StartLoc = S;
2490 Op->EndLoc = S;
2491 return Op;
2492 }
2493
2494 static std::unique_ptr<AArch64Operand>
2495 CreateMatrixRegister(MCRegister Reg, unsigned ElementWidth, MatrixKind Kind,
2496 SMLoc S, SMLoc E, MCContext &Ctx) {
2497 auto Op = std::make_unique<AArch64Operand>(args: k_MatrixRegister, args&: Ctx);
2498 Op->MatrixReg.Reg = Reg;
2499 Op->MatrixReg.ElementWidth = ElementWidth;
2500 Op->MatrixReg.Kind = Kind;
2501 Op->StartLoc = S;
2502 Op->EndLoc = E;
2503 return Op;
2504 }
2505
2506 static std::unique_ptr<AArch64Operand>
2507 CreateSVCR(uint32_t PStateField, StringRef Str, SMLoc S, MCContext &Ctx) {
2508 auto Op = std::make_unique<AArch64Operand>(args: k_SVCR, args&: Ctx);
2509 Op->SVCR.PStateField = PStateField;
2510 Op->SVCR.Data = Str.data();
2511 Op->SVCR.Length = Str.size();
2512 Op->StartLoc = S;
2513 Op->EndLoc = S;
2514 return Op;
2515 }
2516
2517 static std::unique_ptr<AArch64Operand>
2518 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2519 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2520 auto Op = std::make_unique<AArch64Operand>(args: k_ShiftExtend, args&: Ctx);
2521 Op->ShiftExtend.Type = ShOp;
2522 Op->ShiftExtend.Amount = Val;
2523 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2524 Op->StartLoc = S;
2525 Op->EndLoc = E;
2526 return Op;
2527 }
2528};
2529
2530} // end anonymous namespace.
2531
2532void AArch64Operand::print(raw_ostream &OS, const MCAsmInfo &MAI) const {
2533 switch (Kind) {
2534 case k_FPImm:
2535 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2536 if (!getFPImmIsExact())
2537 OS << " (inexact)";
2538 OS << ">";
2539 break;
2540 case k_Barrier: {
2541 StringRef Name = getBarrierName();
2542 if (!Name.empty())
2543 OS << "<barrier " << Name << ">";
2544 else
2545 OS << "<barrier invalid #" << getBarrier() << ">";
2546 break;
2547 }
2548 case k_Immediate:
2549 MAI.printExpr(OS, *getImm());
2550 break;
2551 case k_ShiftedImm: {
2552 unsigned Shift = getShiftedImmShift();
2553 OS << "<shiftedimm ";
2554 MAI.printExpr(OS, *getShiftedImmVal());
2555 OS << ", lsl #" << AArch64_AM::getShiftValue(Imm: Shift) << ">";
2556 break;
2557 }
2558 case k_ImmRange: {
2559 OS << "<immrange ";
2560 OS << getFirstImmVal();
2561 OS << ":" << getLastImmVal() << ">";
2562 break;
2563 }
2564 case k_CondCode:
2565 OS << "<condcode " << getCondCode() << ">";
2566 break;
2567 case k_VectorList: {
2568 OS << "<vectorlist ";
2569 MCRegister Reg = getVectorListStart();
2570 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2571 OS << Reg.id() + i * getVectorListStride() << " ";
2572 OS << ">";
2573 break;
2574 }
2575 case k_VectorIndex:
2576 OS << "<vectorindex " << getVectorIndex() << ">";
2577 break;
2578 case k_SysReg:
2579 OS << "<sysreg: " << getSysReg() << '>';
2580 break;
2581 case k_Token:
2582 OS << "'" << getToken() << "'";
2583 break;
2584 case k_SysCR:
2585 OS << "c" << getSysCR();
2586 break;
2587 case k_Prefetch: {
2588 StringRef Name = getPrefetchName();
2589 if (!Name.empty())
2590 OS << "<prfop " << Name << ">";
2591 else
2592 OS << "<prfop invalid #" << getPrefetch() << ">";
2593 break;
2594 }
2595 case k_TIndexHint:
2596 OS << getTIndexHintName();
2597 break;
2598 case k_MatrixRegister:
2599 OS << "<matrix " << getMatrixReg().id() << ">";
2600 break;
2601 case k_MatrixTileList: {
2602 OS << "<matrixlist ";
2603 unsigned RegMask = getMatrixTileListRegMask();
2604 unsigned MaxBits = 8;
2605 for (unsigned I = MaxBits; I > 0; --I)
2606 OS << ((RegMask & (1 << (I - 1))) >> (I - 1));
2607 OS << '>';
2608 break;
2609 }
2610 case k_SVCR: {
2611 OS << getSVCR();
2612 break;
2613 }
2614 case k_Register:
2615 OS << "<register " << getReg().id() << ">";
2616 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2617 break;
2618 [[fallthrough]];
2619 case k_ShiftExtend:
2620 OS << "<" << AArch64_AM::getShiftExtendName(ST: getShiftExtendType()) << " #"
2621 << getShiftExtendAmount();
2622 if (!hasShiftExtendAmount())
2623 OS << "<imp>";
2624 OS << '>';
2625 break;
2626 }
2627}
2628
2629/// @name Auto-generated Match Functions
2630/// {
2631
2632static MCRegister MatchRegisterName(StringRef Name);
2633
2634/// }
2635
2636static unsigned MatchNeonVectorRegName(StringRef Name) {
2637 return StringSwitch<unsigned>(Name.lower())
2638 .Case(S: "v0", Value: AArch64::Q0)
2639 .Case(S: "v1", Value: AArch64::Q1)
2640 .Case(S: "v2", Value: AArch64::Q2)
2641 .Case(S: "v3", Value: AArch64::Q3)
2642 .Case(S: "v4", Value: AArch64::Q4)
2643 .Case(S: "v5", Value: AArch64::Q5)
2644 .Case(S: "v6", Value: AArch64::Q6)
2645 .Case(S: "v7", Value: AArch64::Q7)
2646 .Case(S: "v8", Value: AArch64::Q8)
2647 .Case(S: "v9", Value: AArch64::Q9)
2648 .Case(S: "v10", Value: AArch64::Q10)
2649 .Case(S: "v11", Value: AArch64::Q11)
2650 .Case(S: "v12", Value: AArch64::Q12)
2651 .Case(S: "v13", Value: AArch64::Q13)
2652 .Case(S: "v14", Value: AArch64::Q14)
2653 .Case(S: "v15", Value: AArch64::Q15)
2654 .Case(S: "v16", Value: AArch64::Q16)
2655 .Case(S: "v17", Value: AArch64::Q17)
2656 .Case(S: "v18", Value: AArch64::Q18)
2657 .Case(S: "v19", Value: AArch64::Q19)
2658 .Case(S: "v20", Value: AArch64::Q20)
2659 .Case(S: "v21", Value: AArch64::Q21)
2660 .Case(S: "v22", Value: AArch64::Q22)
2661 .Case(S: "v23", Value: AArch64::Q23)
2662 .Case(S: "v24", Value: AArch64::Q24)
2663 .Case(S: "v25", Value: AArch64::Q25)
2664 .Case(S: "v26", Value: AArch64::Q26)
2665 .Case(S: "v27", Value: AArch64::Q27)
2666 .Case(S: "v28", Value: AArch64::Q28)
2667 .Case(S: "v29", Value: AArch64::Q29)
2668 .Case(S: "v30", Value: AArch64::Q30)
2669 .Case(S: "v31", Value: AArch64::Q31)
2670 .Default(Value: 0);
2671}
2672
2673/// Returns an optional pair of (#elements, element-width) if Suffix
2674/// is a valid vector kind. Where the number of elements in a vector
2675/// or the vector width is implicit or explicitly unknown (but still a
2676/// valid suffix kind), 0 is used.
2677static std::optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2678 RegKind VectorKind) {
2679 std::pair<int, int> Res = {-1, -1};
2680
2681 switch (VectorKind) {
2682 case RegKind::NeonVector:
2683 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2684 .Case(S: "", Value: {0, 0})
2685 .Case(S: ".1d", Value: {1, 64})
2686 .Case(S: ".1q", Value: {1, 128})
2687 // '.2h' needed for fp16 scalar pairwise reductions
2688 .Case(S: ".2h", Value: {2, 16})
2689 .Case(S: ".2b", Value: {2, 8})
2690 .Case(S: ".2s", Value: {2, 32})
2691 .Case(S: ".2d", Value: {2, 64})
2692 // '.4b' is another special case for the ARMv8.2a dot product
2693 // operand
2694 .Case(S: ".4b", Value: {4, 8})
2695 .Case(S: ".4h", Value: {4, 16})
2696 .Case(S: ".4s", Value: {4, 32})
2697 .Case(S: ".8b", Value: {8, 8})
2698 .Case(S: ".8h", Value: {8, 16})
2699 .Case(S: ".16b", Value: {16, 8})
2700 // Accept the width neutral ones, too, for verbose syntax. If
2701 // those aren't used in the right places, the token operand won't
2702 // match so all will work out.
2703 .Case(S: ".b", Value: {0, 8})
2704 .Case(S: ".h", Value: {0, 16})
2705 .Case(S: ".s", Value: {0, 32})
2706 .Case(S: ".d", Value: {0, 64})
2707 .Default(Value: {-1, -1});
2708 break;
2709 case RegKind::SVEPredicateAsCounter:
2710 case RegKind::SVEPredicateVector:
2711 case RegKind::SVEDataVector:
2712 case RegKind::Matrix:
2713 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2714 .Case(S: "", Value: {0, 0})
2715 .Case(S: ".b", Value: {0, 8})
2716 .Case(S: ".h", Value: {0, 16})
2717 .Case(S: ".s", Value: {0, 32})
2718 .Case(S: ".d", Value: {0, 64})
2719 .Case(S: ".q", Value: {0, 128})
2720 .Default(Value: {-1, -1});
2721 break;
2722 default:
2723 llvm_unreachable("Unsupported RegKind");
2724 }
2725
2726 if (Res == std::make_pair(x: -1, y: -1))
2727 return std::nullopt;
2728
2729 return std::optional<std::pair<int, int>>(Res);
2730}
2731
2732static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2733 return parseVectorKind(Suffix, VectorKind).has_value();
2734}
2735
2736static unsigned matchSVEDataVectorRegName(StringRef Name) {
2737 return StringSwitch<unsigned>(Name.lower())
2738 .Case(S: "z0", Value: AArch64::Z0)
2739 .Case(S: "z1", Value: AArch64::Z1)
2740 .Case(S: "z2", Value: AArch64::Z2)
2741 .Case(S: "z3", Value: AArch64::Z3)
2742 .Case(S: "z4", Value: AArch64::Z4)
2743 .Case(S: "z5", Value: AArch64::Z5)
2744 .Case(S: "z6", Value: AArch64::Z6)
2745 .Case(S: "z7", Value: AArch64::Z7)
2746 .Case(S: "z8", Value: AArch64::Z8)
2747 .Case(S: "z9", Value: AArch64::Z9)
2748 .Case(S: "z10", Value: AArch64::Z10)
2749 .Case(S: "z11", Value: AArch64::Z11)
2750 .Case(S: "z12", Value: AArch64::Z12)
2751 .Case(S: "z13", Value: AArch64::Z13)
2752 .Case(S: "z14", Value: AArch64::Z14)
2753 .Case(S: "z15", Value: AArch64::Z15)
2754 .Case(S: "z16", Value: AArch64::Z16)
2755 .Case(S: "z17", Value: AArch64::Z17)
2756 .Case(S: "z18", Value: AArch64::Z18)
2757 .Case(S: "z19", Value: AArch64::Z19)
2758 .Case(S: "z20", Value: AArch64::Z20)
2759 .Case(S: "z21", Value: AArch64::Z21)
2760 .Case(S: "z22", Value: AArch64::Z22)
2761 .Case(S: "z23", Value: AArch64::Z23)
2762 .Case(S: "z24", Value: AArch64::Z24)
2763 .Case(S: "z25", Value: AArch64::Z25)
2764 .Case(S: "z26", Value: AArch64::Z26)
2765 .Case(S: "z27", Value: AArch64::Z27)
2766 .Case(S: "z28", Value: AArch64::Z28)
2767 .Case(S: "z29", Value: AArch64::Z29)
2768 .Case(S: "z30", Value: AArch64::Z30)
2769 .Case(S: "z31", Value: AArch64::Z31)
2770 .Default(Value: 0);
2771}
2772
2773static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2774 return StringSwitch<unsigned>(Name.lower())
2775 .Case(S: "p0", Value: AArch64::P0)
2776 .Case(S: "p1", Value: AArch64::P1)
2777 .Case(S: "p2", Value: AArch64::P2)
2778 .Case(S: "p3", Value: AArch64::P3)
2779 .Case(S: "p4", Value: AArch64::P4)
2780 .Case(S: "p5", Value: AArch64::P5)
2781 .Case(S: "p6", Value: AArch64::P6)
2782 .Case(S: "p7", Value: AArch64::P7)
2783 .Case(S: "p8", Value: AArch64::P8)
2784 .Case(S: "p9", Value: AArch64::P9)
2785 .Case(S: "p10", Value: AArch64::P10)
2786 .Case(S: "p11", Value: AArch64::P11)
2787 .Case(S: "p12", Value: AArch64::P12)
2788 .Case(S: "p13", Value: AArch64::P13)
2789 .Case(S: "p14", Value: AArch64::P14)
2790 .Case(S: "p15", Value: AArch64::P15)
2791 .Default(Value: 0);
2792}
2793
2794static unsigned matchSVEPredicateAsCounterRegName(StringRef Name) {
2795 return StringSwitch<unsigned>(Name.lower())
2796 .Case(S: "pn0", Value: AArch64::PN0)
2797 .Case(S: "pn1", Value: AArch64::PN1)
2798 .Case(S: "pn2", Value: AArch64::PN2)
2799 .Case(S: "pn3", Value: AArch64::PN3)
2800 .Case(S: "pn4", Value: AArch64::PN4)
2801 .Case(S: "pn5", Value: AArch64::PN5)
2802 .Case(S: "pn6", Value: AArch64::PN6)
2803 .Case(S: "pn7", Value: AArch64::PN7)
2804 .Case(S: "pn8", Value: AArch64::PN8)
2805 .Case(S: "pn9", Value: AArch64::PN9)
2806 .Case(S: "pn10", Value: AArch64::PN10)
2807 .Case(S: "pn11", Value: AArch64::PN11)
2808 .Case(S: "pn12", Value: AArch64::PN12)
2809 .Case(S: "pn13", Value: AArch64::PN13)
2810 .Case(S: "pn14", Value: AArch64::PN14)
2811 .Case(S: "pn15", Value: AArch64::PN15)
2812 .Default(Value: 0);
2813}
2814
2815static unsigned matchMatrixTileListRegName(StringRef Name) {
2816 return StringSwitch<unsigned>(Name.lower())
2817 .Case(S: "za0.d", Value: AArch64::ZAD0)
2818 .Case(S: "za1.d", Value: AArch64::ZAD1)
2819 .Case(S: "za2.d", Value: AArch64::ZAD2)
2820 .Case(S: "za3.d", Value: AArch64::ZAD3)
2821 .Case(S: "za4.d", Value: AArch64::ZAD4)
2822 .Case(S: "za5.d", Value: AArch64::ZAD5)
2823 .Case(S: "za6.d", Value: AArch64::ZAD6)
2824 .Case(S: "za7.d", Value: AArch64::ZAD7)
2825 .Case(S: "za0.s", Value: AArch64::ZAS0)
2826 .Case(S: "za1.s", Value: AArch64::ZAS1)
2827 .Case(S: "za2.s", Value: AArch64::ZAS2)
2828 .Case(S: "za3.s", Value: AArch64::ZAS3)
2829 .Case(S: "za0.h", Value: AArch64::ZAH0)
2830 .Case(S: "za1.h", Value: AArch64::ZAH1)
2831 .Case(S: "za0.b", Value: AArch64::ZAB0)
2832 .Default(Value: 0);
2833}
2834
2835static unsigned matchMatrixRegName(StringRef Name) {
2836 return StringSwitch<unsigned>(Name.lower())
2837 .Case(S: "za", Value: AArch64::ZA)
2838 .Case(S: "za0.q", Value: AArch64::ZAQ0)
2839 .Case(S: "za1.q", Value: AArch64::ZAQ1)
2840 .Case(S: "za2.q", Value: AArch64::ZAQ2)
2841 .Case(S: "za3.q", Value: AArch64::ZAQ3)
2842 .Case(S: "za4.q", Value: AArch64::ZAQ4)
2843 .Case(S: "za5.q", Value: AArch64::ZAQ5)
2844 .Case(S: "za6.q", Value: AArch64::ZAQ6)
2845 .Case(S: "za7.q", Value: AArch64::ZAQ7)
2846 .Case(S: "za8.q", Value: AArch64::ZAQ8)
2847 .Case(S: "za9.q", Value: AArch64::ZAQ9)
2848 .Case(S: "za10.q", Value: AArch64::ZAQ10)
2849 .Case(S: "za11.q", Value: AArch64::ZAQ11)
2850 .Case(S: "za12.q", Value: AArch64::ZAQ12)
2851 .Case(S: "za13.q", Value: AArch64::ZAQ13)
2852 .Case(S: "za14.q", Value: AArch64::ZAQ14)
2853 .Case(S: "za15.q", Value: AArch64::ZAQ15)
2854 .Case(S: "za0.d", Value: AArch64::ZAD0)
2855 .Case(S: "za1.d", Value: AArch64::ZAD1)
2856 .Case(S: "za2.d", Value: AArch64::ZAD2)
2857 .Case(S: "za3.d", Value: AArch64::ZAD3)
2858 .Case(S: "za4.d", Value: AArch64::ZAD4)
2859 .Case(S: "za5.d", Value: AArch64::ZAD5)
2860 .Case(S: "za6.d", Value: AArch64::ZAD6)
2861 .Case(S: "za7.d", Value: AArch64::ZAD7)
2862 .Case(S: "za0.s", Value: AArch64::ZAS0)
2863 .Case(S: "za1.s", Value: AArch64::ZAS1)
2864 .Case(S: "za2.s", Value: AArch64::ZAS2)
2865 .Case(S: "za3.s", Value: AArch64::ZAS3)
2866 .Case(S: "za0.h", Value: AArch64::ZAH0)
2867 .Case(S: "za1.h", Value: AArch64::ZAH1)
2868 .Case(S: "za0.b", Value: AArch64::ZAB0)
2869 .Case(S: "za0h.q", Value: AArch64::ZAQ0)
2870 .Case(S: "za1h.q", Value: AArch64::ZAQ1)
2871 .Case(S: "za2h.q", Value: AArch64::ZAQ2)
2872 .Case(S: "za3h.q", Value: AArch64::ZAQ3)
2873 .Case(S: "za4h.q", Value: AArch64::ZAQ4)
2874 .Case(S: "za5h.q", Value: AArch64::ZAQ5)
2875 .Case(S: "za6h.q", Value: AArch64::ZAQ6)
2876 .Case(S: "za7h.q", Value: AArch64::ZAQ7)
2877 .Case(S: "za8h.q", Value: AArch64::ZAQ8)
2878 .Case(S: "za9h.q", Value: AArch64::ZAQ9)
2879 .Case(S: "za10h.q", Value: AArch64::ZAQ10)
2880 .Case(S: "za11h.q", Value: AArch64::ZAQ11)
2881 .Case(S: "za12h.q", Value: AArch64::ZAQ12)
2882 .Case(S: "za13h.q", Value: AArch64::ZAQ13)
2883 .Case(S: "za14h.q", Value: AArch64::ZAQ14)
2884 .Case(S: "za15h.q", Value: AArch64::ZAQ15)
2885 .Case(S: "za0h.d", Value: AArch64::ZAD0)
2886 .Case(S: "za1h.d", Value: AArch64::ZAD1)
2887 .Case(S: "za2h.d", Value: AArch64::ZAD2)
2888 .Case(S: "za3h.d", Value: AArch64::ZAD3)
2889 .Case(S: "za4h.d", Value: AArch64::ZAD4)
2890 .Case(S: "za5h.d", Value: AArch64::ZAD5)
2891 .Case(S: "za6h.d", Value: AArch64::ZAD6)
2892 .Case(S: "za7h.d", Value: AArch64::ZAD7)
2893 .Case(S: "za0h.s", Value: AArch64::ZAS0)
2894 .Case(S: "za1h.s", Value: AArch64::ZAS1)
2895 .Case(S: "za2h.s", Value: AArch64::ZAS2)
2896 .Case(S: "za3h.s", Value: AArch64::ZAS3)
2897 .Case(S: "za0h.h", Value: AArch64::ZAH0)
2898 .Case(S: "za1h.h", Value: AArch64::ZAH1)
2899 .Case(S: "za0h.b", Value: AArch64::ZAB0)
2900 .Case(S: "za0v.q", Value: AArch64::ZAQ0)
2901 .Case(S: "za1v.q", Value: AArch64::ZAQ1)
2902 .Case(S: "za2v.q", Value: AArch64::ZAQ2)
2903 .Case(S: "za3v.q", Value: AArch64::ZAQ3)
2904 .Case(S: "za4v.q", Value: AArch64::ZAQ4)
2905 .Case(S: "za5v.q", Value: AArch64::ZAQ5)
2906 .Case(S: "za6v.q", Value: AArch64::ZAQ6)
2907 .Case(S: "za7v.q", Value: AArch64::ZAQ7)
2908 .Case(S: "za8v.q", Value: AArch64::ZAQ8)
2909 .Case(S: "za9v.q", Value: AArch64::ZAQ9)
2910 .Case(S: "za10v.q", Value: AArch64::ZAQ10)
2911 .Case(S: "za11v.q", Value: AArch64::ZAQ11)
2912 .Case(S: "za12v.q", Value: AArch64::ZAQ12)
2913 .Case(S: "za13v.q", Value: AArch64::ZAQ13)
2914 .Case(S: "za14v.q", Value: AArch64::ZAQ14)
2915 .Case(S: "za15v.q", Value: AArch64::ZAQ15)
2916 .Case(S: "za0v.d", Value: AArch64::ZAD0)
2917 .Case(S: "za1v.d", Value: AArch64::ZAD1)
2918 .Case(S: "za2v.d", Value: AArch64::ZAD2)
2919 .Case(S: "za3v.d", Value: AArch64::ZAD3)
2920 .Case(S: "za4v.d", Value: AArch64::ZAD4)
2921 .Case(S: "za5v.d", Value: AArch64::ZAD5)
2922 .Case(S: "za6v.d", Value: AArch64::ZAD6)
2923 .Case(S: "za7v.d", Value: AArch64::ZAD7)
2924 .Case(S: "za0v.s", Value: AArch64::ZAS0)
2925 .Case(S: "za1v.s", Value: AArch64::ZAS1)
2926 .Case(S: "za2v.s", Value: AArch64::ZAS2)
2927 .Case(S: "za3v.s", Value: AArch64::ZAS3)
2928 .Case(S: "za0v.h", Value: AArch64::ZAH0)
2929 .Case(S: "za1v.h", Value: AArch64::ZAH1)
2930 .Case(S: "za0v.b", Value: AArch64::ZAB0)
2931 .Default(Value: 0);
2932}
2933
2934bool AArch64AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
2935 SMLoc &EndLoc) {
2936 return !tryParseRegister(Reg, StartLoc, EndLoc).isSuccess();
2937}
2938
2939ParseStatus AArch64AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
2940 SMLoc &EndLoc) {
2941 StartLoc = getLoc();
2942 ParseStatus Res = tryParseScalarRegister(Reg);
2943 EndLoc = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
2944 return Res;
2945}
2946
2947// Matches a register name or register alias previously defined by '.req'
2948MCRegister AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
2949 RegKind Kind) {
2950 MCRegister Reg = MCRegister();
2951 if ((Reg = matchSVEDataVectorRegName(Name)))
2952 return Kind == RegKind::SVEDataVector ? Reg : MCRegister();
2953
2954 if ((Reg = matchSVEPredicateVectorRegName(Name)))
2955 return Kind == RegKind::SVEPredicateVector ? Reg : MCRegister();
2956
2957 if ((Reg = matchSVEPredicateAsCounterRegName(Name)))
2958 return Kind == RegKind::SVEPredicateAsCounter ? Reg : MCRegister();
2959
2960 if ((Reg = MatchNeonVectorRegName(Name)))
2961 return Kind == RegKind::NeonVector ? Reg : MCRegister();
2962
2963 if ((Reg = matchMatrixRegName(Name)))
2964 return Kind == RegKind::Matrix ? Reg : MCRegister();
2965
2966 if (Name.equals_insensitive(RHS: "zt0"))
2967 return Kind == RegKind::LookupTable ? unsigned(AArch64::ZT0) : 0;
2968
2969 // The parsed register must be of RegKind Scalar
2970 if ((Reg = MatchRegisterName(Name)))
2971 return (Kind == RegKind::Scalar) ? Reg : MCRegister();
2972
2973 if (!Reg) {
2974 // Handle a few common aliases of registers.
2975 if (MCRegister Reg = StringSwitch<unsigned>(Name.lower())
2976 .Case(S: "fp", Value: AArch64::FP)
2977 .Case(S: "lr", Value: AArch64::LR)
2978 .Case(S: "x31", Value: AArch64::XZR)
2979 .Case(S: "w31", Value: AArch64::WZR)
2980 .Default(Value: 0))
2981 return Kind == RegKind::Scalar ? Reg : MCRegister();
2982
2983 // Check for aliases registered via .req. Canonicalize to lower case.
2984 // That's more consistent since register names are case insensitive, and
2985 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2986 auto Entry = RegisterReqs.find(Key: Name.lower());
2987 if (Entry == RegisterReqs.end())
2988 return MCRegister();
2989
2990 // set Reg if the match is the right kind of register
2991 if (Kind == Entry->getValue().first)
2992 Reg = Entry->getValue().second;
2993 }
2994 return Reg;
2995}
2996
2997unsigned AArch64AsmParser::getNumRegsForRegKind(RegKind K) {
2998 switch (K) {
2999 case RegKind::Scalar:
3000 case RegKind::NeonVector:
3001 case RegKind::SVEDataVector:
3002 return 32;
3003 case RegKind::Matrix:
3004 case RegKind::SVEPredicateVector:
3005 case RegKind::SVEPredicateAsCounter:
3006 return 16;
3007 case RegKind::LookupTable:
3008 return 1;
3009 }
3010 llvm_unreachable("Unsupported RegKind");
3011}
3012
3013/// tryParseScalarRegister - Try to parse a register name. The token must be an
3014/// Identifier when called, and if it is a register name the token is eaten and
3015/// the register is added to the operand list.
3016ParseStatus AArch64AsmParser::tryParseScalarRegister(MCRegister &RegNum) {
3017 const AsmToken &Tok = getTok();
3018 if (Tok.isNot(K: AsmToken::Identifier))
3019 return ParseStatus::NoMatch;
3020
3021 std::string lowerCase = Tok.getString().lower();
3022 MCRegister Reg = matchRegisterNameAlias(Name: lowerCase, Kind: RegKind::Scalar);
3023 if (!Reg)
3024 return ParseStatus::NoMatch;
3025
3026 RegNum = Reg;
3027 Lex(); // Eat identifier token.
3028 return ParseStatus::Success;
3029}
3030
3031/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
3032ParseStatus AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
3033 SMLoc S = getLoc();
3034
3035 if (getTok().isNot(K: AsmToken::Identifier))
3036 return Error(L: S, Msg: "Expected cN operand where 0 <= N <= 15");
3037
3038 StringRef Tok = getTok().getIdentifier();
3039 if (Tok[0] != 'c' && Tok[0] != 'C')
3040 return Error(L: S, Msg: "Expected cN operand where 0 <= N <= 15");
3041
3042 uint32_t CRNum;
3043 bool BadNum = Tok.drop_front().getAsInteger(Radix: 10, Result&: CRNum);
3044 if (BadNum || CRNum > 15)
3045 return Error(L: S, Msg: "Expected cN operand where 0 <= N <= 15");
3046
3047 Lex(); // Eat identifier token.
3048 Operands.push_back(
3049 Elt: AArch64Operand::CreateSysCR(Val: CRNum, S, E: getLoc(), Ctx&: getContext()));
3050 return ParseStatus::Success;
3051}
3052
3053// Either an identifier for named values or a 6-bit immediate.
3054ParseStatus AArch64AsmParser::tryParseRPRFMOperand(OperandVector &Operands) {
3055 SMLoc S = getLoc();
3056 const AsmToken &Tok = getTok();
3057
3058 unsigned MaxVal = 63;
3059
3060 // Immediate case, with optional leading hash:
3061 if (parseOptionalToken(T: AsmToken::Hash) ||
3062 Tok.is(K: AsmToken::Integer)) {
3063 const MCExpr *ImmVal;
3064 if (getParser().parseExpression(Res&: ImmVal))
3065 return ParseStatus::Failure;
3066
3067 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
3068 if (!MCE)
3069 return TokError(Msg: "immediate value expected for prefetch operand");
3070 unsigned prfop = MCE->getValue();
3071 if (prfop > MaxVal)
3072 return TokError(Msg: "prefetch operand out of range, [0," + utostr(X: MaxVal) +
3073 "] expected");
3074
3075 auto RPRFM = AArch64RPRFM::lookupRPRFMByEncoding(Encoding: MCE->getValue());
3076 Operands.push_back(Elt: AArch64Operand::CreatePrefetch(
3077 Val: prfop, Str: RPRFM ? AArch64RPRFM::getRPRFMStr(RPRFM->Name) : "", S,
3078 Ctx&: getContext()));
3079 return ParseStatus::Success;
3080 }
3081
3082 if (Tok.isNot(K: AsmToken::Identifier))
3083 return TokError(Msg: "prefetch hint expected");
3084
3085 auto RPRFM = AArch64RPRFM::lookupRPRFMByName(Name: Tok.getString());
3086 if (!RPRFM)
3087 return TokError(Msg: "prefetch hint expected");
3088
3089 Operands.push_back(Elt: AArch64Operand::CreatePrefetch(
3090 Val: RPRFM->Encoding, Str: Tok.getString(), S, Ctx&: getContext()));
3091 Lex(); // Eat identifier token.
3092 return ParseStatus::Success;
3093}
3094
3095/// tryParsePrefetch - Try to parse a prefetch operand.
3096template <bool IsSVEPrefetch>
3097ParseStatus AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
3098 SMLoc S = getLoc();
3099 const AsmToken &Tok = getTok();
3100
3101 auto LookupByName = [](StringRef N) {
3102 if (IsSVEPrefetch) {
3103 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(Name: N))
3104 return std::optional<unsigned>(Res->Encoding);
3105 } else if (auto Res = AArch64PRFM::lookupPRFMByName(Name: N))
3106 return std::optional<unsigned>(Res->Encoding);
3107 return std::optional<unsigned>();
3108 };
3109
3110 auto LookupByEncoding = [](unsigned E) {
3111 if (IsSVEPrefetch) {
3112 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(Encoding: E))
3113 return std::optional<StringRef>(
3114 AArch64SVEPRFM::getSVEPRFMStr(Res->Name));
3115 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(Encoding: E))
3116 return std::optional<StringRef>(AArch64PRFM::getPRFMStr(Res->Name));
3117 return std::optional<StringRef>();
3118 };
3119 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
3120
3121 // Either an identifier for named values or a 5-bit immediate.
3122 // Eat optional hash.
3123 if (parseOptionalToken(T: AsmToken::Hash) ||
3124 Tok.is(K: AsmToken::Integer)) {
3125 const MCExpr *ImmVal;
3126 if (getParser().parseExpression(Res&: ImmVal))
3127 return ParseStatus::Failure;
3128
3129 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
3130 if (!MCE)
3131 return TokError(Msg: "immediate value expected for prefetch operand");
3132 unsigned prfop = MCE->getValue();
3133 if (prfop > MaxVal)
3134 return TokError(Msg: "prefetch operand out of range, [0," + utostr(X: MaxVal) +
3135 "] expected");
3136
3137 auto PRFM = LookupByEncoding(MCE->getValue());
3138 Operands.push_back(AArch64Operand::CreatePrefetch(Val: prfop, Str: PRFM.value_or(""),
3139 S, Ctx&: getContext()));
3140 return ParseStatus::Success;
3141 }
3142
3143 if (Tok.isNot(K: AsmToken::Identifier))
3144 return TokError(Msg: "prefetch hint expected");
3145
3146 auto PRFM = LookupByName(Tok.getString());
3147 if (!PRFM)
3148 return TokError(Msg: "prefetch hint expected");
3149
3150 Operands.push_back(AArch64Operand::CreatePrefetch(
3151 Val: *PRFM, Str: Tok.getString(), S, Ctx&: getContext()));
3152 Lex(); // Eat identifier token.
3153 return ParseStatus::Success;
3154}
3155
3156ParseStatus AArch64AsmParser::tryParseSyspXzrPair(OperandVector &Operands) {
3157 SMLoc StartLoc = getLoc();
3158
3159 MCRegister RegNum;
3160
3161 // The case where xzr, xzr is not present is handled by an InstAlias.
3162
3163 auto RegTok = getTok(); // in case we need to backtrack
3164 if (!tryParseScalarRegister(RegNum).isSuccess())
3165 return ParseStatus::NoMatch;
3166
3167 if (RegNum != AArch64::XZR) {
3168 getLexer().UnLex(Token: RegTok);
3169 return ParseStatus::NoMatch;
3170 }
3171
3172 if (parseComma())
3173 return ParseStatus::Failure;
3174
3175 if (!tryParseScalarRegister(RegNum).isSuccess())
3176 return TokError(Msg: "expected register operand");
3177
3178 if (RegNum != AArch64::XZR)
3179 return TokError(Msg: "xzr must be followed by xzr");
3180
3181 // We need to push something, since we claim this is an operand in .td.
3182 // See also AArch64AsmParser::parseKeywordOperand.
3183 Operands.push_back(Elt: AArch64Operand::CreateReg(
3184 Reg: RegNum, Kind: RegKind::Scalar, S: StartLoc, E: getLoc(), Ctx&: getContext()));
3185
3186 return ParseStatus::Success;
3187}
3188
3189/// tryParseTIndexHint - Try to parse a TIndex operand
3190ParseStatus AArch64AsmParser::tryParseTIndexHint(OperandVector &Operands) {
3191 SMLoc S = getLoc();
3192 const AsmToken &Tok = getTok();
3193 if (Tok.isNot(K: AsmToken::Identifier))
3194 return TokError(Msg: "invalid operand for instruction");
3195
3196 auto TIndex = AArch64TIndexHint::lookupTIndexByName(Name: Tok.getString());
3197 if (!TIndex)
3198 return TokError(Msg: "invalid operand for instruction");
3199
3200 Operands.push_back(Elt: AArch64Operand::CreateTIndexHint(
3201 Val: TIndex->Encoding, Str: Tok.getString(), S, Ctx&: getContext()));
3202 Lex(); // Eat identifier token.
3203 return ParseStatus::Success;
3204}
3205
3206/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
3207/// instruction.
3208ParseStatus AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
3209 SMLoc S = getLoc();
3210 const MCExpr *Expr = nullptr;
3211
3212 if (getTok().is(K: AsmToken::Hash)) {
3213 Lex(); // Eat hash token.
3214 }
3215
3216 if (parseSymbolicImmVal(ImmVal&: Expr))
3217 return ParseStatus::Failure;
3218
3219 AArch64::Specifier ELFSpec;
3220 AArch64::Specifier DarwinSpec;
3221 int64_t Addend;
3222 if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
3223 if (DarwinSpec == AArch64::S_None && ELFSpec == AArch64::S_INVALID) {
3224 // No modifier was specified at all; this is the syntax for an ELF basic
3225 // ADRP relocation (unfortunately).
3226 Expr =
3227 MCSpecifierExpr::create(Expr, S: AArch64::S_ABS_PAGE, Ctx&: getContext(), Loc: S);
3228 } else if ((DarwinSpec == AArch64::S_MACHO_GOTPAGE ||
3229 DarwinSpec == AArch64::S_MACHO_TLVPPAGE) &&
3230 Addend != 0) {
3231 return Error(L: S, Msg: "gotpage label reference not allowed an addend");
3232 } else if (DarwinSpec != AArch64::S_MACHO_PAGE &&
3233 DarwinSpec != AArch64::S_MACHO_GOTPAGE &&
3234 DarwinSpec != AArch64::S_MACHO_TLVPPAGE &&
3235 ELFSpec != AArch64::S_ABS_PAGE_NC &&
3236 ELFSpec != AArch64::S_GOT_PAGE &&
3237 ELFSpec != AArch64::S_GOT_AUTH_PAGE &&
3238 ELFSpec != AArch64::S_GOT_PAGE_LO15 &&
3239 ELFSpec != AArch64::S_GOTTPREL_PAGE &&
3240 ELFSpec != AArch64::S_TLSDESC_PAGE &&
3241 ELFSpec != AArch64::S_TLSDESC_AUTH_PAGE) {
3242 // The operand must be an @page or @gotpage qualified symbolref.
3243 return Error(L: S, Msg: "page or gotpage label reference expected");
3244 }
3245 }
3246
3247 // We have either a label reference possibly with addend or an immediate. The
3248 // addend is a raw value here. The linker will adjust it to only reference the
3249 // page.
3250 SMLoc E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
3251 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: Expr, S, E, Ctx&: getContext()));
3252
3253 return ParseStatus::Success;
3254}
3255
3256/// tryParseAdrLabel - Parse and validate a source label for the ADR
3257/// instruction.
3258ParseStatus AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
3259 SMLoc S = getLoc();
3260 const MCExpr *Expr = nullptr;
3261
3262 // Leave anything with a bracket to the default for SVE
3263 if (getTok().is(K: AsmToken::LBrac))
3264 return ParseStatus::NoMatch;
3265
3266 if (getTok().is(K: AsmToken::Hash))
3267 Lex(); // Eat hash token.
3268
3269 if (parseSymbolicImmVal(ImmVal&: Expr))
3270 return ParseStatus::Failure;
3271
3272 AArch64::Specifier ELFSpec;
3273 AArch64::Specifier DarwinSpec;
3274 int64_t Addend;
3275 if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
3276 if (DarwinSpec == AArch64::S_None && ELFSpec == AArch64::S_INVALID) {
3277 // No modifier was specified at all; this is the syntax for an ELF basic
3278 // ADR relocation (unfortunately).
3279 Expr = MCSpecifierExpr::create(Expr, S: AArch64::S_ABS, Ctx&: getContext(), Loc: S);
3280 } else if (ELFSpec != AArch64::S_GOT_AUTH_PAGE) {
3281 // For tiny code model, we use :got_auth: operator to fill 21-bit imm of
3282 // adr. It's not actually GOT entry page address but the GOT address
3283 // itself - we just share the same variant kind with :got_auth: operator
3284 // applied for adrp.
3285 // TODO: can we somehow get current TargetMachine object to call
3286 // getCodeModel() on it to ensure we are using tiny code model?
3287 return Error(L: S, Msg: "unexpected adr label");
3288 }
3289 }
3290
3291 SMLoc E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
3292 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: Expr, S, E, Ctx&: getContext()));
3293 return ParseStatus::Success;
3294}
3295
3296/// tryParseFPImm - A floating point immediate expression operand.
3297template <bool AddFPZeroAsLiteral>
3298ParseStatus AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
3299 SMLoc S = getLoc();
3300
3301 bool Hash = parseOptionalToken(T: AsmToken::Hash);
3302
3303 // Handle negation, as that still comes through as a separate token.
3304 bool isNegative = parseOptionalToken(T: AsmToken::Minus);
3305
3306 const AsmToken &Tok = getTok();
3307 if (!Tok.is(K: AsmToken::Real) && !Tok.is(K: AsmToken::Integer)) {
3308 if (!Hash)
3309 return ParseStatus::NoMatch;
3310 return TokError(Msg: "invalid floating point immediate");
3311 }
3312
3313 // Parse hexadecimal representation.
3314 if (Tok.is(K: AsmToken::Integer) && Tok.getString().starts_with(Prefix: "0x")) {
3315 if (Tok.getIntVal() > 255 || isNegative)
3316 return TokError(Msg: "encoded floating point value out of range");
3317
3318 APFloat F((double)AArch64_AM::getFPImmFloat(Imm: Tok.getIntVal()));
3319 Operands.push_back(
3320 Elt: AArch64Operand::CreateFPImm(Val: F, IsExact: true, S, Ctx&: getContext()));
3321 } else {
3322 // Parse FP representation.
3323 APFloat RealVal(APFloat::IEEEdouble());
3324 auto StatusOrErr =
3325 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
3326 if (errorToBool(Err: StatusOrErr.takeError()))
3327 return TokError(Msg: "invalid floating point representation");
3328
3329 if (isNegative)
3330 RealVal.changeSign();
3331
3332 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
3333 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: "#0", S, Ctx&: getContext()));
3334 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: ".0", S, Ctx&: getContext()));
3335 } else
3336 Operands.push_back(Elt: AArch64Operand::CreateFPImm(
3337 Val: RealVal, IsExact: *StatusOrErr == APFloat::opOK, S, Ctx&: getContext()));
3338 }
3339
3340 Lex(); // Eat the token.
3341
3342 return ParseStatus::Success;
3343}
3344
3345/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
3346/// a shift suffix, for example '#1, lsl #12'.
3347ParseStatus
3348AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
3349 SMLoc S = getLoc();
3350
3351 if (getTok().is(K: AsmToken::Hash))
3352 Lex(); // Eat '#'
3353 else if (getTok().isNot(K: AsmToken::Integer))
3354 // Operand should start from # or should be integer, emit error otherwise.
3355 return ParseStatus::NoMatch;
3356
3357 if (getTok().is(K: AsmToken::Integer) &&
3358 getLexer().peekTok().is(K: AsmToken::Colon))
3359 return tryParseImmRange(Operands);
3360
3361 const MCExpr *Imm = nullptr;
3362 if (parseSymbolicImmVal(ImmVal&: Imm))
3363 return ParseStatus::Failure;
3364 else if (getTok().isNot(K: AsmToken::Comma)) {
3365 Operands.push_back(
3366 Elt: AArch64Operand::CreateImm(Val: Imm, S, E: getLoc(), Ctx&: getContext()));
3367 return ParseStatus::Success;
3368 }
3369
3370 // Eat ','
3371 Lex();
3372 StringRef VecGroup;
3373 if (!parseOptionalVGOperand(Operands, VecGroup)) {
3374 Operands.push_back(
3375 Elt: AArch64Operand::CreateImm(Val: Imm, S, E: getLoc(), Ctx&: getContext()));
3376 Operands.push_back(
3377 Elt: AArch64Operand::CreateToken(Str: VecGroup, S: getLoc(), Ctx&: getContext()));
3378 return ParseStatus::Success;
3379 }
3380
3381 // The optional operand must be "lsl #N" where N is non-negative.
3382 if (!getTok().is(K: AsmToken::Identifier) ||
3383 !getTok().getIdentifier().equals_insensitive(RHS: "lsl"))
3384 return Error(L: getLoc(), Msg: "only 'lsl #+N' valid after immediate");
3385
3386 // Eat 'lsl'
3387 Lex();
3388
3389 parseOptionalToken(T: AsmToken::Hash);
3390
3391 if (getTok().isNot(K: AsmToken::Integer))
3392 return Error(L: getLoc(), Msg: "only 'lsl #+N' valid after immediate");
3393
3394 int64_t ShiftAmount = getTok().getIntVal();
3395
3396 if (ShiftAmount < 0)
3397 return Error(L: getLoc(), Msg: "positive shift amount required");
3398 Lex(); // Eat the number
3399
3400 // Just in case the optional lsl #0 is used for immediates other than zero.
3401 if (ShiftAmount == 0 && Imm != nullptr) {
3402 Operands.push_back(
3403 Elt: AArch64Operand::CreateImm(Val: Imm, S, E: getLoc(), Ctx&: getContext()));
3404 return ParseStatus::Success;
3405 }
3406
3407 Operands.push_back(Elt: AArch64Operand::CreateShiftedImm(Val: Imm, ShiftAmount, S,
3408 E: getLoc(), Ctx&: getContext()));
3409 return ParseStatus::Success;
3410}
3411
3412/// parseCondCodeString - Parse a Condition Code string, optionally returning a
3413/// suggestion to help common typos.
3414AArch64CC::CondCode
3415AArch64AsmParser::parseCondCodeString(StringRef Cond, std::string &Suggestion) {
3416 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
3417 .Case(S: "eq", Value: AArch64CC::EQ)
3418 .Case(S: "ne", Value: AArch64CC::NE)
3419 .Case(S: "cs", Value: AArch64CC::HS)
3420 .Case(S: "hs", Value: AArch64CC::HS)
3421 .Case(S: "cc", Value: AArch64CC::LO)
3422 .Case(S: "lo", Value: AArch64CC::LO)
3423 .Case(S: "mi", Value: AArch64CC::MI)
3424 .Case(S: "pl", Value: AArch64CC::PL)
3425 .Case(S: "vs", Value: AArch64CC::VS)
3426 .Case(S: "vc", Value: AArch64CC::VC)
3427 .Case(S: "hi", Value: AArch64CC::HI)
3428 .Case(S: "ls", Value: AArch64CC::LS)
3429 .Case(S: "ge", Value: AArch64CC::GE)
3430 .Case(S: "lt", Value: AArch64CC::LT)
3431 .Case(S: "gt", Value: AArch64CC::GT)
3432 .Case(S: "le", Value: AArch64CC::LE)
3433 .Case(S: "al", Value: AArch64CC::AL)
3434 .Case(S: "nv", Value: AArch64CC::NV)
3435 // SVE condition code aliases:
3436 .Case(S: "none", Value: AArch64CC::EQ)
3437 .Case(S: "any", Value: AArch64CC::NE)
3438 .Case(S: "nlast", Value: AArch64CC::HS)
3439 .Case(S: "last", Value: AArch64CC::LO)
3440 .Case(S: "first", Value: AArch64CC::MI)
3441 .Case(S: "nfrst", Value: AArch64CC::PL)
3442 .Case(S: "pmore", Value: AArch64CC::HI)
3443 .Case(S: "plast", Value: AArch64CC::LS)
3444 .Case(S: "tcont", Value: AArch64CC::GE)
3445 .Case(S: "tstop", Value: AArch64CC::LT)
3446 .Default(Value: AArch64CC::Invalid);
3447
3448 if (CC == AArch64CC::Invalid && Cond.lower() == "nfirst")
3449 Suggestion = "nfrst";
3450
3451 return CC;
3452}
3453
3454/// parseCondCode - Parse a Condition Code operand.
3455bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
3456 bool invertCondCode) {
3457 SMLoc S = getLoc();
3458 const AsmToken &Tok = getTok();
3459 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3460
3461 StringRef Cond = Tok.getString();
3462 std::string Suggestion;
3463 AArch64CC::CondCode CC = parseCondCodeString(Cond, Suggestion);
3464 if (CC == AArch64CC::Invalid) {
3465 std::string Msg = "invalid condition code";
3466 if (!Suggestion.empty())
3467 Msg += ", did you mean " + Suggestion + "?";
3468 return TokError(Msg);
3469 }
3470 Lex(); // Eat identifier token.
3471
3472 if (invertCondCode) {
3473 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
3474 return TokError(Msg: "condition codes AL and NV are invalid for this instruction");
3475 CC = AArch64CC::getInvertedCondCode(Code: AArch64CC::CondCode(CC));
3476 }
3477
3478 Operands.push_back(
3479 Elt: AArch64Operand::CreateCondCode(Code: CC, S, E: getLoc(), Ctx&: getContext()));
3480 return false;
3481}
3482
3483ParseStatus AArch64AsmParser::tryParseSVCR(OperandVector &Operands) {
3484 const AsmToken &Tok = getTok();
3485 SMLoc S = getLoc();
3486
3487 if (Tok.isNot(K: AsmToken::Identifier))
3488 return TokError(Msg: "invalid operand for instruction");
3489
3490 unsigned PStateImm = -1;
3491 const auto *SVCR = AArch64SVCR::lookupSVCRByName(Name: Tok.getString());
3492 if (!SVCR)
3493 return ParseStatus::NoMatch;
3494 if (SVCR->haveFeatures(ActiveFeatures: getSTI().getFeatureBits()))
3495 PStateImm = SVCR->Encoding;
3496
3497 Operands.push_back(
3498 Elt: AArch64Operand::CreateSVCR(PStateField: PStateImm, Str: Tok.getString(), S, Ctx&: getContext()));
3499 Lex(); // Eat identifier token.
3500 return ParseStatus::Success;
3501}
3502
3503ParseStatus AArch64AsmParser::tryParseMatrixRegister(OperandVector &Operands) {
3504 const AsmToken &Tok = getTok();
3505 SMLoc S = getLoc();
3506
3507 StringRef Name = Tok.getString();
3508
3509 if (Name.equals_insensitive(RHS: "za") || Name.starts_with_insensitive(Prefix: "za.")) {
3510 Lex(); // eat "za[.(b|h|s|d)]"
3511 unsigned ElementWidth = 0;
3512 auto DotPosition = Name.find(C: '.');
3513 if (DotPosition != StringRef::npos) {
3514 const auto &KindRes =
3515 parseVectorKind(Suffix: Name.drop_front(N: DotPosition), VectorKind: RegKind::Matrix);
3516 if (!KindRes)
3517 return TokError(
3518 Msg: "Expected the register to be followed by element width suffix");
3519 ElementWidth = KindRes->second;
3520 }
3521 Operands.push_back(Elt: AArch64Operand::CreateMatrixRegister(
3522 Reg: AArch64::ZA, ElementWidth, Kind: MatrixKind::Array, S, E: getLoc(),
3523 Ctx&: getContext()));
3524 if (getLexer().is(K: AsmToken::LBrac)) {
3525 // There's no comma after matrix operand, so we can parse the next operand
3526 // immediately.
3527 if (parseOperand(Operands, isCondCode: false, invertCondCode: false))
3528 return ParseStatus::NoMatch;
3529 }
3530 return ParseStatus::Success;
3531 }
3532
3533 // Try to parse matrix register.
3534 MCRegister Reg = matchRegisterNameAlias(Name, Kind: RegKind::Matrix);
3535 if (!Reg)
3536 return ParseStatus::NoMatch;
3537
3538 size_t DotPosition = Name.find(C: '.');
3539 assert(DotPosition != StringRef::npos && "Unexpected register");
3540
3541 StringRef Head = Name.take_front(N: DotPosition);
3542 StringRef Tail = Name.drop_front(N: DotPosition);
3543 StringRef RowOrColumn = Head.take_back();
3544
3545 MatrixKind Kind = StringSwitch<MatrixKind>(RowOrColumn.lower())
3546 .Case(S: "h", Value: MatrixKind::Row)
3547 .Case(S: "v", Value: MatrixKind::Col)
3548 .Default(Value: MatrixKind::Tile);
3549
3550 // Next up, parsing the suffix
3551 const auto &KindRes = parseVectorKind(Suffix: Tail, VectorKind: RegKind::Matrix);
3552 if (!KindRes)
3553 return TokError(
3554 Msg: "Expected the register to be followed by element width suffix");
3555 unsigned ElementWidth = KindRes->second;
3556
3557 Lex();
3558
3559 Operands.push_back(Elt: AArch64Operand::CreateMatrixRegister(
3560 Reg, ElementWidth, Kind, S, E: getLoc(), Ctx&: getContext()));
3561
3562 if (getLexer().is(K: AsmToken::LBrac)) {
3563 // There's no comma after matrix operand, so we can parse the next operand
3564 // immediately.
3565 if (parseOperand(Operands, isCondCode: false, invertCondCode: false))
3566 return ParseStatus::NoMatch;
3567 }
3568 return ParseStatus::Success;
3569}
3570
3571/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
3572/// them if present.
3573ParseStatus
3574AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
3575 const AsmToken &Tok = getTok();
3576 std::string LowerID = Tok.getString().lower();
3577 AArch64_AM::ShiftExtendType ShOp =
3578 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
3579 .Case(S: "lsl", Value: AArch64_AM::LSL)
3580 .Case(S: "lsr", Value: AArch64_AM::LSR)
3581 .Case(S: "asr", Value: AArch64_AM::ASR)
3582 .Case(S: "ror", Value: AArch64_AM::ROR)
3583 .Case(S: "msl", Value: AArch64_AM::MSL)
3584 .Case(S: "uxtb", Value: AArch64_AM::UXTB)
3585 .Case(S: "uxth", Value: AArch64_AM::UXTH)
3586 .Case(S: "uxtw", Value: AArch64_AM::UXTW)
3587 .Case(S: "uxtx", Value: AArch64_AM::UXTX)
3588 .Case(S: "sxtb", Value: AArch64_AM::SXTB)
3589 .Case(S: "sxth", Value: AArch64_AM::SXTH)
3590 .Case(S: "sxtw", Value: AArch64_AM::SXTW)
3591 .Case(S: "sxtx", Value: AArch64_AM::SXTX)
3592 .Default(Value: AArch64_AM::InvalidShiftExtend);
3593
3594 if (ShOp == AArch64_AM::InvalidShiftExtend)
3595 return ParseStatus::NoMatch;
3596
3597 SMLoc S = Tok.getLoc();
3598 Lex();
3599
3600 bool Hash = parseOptionalToken(T: AsmToken::Hash);
3601
3602 if (!Hash && getLexer().isNot(K: AsmToken::Integer)) {
3603 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
3604 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
3605 ShOp == AArch64_AM::MSL) {
3606 // We expect a number here.
3607 return TokError(Msg: "expected #imm after shift specifier");
3608 }
3609
3610 // "extend" type operations don't need an immediate, #0 is implicit.
3611 SMLoc E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
3612 Operands.push_back(
3613 Elt: AArch64Operand::CreateShiftExtend(ShOp, Val: 0, HasExplicitAmount: false, S, E, Ctx&: getContext()));
3614 return ParseStatus::Success;
3615 }
3616
3617 // Make sure we do actually have a number, identifier or a parenthesized
3618 // expression.
3619 SMLoc E = getLoc();
3620 if (!getTok().is(K: AsmToken::Integer) && !getTok().is(K: AsmToken::LParen) &&
3621 !getTok().is(K: AsmToken::Identifier))
3622 return Error(L: E, Msg: "expected integer shift amount");
3623
3624 const MCExpr *ImmVal;
3625 if (getParser().parseExpression(Res&: ImmVal))
3626 return ParseStatus::Failure;
3627
3628 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
3629 if (!MCE)
3630 return Error(L: E, Msg: "expected constant '#imm' after shift specifier");
3631
3632 E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
3633 Operands.push_back(Elt: AArch64Operand::CreateShiftExtend(
3634 ShOp, Val: MCE->getValue(), HasExplicitAmount: true, S, E, Ctx&: getContext()));
3635 return ParseStatus::Success;
3636}
3637
3638constexpr EnumStringDef<FeatureBitset> ExtensionDefs[] = {
3639 {.Names: {"crc"}, .Value: {AArch64::FeatureCRC}},
3640 {.Names: {"sm4"}, .Value: {AArch64::FeatureSM4}},
3641 {.Names: {"sha3"}, .Value: {AArch64::FeatureSHA3}},
3642 {.Names: {"sha2"}, .Value: {AArch64::FeatureSHA2}},
3643 {.Names: {"aes"}, .Value: {AArch64::FeatureAES}},
3644 {.Names: {"crypto"}, .Value: {AArch64::FeatureCrypto}},
3645 {.Names: {"fp"}, .Value: {AArch64::FeatureFPARMv8}},
3646 {.Names: {"simd"}, .Value: {AArch64::FeatureNEON}},
3647 {.Names: {"ras"}, .Value: {AArch64::FeatureRAS}},
3648 {.Names: {"rasv2"}, .Value: {AArch64::FeatureRASv2}},
3649 {.Names: {"lse"}, .Value: {AArch64::FeatureLSE}},
3650 {.Names: {"predres"}, .Value: {AArch64::FeaturePredRes}},
3651 {.Names: {"predres2"}, .Value: {AArch64::FeatureSPECRES2}},
3652 {.Names: {"ccdp"}, .Value: {AArch64::FeatureCacheDeepPersist}},
3653 {.Names: {"mte"}, .Value: {AArch64::FeatureMTE}},
3654 {.Names: {"memtag"}, .Value: {AArch64::FeatureMTE}},
3655 {.Names: {"tlb-rmi"}, .Value: {AArch64::FeatureTLB_RMI}},
3656 {.Names: {"pan"}, .Value: {AArch64::FeaturePAN}},
3657 {.Names: {"pan-rwv"}, .Value: {AArch64::FeaturePAN_RWV}},
3658 {.Names: {"ccpp"}, .Value: {AArch64::FeatureCCPP}},
3659 {.Names: {"rcpc"}, .Value: {AArch64::FeatureRCPC}},
3660 {.Names: {"rng"}, .Value: {AArch64::FeatureRandGen}},
3661 {.Names: {"sve"}, .Value: {AArch64::FeatureSVE}},
3662 {.Names: {"sve-b16b16"}, .Value: {AArch64::FeatureSVEB16B16}},
3663 {.Names: {"sve2"}, .Value: {AArch64::FeatureSVE2}},
3664 {.Names: {"sve-aes"}, .Value: {AArch64::FeatureSVEAES}},
3665 {.Names: {"sve2-aes"}, .Value: {AArch64::FeatureAliasSVE2AES, AArch64::FeatureSVEAES}},
3666 {.Names: {"sve-sm4"}, .Value: {AArch64::FeatureSVESM4}},
3667 {.Names: {"sve2-sm4"}, .Value: {AArch64::FeatureAliasSVE2SM4, AArch64::FeatureSVESM4}},
3668 {.Names: {"sve-sha3"}, .Value: {AArch64::FeatureSVESHA3}},
3669 {.Names: {"sve2-sha3"}, .Value: {AArch64::FeatureAliasSVE2SHA3, AArch64::FeatureSVESHA3}},
3670 {.Names: {"sve-bitperm"}, .Value: {AArch64::FeatureSVEBitPerm}},
3671 {.Names: {"sve2-bitperm"},
3672 .Value: {AArch64::FeatureAliasSVE2BitPerm, AArch64::FeatureSVEBitPerm,
3673 AArch64::FeatureSVE2}},
3674 {.Names: {"sve2p1"}, .Value: {AArch64::FeatureSVE2p1}},
3675 {.Names: {"ls64"}, .Value: {AArch64::FeatureLS64}},
3676 {.Names: {"xs"}, .Value: {AArch64::FeatureXS}},
3677 {.Names: {"pauth"}, .Value: {AArch64::FeaturePAuth}},
3678 {.Names: {"flagm"}, .Value: {AArch64::FeatureFlagM}},
3679 {.Names: {"rme"}, .Value: {AArch64::FeatureRME}},
3680 {.Names: {"sme"}, .Value: {AArch64::FeatureSME}},
3681 {.Names: {"sme-f64f64"}, .Value: {AArch64::FeatureSMEF64F64}},
3682 {.Names: {"sme-f16f16"}, .Value: {AArch64::FeatureSMEF16F16}},
3683 {.Names: {"sme-i16i64"}, .Value: {AArch64::FeatureSMEI16I64}},
3684 {.Names: {"sme2"}, .Value: {AArch64::FeatureSME2}},
3685 {.Names: {"sme2p1"}, .Value: {AArch64::FeatureSME2p1}},
3686 {.Names: {"sme-b16b16"}, .Value: {AArch64::FeatureSMEB16B16}},
3687 {.Names: {"hbc"}, .Value: {AArch64::FeatureHBC}},
3688 {.Names: {"mops"}, .Value: {AArch64::FeatureMOPS}},
3689 {.Names: {"mec"}, .Value: {AArch64::FeatureMEC}},
3690 {.Names: {"the"}, .Value: {AArch64::FeatureTHE}},
3691 {.Names: {"d128"}, .Value: {AArch64::FeatureD128}},
3692 {.Names: {"lse128"}, .Value: {AArch64::FeatureLSE128}},
3693 {.Names: {"ite"}, .Value: {AArch64::FeatureITE}},
3694 {.Names: {"cssc"}, .Value: {AArch64::FeatureCSSC}},
3695 {.Names: {"rcpc3"}, .Value: {AArch64::FeatureRCPC3}},
3696 {.Names: {"gcs"}, .Value: {AArch64::FeatureGCS}},
3697 {.Names: {"bf16"}, .Value: {AArch64::FeatureBF16}},
3698 {.Names: {"compnum"}, .Value: {AArch64::FeatureComplxNum}},
3699 {.Names: {"dotprod"}, .Value: {AArch64::FeatureDotProd}},
3700 {.Names: {"f32mm"}, .Value: {AArch64::FeatureMatMulFP32}},
3701 {.Names: {"f64mm"}, .Value: {AArch64::FeatureMatMulFP64}},
3702 {.Names: {"fp16"}, .Value: {AArch64::FeatureFullFP16}},
3703 {.Names: {"fp16fml"}, .Value: {AArch64::FeatureFP16FML}},
3704 {.Names: {"i8mm"}, .Value: {AArch64::FeatureMatMulInt8}},
3705 {.Names: {"lor"}, .Value: {AArch64::FeatureLOR}},
3706 {.Names: {"profile"}, .Value: {AArch64::FeatureSPE}},
3707 // "rdma" is the name documented by binutils for the feature, but
3708 // binutils also accepts incomplete prefixes of features, so "rdm"
3709 // works too. Support both spellings here.
3710 {.Names: {"rdm"}, .Value: {AArch64::FeatureRDM}},
3711 {.Names: {"rdma"}, .Value: {AArch64::FeatureRDM}},
3712 {.Names: {"sb"}, .Value: {AArch64::FeatureSB}},
3713 {.Names: {"ssbs"}, .Value: {AArch64::FeatureSSBS}},
3714 {.Names: {"fp8"}, .Value: {AArch64::FeatureFP8}},
3715 {.Names: {"faminmax"}, .Value: {AArch64::FeatureFAMINMAX}},
3716 {.Names: {"fp8fma"}, .Value: {AArch64::FeatureFP8FMA}},
3717 {.Names: {"ssve-fp8fma"}, .Value: {AArch64::FeatureSSVE_FP8FMA}},
3718 {.Names: {"fp8dot2"}, .Value: {AArch64::FeatureFP8DOT2}},
3719 {.Names: {"ssve-fp8dot2"}, .Value: {AArch64::FeatureSSVE_FP8DOT2}},
3720 {.Names: {"fp8dot4"}, .Value: {AArch64::FeatureFP8DOT4}},
3721 {.Names: {"ssve-fp8dot4"}, .Value: {AArch64::FeatureSSVE_FP8DOT4}},
3722 {.Names: {"lut"}, .Value: {AArch64::FeatureLUT}},
3723 {.Names: {"sme-lutv2"}, .Value: {AArch64::FeatureSME_LUTv2}},
3724 {.Names: {"sme-f8f16"}, .Value: {AArch64::FeatureSMEF8F16}},
3725 {.Names: {"sme-f8f32"}, .Value: {AArch64::FeatureSMEF8F32}},
3726 {.Names: {"sme-fa64"}, .Value: {AArch64::FeatureSMEFA64}},
3727 {.Names: {"cpa"}, .Value: {AArch64::FeatureCPA}},
3728 {.Names: {"tlbiw"}, .Value: {AArch64::FeatureTLBIW}},
3729 {.Names: {"pops"}, .Value: {AArch64::FeaturePoPS}},
3730 {.Names: {"cmpbr"}, .Value: {AArch64::FeatureCMPBR}},
3731 {.Names: {"f8f32mm"}, .Value: {AArch64::FeatureF8F32MM}},
3732 {.Names: {"f8f16mm"}, .Value: {AArch64::FeatureF8F16MM}},
3733 {.Names: {"fprcvt"}, .Value: {AArch64::FeatureFPRCVT}},
3734 {.Names: {"lsfe"}, .Value: {AArch64::FeatureLSFE}},
3735 {.Names: {"sme2p2"}, .Value: {AArch64::FeatureSME2p2}},
3736 {.Names: {"ssve-aes"}, .Value: {AArch64::FeatureSSVE_AES}},
3737 {.Names: {"sve2p2"}, .Value: {AArch64::FeatureSVE2p2}},
3738 {.Names: {"sve-aes2"}, .Value: {AArch64::FeatureSVEAES2}},
3739 {.Names: {"sve-bfscale"}, .Value: {AArch64::FeatureSVEBFSCALE}},
3740 {.Names: {"sve-f16f32mm"}, .Value: {AArch64::FeatureSVE_F16F32MM}},
3741 {.Names: {"lsui"}, .Value: {AArch64::FeatureLSUI}},
3742 {.Names: {"occmo"}, .Value: {AArch64::FeatureOCCMO}},
3743 {.Names: {"ssve-bitperm"}, .Value: {AArch64::FeatureSSVE_BitPerm}},
3744 {.Names: {"sme-mop4"}, .Value: {AArch64::FeatureSME_MOP4}},
3745 {.Names: {"sme-tmop"}, .Value: {AArch64::FeatureSME_TMOP}},
3746 {.Names: {"lscp"}, .Value: {AArch64::FeatureLSCP}},
3747 {.Names: {"tlbid"}, .Value: {AArch64::FeatureTLBID}},
3748 {.Names: {"mtetc"}, .Value: {AArch64::FeatureMTETC}},
3749 {.Names: {"gcie"}, .Value: {AArch64::FeatureGCIE}},
3750 {.Names: {"sme2p3"}, .Value: {AArch64::FeatureSME2p3}},
3751 {.Names: {"sve2p3"}, .Value: {AArch64::FeatureSVE2p3}},
3752 {.Names: {"sve-b16mm"}, .Value: {AArch64::FeatureSVE_B16MM}},
3753 {.Names: {"f16mm"}, .Value: {AArch64::FeatureF16MM}},
3754 {.Names: {"f16f32dot"}, .Value: {AArch64::FeatureF16F32DOT}},
3755 {.Names: {"f16f32mm"}, .Value: {AArch64::FeatureF16F32MM}},
3756 {.Names: {"mops-go"}, .Value: {AArch64::FeatureMOPS_GO}},
3757 {.Names: {"poe2"}, .Value: {AArch64::FeatureS1POE2}},
3758 {.Names: {"tev"}, .Value: {AArch64::FeatureTEV}},
3759 {.Names: {"btie"}, .Value: {AArch64::FeatureBTIE}},
3760 {.Names: {"hinte"}, .Value: {AArch64::FeatureHINTE}},
3761 {.Names: {"dit"}, .Value: {AArch64::FeatureDIT}},
3762 {.Names: {"brbe"}, .Value: {AArch64::FeatureBRBE}},
3763 {.Names: {"bti"}, .Value: {AArch64::FeatureBranchTargetId}},
3764 {.Names: {"fcma"}, .Value: {AArch64::FeatureComplxNum}},
3765 {.Names: {"jscvt"}, .Value: {AArch64::FeatureJS}},
3766 {.Names: {"pauth-lr"}, .Value: {AArch64::FeaturePAuthLR}},
3767 {.Names: {"ssve-fexpa"}, .Value: {AArch64::FeatureSSVE_FEXPA}},
3768 {.Names: {"wfxt"}, .Value: {AArch64::FeatureWFxT}},
3769 {.Names: {"cflt"}, .Value: {AArch64::FeatureCFLT}},
3770 {.Names: {"lsc64b"}, .Value: {AArch64::FeatureLSC64B}},
3771 {.Names: {"sve-lrcpc"}, .Value: {AArch64::FeatureSVE_LRCPC}},
3772};
3773constexpr auto ExtensionMap = BUILD_ENUM_STRINGS(ExtensionDefs);
3774
3775static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
3776 if (FBS[AArch64::HasV8_0aOps])
3777 Str += "ARMv8a";
3778 if (FBS[AArch64::HasV8_1aOps])
3779 Str += "ARMv8.1a";
3780 else if (FBS[AArch64::HasV8_2aOps])
3781 Str += "ARMv8.2a";
3782 else if (FBS[AArch64::HasV8_3aOps])
3783 Str += "ARMv8.3a";
3784 else if (FBS[AArch64::HasV8_4aOps])
3785 Str += "ARMv8.4a";
3786 else if (FBS[AArch64::HasV8_5aOps])
3787 Str += "ARMv8.5a";
3788 else if (FBS[AArch64::HasV8_6aOps])
3789 Str += "ARMv8.6a";
3790 else if (FBS[AArch64::HasV8_7aOps])
3791 Str += "ARMv8.7a";
3792 else if (FBS[AArch64::HasV8_8aOps])
3793 Str += "ARMv8.8a";
3794 else if (FBS[AArch64::HasV8_9aOps])
3795 Str += "ARMv8.9a";
3796 else if (FBS[AArch64::HasV9_0aOps])
3797 Str += "ARMv9-a";
3798 else if (FBS[AArch64::HasV9_1aOps])
3799 Str += "ARMv9.1a";
3800 else if (FBS[AArch64::HasV9_2aOps])
3801 Str += "ARMv9.2a";
3802 else if (FBS[AArch64::HasV9_3aOps])
3803 Str += "ARMv9.3a";
3804 else if (FBS[AArch64::HasV9_4aOps])
3805 Str += "ARMv9.4a";
3806 else if (FBS[AArch64::HasV9_5aOps])
3807 Str += "ARMv9.5a";
3808 else if (FBS[AArch64::HasV9_6aOps])
3809 Str += "ARMv9.6a";
3810 else if (FBS[AArch64::HasV9_7aOps])
3811 Str += "ARMv9.7a";
3812 else if (FBS[AArch64::HasV9_8aOps])
3813 Str += "ARMv9.8a";
3814 else if (FBS[AArch64::HasV8_0rOps])
3815 Str += "ARMv8r";
3816 else {
3817 SmallVector<StringRef, 2> ExtMatches;
3818 for (const auto& Ext : ExtensionMap) {
3819 // Use & in case multiple features are enabled
3820 if ((FBS & Ext.value()) != FeatureBitset())
3821 ExtMatches.push_back(Elt: Ext.name());
3822 }
3823 Str += !ExtMatches.empty() ? llvm::join(R&: ExtMatches, Separator: ", ") : "(unknown)";
3824 }
3825}
3826
3827void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
3828 SMLoc S) {
3829 const uint16_t Op2 = Encoding & 7;
3830 const uint16_t Cm = (Encoding & 0x78) >> 3;
3831 const uint16_t Cn = (Encoding & 0x780) >> 7;
3832 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
3833
3834 const MCExpr *Expr = MCConstantExpr::create(Value: Op1, Ctx&: getContext());
3835
3836 Operands.push_back(
3837 Elt: AArch64Operand::CreateImm(Val: Expr, S, E: getLoc(), Ctx&: getContext()));
3838 Operands.push_back(
3839 Elt: AArch64Operand::CreateSysCR(Val: Cn, S, E: getLoc(), Ctx&: getContext()));
3840 Operands.push_back(
3841 Elt: AArch64Operand::CreateSysCR(Val: Cm, S, E: getLoc(), Ctx&: getContext()));
3842 Expr = MCConstantExpr::create(Value: Op2, Ctx&: getContext());
3843 Operands.push_back(
3844 Elt: AArch64Operand::CreateImm(Val: Expr, S, E: getLoc(), Ctx&: getContext()));
3845}
3846
3847/// parseSysAlias - The IC, DC, AT, TLBI and GIC{R} and GSB instructions are
3848/// simple aliases for the SYS instruction. Parse them specially so that we
3849/// create a SYS MCInst.
3850bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
3851 OperandVector &Operands) {
3852 if (Name.contains(C: '.'))
3853 return TokError(Msg: "invalid operand");
3854
3855 Mnemonic = Name;
3856 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: "sys", S: NameLoc, Ctx&: getContext()));
3857
3858 const AsmToken &Tok = getTok();
3859 StringRef Op = Tok.getString();
3860 SMLoc S = Tok.getLoc();
3861 bool ExpectRegister = true;
3862 bool OptionalRegister = false;
3863 bool hasAll = getSTI().hasFeature(Feature: AArch64::FeatureAll);
3864 bool hasTLBID = getSTI().hasFeature(Feature: AArch64::FeatureTLBID);
3865
3866 if (Mnemonic == "ic") {
3867 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Name: Op);
3868 if (!IC)
3869 return TokError(Msg: "invalid operand for IC instruction");
3870 else if (!IC->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3871 std::string Str("IC " + std::string(AArch64IC::getICStr(IC->Name)) +
3872 " requires: ");
3873 setRequiredFeatureString(FBS: IC->getRequiredFeatures(), Str);
3874 return TokError(Msg: Str);
3875 }
3876 ExpectRegister = IC->NeedsReg;
3877 createSysAlias(Encoding: IC->Encoding, Operands, S);
3878 } else if (Mnemonic == "dc") {
3879 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Name: Op);
3880 if (!DC)
3881 return TokError(Msg: "invalid operand for DC instruction");
3882 else if (!DC->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3883 std::string Str("DC " + std::string(AArch64DC::getDCStr(DC->Name)) +
3884 " requires: ");
3885 setRequiredFeatureString(FBS: DC->getRequiredFeatures(), Str);
3886 return TokError(Msg: Str);
3887 }
3888 createSysAlias(Encoding: DC->Encoding, Operands, S);
3889 } else if (Mnemonic == "at") {
3890 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Name: Op);
3891 if (!AT)
3892 return TokError(Msg: "invalid operand for AT instruction");
3893 else if (!AT->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3894 std::string Str("AT " + std::string(AArch64AT::getATStr(AT->Name)) +
3895 " requires: ");
3896 setRequiredFeatureString(FBS: AT->getRequiredFeatures(), Str);
3897 return TokError(Msg: Str);
3898 }
3899 createSysAlias(Encoding: AT->Encoding, Operands, S);
3900 } else if (Mnemonic == "tlbi") {
3901 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Name: Op);
3902 if (!TLBI)
3903 return TokError(Msg: "invalid operand for TLBI instruction");
3904 else if (!TLBI->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3905 std::string Str("TLBI " +
3906 std::string(AArch64TLBI::getTLBIStr(TLBI->Name)) +
3907 " requires: ");
3908 setRequiredFeatureString(FBS: TLBI->getRequiredFeatures(), Str);
3909 return TokError(Msg: Str);
3910 }
3911 ExpectRegister = TLBI->RegUse == REG_REQUIRED;
3912 if (hasAll || hasTLBID)
3913 OptionalRegister = TLBI->RegUse == REG_OPTIONAL;
3914 createSysAlias(Encoding: TLBI->Encoding, Operands, S);
3915 } else if (Mnemonic == "gic") {
3916 const AArch64GIC::GIC *GIC = AArch64GIC::lookupGICByName(Name: Op);
3917 if (!GIC)
3918 return TokError(Msg: "invalid operand for GIC instruction");
3919 else if (!GIC->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3920 std::string Str("GIC " + std::string(AArch64GIC::getGICStr(GIC->Name)) +
3921 " requires: ");
3922 setRequiredFeatureString(FBS: GIC->getRequiredFeatures(), Str);
3923 return TokError(Msg: Str);
3924 }
3925 ExpectRegister = GIC->NeedsReg;
3926 createSysAlias(Encoding: GIC->Encoding, Operands, S);
3927 } else if (Mnemonic == "gsb") {
3928 const AArch64GSB::GSB *GSB = AArch64GSB::lookupGSBByName(Name: Op);
3929 if (!GSB)
3930 return TokError(Msg: "invalid operand for GSB instruction");
3931 else if (!GSB->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3932 std::string Str("GSB " + std::string(AArch64GSB::getGSBStr(GSB->Name)) +
3933 " requires: ");
3934 setRequiredFeatureString(FBS: GSB->getRequiredFeatures(), Str);
3935 return TokError(Msg: Str);
3936 }
3937 ExpectRegister = false;
3938 createSysAlias(Encoding: GSB->Encoding, Operands, S);
3939 } else if (Mnemonic == "plbi") {
3940 const AArch64PLBI::PLBI *PLBI = AArch64PLBI::lookupPLBIByName(Name: Op);
3941 if (!PLBI)
3942 return TokError(Msg: "invalid operand for PLBI instruction");
3943 else if (!PLBI->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
3944 std::string Str("PLBI " +
3945 std::string(AArch64PLBI::getPLBIStr(PLBI->Name)) +
3946 " requires: ");
3947 setRequiredFeatureString(FBS: PLBI->getRequiredFeatures(), Str);
3948 return TokError(Msg: Str);
3949 }
3950 ExpectRegister = PLBI->RegUse == REG_REQUIRED;
3951 if (hasAll || hasTLBID)
3952 OptionalRegister = PLBI->RegUse == REG_OPTIONAL;
3953 createSysAlias(Encoding: PLBI->Encoding, Operands, S);
3954 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp" ||
3955 Mnemonic == "cosp") {
3956
3957 if (Op.lower() != "rctx")
3958 return TokError(Msg: "invalid operand for prediction restriction instruction");
3959
3960 bool hasPredres = hasAll || getSTI().hasFeature(Feature: AArch64::FeaturePredRes);
3961 bool hasSpecres2 = hasAll || getSTI().hasFeature(Feature: AArch64::FeatureSPECRES2);
3962
3963 if (Mnemonic == "cosp" && !hasSpecres2)
3964 return TokError(Msg: "COSP requires: predres2");
3965 if (!hasPredres)
3966 return TokError(Msg: Mnemonic.upper() + "RCTX requires: predres");
3967
3968 uint16_t PRCTX_Op2 = Mnemonic == "cfp" ? 0b100
3969 : Mnemonic == "dvp" ? 0b101
3970 : Mnemonic == "cosp" ? 0b110
3971 : Mnemonic == "cpp" ? 0b111
3972 : 0;
3973 assert(PRCTX_Op2 &&
3974 "Invalid mnemonic for prediction restriction instruction");
3975 const auto SYS_3_7_3 = 0b01101110011; // op=3, CRn=7, CRm=3
3976 const auto Encoding = SYS_3_7_3 << 3 | PRCTX_Op2;
3977
3978 createSysAlias(Encoding, Operands, S);
3979 }
3980
3981 Lex(); // Eat operand.
3982
3983 bool HasRegister = false;
3984
3985 // Check for the optional register operand.
3986 if (parseOptionalToken(T: AsmToken::Comma)) {
3987 if (Tok.isNot(K: AsmToken::Identifier) || parseRegister(Operands))
3988 return TokError(Msg: "expected register operand");
3989 HasRegister = true;
3990 }
3991
3992 if (!OptionalRegister) {
3993 if (ExpectRegister && !HasRegister)
3994 return TokError(Msg: "specified " + Mnemonic + " op requires a register");
3995 else if (!ExpectRegister && HasRegister)
3996 return TokError(Msg: "specified " + Mnemonic + " op does not use a register");
3997 }
3998
3999 if (parseToken(T: AsmToken::EndOfStatement, Msg: "unexpected token in argument list"))
4000 return true;
4001
4002 return false;
4003}
4004
4005/// parseSyslAlias - The GICR instructions are simple aliases for
4006/// the SYSL instruction. Parse them specially so that we create a
4007/// SYS MCInst.
4008bool AArch64AsmParser::parseSyslAlias(StringRef Name, SMLoc NameLoc,
4009 OperandVector &Operands) {
4010
4011 Mnemonic = Name;
4012 Operands.push_back(
4013 Elt: AArch64Operand::CreateToken(Str: "sysl", S: NameLoc, Ctx&: getContext()));
4014
4015 // Now expect two operands (identifier + register)
4016 SMLoc startLoc = getLoc();
4017 const AsmToken &regTok = getTok();
4018 StringRef reg = regTok.getString();
4019 MCRegister Reg = matchRegisterNameAlias(Name: reg.lower(), Kind: RegKind::Scalar);
4020 if (!Reg)
4021 return TokError(Msg: "expected register operand");
4022
4023 Operands.push_back(Elt: AArch64Operand::CreateReg(
4024 Reg, Kind: RegKind::Scalar, S: startLoc, E: getLoc(), Ctx&: getContext(), EqTy: EqualsReg));
4025
4026 Lex(); // Eat token
4027 if (parseToken(T: AsmToken::Comma))
4028 return true;
4029
4030 // Check for identifier
4031 const AsmToken &operandTok = getTok();
4032 StringRef Op = operandTok.getString();
4033 SMLoc S2 = operandTok.getLoc();
4034 Lex(); // Eat token
4035
4036 if (Mnemonic == "gicr") {
4037 const AArch64GICR::GICR *GICR = AArch64GICR::lookupGICRByName(Name: Op);
4038 if (!GICR)
4039 return Error(L: S2, Msg: "invalid operand for GICR instruction");
4040 else if (!GICR->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
4041 std::string Str("GICR " +
4042 std::string(AArch64GICR::getGICRStr(GICR->Name)) +
4043 " requires: ");
4044 setRequiredFeatureString(FBS: GICR->getRequiredFeatures(), Str);
4045 return Error(L: S2, Msg: Str);
4046 }
4047 createSysAlias(Encoding: GICR->Encoding, Operands, S: S2);
4048 }
4049
4050 if (parseToken(T: AsmToken::EndOfStatement, Msg: "unexpected token in argument list"))
4051 return true;
4052
4053 return false;
4054}
4055
4056/// parseSyspAlias - The TLBIP instructions are simple aliases for
4057/// the SYSP instruction. Parse them specially so that we create a SYSP MCInst.
4058bool AArch64AsmParser::parseSyspAlias(StringRef Name, SMLoc NameLoc,
4059 OperandVector &Operands) {
4060 if (Name.contains(C: '.'))
4061 return TokError(Msg: "invalid operand");
4062
4063 Mnemonic = Name;
4064 Operands.push_back(
4065 Elt: AArch64Operand::CreateToken(Str: "sysp", S: NameLoc, Ctx&: getContext()));
4066
4067 const AsmToken &Tok = getTok();
4068 StringRef Op = Tok.getString();
4069 SMLoc S = Tok.getLoc();
4070
4071 if (Mnemonic == "tlbip") {
4072 const AArch64TLBIP::TLBIP *TLBIP = AArch64TLBIP::lookupTLBIPByName(Name: Op);
4073 if (!TLBIP)
4074 return TokError(Msg: "invalid operand for TLBIP instruction");
4075
4076 if (!TLBIP->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
4077 std::string Str("instruction requires: ");
4078 Str += TLBIP->AllowWithTLBID ? "tlbid or d128" : "d128";
4079 return TokError(Msg: Str);
4080 }
4081 createSysAlias(Encoding: TLBIP->Encoding, Operands, S);
4082 }
4083
4084 Lex(); // Eat operand.
4085
4086 if (parseComma())
4087 return true;
4088
4089 if (Tok.isNot(K: AsmToken::Identifier))
4090 return TokError(Msg: "expected register identifier");
4091 auto Result = tryParseSyspXzrPair(Operands);
4092 if (Result.isNoMatch())
4093 Result = tryParseGPRSeqPair(Operands);
4094 if (!Result.isSuccess())
4095 return TokError(Msg: "specified " + Mnemonic +
4096 " op requires a pair of registers");
4097
4098 if (parseToken(T: AsmToken::EndOfStatement, Msg: "unexpected token in argument list"))
4099 return true;
4100
4101 return false;
4102}
4103
4104ParseStatus AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
4105 MCAsmParser &Parser = getParser();
4106 const AsmToken &Tok = getTok();
4107
4108 if (parseOptionalToken(T: AsmToken::Hash) || Tok.is(K: AsmToken::Integer)) {
4109 // Immediate operand.
4110 const MCExpr *ImmVal;
4111 SMLoc ExprLoc = getLoc();
4112 AsmToken IntTok = Tok;
4113 if (getParser().parseExpression(Res&: ImmVal))
4114 return ParseStatus::Failure;
4115 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
4116 if (!MCE)
4117 return Error(L: ExprLoc, Msg: "immediate value expected for barrier operand");
4118 int64_t Value = MCE->getValue();
4119 if (Mnemonic == "dsb" && Value > 15) {
4120 // This case is a no match here, but it might be matched by the nXS
4121 // variant. Deliberately not unlex the optional '#' as it is not necessary
4122 // to characterize an integer immediate.
4123 Parser.getLexer().UnLex(Token: IntTok);
4124 return ParseStatus::NoMatch;
4125 }
4126 if (Value < 0 || Value > 15)
4127 return Error(L: ExprLoc, Msg: "barrier operand out of range");
4128 auto DB = AArch64DB::lookupDBByEncoding(Encoding: Value);
4129 StringRef DBStr = DB ? AArch64DB::getDBStr(DB->Name) : "";
4130 Operands.push_back(Elt: AArch64Operand::CreateBarrier(
4131 Val: Value, Str: DBStr, S: ExprLoc, Ctx&: getContext(), HasnXSModifier: false /*hasnXSModifier*/));
4132 return ParseStatus::Success;
4133 }
4134
4135 if (Tok.isNot(K: AsmToken::Identifier))
4136 return TokError(Msg: "invalid operand for instruction");
4137
4138 StringRef Operand = Tok.getString();
4139 auto DB = AArch64DB::lookupDBByName(Name: Operand);
4140 // The only valid named option for ISB is 'sy'
4141 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy))
4142 return TokError(Msg: "'sy' or #imm operand expected");
4143 if (!DB) {
4144 if (Mnemonic == "dsb") {
4145 // This case is a no match here, but it might be matched by the nXS
4146 // variant.
4147 return ParseStatus::NoMatch;
4148 }
4149 return TokError(Msg: "invalid barrier option name");
4150 }
4151
4152 Operands.push_back(
4153 Elt: AArch64Operand::CreateBarrier(Val: DB->Encoding, Str: Tok.getString(), S: getLoc(),
4154 Ctx&: getContext(), HasnXSModifier: false /*hasnXSModifier*/));
4155 Lex(); // Consume the option
4156
4157 return ParseStatus::Success;
4158}
4159
4160ParseStatus
4161AArch64AsmParser::tryParseBarriernXSOperand(OperandVector &Operands) {
4162 const AsmToken &Tok = getTok();
4163
4164 assert(Mnemonic == "dsb" && "Instruction does not accept nXS operands");
4165 if (Mnemonic != "dsb")
4166 return ParseStatus::Failure;
4167
4168 if (parseOptionalToken(T: AsmToken::Hash) || Tok.is(K: AsmToken::Integer)) {
4169 // Immediate operand.
4170 const MCExpr *ImmVal;
4171 SMLoc ExprLoc = getLoc();
4172 if (getParser().parseExpression(Res&: ImmVal))
4173 return ParseStatus::Failure;
4174 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
4175 if (!MCE)
4176 return Error(L: ExprLoc, Msg: "immediate value expected for barrier operand");
4177 int64_t Value = MCE->getValue();
4178 // v8.7-A DSB in the nXS variant accepts only the following immediate
4179 // values: 16, 20, 24, 28.
4180 if (Value != 16 && Value != 20 && Value != 24 && Value != 28)
4181 return Error(L: ExprLoc, Msg: "barrier operand out of range");
4182 auto DB = AArch64DBnXS::lookupDBnXSByImmValue(ImmValue: Value);
4183 StringRef DBName = AArch64DBnXS::getDBnXSStr(DB->Name);
4184 Operands.push_back(Elt: AArch64Operand::CreateBarrier(
4185 Val: DB->Encoding, Str: DBName, S: ExprLoc, Ctx&: getContext(), HasnXSModifier: true /*hasnXSModifier*/));
4186 return ParseStatus::Success;
4187 }
4188
4189 if (Tok.isNot(K: AsmToken::Identifier))
4190 return TokError(Msg: "invalid operand for instruction");
4191
4192 StringRef Operand = Tok.getString();
4193 auto DB = AArch64DBnXS::lookupDBnXSByName(Name: Operand);
4194
4195 if (!DB)
4196 return TokError(Msg: "invalid barrier option name");
4197
4198 Operands.push_back(
4199 Elt: AArch64Operand::CreateBarrier(Val: DB->Encoding, Str: Tok.getString(), S: getLoc(),
4200 Ctx&: getContext(), HasnXSModifier: true /*hasnXSModifier*/));
4201 Lex(); // Consume the option
4202
4203 return ParseStatus::Success;
4204}
4205
4206ParseStatus AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
4207 const AsmToken &Tok = getTok();
4208
4209 if (Tok.isNot(K: AsmToken::Identifier))
4210 return ParseStatus::NoMatch;
4211
4212 if (AArch64SVCR::lookupSVCRByName(Name: Tok.getString()))
4213 return ParseStatus::NoMatch;
4214
4215 int MRSReg, MSRReg;
4216 auto SysReg = AArch64SysReg::lookupSysRegByName(Name: Tok.getString());
4217 if (SysReg && SysReg->haveFeatures(ActiveFeatures: getSTI().getFeatureBits())) {
4218 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
4219 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
4220 } else
4221 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Name: Tok.getString());
4222
4223 unsigned PStateImm = -1;
4224 auto PState15 = AArch64PState::lookupPStateImm0_15ByName(Name: Tok.getString());
4225 if (PState15 && PState15->haveFeatures(ActiveFeatures: getSTI().getFeatureBits()))
4226 PStateImm = PState15->Encoding;
4227 if (!PState15) {
4228 auto PState1 = AArch64PState::lookupPStateImm0_1ByName(Name: Tok.getString());
4229 if (PState1 && PState1->haveFeatures(ActiveFeatures: getSTI().getFeatureBits()))
4230 PStateImm = PState1->Encoding;
4231 }
4232
4233 Operands.push_back(
4234 Elt: AArch64Operand::CreateSysReg(Str: Tok.getString(), S: getLoc(), MRSReg, MSRReg,
4235 PStateField: PStateImm, Ctx&: getContext()));
4236 Lex(); // Eat identifier
4237
4238 return ParseStatus::Success;
4239}
4240
4241/// tryParseNeonVectorRegister - Parse a vector register operand.
4242bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
4243 if (getTok().isNot(K: AsmToken::Identifier))
4244 return true;
4245
4246 SMLoc S = getLoc();
4247 // Check for a vector register specifier first.
4248 StringRef Kind;
4249 MCRegister Reg;
4250 ParseStatus Res = tryParseVectorRegister(Reg, Kind, MatchKind: RegKind::NeonVector);
4251 if (!Res.isSuccess())
4252 return true;
4253
4254 const auto &KindRes = parseVectorKind(Suffix: Kind, VectorKind: RegKind::NeonVector);
4255 if (!KindRes)
4256 return true;
4257
4258 unsigned ElementWidth = KindRes->second;
4259 Operands.push_back(
4260 Elt: AArch64Operand::CreateVectorReg(Reg, Kind: RegKind::NeonVector, ElementWidth,
4261 S, E: getLoc(), Ctx&: getContext()));
4262
4263 // If there was an explicit qualifier, that goes on as a literal text
4264 // operand.
4265 if (!Kind.empty())
4266 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: Kind, S, Ctx&: getContext()));
4267
4268 return tryParseVectorIndex(Operands).isFailure();
4269}
4270
4271ParseStatus AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
4272 SMLoc SIdx = getLoc();
4273 if (parseOptionalToken(T: AsmToken::LBrac)) {
4274 const MCExpr *ImmVal;
4275 if (getParser().parseExpression(Res&: ImmVal))
4276 return ParseStatus::NoMatch;
4277 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
4278 if (!MCE)
4279 return TokError(Msg: "immediate value expected for vector index");
4280
4281 SMLoc E = getLoc();
4282
4283 if (parseToken(T: AsmToken::RBrac, Msg: "']' expected"))
4284 return ParseStatus::Failure;
4285
4286 Operands.push_back(Elt: AArch64Operand::CreateVectorIndex(Idx: MCE->getValue(), S: SIdx,
4287 E, Ctx&: getContext()));
4288 return ParseStatus::Success;
4289 }
4290
4291 return ParseStatus::NoMatch;
4292}
4293
4294// tryParseVectorRegister - Try to parse a vector register name with
4295// optional kind specifier. If it is a register specifier, eat the token
4296// and return it.
4297ParseStatus AArch64AsmParser::tryParseVectorRegister(MCRegister &Reg,
4298 StringRef &Kind,
4299 RegKind MatchKind) {
4300 const AsmToken &Tok = getTok();
4301
4302 if (Tok.isNot(K: AsmToken::Identifier))
4303 return ParseStatus::NoMatch;
4304
4305 StringRef Name = Tok.getString();
4306 // If there is a kind specifier, it's separated from the register name by
4307 // a '.'.
4308 size_t Start = 0, Next = Name.find(C: '.');
4309 StringRef Head = Name.slice(Start, End: Next);
4310 MCRegister RegNum = matchRegisterNameAlias(Name: Head, Kind: MatchKind);
4311
4312 if (RegNum) {
4313 if (Next != StringRef::npos) {
4314 Kind = Name.substr(Start: Next);
4315 if (!isValidVectorKind(Suffix: Kind, VectorKind: MatchKind))
4316 return TokError(Msg: "invalid vector kind qualifier");
4317 }
4318 Lex(); // Eat the register token.
4319
4320 Reg = RegNum;
4321 return ParseStatus::Success;
4322 }
4323
4324 return ParseStatus::NoMatch;
4325}
4326
4327ParseStatus AArch64AsmParser::tryParseSVEPredicateOrPredicateAsCounterVector(
4328 OperandVector &Operands) {
4329 ParseStatus Status =
4330 tryParseSVEPredicateVector<RegKind::SVEPredicateAsCounter>(Operands);
4331 if (!Status.isSuccess())
4332 Status = tryParseSVEPredicateVector<RegKind::SVEPredicateVector>(Operands);
4333 return Status;
4334}
4335
4336/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
4337template <RegKind RK>
4338ParseStatus
4339AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
4340 // Check for a SVE predicate register specifier first.
4341 const SMLoc S = getLoc();
4342 StringRef Kind;
4343 MCRegister RegNum;
4344 auto Res = tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RK);
4345 if (!Res.isSuccess())
4346 return Res;
4347
4348 const auto &KindRes = parseVectorKind(Suffix: Kind, VectorKind: RK);
4349 if (!KindRes)
4350 return ParseStatus::NoMatch;
4351
4352 unsigned ElementWidth = KindRes->second;
4353 Operands.push_back(Elt: AArch64Operand::CreateVectorReg(
4354 Reg: RegNum, Kind: RK, ElementWidth, S,
4355 E: getLoc(), Ctx&: getContext()));
4356
4357 if (getLexer().is(K: AsmToken::LBrac)) {
4358 if (RK == RegKind::SVEPredicateAsCounter) {
4359 ParseStatus ResIndex = tryParseVectorIndex(Operands);
4360 if (ResIndex.isSuccess())
4361 return ParseStatus::Success;
4362 } else {
4363 // Indexed predicate, there's no comma so try parse the next operand
4364 // immediately.
4365 if (parseOperand(Operands, isCondCode: false, invertCondCode: false))
4366 return ParseStatus::NoMatch;
4367 }
4368 }
4369
4370 // Not all predicates are followed by a '/m' or '/z'.
4371 if (getTok().isNot(K: AsmToken::Slash))
4372 return ParseStatus::Success;
4373
4374 // But when they do they shouldn't have an element type suffix.
4375 if (!Kind.empty())
4376 return Error(L: S, Msg: "not expecting size suffix");
4377
4378 // Add a literal slash as operand
4379 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: "/", S: getLoc(), Ctx&: getContext()));
4380
4381 Lex(); // Eat the slash.
4382
4383 // Zeroing or merging?
4384 auto Pred = getTok().getString().lower();
4385 if (RK == RegKind::SVEPredicateAsCounter && Pred != "z")
4386 return Error(L: getLoc(), Msg: "expecting 'z' predication");
4387
4388 if (RK == RegKind::SVEPredicateVector && Pred != "z" && Pred != "m")
4389 return Error(L: getLoc(), Msg: "expecting 'm' or 'z' predication");
4390
4391 // Add zero/merge token.
4392 const char *ZM = Pred == "z" ? "z" : "m";
4393 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: ZM, S: getLoc(), Ctx&: getContext()));
4394
4395 Lex(); // Eat zero/merge token.
4396 return ParseStatus::Success;
4397}
4398
4399/// parseRegister - Parse a register operand.
4400bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
4401 // Try for a Neon vector register.
4402 if (!tryParseNeonVectorRegister(Operands))
4403 return false;
4404
4405 if (tryParseZTOperand(Operands).isSuccess())
4406 return false;
4407
4408 // Otherwise try for a scalar register.
4409 if (tryParseGPROperand<false>(Operands).isSuccess())
4410 return false;
4411
4412 return true;
4413}
4414
4415bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
4416 bool HasELFModifier = false;
4417 AArch64::Specifier RefKind;
4418 SMLoc Loc = getLexer().getLoc();
4419 if (parseOptionalToken(T: AsmToken::Colon)) {
4420 HasELFModifier = true;
4421
4422 if (getTok().isNot(K: AsmToken::Identifier))
4423 return TokError(Msg: "expect relocation specifier in operand after ':'");
4424
4425 std::string LowerCase = getTok().getIdentifier().lower();
4426 RefKind = StringSwitch<AArch64::Specifier>(LowerCase)
4427 .Case(S: "lo12", Value: AArch64::S_LO12)
4428 .Case(S: "abs_g3", Value: AArch64::S_ABS_G3)
4429 .Case(S: "abs_g2", Value: AArch64::S_ABS_G2)
4430 .Case(S: "abs_g2_s", Value: AArch64::S_ABS_G2_S)
4431 .Case(S: "abs_g2_nc", Value: AArch64::S_ABS_G2_NC)
4432 .Case(S: "abs_g1", Value: AArch64::S_ABS_G1)
4433 .Case(S: "abs_g1_s", Value: AArch64::S_ABS_G1_S)
4434 .Case(S: "abs_g1_nc", Value: AArch64::S_ABS_G1_NC)
4435 .Case(S: "abs_g0", Value: AArch64::S_ABS_G0)
4436 .Case(S: "abs_g0_s", Value: AArch64::S_ABS_G0_S)
4437 .Case(S: "abs_g0_nc", Value: AArch64::S_ABS_G0_NC)
4438 .Case(S: "prel_g3", Value: AArch64::S_PREL_G3)
4439 .Case(S: "prel_g2", Value: AArch64::S_PREL_G2)
4440 .Case(S: "prel_g2_nc", Value: AArch64::S_PREL_G2_NC)
4441 .Case(S: "prel_g1", Value: AArch64::S_PREL_G1)
4442 .Case(S: "prel_g1_nc", Value: AArch64::S_PREL_G1_NC)
4443 .Case(S: "prel_g0", Value: AArch64::S_PREL_G0)
4444 .Case(S: "prel_g0_nc", Value: AArch64::S_PREL_G0_NC)
4445 .Case(S: "dtprel", Value: AArch64::S_DTPREL)
4446 .Case(S: "dtprel_g2", Value: AArch64::S_DTPREL_G2)
4447 .Case(S: "dtprel_g1", Value: AArch64::S_DTPREL_G1)
4448 .Case(S: "dtprel_g1_nc", Value: AArch64::S_DTPREL_G1_NC)
4449 .Case(S: "dtprel_g0", Value: AArch64::S_DTPREL_G0)
4450 .Case(S: "dtprel_g0_nc", Value: AArch64::S_DTPREL_G0_NC)
4451 .Case(S: "dtprel_hi12", Value: AArch64::S_DTPREL_HI12)
4452 .Case(S: "dtprel_lo12", Value: AArch64::S_DTPREL_LO12)
4453 .Case(S: "dtprel_lo12_nc", Value: AArch64::S_DTPREL_LO12_NC)
4454 .Case(S: "pg_hi21_nc", Value: AArch64::S_ABS_PAGE_NC)
4455 .Case(S: "tprel_g2", Value: AArch64::S_TPREL_G2)
4456 .Case(S: "tprel_g1", Value: AArch64::S_TPREL_G1)
4457 .Case(S: "tprel_g1_nc", Value: AArch64::S_TPREL_G1_NC)
4458 .Case(S: "tprel_g0", Value: AArch64::S_TPREL_G0)
4459 .Case(S: "tprel_g0_nc", Value: AArch64::S_TPREL_G0_NC)
4460 .Case(S: "tprel_hi12", Value: AArch64::S_TPREL_HI12)
4461 .Case(S: "tprel_lo12", Value: AArch64::S_TPREL_LO12)
4462 .Case(S: "tprel_lo12_nc", Value: AArch64::S_TPREL_LO12_NC)
4463 .Case(S: "tlsdesc_lo12", Value: AArch64::S_TLSDESC_LO12)
4464 .Case(S: "tlsdesc_auth_lo12", Value: AArch64::S_TLSDESC_AUTH_LO12)
4465 .Case(S: "got", Value: AArch64::S_GOT_PAGE)
4466 .Case(S: "gotpage_lo15", Value: AArch64::S_GOT_PAGE_LO15)
4467 .Case(S: "got_lo12", Value: AArch64::S_GOT_LO12)
4468 .Case(S: "got_auth", Value: AArch64::S_GOT_AUTH_PAGE)
4469 .Case(S: "got_auth_lo12", Value: AArch64::S_GOT_AUTH_LO12)
4470 .Case(S: "gottprel", Value: AArch64::S_GOTTPREL_PAGE)
4471 .Case(S: "gottprel_lo12", Value: AArch64::S_GOTTPREL_LO12_NC)
4472 .Case(S: "gottprel_g1", Value: AArch64::S_GOTTPREL_G1)
4473 .Case(S: "gottprel_g0_nc", Value: AArch64::S_GOTTPREL_G0_NC)
4474 .Case(S: "tlsdesc", Value: AArch64::S_TLSDESC_PAGE)
4475 .Case(S: "tlsdesc_auth", Value: AArch64::S_TLSDESC_AUTH_PAGE)
4476 .Case(S: "secrel_lo12", Value: AArch64::S_SECREL_LO12)
4477 .Case(S: "secrel_hi12", Value: AArch64::S_SECREL_HI12)
4478 .Default(Value: AArch64::S_INVALID);
4479
4480 if (RefKind == AArch64::S_INVALID)
4481 return TokError(Msg: "expect relocation specifier in operand after ':'");
4482
4483 Lex(); // Eat identifier
4484
4485 if (parseToken(T: AsmToken::Colon, Msg: "expect ':' after relocation specifier"))
4486 return true;
4487 }
4488
4489 if (getParser().parseExpression(Res&: ImmVal))
4490 return true;
4491
4492 if (HasELFModifier)
4493 ImmVal = MCSpecifierExpr::create(Expr: ImmVal, S: RefKind, Ctx&: getContext(), Loc);
4494
4495 SMLoc EndLoc;
4496 // :specifier: and @specifier are alternative syntaxes; nesting them is invalid.
4497 if (!HasELFModifier && getContext().getAsmInfo().hasSubsectionsViaSymbols()) {
4498 if (getParser().parseAtSpecifier(Res&: ImmVal, EndLoc))
4499 return true;
4500 const MCExpr *Term;
4501 MCBinaryExpr::Opcode Opcode;
4502 if (parseOptionalToken(T: AsmToken::Plus))
4503 Opcode = MCBinaryExpr::Add;
4504 else if (parseOptionalToken(T: AsmToken::Minus))
4505 Opcode = MCBinaryExpr::Sub;
4506 else
4507 return false;
4508 if (getParser().parsePrimaryExpr(Res&: Term, EndLoc))
4509 return true;
4510 ImmVal = MCBinaryExpr::create(Op: Opcode, LHS: ImmVal, RHS: Term, Ctx&: getContext());
4511 }
4512
4513 return false;
4514}
4515
4516ParseStatus AArch64AsmParser::tryParseMatrixTileList(OperandVector &Operands) {
4517 if (getTok().isNot(K: AsmToken::LCurly))
4518 return ParseStatus::NoMatch;
4519
4520 auto ParseMatrixTile = [this](unsigned &Reg,
4521 unsigned &ElementWidth) -> ParseStatus {
4522 StringRef Name = getTok().getString();
4523 size_t DotPosition = Name.find(C: '.');
4524 if (DotPosition == StringRef::npos)
4525 return ParseStatus::NoMatch;
4526
4527 unsigned RegNum = matchMatrixTileListRegName(Name);
4528 if (!RegNum)
4529 return ParseStatus::NoMatch;
4530
4531 StringRef Tail = Name.drop_front(N: DotPosition);
4532 const std::optional<std::pair<int, int>> &KindRes =
4533 parseVectorKind(Suffix: Tail, VectorKind: RegKind::Matrix);
4534 if (!KindRes)
4535 return TokError(
4536 Msg: "Expected the register to be followed by element width suffix");
4537 ElementWidth = KindRes->second;
4538 Reg = RegNum;
4539 Lex(); // Eat the register.
4540 return ParseStatus::Success;
4541 };
4542
4543 SMLoc S = getLoc();
4544 auto LCurly = getTok();
4545 Lex(); // Eat left bracket token.
4546
4547 // Empty matrix list
4548 if (parseOptionalToken(T: AsmToken::RCurly)) {
4549 Operands.push_back(Elt: AArch64Operand::CreateMatrixTileList(
4550 /*RegMask=*/0, S, E: getLoc(), Ctx&: getContext()));
4551 return ParseStatus::Success;
4552 }
4553
4554 // Try parse {za} alias early
4555 if (getTok().getString().equals_insensitive(RHS: "za")) {
4556 Lex(); // Eat 'za'
4557
4558 if (parseToken(T: AsmToken::RCurly, Msg: "'}' expected"))
4559 return ParseStatus::Failure;
4560
4561 Operands.push_back(Elt: AArch64Operand::CreateMatrixTileList(
4562 /*RegMask=*/0xFF, S, E: getLoc(), Ctx&: getContext()));
4563 return ParseStatus::Success;
4564 }
4565
4566 SMLoc TileLoc = getLoc();
4567
4568 unsigned FirstReg, ElementWidth;
4569 auto ParseRes = ParseMatrixTile(FirstReg, ElementWidth);
4570 if (!ParseRes.isSuccess()) {
4571 getLexer().UnLex(Token: LCurly);
4572 return ParseRes;
4573 }
4574
4575 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4576
4577 unsigned PrevReg = FirstReg;
4578
4579 SmallSet<unsigned, 8> DRegs;
4580 AArch64Operand::ComputeRegsForAlias(Reg: FirstReg, OutRegs&: DRegs, ElementWidth);
4581
4582 SmallSet<unsigned, 8> SeenRegs;
4583 SeenRegs.insert(V: FirstReg);
4584
4585 while (parseOptionalToken(T: AsmToken::Comma)) {
4586 TileLoc = getLoc();
4587 unsigned Reg, NextElementWidth;
4588 ParseRes = ParseMatrixTile(Reg, NextElementWidth);
4589 if (!ParseRes.isSuccess())
4590 return ParseRes;
4591
4592 // Element size must match on all regs in the list.
4593 if (ElementWidth != NextElementWidth)
4594 return Error(L: TileLoc, Msg: "mismatched register size suffix");
4595
4596 if (RI->getEncodingValue(Reg) <= (RI->getEncodingValue(Reg: PrevReg)))
4597 Warning(L: TileLoc, Msg: "tile list not in ascending order");
4598
4599 if (SeenRegs.contains(V: Reg))
4600 Warning(L: TileLoc, Msg: "duplicate tile in list");
4601 else {
4602 SeenRegs.insert(V: Reg);
4603 AArch64Operand::ComputeRegsForAlias(Reg, OutRegs&: DRegs, ElementWidth);
4604 }
4605
4606 PrevReg = Reg;
4607 }
4608
4609 if (parseToken(T: AsmToken::RCurly, Msg: "'}' expected"))
4610 return ParseStatus::Failure;
4611
4612 unsigned RegMask = 0;
4613 for (auto Reg : DRegs)
4614 RegMask |= 0x1 << (RI->getEncodingValue(Reg) -
4615 RI->getEncodingValue(Reg: AArch64::ZAD0));
4616 Operands.push_back(
4617 Elt: AArch64Operand::CreateMatrixTileList(RegMask, S, E: getLoc(), Ctx&: getContext()));
4618
4619 return ParseStatus::Success;
4620}
4621
4622template <RegKind VectorKind>
4623ParseStatus AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
4624 bool ExpectMatch) {
4625 MCAsmParser &Parser = getParser();
4626 if (!getTok().is(K: AsmToken::LCurly))
4627 return ParseStatus::NoMatch;
4628
4629 // Wrapper around parse function
4630 auto ParseVector = [this](MCRegister &Reg, StringRef &Kind, SMLoc Loc,
4631 bool NoMatchIsError) -> ParseStatus {
4632 auto RegTok = getTok();
4633 auto ParseRes = tryParseVectorRegister(Reg, Kind, MatchKind: VectorKind);
4634 if (ParseRes.isSuccess()) {
4635 if (parseVectorKind(Suffix: Kind, VectorKind))
4636 return ParseRes;
4637 llvm_unreachable("Expected a valid vector kind");
4638 }
4639
4640 if (RegTok.is(K: AsmToken::Identifier) && ParseRes.isNoMatch() &&
4641 RegTok.getString().equals_insensitive(RHS: "zt0"))
4642 return ParseStatus::NoMatch;
4643
4644 if (RegTok.isNot(K: AsmToken::Identifier) || ParseRes.isFailure() ||
4645 (ParseRes.isNoMatch() && NoMatchIsError &&
4646 !RegTok.getString().starts_with_insensitive(Prefix: "za")))
4647 return Error(L: Loc, Msg: "vector register expected");
4648
4649 return ParseStatus::NoMatch;
4650 };
4651
4652 unsigned NumRegs = getNumRegsForRegKind(K: VectorKind);
4653 SMLoc S = getLoc();
4654 auto LCurly = getTok();
4655 Lex(); // Eat left bracket token.
4656
4657 StringRef Kind;
4658 MCRegister FirstReg;
4659 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
4660
4661 // Put back the original left bracket if there was no match, so that
4662 // different types of list-operands can be matched (e.g. SVE, Neon).
4663 if (ParseRes.isNoMatch())
4664 Parser.getLexer().UnLex(Token: LCurly);
4665
4666 if (!ParseRes.isSuccess())
4667 return ParseRes;
4668
4669 MCRegister PrevReg = FirstReg;
4670 unsigned Count = 1;
4671
4672 unsigned Stride = 1;
4673 if (parseOptionalToken(T: AsmToken::Minus)) {
4674 SMLoc Loc = getLoc();
4675 StringRef NextKind;
4676
4677 MCRegister Reg;
4678 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
4679 if (!ParseRes.isSuccess())
4680 return ParseRes;
4681
4682 // Any Kind suffices must match on all regs in the list.
4683 if (Kind != NextKind)
4684 return Error(L: Loc, Msg: "mismatched register size suffix");
4685
4686 unsigned Space =
4687 (PrevReg < Reg) ? (Reg - PrevReg) : (NumRegs - (PrevReg - Reg));
4688
4689 if (Space == 0 || Space > 3)
4690 return Error(L: Loc, Msg: "invalid number of vectors");
4691
4692 Count += Space;
4693 }
4694 else {
4695 bool HasCalculatedStride = false;
4696 while (parseOptionalToken(T: AsmToken::Comma)) {
4697 SMLoc Loc = getLoc();
4698 StringRef NextKind;
4699 MCRegister Reg;
4700 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
4701 if (!ParseRes.isSuccess())
4702 return ParseRes;
4703
4704 // Any Kind suffices must match on all regs in the list.
4705 if (Kind != NextKind)
4706 return Error(L: Loc, Msg: "mismatched register size suffix");
4707
4708 unsigned RegVal = getContext().getRegisterInfo()->getEncodingValue(Reg);
4709 unsigned PrevRegVal =
4710 getContext().getRegisterInfo()->getEncodingValue(Reg: PrevReg);
4711 if (!HasCalculatedStride) {
4712 Stride = (PrevRegVal < RegVal) ? (RegVal - PrevRegVal)
4713 : (NumRegs - (PrevRegVal - RegVal));
4714 HasCalculatedStride = true;
4715 }
4716
4717 // Register must be incremental (with a wraparound at last register).
4718 if (Stride == 0 || RegVal != ((PrevRegVal + Stride) % NumRegs))
4719 return Error(L: Loc, Msg: "registers must have the same sequential stride");
4720
4721 PrevReg = Reg;
4722 ++Count;
4723 }
4724 }
4725
4726 if (parseToken(T: AsmToken::RCurly, Msg: "'}' expected"))
4727 return ParseStatus::Failure;
4728
4729 if (Count > 4)
4730 return Error(L: S, Msg: "invalid number of vectors");
4731
4732 unsigned NumElements = 0;
4733 unsigned ElementWidth = 0;
4734 if (!Kind.empty()) {
4735 if (const auto &VK = parseVectorKind(Suffix: Kind, VectorKind))
4736 std::tie(args&: NumElements, args&: ElementWidth) = *VK;
4737 }
4738
4739 Operands.push_back(Elt: AArch64Operand::CreateVectorList(
4740 Reg: FirstReg, Count, Stride, NumElements, ElementWidth, RegisterKind: VectorKind, S,
4741 E: getLoc(), Ctx&: getContext()));
4742
4743 if (getTok().is(K: AsmToken::LBrac)) {
4744 ParseStatus Res = tryParseVectorIndex(Operands);
4745 if (Res.isFailure())
4746 return ParseStatus::Failure;
4747 return ParseStatus::Success;
4748 }
4749
4750 return ParseStatus::Success;
4751}
4752
4753/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
4754bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
4755 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, ExpectMatch: true);
4756 if (!ParseRes.isSuccess())
4757 return true;
4758
4759 return tryParseVectorIndex(Operands).isFailure();
4760}
4761
4762ParseStatus AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
4763 SMLoc StartLoc = getLoc();
4764
4765 MCRegister RegNum;
4766 ParseStatus Res = tryParseScalarRegister(RegNum);
4767 if (!Res.isSuccess())
4768 return Res;
4769
4770 if (!parseOptionalToken(T: AsmToken::Comma)) {
4771 Operands.push_back(Elt: AArch64Operand::CreateReg(
4772 Reg: RegNum, Kind: RegKind::Scalar, S: StartLoc, E: getLoc(), Ctx&: getContext()));
4773 return ParseStatus::Success;
4774 }
4775
4776 parseOptionalToken(T: AsmToken::Hash);
4777
4778 if (getTok().isNot(K: AsmToken::Integer))
4779 return Error(L: getLoc(), Msg: "index must be absent or #0");
4780
4781 const MCExpr *ImmVal;
4782 if (getParser().parseExpression(Res&: ImmVal) || !isa<MCConstantExpr>(Val: ImmVal) ||
4783 cast<MCConstantExpr>(Val: ImmVal)->getValue() != 0)
4784 return Error(L: getLoc(), Msg: "index must be absent or #0");
4785
4786 Operands.push_back(Elt: AArch64Operand::CreateReg(
4787 Reg: RegNum, Kind: RegKind::Scalar, S: StartLoc, E: getLoc(), Ctx&: getContext()));
4788 return ParseStatus::Success;
4789}
4790
4791ParseStatus AArch64AsmParser::tryParseZTOperand(OperandVector &Operands) {
4792 SMLoc StartLoc = getLoc();
4793 const AsmToken &Tok = getTok();
4794 std::string Name = Tok.getString().lower();
4795
4796 MCRegister Reg = matchRegisterNameAlias(Name, Kind: RegKind::LookupTable);
4797
4798 if (!Reg)
4799 return ParseStatus::NoMatch;
4800
4801 Operands.push_back(Elt: AArch64Operand::CreateReg(
4802 Reg, Kind: RegKind::LookupTable, S: StartLoc, E: getLoc(), Ctx&: getContext()));
4803 Lex(); // Eat register.
4804
4805 // Check if register is followed by an index
4806 if (parseOptionalToken(T: AsmToken::LBrac)) {
4807 Operands.push_back(
4808 Elt: AArch64Operand::CreateToken(Str: "[", S: getLoc(), Ctx&: getContext()));
4809 const MCExpr *ImmVal;
4810 if (getParser().parseExpression(Res&: ImmVal))
4811 return ParseStatus::NoMatch;
4812 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal);
4813 if (!MCE)
4814 return TokError(Msg: "immediate value expected for vector index");
4815 Operands.push_back(Elt: AArch64Operand::CreateImm(
4816 Val: MCConstantExpr::create(Value: MCE->getValue(), Ctx&: getContext()), S: StartLoc,
4817 E: getLoc(), Ctx&: getContext()));
4818 if (parseOptionalToken(T: AsmToken::Comma))
4819 if (parseOptionalMulOperand(Operands))
4820 return ParseStatus::Failure;
4821 if (parseToken(T: AsmToken::RBrac, Msg: "']' expected"))
4822 return ParseStatus::Failure;
4823 Operands.push_back(
4824 Elt: AArch64Operand::CreateToken(Str: "]", S: getLoc(), Ctx&: getContext()));
4825 }
4826 return ParseStatus::Success;
4827}
4828
4829template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
4830ParseStatus AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
4831 SMLoc StartLoc = getLoc();
4832
4833 MCRegister RegNum;
4834 ParseStatus Res = tryParseScalarRegister(RegNum);
4835 if (!Res.isSuccess())
4836 return Res;
4837
4838 // No shift/extend is the default.
4839 if (!ParseShiftExtend || getTok().isNot(K: AsmToken::Comma)) {
4840 Operands.push_back(Elt: AArch64Operand::CreateReg(
4841 Reg: RegNum, Kind: RegKind::Scalar, S: StartLoc, E: getLoc(), Ctx&: getContext(), EqTy));
4842 return ParseStatus::Success;
4843 }
4844
4845 // Eat the comma
4846 Lex();
4847
4848 // Match the shift
4849 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
4850 Res = tryParseOptionalShiftExtend(Operands&: ExtOpnd);
4851 if (!Res.isSuccess())
4852 return Res;
4853
4854 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
4855 Operands.push_back(Elt: AArch64Operand::CreateReg(
4856 Reg: RegNum, Kind: RegKind::Scalar, S: StartLoc, E: Ext->getEndLoc(), Ctx&: getContext(), EqTy,
4857 ExtTy: Ext->getShiftExtendType(), ShiftAmount: Ext->getShiftExtendAmount(),
4858 HasExplicitAmount: Ext->hasShiftExtendAmount()));
4859
4860 return ParseStatus::Success;
4861}
4862
4863bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
4864 MCAsmParser &Parser = getParser();
4865
4866 // Some SVE instructions have a decoration after the immediate, i.e.
4867 // "mul vl". We parse them here and add tokens, which must be present in the
4868 // asm string in the tablegen instruction.
4869 bool NextIsVL =
4870 Parser.getLexer().peekTok().getString().equals_insensitive(RHS: "vl");
4871 bool NextIsHash = Parser.getLexer().peekTok().is(K: AsmToken::Hash);
4872 if (!getTok().getString().equals_insensitive(RHS: "mul") ||
4873 !(NextIsVL || NextIsHash))
4874 return true;
4875
4876 Operands.push_back(
4877 Elt: AArch64Operand::CreateToken(Str: "mul", S: getLoc(), Ctx&: getContext()));
4878 Lex(); // Eat the "mul"
4879
4880 if (NextIsVL) {
4881 Operands.push_back(
4882 Elt: AArch64Operand::CreateToken(Str: "vl", S: getLoc(), Ctx&: getContext()));
4883 Lex(); // Eat the "vl"
4884 return false;
4885 }
4886
4887 if (NextIsHash) {
4888 Lex(); // Eat the #
4889 SMLoc S = getLoc();
4890
4891 // Parse immediate operand.
4892 const MCExpr *ImmVal;
4893 if (!Parser.parseExpression(Res&: ImmVal))
4894 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Val: ImmVal)) {
4895 Operands.push_back(Elt: AArch64Operand::CreateImm(
4896 Val: MCConstantExpr::create(Value: MCE->getValue(), Ctx&: getContext()), S, E: getLoc(),
4897 Ctx&: getContext()));
4898 return false;
4899 }
4900 }
4901
4902 return Error(L: getLoc(), Msg: "expected 'vl' or '#<imm>'");
4903}
4904
4905bool AArch64AsmParser::parseOptionalVGOperand(OperandVector &Operands,
4906 StringRef &VecGroup) {
4907 MCAsmParser &Parser = getParser();
4908 auto Tok = Parser.getTok();
4909 if (Tok.isNot(K: AsmToken::Identifier))
4910 return true;
4911
4912 StringRef VG = StringSwitch<StringRef>(Tok.getString().lower())
4913 .Case(S: "vgx2", Value: "vgx2")
4914 .Case(S: "vgx4", Value: "vgx4")
4915 .Default(Value: "");
4916
4917 if (VG.empty())
4918 return true;
4919
4920 VecGroup = VG;
4921 Parser.Lex(); // Eat vgx[2|4]
4922 return false;
4923}
4924
4925bool AArch64AsmParser::parseKeywordOperand(OperandVector &Operands) {
4926 auto Tok = getTok();
4927 if (Tok.isNot(K: AsmToken::Identifier))
4928 return true;
4929
4930 auto Keyword = Tok.getString();
4931 Keyword = StringSwitch<StringRef>(Keyword.lower())
4932 .Case(S: "c", Value: "c")
4933 .Case(S: "csync", Value: "csync")
4934 .Case(S: "j", Value: "j")
4935 .Case(S: "jc", Value: "jc")
4936 .Case(S: "keep", Value: "keep")
4937 .Case(S: "ph", Value: "ph")
4938 .Case(S: "r", Value: "r")
4939 .Case(S: "sm", Value: "sm")
4940 .Case(S: "stshstrm", Value: "stshstrm")
4941 .Case(S: "strm", Value: "strm")
4942 .Case(S: "za", Value: "za")
4943 .Default(Value: Keyword);
4944 Operands.push_back(
4945 Elt: AArch64Operand::CreateToken(Str: Keyword, S: Tok.getLoc(), Ctx&: getContext()));
4946
4947 Lex();
4948 return false;
4949}
4950
4951/// parseOperand - Parse a arm instruction operand. For now this parses the
4952/// operand regardless of the mnemonic.
4953bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
4954 bool invertCondCode) {
4955 MCAsmParser &Parser = getParser();
4956
4957 ParseStatus ResTy =
4958 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/true);
4959
4960 // Check if the current operand has a custom associated parser, if so, try to
4961 // custom parse the operand, or fallback to the general approach.
4962 if (ResTy.isSuccess())
4963 return false;
4964 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4965 // there was a match, but an error occurred, in which case, just return that
4966 // the operand parsing failed.
4967 if (ResTy.isFailure())
4968 return true;
4969
4970 // Nothing custom, so do general case parsing.
4971 SMLoc S, E;
4972 auto parseOptionalShiftExtend = [&](AsmToken SavedTok) {
4973 if (parseOptionalToken(T: AsmToken::Comma)) {
4974 ParseStatus Res = tryParseOptionalShiftExtend(Operands);
4975 if (!Res.isNoMatch())
4976 return Res.isFailure();
4977 getLexer().UnLex(Token: SavedTok);
4978 }
4979 return false;
4980 };
4981 switch (getLexer().getKind()) {
4982 default: {
4983 SMLoc S = getLoc();
4984 const MCExpr *Expr;
4985 if (parseSymbolicImmVal(ImmVal&: Expr))
4986 return Error(L: S, Msg: "invalid operand");
4987
4988 SMLoc E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
4989 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: Expr, S, E, Ctx&: getContext()));
4990 return parseOptionalShiftExtend(getTok());
4991 }
4992 case AsmToken::LBrac: {
4993 Operands.push_back(
4994 Elt: AArch64Operand::CreateToken(Str: "[", S: getLoc(), Ctx&: getContext()));
4995 Lex(); // Eat '['
4996
4997 // There's no comma after a '[', so we can parse the next operand
4998 // immediately.
4999 return parseOperand(Operands, isCondCode: false, invertCondCode: false);
5000 }
5001 case AsmToken::LCurly: {
5002 if (!parseNeonVectorList(Operands))
5003 return false;
5004
5005 Operands.push_back(
5006 Elt: AArch64Operand::CreateToken(Str: "{", S: getLoc(), Ctx&: getContext()));
5007 Lex(); // Eat '{'
5008
5009 // There's no comma after a '{', so we can parse the next operand
5010 // immediately.
5011 return parseOperand(Operands, isCondCode: false, invertCondCode: false);
5012 }
5013 case AsmToken::Identifier: {
5014 // See if this is a "VG" decoration used by SME instructions.
5015 StringRef VecGroup;
5016 if (!parseOptionalVGOperand(Operands, VecGroup)) {
5017 Operands.push_back(
5018 Elt: AArch64Operand::CreateToken(Str: VecGroup, S: getLoc(), Ctx&: getContext()));
5019 return false;
5020 }
5021 // If we're expecting a Condition Code operand, then just parse that.
5022 if (isCondCode)
5023 return parseCondCode(Operands, invertCondCode);
5024
5025 // If it's a register name, parse it.
5026 if (!parseRegister(Operands)) {
5027 // Parse an optional shift/extend modifier.
5028 AsmToken SavedTok = getTok();
5029 if (parseOptionalToken(T: AsmToken::Comma)) {
5030 // The operand after the register may be a label (e.g. ADR/ADRP). Check
5031 // such cases and don't report an error when <label> happens to match a
5032 // shift/extend modifier.
5033 ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic,
5034 /*ParseForAllFeatures=*/true);
5035 if (!Res.isNoMatch())
5036 return Res.isFailure();
5037 Res = tryParseOptionalShiftExtend(Operands);
5038 if (!Res.isNoMatch())
5039 return Res.isFailure();
5040 getLexer().UnLex(Token: SavedTok);
5041 }
5042 return false;
5043 }
5044
5045 // See if this is a "mul vl" decoration or "mul #<int>" operand used
5046 // by SVE instructions.
5047 if (!parseOptionalMulOperand(Operands))
5048 return false;
5049
5050 // If this is a two-word mnemonic, parse its special keyword
5051 // operand as an identifier.
5052 if (Mnemonic == "brb" || Mnemonic == "smstart" || Mnemonic == "smstop" ||
5053 Mnemonic == "gcsb" || Mnemonic == "bti" || Mnemonic == "stshh" ||
5054 Mnemonic == "psb" || Mnemonic == "tsb" || Mnemonic == "shuh" ||
5055 Mnemonic == "srls")
5056 return parseKeywordOperand(Operands);
5057
5058 // This was not a register so parse other operands that start with an
5059 // identifier (like labels) as expressions and create them as immediates.
5060 const MCExpr *IdVal, *Term;
5061 S = getLoc();
5062 if (getParser().parseExpression(Res&: IdVal))
5063 return true;
5064 if (getParser().parseAtSpecifier(Res&: IdVal, EndLoc&: E))
5065 return true;
5066 std::optional<MCBinaryExpr::Opcode> Opcode;
5067 if (parseOptionalToken(T: AsmToken::Plus))
5068 Opcode = MCBinaryExpr::Add;
5069 else if (parseOptionalToken(T: AsmToken::Minus))
5070 Opcode = MCBinaryExpr::Sub;
5071 if (Opcode) {
5072 if (getParser().parsePrimaryExpr(Res&: Term, EndLoc&: E))
5073 return true;
5074 IdVal = MCBinaryExpr::create(Op: *Opcode, LHS: IdVal, RHS: Term, Ctx&: getContext());
5075 }
5076 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: IdVal, S, E, Ctx&: getContext()));
5077
5078 // Parse an optional shift/extend modifier.
5079 return parseOptionalShiftExtend(getTok());
5080 }
5081 case AsmToken::Integer:
5082 case AsmToken::Real:
5083 case AsmToken::Hash: {
5084 // #42 -> immediate.
5085 S = getLoc();
5086
5087 parseOptionalToken(T: AsmToken::Hash);
5088
5089 // Parse a negative sign
5090 bool isNegative = false;
5091 if (getTok().is(K: AsmToken::Minus)) {
5092 isNegative = true;
5093 // We need to consume this token only when we have a Real, otherwise
5094 // we let parseSymbolicImmVal take care of it
5095 if (Parser.getLexer().peekTok().is(K: AsmToken::Real))
5096 Lex();
5097 }
5098
5099 // The only Real that should come through here is a literal #0.0 for
5100 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
5101 // so convert the value.
5102 const AsmToken &Tok = getTok();
5103 if (Tok.is(K: AsmToken::Real)) {
5104 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
5105 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
5106 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
5107 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
5108 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
5109 return TokError(Msg: "unexpected floating point literal");
5110 else if (IntVal != 0 || isNegative)
5111 return TokError(Msg: "expected floating-point constant #0.0");
5112 Lex(); // Eat the token.
5113
5114 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: "#0", S, Ctx&: getContext()));
5115 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: ".0", S, Ctx&: getContext()));
5116 return false;
5117 }
5118
5119 const MCExpr *ImmVal;
5120 if (parseSymbolicImmVal(ImmVal))
5121 return true;
5122
5123 E = SMLoc::getFromPointer(Ptr: getLoc().getPointer() - 1);
5124 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: ImmVal, S, E, Ctx&: getContext()));
5125
5126 // Parse an optional shift/extend modifier.
5127 return parseOptionalShiftExtend(Tok);
5128 }
5129 case AsmToken::Equal: {
5130 SMLoc Loc = getLoc();
5131 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
5132 return TokError(Msg: "unexpected token in operand");
5133 Lex(); // Eat '='
5134 const MCExpr *SubExprVal;
5135 if (getParser().parseExpression(Res&: SubExprVal))
5136 return true;
5137
5138 if (Operands.size() < 2 ||
5139 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
5140 return Error(L: Loc, Msg: "Only valid when first operand is register");
5141
5142 bool IsXReg = getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
5143 .contains(Reg: Operands[1]->getReg());
5144
5145 MCContext& Ctx = getContext();
5146 E = SMLoc::getFromPointer(Ptr: Loc.getPointer() - 1);
5147 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
5148 if (isa<MCConstantExpr>(Val: SubExprVal)) {
5149 uint64_t Imm = (cast<MCConstantExpr>(Val: SubExprVal))->getValue();
5150 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
5151 while (Imm > 0xFFFF && llvm::countr_zero(Val: Imm) >= 16) {
5152 ShiftAmt += 16;
5153 Imm >>= 16;
5154 }
5155 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
5156 Operands[0] = AArch64Operand::CreateToken(Str: "movz", S: Loc, Ctx);
5157 Operands.push_back(Elt: AArch64Operand::CreateImm(
5158 Val: MCConstantExpr::create(Value: Imm, Ctx), S, E, Ctx));
5159 if (ShiftAmt)
5160 Operands.push_back(Elt: AArch64Operand::CreateShiftExtend(ShOp: AArch64_AM::LSL,
5161 Val: ShiftAmt, HasExplicitAmount: true, S, E, Ctx));
5162 return false;
5163 }
5164 APInt Simm = APInt(64, Imm << ShiftAmt);
5165 // check if the immediate is an unsigned or signed 32-bit int for W regs
5166 if (!IsXReg && !(Simm.isIntN(N: 32) || Simm.isSignedIntN(N: 32)))
5167 return Error(L: Loc, Msg: "Immediate too large for register");
5168 }
5169 // If it is a label or an imm that cannot fit in a movz, put it into CP.
5170 const MCExpr *CPLoc =
5171 getTargetStreamer().addConstantPoolEntry(SubExprVal, Size: IsXReg ? 8 : 4, Loc);
5172 Operands.push_back(Elt: AArch64Operand::CreateImm(Val: CPLoc, S, E, Ctx));
5173 return false;
5174 }
5175 }
5176}
5177
5178bool AArch64AsmParser::parseImmExpr(int64_t &Out) {
5179 const MCExpr *Expr = nullptr;
5180 SMLoc L = getLoc();
5181 if (check(P: getParser().parseExpression(Res&: Expr), Loc: L, Msg: "expected expression"))
5182 return true;
5183 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Val: Expr);
5184 if (check(P: !Value, Loc: L, Msg: "expected constant expression"))
5185 return true;
5186 Out = Value->getValue();
5187 return false;
5188}
5189
5190bool AArch64AsmParser::parseComma() {
5191 if (check(P: getTok().isNot(K: AsmToken::Comma), Loc: getLoc(), Msg: "expected comma"))
5192 return true;
5193 // Eat the comma
5194 Lex();
5195 return false;
5196}
5197
5198bool AArch64AsmParser::parseRegisterInRange(unsigned &Out, unsigned Base,
5199 unsigned First, unsigned Last) {
5200 MCRegister Reg;
5201 SMLoc Start, End;
5202 if (check(P: parseRegister(Reg, StartLoc&: Start, EndLoc&: End), Loc: getLoc(), Msg: "expected register"))
5203 return true;
5204
5205 // Special handling for FP and LR; they aren't linearly after x28 in
5206 // the registers enum.
5207 unsigned RangeEnd = Last;
5208 if (Base == AArch64::X0) {
5209 if (Last == AArch64::FP) {
5210 RangeEnd = AArch64::X28;
5211 if (Reg == AArch64::FP) {
5212 Out = 29;
5213 return false;
5214 }
5215 }
5216 if (Last == AArch64::LR) {
5217 RangeEnd = AArch64::X28;
5218 if (Reg == AArch64::FP) {
5219 Out = 29;
5220 return false;
5221 } else if (Reg == AArch64::LR) {
5222 Out = 30;
5223 return false;
5224 }
5225 }
5226 }
5227
5228 if (check(P: Reg < First || Reg > RangeEnd, Loc: Start,
5229 Msg: Twine("expected register in range ") +
5230 AArch64InstPrinter::getRegisterName(Reg: First) + " to " +
5231 AArch64InstPrinter::getRegisterName(Reg: Last)))
5232 return true;
5233 Out = Reg - Base;
5234 return false;
5235}
5236
5237bool AArch64AsmParser::areEqualRegs(const MCParsedAsmOperand &Op1,
5238 const MCParsedAsmOperand &Op2) const {
5239 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
5240 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
5241
5242 if (AOp1.isVectorList() && AOp2.isVectorList())
5243 return AOp1.getVectorListCount() == AOp2.getVectorListCount() &&
5244 AOp1.getVectorListStart() == AOp2.getVectorListStart() &&
5245 AOp1.getVectorListStride() == AOp2.getVectorListStride();
5246
5247 if (!AOp1.isReg() || !AOp2.isReg())
5248 return false;
5249
5250 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
5251 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
5252 return MCTargetAsmParser::areEqualRegs(Op1, Op2);
5253
5254 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
5255 "Testing equality of non-scalar registers not supported");
5256
5257 // Check if a registers match their sub/super register classes.
5258 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
5259 return getXRegFromWReg(Reg: Op1.getReg()) == Op2.getReg();
5260 if (AOp1.getRegEqualityTy() == EqualsSubReg)
5261 return getWRegFromXReg(Reg: Op1.getReg()) == Op2.getReg();
5262 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
5263 return getXRegFromWReg(Reg: Op2.getReg()) == Op1.getReg();
5264 if (AOp2.getRegEqualityTy() == EqualsSubReg)
5265 return getWRegFromXReg(Reg: Op2.getReg()) == Op1.getReg();
5266
5267 return false;
5268}
5269
5270/// Parse an AArch64 instruction mnemonic followed by its operands.
5271bool AArch64AsmParser::parseInstruction(ParseInstructionInfo &Info,
5272 StringRef Name, SMLoc NameLoc,
5273 OperandVector &Operands) {
5274 Name = StringSwitch<StringRef>(Name.lower())
5275 .Case(S: "beq", Value: "b.eq")
5276 .Case(S: "bne", Value: "b.ne")
5277 .Case(S: "bhs", Value: "b.hs")
5278 .Case(S: "bcs", Value: "b.cs")
5279 .Case(S: "blo", Value: "b.lo")
5280 .Case(S: "bcc", Value: "b.cc")
5281 .Case(S: "bmi", Value: "b.mi")
5282 .Case(S: "bpl", Value: "b.pl")
5283 .Case(S: "bvs", Value: "b.vs")
5284 .Case(S: "bvc", Value: "b.vc")
5285 .Case(S: "bhi", Value: "b.hi")
5286 .Case(S: "bls", Value: "b.ls")
5287 .Case(S: "bge", Value: "b.ge")
5288 .Case(S: "blt", Value: "b.lt")
5289 .Case(S: "bgt", Value: "b.gt")
5290 .Case(S: "ble", Value: "b.le")
5291 .Case(S: "bal", Value: "b.al")
5292 .Case(S: "bnv", Value: "b.nv")
5293 .Default(Value: Name);
5294
5295 // First check for the AArch64-specific .req directive.
5296 if (getTok().is(K: AsmToken::Identifier) &&
5297 getTok().getIdentifier().lower() == ".req") {
5298 parseDirectiveReq(Name, L: NameLoc);
5299 // We always return 'error' for this, as we're done with this
5300 // statement and don't need to match the 'instruction."
5301 return true;
5302 }
5303
5304 // Create the leading tokens for the mnemonic, split by '.' characters.
5305 size_t Start = 0, Next = Name.find(C: '.');
5306 StringRef Head = Name.slice(Start, End: Next);
5307
5308 // IC, DC, AT, TLBI, PLBI, GIC{R}, GSB and Prediction invalidation
5309 // instructions are aliases for the SYS instruction.
5310 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
5311 Head == "cfp" || Head == "dvp" || Head == "cpp" || Head == "cosp" ||
5312 Head == "plbi" || Head == "gic" || Head == "gsb")
5313 return parseSysAlias(Name: Head, NameLoc, Operands);
5314
5315 // GICR instructions are aliases for the SYSL instruction.
5316 if (Head == "gicr")
5317 return parseSyslAlias(Name: Head, NameLoc, Operands);
5318
5319 // TLBIP instructions are aliases for the SYSP instruction.
5320 if (Head == "tlbip")
5321 return parseSyspAlias(Name: Head, NameLoc, Operands);
5322
5323 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: Head, S: NameLoc, Ctx&: getContext()));
5324 Mnemonic = Head;
5325
5326 // Handle condition codes for a branch or fault mnemonic.
5327 if ((Head == "b" || Head == "bc" || Head == "flt") &&
5328 Next != StringRef::npos) {
5329 Start = Next;
5330 Next = Name.find(C: '.', From: Start + 1);
5331 Head = Name.slice(Start: Start + 1, End: Next);
5332
5333 SMLoc SuffixLoc = SMLoc::getFromPointer(Ptr: NameLoc.getPointer() +
5334 (Head.data() - Name.data()));
5335 std::string Suggestion;
5336 AArch64CC::CondCode CC = parseCondCodeString(Cond: Head, Suggestion);
5337 if (CC == AArch64CC::Invalid) {
5338 std::string Msg = "invalid condition code";
5339 if (!Suggestion.empty())
5340 Msg += ", did you mean " + Suggestion + "?";
5341 return Error(L: SuffixLoc, Msg);
5342 }
5343 Operands.push_back(Elt: AArch64Operand::CreateToken(Str: ".", S: SuffixLoc, Ctx&: getContext(),
5344 /*IsSuffix=*/true));
5345 Operands.push_back(
5346 Elt: AArch64Operand::CreateCondCode(Code: CC, S: NameLoc, E: NameLoc, Ctx&: getContext()));
5347 }
5348
5349 // Add the remaining tokens in the mnemonic.
5350 while (Next != StringRef::npos) {
5351 Start = Next;
5352 Next = Name.find(C: '.', From: Start + 1);
5353 Head = Name.slice(Start, End: Next);
5354 SMLoc SuffixLoc = SMLoc::getFromPointer(Ptr: NameLoc.getPointer() +
5355 (Head.data() - Name.data()) + 1);
5356 Operands.push_back(Elt: AArch64Operand::CreateToken(
5357 Str: Head, S: SuffixLoc, Ctx&: getContext(), /*IsSuffix=*/true));
5358 }
5359
5360 // Conditional compare instructions have a Condition Code operand, which needs
5361 // to be parsed and an immediate operand created.
5362 bool condCodeFourthOperand =
5363 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
5364 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
5365 Head == "csinc" || Head == "csinv" || Head == "csneg");
5366
5367 // These instructions are aliases to some of the conditional select
5368 // instructions. However, the condition code is inverted in the aliased
5369 // instruction.
5370 //
5371 // FIXME: Is this the correct way to handle these? Or should the parser
5372 // generate the aliased instructions directly?
5373 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
5374 bool condCodeThirdOperand =
5375 (Head == "cinc" || Head == "cinv" || Head == "cneg");
5376
5377 // Read the remaining operands.
5378 if (getLexer().isNot(K: AsmToken::EndOfStatement)) {
5379
5380 unsigned N = 1;
5381 do {
5382 // Parse and remember the operand.
5383 if (parseOperand(Operands, isCondCode: (N == 4 && condCodeFourthOperand) ||
5384 (N == 3 && condCodeThirdOperand) ||
5385 (N == 2 && condCodeSecondOperand),
5386 invertCondCode: condCodeSecondOperand || condCodeThirdOperand)) {
5387 return true;
5388 }
5389
5390 // After successfully parsing some operands there are three special cases
5391 // to consider (i.e. notional operands not separated by commas). Two are
5392 // due to memory specifiers:
5393 // + An RBrac will end an address for load/store/prefetch
5394 // + An '!' will indicate a pre-indexed operation.
5395 //
5396 // And a further case is '}', which ends a group of tokens specifying the
5397 // SME accumulator array 'ZA' or tile vector, i.e.
5398 //
5399 // '{ ZA }' or '{ <ZAt><HV>.<BHSDQ>[<Wv>, #<imm>] }'
5400 //
5401 // It's someone else's responsibility to make sure these tokens are sane
5402 // in the given context!
5403
5404 if (parseOptionalToken(T: AsmToken::RBrac))
5405 Operands.push_back(
5406 Elt: AArch64Operand::CreateToken(Str: "]", S: getLoc(), Ctx&: getContext()));
5407 if (parseOptionalToken(T: AsmToken::Exclaim))
5408 Operands.push_back(
5409 Elt: AArch64Operand::CreateToken(Str: "!", S: getLoc(), Ctx&: getContext()));
5410 if (parseOptionalToken(T: AsmToken::RCurly))
5411 Operands.push_back(
5412 Elt: AArch64Operand::CreateToken(Str: "}", S: getLoc(), Ctx&: getContext()));
5413
5414 ++N;
5415 } while (parseOptionalToken(T: AsmToken::Comma));
5416 }
5417
5418 if (parseToken(T: AsmToken::EndOfStatement, Msg: "unexpected token in argument list"))
5419 return true;
5420
5421 return false;
5422}
5423
5424static inline bool isMatchingOrAlias(MCRegister ZReg, MCRegister Reg) {
5425 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
5426 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
5427 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
5428 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
5429 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
5430 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
5431 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
5432}
5433
5434static bool isMovPrfxable(unsigned TSFlags) {
5435 unsigned Flags = TSFlags & AArch64::DestructiveInstTypeMask;
5436 return Flags != AArch64::NotDestructive &&
5437 Flags != AArch64::DestructivePredicate;
5438}
5439
5440// FIXME: This entire function is a giant hack to provide us with decent
5441// operand range validation/diagnostics until TableGen/MC can be extended
5442// to support autogeneration of this kind of validation.
5443bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
5444 SmallVectorImpl<SMLoc> &Loc) {
5445 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5446 const MCInstrDesc &MCID = MII.get(Opcode: Inst.getOpcode());
5447
5448 // A prefix only applies to the instruction following it. Here we extract
5449 // prefix information for the next instruction before validating the current
5450 // one so that in the case of failure we don't erroneously continue using the
5451 // current prefix.
5452 PrefixInfo Prefix = NextPrefix;
5453 NextPrefix = PrefixInfo::CreateFromInst(Inst, TSFlags: MCID.TSFlags);
5454
5455 // Before validating the instruction in isolation we run through the rules
5456 // applicable when it follows a prefix instruction.
5457 // NOTE: brk & hlt can be prefixed but require no additional validation.
5458 if (Prefix.isActive() &&
5459 (Inst.getOpcode() != AArch64::BRK) &&
5460 (Inst.getOpcode() != AArch64::HLT)) {
5461
5462 // Prefixed instructions must have a destructive operand.
5463 if (!isMovPrfxable(TSFlags: MCID.TSFlags))
5464 return Error(L: IDLoc, Msg: "instruction is unpredictable when following a"
5465 " movprfx, suggest replacing movprfx with mov");
5466
5467 // Destination operands must match.
5468 if (Inst.getOperand(i: 0).getReg() != Prefix.getDstReg())
5469 return Error(L: Loc[0], Msg: "instruction is unpredictable when following a"
5470 " movprfx writing to a different destination");
5471
5472 // Destination operand must not be used in any other location.
5473 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
5474 if (Inst.getOperand(i).isReg() &&
5475 (MCID.getOperandConstraint(OpNum: i, Constraint: MCOI::TIED_TO) == -1) &&
5476 isMatchingOrAlias(ZReg: Prefix.getDstReg(), Reg: Inst.getOperand(i).getReg()))
5477 return Error(L: Loc[0], Msg: "instruction is unpredictable when following a"
5478 " movprfx and destination also used as non-destructive"
5479 " source");
5480 }
5481
5482 const auto &PPRRegClass = getAArch64MCRegisterClass(RC: AArch64::PPRRegClassID);
5483 if (Prefix.isPredicated()) {
5484 int PgIdx = -1;
5485
5486 // Find the instructions general predicate.
5487 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
5488 if (Inst.getOperand(i).isReg() &&
5489 PPRRegClass.contains(Reg: Inst.getOperand(i).getReg())) {
5490 PgIdx = i;
5491 break;
5492 }
5493
5494 // Instruction must be predicated if the movprfx is predicated.
5495 if (PgIdx == -1 ||
5496 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
5497 return Error(L: IDLoc, Msg: "instruction is unpredictable when following a"
5498 " predicated movprfx, suggest using unpredicated movprfx");
5499
5500 // Instruction must use same general predicate as the movprfx.
5501 if (Inst.getOperand(i: PgIdx).getReg() != Prefix.getPgReg())
5502 return Error(L: IDLoc, Msg: "instruction is unpredictable when following a"
5503 " predicated movprfx using a different general predicate");
5504
5505 // Instruction element type must match the movprfx.
5506 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
5507 return Error(L: IDLoc, Msg: "instruction is unpredictable when following a"
5508 " predicated movprfx with a different element size");
5509 }
5510 }
5511
5512 // On ARM64EC, only valid registers may be used. Warn against using
5513 // explicitly disallowed registers.
5514 if (IsWindowsArm64EC) {
5515 for (unsigned i = 0; i < Inst.getNumOperands(); ++i) {
5516 if (Inst.getOperand(i).isReg()) {
5517 MCRegister Reg = Inst.getOperand(i).getReg();
5518 // At this point, vector registers are matched to their
5519 // appropriately sized alias.
5520 if ((Reg == AArch64::W13 || Reg == AArch64::X13) ||
5521 (Reg == AArch64::W14 || Reg == AArch64::X14) ||
5522 (Reg == AArch64::W23 || Reg == AArch64::X23) ||
5523 (Reg == AArch64::W24 || Reg == AArch64::X24) ||
5524 (Reg == AArch64::W28 || Reg == AArch64::X28) ||
5525 (Reg >= AArch64::Q16 && Reg <= AArch64::Q31) ||
5526 (Reg >= AArch64::D16 && Reg <= AArch64::D31) ||
5527 (Reg >= AArch64::S16 && Reg <= AArch64::S31) ||
5528 (Reg >= AArch64::H16 && Reg <= AArch64::H31) ||
5529 (Reg >= AArch64::B16 && Reg <= AArch64::B31)) {
5530 Warning(L: IDLoc, Msg: "register " + Twine(RI->getName(RegNo: Reg)) +
5531 " is disallowed on ARM64EC.");
5532 }
5533 }
5534 }
5535 }
5536
5537 // Check for indexed addressing modes w/ the base register being the
5538 // same as a destination/source register or pair load where
5539 // the Rt == Rt2. All of those are undefined behaviour.
5540 switch (Inst.getOpcode()) {
5541 case AArch64::LDPSWpre:
5542 case AArch64::LDPWpost:
5543 case AArch64::LDPWpre:
5544 case AArch64::LDPXpost:
5545 case AArch64::LDPXpre: {
5546 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5547 MCRegister Rt2 = Inst.getOperand(i: 2).getReg();
5548 MCRegister Rn = Inst.getOperand(i: 3).getReg();
5549 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt))
5550 return Error(L: Loc[0], Msg: "unpredictable LDP instruction, writeback base "
5551 "is also a destination");
5552 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt2))
5553 return Error(L: Loc[1], Msg: "unpredictable LDP instruction, writeback base "
5554 "is also a destination");
5555 [[fallthrough]];
5556 }
5557 case AArch64::LDR_ZA:
5558 case AArch64::STR_ZA: {
5559 if (Inst.getOperand(i: 2).isImm() && Inst.getOperand(i: 4).isImm() &&
5560 Inst.getOperand(i: 2).getImm() != Inst.getOperand(i: 4).getImm())
5561 return Error(L: Loc[1],
5562 Msg: "unpredictable instruction, immediate and offset mismatch.");
5563 break;
5564 }
5565 case AArch64::LDPDi:
5566 case AArch64::LDPQi:
5567 case AArch64::LDPSi:
5568 case AArch64::LDPSWi:
5569 case AArch64::LDPWi:
5570 case AArch64::LDPXi: {
5571 MCRegister Rt = Inst.getOperand(i: 0).getReg();
5572 MCRegister Rt2 = Inst.getOperand(i: 1).getReg();
5573 if (Rt == Rt2)
5574 return Error(L: Loc[1], Msg: "unpredictable LDP instruction, Rt2==Rt");
5575 break;
5576 }
5577 case AArch64::LDPDpost:
5578 case AArch64::LDPDpre:
5579 case AArch64::LDPQpost:
5580 case AArch64::LDPQpre:
5581 case AArch64::LDPSpost:
5582 case AArch64::LDPSpre:
5583 case AArch64::LDPSWpost: {
5584 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5585 MCRegister Rt2 = Inst.getOperand(i: 2).getReg();
5586 if (Rt == Rt2)
5587 return Error(L: Loc[1], Msg: "unpredictable LDP instruction, Rt2==Rt");
5588 break;
5589 }
5590 case AArch64::STPDpost:
5591 case AArch64::STPDpre:
5592 case AArch64::STPQpost:
5593 case AArch64::STPQpre:
5594 case AArch64::STPSpost:
5595 case AArch64::STPSpre:
5596 case AArch64::STPWpost:
5597 case AArch64::STPWpre:
5598 case AArch64::STPXpost:
5599 case AArch64::STPXpre: {
5600 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5601 MCRegister Rt2 = Inst.getOperand(i: 2).getReg();
5602 MCRegister Rn = Inst.getOperand(i: 3).getReg();
5603 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt))
5604 return Error(L: Loc[0], Msg: "unpredictable STP instruction, writeback base "
5605 "is also a source");
5606 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt2))
5607 return Error(L: Loc[1], Msg: "unpredictable STP instruction, writeback base "
5608 "is also a source");
5609 break;
5610 }
5611 case AArch64::LDRBBpre:
5612 case AArch64::LDRBpre:
5613 case AArch64::LDRHHpre:
5614 case AArch64::LDRHpre:
5615 case AArch64::LDRSBWpre:
5616 case AArch64::LDRSBXpre:
5617 case AArch64::LDRSHWpre:
5618 case AArch64::LDRSHXpre:
5619 case AArch64::LDRSWpre:
5620 case AArch64::LDRWpre:
5621 case AArch64::LDRXpre:
5622 case AArch64::LDRBBpost:
5623 case AArch64::LDRBpost:
5624 case AArch64::LDRHHpost:
5625 case AArch64::LDRHpost:
5626 case AArch64::LDRSBWpost:
5627 case AArch64::LDRSBXpost:
5628 case AArch64::LDRSHWpost:
5629 case AArch64::LDRSHXpost:
5630 case AArch64::LDRSWpost:
5631 case AArch64::LDRWpost:
5632 case AArch64::LDRXpost: {
5633 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5634 MCRegister Rn = Inst.getOperand(i: 2).getReg();
5635 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt))
5636 return Error(L: Loc[0], Msg: "unpredictable LDR instruction, writeback base "
5637 "is also a source");
5638 break;
5639 }
5640 case AArch64::STRBBpost:
5641 case AArch64::STRBpost:
5642 case AArch64::STRHHpost:
5643 case AArch64::STRHpost:
5644 case AArch64::STRWpost:
5645 case AArch64::STRXpost:
5646 case AArch64::STRBBpre:
5647 case AArch64::STRBpre:
5648 case AArch64::STRHHpre:
5649 case AArch64::STRHpre:
5650 case AArch64::STRWpre:
5651 case AArch64::STRXpre: {
5652 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5653 MCRegister Rn = Inst.getOperand(i: 2).getReg();
5654 if (RI->isSubRegisterEq(RegA: Rn, RegB: Rt))
5655 return Error(L: Loc[0], Msg: "unpredictable STR instruction, writeback base "
5656 "is also a source");
5657 break;
5658 }
5659 case AArch64::STXRB:
5660 case AArch64::STXRH:
5661 case AArch64::STXRW:
5662 case AArch64::STXRX:
5663 case AArch64::STLXRB:
5664 case AArch64::STLXRH:
5665 case AArch64::STLXRW:
5666 case AArch64::STLXRX: {
5667 MCRegister Rs = Inst.getOperand(i: 0).getReg();
5668 MCRegister Rt = Inst.getOperand(i: 1).getReg();
5669 MCRegister Rn = Inst.getOperand(i: 2).getReg();
5670 if (RI->isSubRegisterEq(RegA: Rt, RegB: Rs) ||
5671 (RI->isSubRegisterEq(RegA: Rn, RegB: Rs) && Rn != AArch64::SP))
5672 return Error(L: Loc[0],
5673 Msg: "unpredictable STXR instruction, status is also a source");
5674 break;
5675 }
5676 case AArch64::STXPW:
5677 case AArch64::STXPX:
5678 case AArch64::STLXPW:
5679 case AArch64::STLXPX: {
5680 MCRegister Rs = Inst.getOperand(i: 0).getReg();
5681 MCRegister Rt1 = Inst.getOperand(i: 1).getReg();
5682 MCRegister Rt2 = Inst.getOperand(i: 2).getReg();
5683 MCRegister Rn = Inst.getOperand(i: 3).getReg();
5684 if (RI->isSubRegisterEq(RegA: Rt1, RegB: Rs) || RI->isSubRegisterEq(RegA: Rt2, RegB: Rs) ||
5685 (RI->isSubRegisterEq(RegA: Rn, RegB: Rs) && Rn != AArch64::SP))
5686 return Error(L: Loc[0],
5687 Msg: "unpredictable STXP instruction, status is also a source");
5688 break;
5689 }
5690 case AArch64::LDRABwriteback:
5691 case AArch64::LDRAAwriteback: {
5692 MCRegister Xt = Inst.getOperand(i: 0).getReg();
5693 MCRegister Xn = Inst.getOperand(i: 1).getReg();
5694 if (Xt == Xn)
5695 return Error(L: Loc[0],
5696 Msg: "unpredictable LDRA instruction, writeback base"
5697 " is also a destination");
5698 break;
5699 }
5700 }
5701
5702 // Check v8.8-A memops instructions.
5703 switch (Inst.getOpcode()) {
5704 case AArch64::CPYFP:
5705 case AArch64::CPYFPWN:
5706 case AArch64::CPYFPRN:
5707 case AArch64::CPYFPN:
5708 case AArch64::CPYFPWT:
5709 case AArch64::CPYFPWTWN:
5710 case AArch64::CPYFPWTRN:
5711 case AArch64::CPYFPWTN:
5712 case AArch64::CPYFPRT:
5713 case AArch64::CPYFPRTWN:
5714 case AArch64::CPYFPRTRN:
5715 case AArch64::CPYFPRTN:
5716 case AArch64::CPYFPT:
5717 case AArch64::CPYFPTWN:
5718 case AArch64::CPYFPTRN:
5719 case AArch64::CPYFPTN:
5720 case AArch64::CPYFM:
5721 case AArch64::CPYFMWN:
5722 case AArch64::CPYFMRN:
5723 case AArch64::CPYFMN:
5724 case AArch64::CPYFMWT:
5725 case AArch64::CPYFMWTWN:
5726 case AArch64::CPYFMWTRN:
5727 case AArch64::CPYFMWTN:
5728 case AArch64::CPYFMRT:
5729 case AArch64::CPYFMRTWN:
5730 case AArch64::CPYFMRTRN:
5731 case AArch64::CPYFMRTN:
5732 case AArch64::CPYFMT:
5733 case AArch64::CPYFMTWN:
5734 case AArch64::CPYFMTRN:
5735 case AArch64::CPYFMTN:
5736 case AArch64::CPYFE:
5737 case AArch64::CPYFEWN:
5738 case AArch64::CPYFERN:
5739 case AArch64::CPYFEN:
5740 case AArch64::CPYFEWT:
5741 case AArch64::CPYFEWTWN:
5742 case AArch64::CPYFEWTRN:
5743 case AArch64::CPYFEWTN:
5744 case AArch64::CPYFERT:
5745 case AArch64::CPYFERTWN:
5746 case AArch64::CPYFERTRN:
5747 case AArch64::CPYFERTN:
5748 case AArch64::CPYFET:
5749 case AArch64::CPYFETWN:
5750 case AArch64::CPYFETRN:
5751 case AArch64::CPYFETN:
5752 case AArch64::CPYP:
5753 case AArch64::CPYPWN:
5754 case AArch64::CPYPRN:
5755 case AArch64::CPYPN:
5756 case AArch64::CPYPWT:
5757 case AArch64::CPYPWTWN:
5758 case AArch64::CPYPWTRN:
5759 case AArch64::CPYPWTN:
5760 case AArch64::CPYPRT:
5761 case AArch64::CPYPRTWN:
5762 case AArch64::CPYPRTRN:
5763 case AArch64::CPYPRTN:
5764 case AArch64::CPYPT:
5765 case AArch64::CPYPTWN:
5766 case AArch64::CPYPTRN:
5767 case AArch64::CPYPTN:
5768 case AArch64::CPYM:
5769 case AArch64::CPYMWN:
5770 case AArch64::CPYMRN:
5771 case AArch64::CPYMN:
5772 case AArch64::CPYMWT:
5773 case AArch64::CPYMWTWN:
5774 case AArch64::CPYMWTRN:
5775 case AArch64::CPYMWTN:
5776 case AArch64::CPYMRT:
5777 case AArch64::CPYMRTWN:
5778 case AArch64::CPYMRTRN:
5779 case AArch64::CPYMRTN:
5780 case AArch64::CPYMT:
5781 case AArch64::CPYMTWN:
5782 case AArch64::CPYMTRN:
5783 case AArch64::CPYMTN:
5784 case AArch64::CPYE:
5785 case AArch64::CPYEWN:
5786 case AArch64::CPYERN:
5787 case AArch64::CPYEN:
5788 case AArch64::CPYEWT:
5789 case AArch64::CPYEWTWN:
5790 case AArch64::CPYEWTRN:
5791 case AArch64::CPYEWTN:
5792 case AArch64::CPYERT:
5793 case AArch64::CPYERTWN:
5794 case AArch64::CPYERTRN:
5795 case AArch64::CPYERTN:
5796 case AArch64::CPYET:
5797 case AArch64::CPYETWN:
5798 case AArch64::CPYETRN:
5799 case AArch64::CPYETN: {
5800 // Xd_wb == op0, Xs_wb == op1, Xn_wb == op2
5801 MCRegister Xd = Inst.getOperand(i: 3).getReg();
5802 MCRegister Xs = Inst.getOperand(i: 4).getReg();
5803 MCRegister Xn = Inst.getOperand(i: 5).getReg();
5804
5805 assert(Xd == Inst.getOperand(0).getReg() && "Xd_wb and Xd do not match");
5806 assert(Xs == Inst.getOperand(1).getReg() && "Xs_wb and Xs do not match");
5807 assert(Xn == Inst.getOperand(2).getReg() && "Xn_wb and Xn do not match");
5808
5809 if (Xd == Xs)
5810 return Error(L: Loc[0], Msg: "invalid CPY instruction, destination and source"
5811 " registers are the same");
5812 if (Xd == Xn)
5813 return Error(L: Loc[0], Msg: "invalid CPY instruction, destination and size"
5814 " registers are the same");
5815 if (Xs == Xn)
5816 return Error(L: Loc[0], Msg: "invalid CPY instruction, source and size"
5817 " registers are the same");
5818 break;
5819 }
5820 case AArch64::SETP:
5821 case AArch64::SETPT:
5822 case AArch64::SETPN:
5823 case AArch64::SETPTN:
5824 case AArch64::SETM:
5825 case AArch64::SETMT:
5826 case AArch64::SETMN:
5827 case AArch64::SETMTN:
5828 case AArch64::SETE:
5829 case AArch64::SETET:
5830 case AArch64::SETEN:
5831 case AArch64::SETETN:
5832 case AArch64::SETGP:
5833 case AArch64::SETGPT:
5834 case AArch64::SETGPN:
5835 case AArch64::SETGPTN:
5836 case AArch64::SETGM:
5837 case AArch64::SETGMT:
5838 case AArch64::SETGMN:
5839 case AArch64::SETGMTN:
5840 case AArch64::MOPSSETGE:
5841 case AArch64::MOPSSETGET:
5842 case AArch64::MOPSSETGEN:
5843 case AArch64::MOPSSETGETN: {
5844 // Xd_wb == op0, Xn_wb == op1
5845 MCRegister Xd = Inst.getOperand(i: 2).getReg();
5846 MCRegister Xn = Inst.getOperand(i: 3).getReg();
5847 MCRegister Xm = Inst.getOperand(i: 4).getReg();
5848
5849 assert(Xd == Inst.getOperand(0).getReg() && "Xd_wb and Xd do not match");
5850 assert(Xn == Inst.getOperand(1).getReg() && "Xn_wb and Xn do not match");
5851
5852 if (Xd == Xn)
5853 return Error(L: Loc[0], Msg: "invalid SET instruction, destination and size"
5854 " registers are the same");
5855 if (Xd == Xm)
5856 return Error(L: Loc[0], Msg: "invalid SET instruction, destination and source"
5857 " registers are the same");
5858 if (Xn == Xm)
5859 return Error(L: Loc[0], Msg: "invalid SET instruction, source and size"
5860 " registers are the same");
5861 break;
5862 }
5863 case AArch64::SETGOP:
5864 case AArch64::SETGOPT:
5865 case AArch64::SETGOPN:
5866 case AArch64::SETGOPTN:
5867 case AArch64::SETGOM:
5868 case AArch64::SETGOMT:
5869 case AArch64::SETGOMN:
5870 case AArch64::SETGOMTN:
5871 case AArch64::SETGOE:
5872 case AArch64::SETGOET:
5873 case AArch64::SETGOEN:
5874 case AArch64::SETGOETN: {
5875 // Xd_wb == op0, Xn_wb == op1
5876 MCRegister Xd = Inst.getOperand(i: 2).getReg();
5877 MCRegister Xn = Inst.getOperand(i: 3).getReg();
5878
5879 assert(Xd == Inst.getOperand(0).getReg() && "Xd_wb and Xd do not match");
5880 assert(Xn == Inst.getOperand(1).getReg() && "Xn_wb and Xn do not match");
5881
5882 if (Xd == Xn)
5883 return Error(L: Loc[0], Msg: "invalid SET instruction, destination and size"
5884 " registers are the same");
5885 break;
5886 }
5887 }
5888
5889 // Now check immediate ranges. Separate from the above as there is overlap
5890 // in the instructions being checked and this keeps the nested conditionals
5891 // to a minimum.
5892 switch (Inst.getOpcode()) {
5893 case AArch64::ADDSWri:
5894 case AArch64::ADDSXri:
5895 case AArch64::ADDWri:
5896 case AArch64::ADDXri:
5897 case AArch64::SUBSWri:
5898 case AArch64::SUBSXri:
5899 case AArch64::SUBWri:
5900 case AArch64::SUBXri: {
5901 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
5902 // some slight duplication here.
5903 if (Inst.getOperand(i: 2).isExpr()) {
5904 const MCExpr *Expr = Inst.getOperand(i: 2).getExpr();
5905 AArch64::Specifier ELFSpec;
5906 AArch64::Specifier DarwinSpec;
5907 int64_t Addend;
5908 if (classifySymbolRef(Expr, ELFSpec, DarwinSpec, Addend)) {
5909
5910 // Only allow these with ADDXri.
5911 if ((DarwinSpec == AArch64::S_MACHO_PAGEOFF ||
5912 DarwinSpec == AArch64::S_MACHO_TLVPPAGEOFF) &&
5913 Inst.getOpcode() == AArch64::ADDXri)
5914 return false;
5915
5916 // Only allow these with ADDXri/ADDWri
5917 if (llvm::is_contained(
5918 Set: {AArch64::S_LO12, AArch64::S_GOT_AUTH_LO12,
5919 AArch64::S_DTPREL_HI12, AArch64::S_DTPREL_LO12,
5920 AArch64::S_DTPREL_LO12_NC, AArch64::S_TPREL_HI12,
5921 AArch64::S_TPREL_LO12, AArch64::S_TPREL_LO12_NC,
5922 AArch64::S_TLSDESC_LO12, AArch64::S_TLSDESC_AUTH_LO12,
5923 AArch64::S_SECREL_LO12, AArch64::S_SECREL_HI12},
5924 Element: ELFSpec) &&
5925 (Inst.getOpcode() == AArch64::ADDXri ||
5926 Inst.getOpcode() == AArch64::ADDWri))
5927 return false;
5928
5929 // Don't allow symbol refs in the immediate field otherwise
5930 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
5931 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
5932 // 'cmp w0, 'borked')
5933 return Error(L: Loc.back(), Msg: "invalid immediate expression");
5934 }
5935 // We don't validate more complex expressions here
5936 }
5937 return false;
5938 }
5939 default:
5940 return false;
5941 }
5942}
5943
5944static std::string AArch64MnemonicSpellCheck(StringRef S,
5945 const FeatureBitset &FBS,
5946 unsigned VariantID = 0);
5947
5948bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
5949 uint64_t ErrorInfo,
5950 OperandVector &Operands) {
5951 switch (ErrCode) {
5952 case Match_InvalidTiedOperand: {
5953 auto &Op = static_cast<const AArch64Operand &>(*Operands[ErrorInfo]);
5954 if (Op.isVectorList())
5955 return Error(L: Loc, Msg: "operand must match destination register list");
5956
5957 assert(Op.isReg() && "Unexpected operand type");
5958 switch (Op.getRegEqualityTy()) {
5959 case RegConstraintEqualityTy::EqualsSubReg:
5960 return Error(L: Loc, Msg: "operand must be 64-bit form of destination register");
5961 case RegConstraintEqualityTy::EqualsSuperReg:
5962 return Error(L: Loc, Msg: "operand must be 32-bit form of destination register");
5963 case RegConstraintEqualityTy::EqualsReg:
5964 return Error(L: Loc, Msg: "operand must match destination register");
5965 }
5966 llvm_unreachable("Unknown RegConstraintEqualityTy");
5967 }
5968 case Match_MissingFeature:
5969 return Error(L: Loc,
5970 Msg: "instruction requires a CPU feature not currently enabled");
5971 case Match_InvalidOperand:
5972 return Error(L: Loc, Msg: "invalid operand for instruction");
5973 case Match_InvalidSuffix:
5974 return Error(L: Loc, Msg: "invalid type suffix for instruction");
5975 case Match_InvalidCondCode:
5976 return Error(L: Loc, Msg: "expected AArch64 condition code");
5977 case Match_AddSubRegExtendSmall:
5978 return Error(L: Loc,
5979 Msg: "expected '[su]xt[bhw]' with optional integer in range [0, 4]");
5980 case Match_AddSubRegExtendLarge:
5981 return Error(L: Loc,
5982 Msg: "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
5983 case Match_AddSubSecondSource:
5984 return Error(L: Loc,
5985 Msg: "expected compatible register, symbol or integer in range [0, 4095]");
5986 case Match_LogicalSecondSource:
5987 return Error(L: Loc, Msg: "expected compatible register or logical immediate");
5988 case Match_InvalidMovImm32Shift:
5989 return Error(L: Loc, Msg: "expected 'lsl' with optional integer 0 or 16");
5990 case Match_InvalidMovImm64Shift:
5991 return Error(L: Loc, Msg: "expected 'lsl' with optional integer 0, 16, 32 or 48");
5992 case Match_AddSubRegShift32:
5993 return Error(L: Loc,
5994 Msg: "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
5995 case Match_AddSubRegShift64:
5996 return Error(L: Loc,
5997 Msg: "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
5998 case Match_InvalidFPImm:
5999 return Error(L: Loc,
6000 Msg: "expected compatible register or floating-point constant");
6001 case Match_InvalidMemoryIndexedSImm6:
6002 return Error(L: Loc, Msg: "index must be an integer in range [-32, 31].");
6003 case Match_InvalidMemoryIndexedSImm5:
6004 return Error(L: Loc, Msg: "index must be an integer in range [-16, 15].");
6005 case Match_InvalidMemoryIndexed1SImm4:
6006 return Error(L: Loc, Msg: "index must be an integer in range [-8, 7].");
6007 case Match_InvalidMemoryIndexed2SImm4:
6008 return Error(L: Loc, Msg: "index must be a multiple of 2 in range [-16, 14].");
6009 case Match_InvalidMemoryIndexed3SImm4:
6010 return Error(L: Loc, Msg: "index must be a multiple of 3 in range [-24, 21].");
6011 case Match_InvalidMemoryIndexed4SImm4:
6012 return Error(L: Loc, Msg: "index must be a multiple of 4 in range [-32, 28].");
6013 case Match_InvalidMemoryIndexed16SImm4:
6014 return Error(L: Loc, Msg: "index must be a multiple of 16 in range [-128, 112].");
6015 case Match_InvalidMemoryIndexed32SImm4:
6016 return Error(L: Loc, Msg: "index must be a multiple of 32 in range [-256, 224].");
6017 case Match_InvalidMemoryIndexed1SImm6:
6018 return Error(L: Loc, Msg: "index must be an integer in range [-32, 31].");
6019 case Match_InvalidMemoryIndexedSImm8:
6020 return Error(L: Loc, Msg: "index must be an integer in range [-128, 127].");
6021 case Match_InvalidMemoryIndexedSImm9:
6022 return Error(L: Loc, Msg: "index must be an integer in range [-256, 255].");
6023 case Match_InvalidMemoryIndexed16SImm9:
6024 return Error(L: Loc, Msg: "index must be a multiple of 16 in range [-4096, 4080].");
6025 case Match_InvalidMemoryIndexed8SImm10:
6026 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [-4096, 4088].");
6027 case Match_InvalidMemoryIndexed4SImm7:
6028 return Error(L: Loc, Msg: "index must be a multiple of 4 in range [-256, 252].");
6029 case Match_InvalidMemoryIndexed8SImm7:
6030 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [-512, 504].");
6031 case Match_InvalidMemoryIndexed16SImm7:
6032 return Error(L: Loc, Msg: "index must be a multiple of 16 in range [-1024, 1008].");
6033 case Match_InvalidMemoryIndexed8UImm5:
6034 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [0, 248].");
6035 case Match_InvalidMemoryIndexed8UImm3:
6036 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [0, 56].");
6037 case Match_InvalidMemoryIndexed4UImm5:
6038 return Error(L: Loc, Msg: "index must be a multiple of 4 in range [0, 124].");
6039 case Match_InvalidMemoryIndexed2UImm5:
6040 return Error(L: Loc, Msg: "index must be a multiple of 2 in range [0, 62].");
6041 case Match_InvalidMemoryIndexed8UImm6:
6042 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [0, 504].");
6043 case Match_InvalidMemoryIndexed16UImm6:
6044 return Error(L: Loc, Msg: "index must be a multiple of 16 in range [0, 1008].");
6045 case Match_InvalidMemoryIndexed32UImm8:
6046 return Error(L: Loc, Msg: "index must be a multiple of 32 in range [0, 8160].");
6047 case Match_InvalidMemoryIndexed4UImm6:
6048 return Error(L: Loc, Msg: "index must be a multiple of 4 in range [0, 252].");
6049 case Match_InvalidMemoryIndexed2UImm6:
6050 return Error(L: Loc, Msg: "index must be a multiple of 2 in range [0, 126].");
6051 case Match_InvalidMemoryIndexed1UImm6:
6052 return Error(L: Loc, Msg: "index must be in range [0, 63].");
6053 case Match_InvalidMemoryWExtend8:
6054 return Error(L: Loc,
6055 Msg: "expected 'uxtw' or 'sxtw' with optional shift of #0");
6056 case Match_InvalidMemoryWExtend16:
6057 return Error(L: Loc,
6058 Msg: "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
6059 case Match_InvalidMemoryWExtend32:
6060 return Error(L: Loc,
6061 Msg: "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
6062 case Match_InvalidMemoryWExtend64:
6063 return Error(L: Loc,
6064 Msg: "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
6065 case Match_InvalidMemoryWExtend128:
6066 return Error(L: Loc,
6067 Msg: "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
6068 case Match_InvalidMemoryXExtend8:
6069 return Error(L: Loc,
6070 Msg: "expected 'lsl' or 'sxtx' with optional shift of #0");
6071 case Match_InvalidMemoryXExtend16:
6072 return Error(L: Loc,
6073 Msg: "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
6074 case Match_InvalidMemoryXExtend32:
6075 return Error(L: Loc,
6076 Msg: "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
6077 case Match_InvalidMemoryXExtend64:
6078 return Error(L: Loc,
6079 Msg: "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
6080 case Match_InvalidMemoryXExtend128:
6081 return Error(L: Loc,
6082 Msg: "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
6083 case Match_InvalidMemoryIndexed1:
6084 return Error(L: Loc, Msg: "index must be an integer in range [0, 4095].");
6085 case Match_InvalidMemoryIndexed2:
6086 return Error(L: Loc, Msg: "index must be a multiple of 2 in range [0, 8190].");
6087 case Match_InvalidMemoryIndexed4:
6088 return Error(L: Loc, Msg: "index must be a multiple of 4 in range [0, 16380].");
6089 case Match_InvalidMemoryIndexed8:
6090 return Error(L: Loc, Msg: "index must be a multiple of 8 in range [0, 32760].");
6091 case Match_InvalidMemoryIndexed16:
6092 return Error(L: Loc, Msg: "index must be a multiple of 16 in range [0, 65520].");
6093 case Match_InvalidImm0_0:
6094 return Error(L: Loc, Msg: "immediate must be 0.");
6095 case Match_InvalidImm0_1:
6096 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 1].");
6097 case Match_InvalidImm0_3:
6098 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 3].");
6099 case Match_InvalidImm0_7:
6100 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 7].");
6101 case Match_InvalidImm0_15:
6102 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 15].");
6103 case Match_InvalidImm0_31:
6104 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 31].");
6105 case Match_InvalidImm0_63:
6106 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 63].");
6107 case Match_InvalidImm0_127:
6108 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 127].");
6109 case Match_InvalidImm0_255:
6110 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 255].");
6111 case Match_InvalidImm0_511:
6112 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 511].");
6113 case Match_InvalidImm0_65535:
6114 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 65535].");
6115 case Match_InvalidHinteUImm16:
6116 return Error(L: Loc,
6117 Msg: "immediate must be an integer in range [0, 65535], excluding "
6118 "values in range [12319, 16383] where (value - 12319) is a "
6119 "multiple of 32.");
6120 case Match_InvalidImm1_8:
6121 return Error(L: Loc, Msg: "immediate must be an integer in range [1, 8].");
6122 case Match_InvalidImm1_16:
6123 return Error(L: Loc, Msg: "immediate must be an integer in range [1, 16].");
6124 case Match_InvalidImm1_32:
6125 return Error(L: Loc, Msg: "immediate must be an integer in range [1, 32].");
6126 case Match_InvalidImm1_64:
6127 return Error(L: Loc, Msg: "immediate must be an integer in range [1, 64].");
6128 case Match_InvalidImm1_512:
6129 return Error(L: Loc, Msg: "immediate must be an integer in range [1, 512].");
6130 case Match_InvalidImmM1_62:
6131 return Error(L: Loc, Msg: "immediate must be an integer in range [-1, 62].");
6132 case Match_InvalidImmM1_510:
6133 return Error(L: Loc, Msg: "immediate must be an integer in range [-1, 510].");
6134 case Match_InvalidImmM255_256:
6135 return Error(L: Loc, Msg: "immediate must be an integer in range [-255, 256].");
6136 case Match_InvalidImmM257_254:
6137 return Error(L: Loc, Msg: "immediate must be an integer in range [-257, 254].");
6138 case Match_InvalidMemoryIndexedRange2UImm0:
6139 return Error(L: Loc, Msg: "vector select offset must be the immediate range 0:1.");
6140 case Match_InvalidMemoryIndexedRange2UImm1:
6141 return Error(L: Loc, Msg: "vector select offset must be an immediate range of the "
6142 "form <immf>:<imml>, where the first "
6143 "immediate is a multiple of 2 in the range [0, 2], and "
6144 "the second immediate is immf + 1.");
6145 case Match_InvalidMemoryIndexedRange2UImm2:
6146 case Match_InvalidMemoryIndexedRange2UImm3:
6147 return Error(
6148 L: Loc,
6149 Msg: "vector select offset must be an immediate range of the form "
6150 "<immf>:<imml>, "
6151 "where the first immediate is a multiple of 2 in the range [0, 6] or "
6152 "[0, 14] "
6153 "depending on the instruction, and the second immediate is immf + 1.");
6154 case Match_InvalidMemoryIndexedRange4UImm0:
6155 return Error(L: Loc, Msg: "vector select offset must be the immediate range 0:3.");
6156 case Match_InvalidMemoryIndexedRange4UImm1:
6157 case Match_InvalidMemoryIndexedRange4UImm2:
6158 return Error(
6159 L: Loc,
6160 Msg: "vector select offset must be an immediate range of the form "
6161 "<immf>:<imml>, "
6162 "where the first immediate is a multiple of 4 in the range [0, 4] or "
6163 "[0, 12] "
6164 "depending on the instruction, and the second immediate is immf + 3.");
6165 case Match_InvalidSVEAddSubImm8:
6166 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 255]"
6167 " with a shift amount of 0");
6168 case Match_InvalidSVEAddSubImm16:
6169 case Match_InvalidSVEAddSubImm32:
6170 case Match_InvalidSVEAddSubImm64:
6171 return Error(L: Loc, Msg: "immediate must be an integer in range [0, 255] or a "
6172 "multiple of 256 in range [256, 65280]");
6173 case Match_InvalidSVECpyImm8:
6174 return Error(L: Loc, Msg: "immediate must be an integer in range [-128, 255]"
6175 " with a shift amount of 0");
6176 case Match_InvalidSVECpyImm16:
6177 return Error(L: Loc, Msg: "immediate must be an integer in range [-128, 127] or a "
6178 "multiple of 256 in range [-32768, 65280]");
6179 case Match_InvalidSVECpyImm32:
6180 case Match_InvalidSVECpyImm64:
6181 return Error(L: Loc, Msg: "immediate must be an integer in range [-128, 127] or a "
6182 "multiple of 256 in range [-32768, 32512]");
6183 case Match_InvalidIndexRange0_0:
6184 return Error(L: Loc, Msg: "expected lane specifier '[0]'");
6185 case Match_InvalidIndexRange1_1:
6186 return Error(L: Loc, Msg: "expected lane specifier '[1]'");
6187 case Match_InvalidIndexRange0_15:
6188 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 15].");
6189 case Match_InvalidIndexRange0_7:
6190 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 7].");
6191 case Match_InvalidIndexRange0_3:
6192 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 3].");
6193 case Match_InvalidIndexRange0_1:
6194 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 1].");
6195 case Match_InvalidSVEIndexRange0_63:
6196 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 63].");
6197 case Match_InvalidSVEIndexRange0_31:
6198 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 31].");
6199 case Match_InvalidSVEIndexRange0_15:
6200 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 15].");
6201 case Match_InvalidSVEIndexRange0_7:
6202 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 7].");
6203 case Match_InvalidSVEIndexRange0_3:
6204 return Error(L: Loc, Msg: "vector lane must be an integer in range [0, 3].");
6205 case Match_InvalidLabel:
6206 return Error(L: Loc, Msg: "expected label or encodable integer pc offset");
6207 case Match_MRS:
6208 return Error(L: Loc, Msg: "expected readable system register");
6209 case Match_MSR:
6210 case Match_InvalidSVCR:
6211 return Error(L: Loc, Msg: "expected writable system register or pstate");
6212 case Match_InvalidComplexRotationEven:
6213 return Error(L: Loc, Msg: "complex rotation must be 0, 90, 180 or 270.");
6214 case Match_InvalidComplexRotationOdd:
6215 return Error(L: Loc, Msg: "complex rotation must be 90 or 270.");
6216 case Match_MnemonicFail: {
6217 std::string Suggestion = AArch64MnemonicSpellCheck(
6218 S: ((AArch64Operand &)*Operands[0]).getToken(),
6219 FBS: ComputeAvailableFeatures(FB: STI->getFeatureBits()));
6220 return Error(L: Loc, Msg: "unrecognized instruction mnemonic" + Suggestion);
6221 }
6222 case Match_InvalidGPR64shifted8:
6223 return Error(L: Loc, Msg: "register must be x0..x30 or xzr, without shift");
6224 case Match_InvalidGPR64shifted16:
6225 return Error(L: Loc, Msg: "register must be x0..x30 or xzr, with required shift 'lsl #1'");
6226 case Match_InvalidGPR64shifted32:
6227 return Error(L: Loc, Msg: "register must be x0..x30 or xzr, with required shift 'lsl #2'");
6228 case Match_InvalidGPR64shifted64:
6229 return Error(L: Loc, Msg: "register must be x0..x30 or xzr, with required shift 'lsl #3'");
6230 case Match_InvalidGPR64shifted128:
6231 return Error(
6232 L: Loc, Msg: "register must be x0..x30 or xzr, with required shift 'lsl #4'");
6233 case Match_InvalidGPR64NoXZRshifted8:
6234 return Error(L: Loc, Msg: "register must be x0..x30 without shift");
6235 case Match_InvalidGPR64NoXZRshifted16:
6236 return Error(L: Loc, Msg: "register must be x0..x30 with required shift 'lsl #1'");
6237 case Match_InvalidGPR64NoXZRshifted32:
6238 return Error(L: Loc, Msg: "register must be x0..x30 with required shift 'lsl #2'");
6239 case Match_InvalidGPR64NoXZRshifted64:
6240 return Error(L: Loc, Msg: "register must be x0..x30 with required shift 'lsl #3'");
6241 case Match_InvalidGPR64NoXZRshifted128:
6242 return Error(L: Loc, Msg: "register must be x0..x30 with required shift 'lsl #4'");
6243 case Match_InvalidZPR32UXTW8:
6244 case Match_InvalidZPR32SXTW8:
6245 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
6246 case Match_InvalidZPR32UXTW16:
6247 case Match_InvalidZPR32SXTW16:
6248 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
6249 case Match_InvalidZPR32UXTW32:
6250 case Match_InvalidZPR32SXTW32:
6251 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
6252 case Match_InvalidZPR32UXTW64:
6253 case Match_InvalidZPR32SXTW64:
6254 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
6255 case Match_InvalidZPR64UXTW8:
6256 case Match_InvalidZPR64SXTW8:
6257 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
6258 case Match_InvalidZPR64UXTW16:
6259 case Match_InvalidZPR64SXTW16:
6260 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
6261 case Match_InvalidZPR64UXTW32:
6262 case Match_InvalidZPR64SXTW32:
6263 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
6264 case Match_InvalidZPR64UXTW64:
6265 case Match_InvalidZPR64SXTW64:
6266 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
6267 case Match_InvalidZPR32LSL8:
6268 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s'");
6269 case Match_InvalidZPR32LSL16:
6270 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
6271 case Match_InvalidZPR32LSL32:
6272 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
6273 case Match_InvalidZPR32LSL64:
6274 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
6275 case Match_InvalidZPR64LSL8:
6276 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d'");
6277 case Match_InvalidZPR64LSL16:
6278 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
6279 case Match_InvalidZPR64LSL32:
6280 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
6281 case Match_InvalidZPR64LSL64:
6282 return Error(L: Loc, Msg: "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
6283 case Match_InvalidZPR0:
6284 return Error(L: Loc, Msg: "expected register without element width suffix");
6285 case Match_InvalidZPR8:
6286 case Match_InvalidZPR16:
6287 case Match_InvalidZPR32:
6288 case Match_InvalidZPR64:
6289 case Match_InvalidZPR128:
6290 return Error(L: Loc, Msg: "invalid element width");
6291 case Match_InvalidZPR_3b8:
6292 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.b..z7.b");
6293 case Match_InvalidZPR_3b16:
6294 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.h..z7.h");
6295 case Match_InvalidZPR_3b32:
6296 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.s..z7.s");
6297 case Match_InvalidZPR_4b8:
6298 return Error(L: Loc,
6299 Msg: "Invalid restricted vector register, expected z0.b..z15.b");
6300 case Match_InvalidZPR_4b16:
6301 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.h..z15.h");
6302 case Match_InvalidZPR_4b32:
6303 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.s..z15.s");
6304 case Match_InvalidZPR_4b64:
6305 return Error(L: Loc, Msg: "Invalid restricted vector register, expected z0.d..z15.d");
6306 case Match_InvalidZPRMul2_Lo8:
6307 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6308 "register in z0.b..z14.b");
6309 case Match_InvalidZPRMul2_Hi8:
6310 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6311 "register in z16.b..z30.b");
6312 case Match_InvalidZPRMul2_Lo16:
6313 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6314 "register in z0.h..z14.h");
6315 case Match_InvalidZPRMul2_Hi16:
6316 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6317 "register in z16.h..z30.h");
6318 case Match_InvalidZPRMul2_Lo32:
6319 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6320 "register in z0.s..z14.s");
6321 case Match_InvalidZPRMul2_Hi32:
6322 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6323 "register in z16.s..z30.s");
6324 case Match_InvalidZPRMul2_Lo64:
6325 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6326 "register in z0.d..z14.d");
6327 case Match_InvalidZPRMul2_Hi64:
6328 return Error(L: Loc, Msg: "Invalid restricted vector register, expected even "
6329 "register in z16.d..z30.d");
6330 case Match_InvalidZPR_K0:
6331 return Error(L: Loc, Msg: "invalid restricted vector register, expected register "
6332 "in z20..z23 or z28..z31");
6333 case Match_InvalidSVEPattern:
6334 return Error(L: Loc, Msg: "invalid predicate pattern");
6335 case Match_InvalidSVEPPRorPNRAnyReg:
6336 case Match_InvalidSVEPPRorPNRBReg:
6337 case Match_InvalidSVEPredicateAnyReg:
6338 case Match_InvalidSVEPredicateBReg:
6339 case Match_InvalidSVEPredicateHReg:
6340 case Match_InvalidSVEPredicateSReg:
6341 case Match_InvalidSVEPredicateDReg:
6342 return Error(L: Loc, Msg: "invalid predicate register.");
6343 case Match_InvalidSVEPredicate3bAnyReg:
6344 return Error(L: Loc, Msg: "invalid restricted predicate register, expected p0..p7 (without element suffix)");
6345 case Match_InvalidSVEPNPredicateB_p8to15Reg:
6346 case Match_InvalidSVEPNPredicateH_p8to15Reg:
6347 case Match_InvalidSVEPNPredicateS_p8to15Reg:
6348 case Match_InvalidSVEPNPredicateD_p8to15Reg:
6349 return Error(L: Loc, Msg: "Invalid predicate register, expected PN in range "
6350 "pn8..pn15 with element suffix.");
6351 case Match_InvalidSVEPNPredicateAny_p8to15Reg:
6352 return Error(L: Loc, Msg: "invalid restricted predicate-as-counter register "
6353 "expected pn8..pn15");
6354 case Match_InvalidSVEPNPredicateBReg:
6355 case Match_InvalidSVEPNPredicateHReg:
6356 case Match_InvalidSVEPNPredicateSReg:
6357 case Match_InvalidSVEPNPredicateDReg:
6358 return Error(L: Loc, Msg: "Invalid predicate register, expected PN in range "
6359 "pn0..pn15 with element suffix.");
6360 case Match_InvalidSVEVecLenSpecifier:
6361 return Error(L: Loc, Msg: "Invalid vector length specifier, expected VLx2 or VLx4");
6362 case Match_InvalidSVEPredicateListMul2x8:
6363 case Match_InvalidSVEPredicateListMul2x16:
6364 case Match_InvalidSVEPredicateListMul2x32:
6365 case Match_InvalidSVEPredicateListMul2x64:
6366 return Error(L: Loc, Msg: "Invalid vector list, expected list with 2 consecutive "
6367 "predicate registers, where the first vector is a multiple of 2 "
6368 "and with correct element type");
6369 case Match_InvalidSVEExactFPImmOperandHalfOne:
6370 return Error(L: Loc, Msg: "Invalid floating point constant, expected 0.5 or 1.0.");
6371 case Match_InvalidSVEExactFPImmOperandHalfTwo:
6372 return Error(L: Loc, Msg: "Invalid floating point constant, expected 0.5 or 2.0.");
6373 case Match_InvalidSVEExactFPImmOperandZeroOne:
6374 return Error(L: Loc, Msg: "Invalid floating point constant, expected 0.0 or 1.0.");
6375 case Match_InvalidMatrixTileVectorH8:
6376 case Match_InvalidMatrixTileVectorV8:
6377 return Error(L: Loc, Msg: "invalid matrix operand, expected za0h.b or za0v.b");
6378 case Match_InvalidMatrixTileVectorH16:
6379 case Match_InvalidMatrixTileVectorV16:
6380 return Error(L: Loc,
6381 Msg: "invalid matrix operand, expected za[0-1]h.h or za[0-1]v.h");
6382 case Match_InvalidMatrixTileVectorH32:
6383 case Match_InvalidMatrixTileVectorV32:
6384 return Error(L: Loc,
6385 Msg: "invalid matrix operand, expected za[0-3]h.s or za[0-3]v.s");
6386 case Match_InvalidMatrixTileVectorH64:
6387 case Match_InvalidMatrixTileVectorV64:
6388 return Error(L: Loc,
6389 Msg: "invalid matrix operand, expected za[0-7]h.d or za[0-7]v.d");
6390 case Match_InvalidMatrixTileVectorH128:
6391 case Match_InvalidMatrixTileVectorV128:
6392 return Error(L: Loc,
6393 Msg: "invalid matrix operand, expected za[0-15]h.q or za[0-15]v.q");
6394 case Match_InvalidMatrixTile16:
6395 return Error(L: Loc, Msg: "invalid matrix operand, expected za[0-1].h");
6396 case Match_InvalidMatrixTile32:
6397 return Error(L: Loc, Msg: "invalid matrix operand, expected za[0-3].s");
6398 case Match_InvalidMatrixTile64:
6399 return Error(L: Loc, Msg: "invalid matrix operand, expected za[0-7].d");
6400 case Match_InvalidMatrix:
6401 return Error(L: Loc, Msg: "invalid matrix operand, expected za");
6402 case Match_InvalidMatrix8:
6403 return Error(L: Loc, Msg: "invalid matrix operand, expected suffix .b");
6404 case Match_InvalidMatrix16:
6405 return Error(L: Loc, Msg: "invalid matrix operand, expected suffix .h");
6406 case Match_InvalidMatrix32:
6407 return Error(L: Loc, Msg: "invalid matrix operand, expected suffix .s");
6408 case Match_InvalidMatrix64:
6409 return Error(L: Loc, Msg: "invalid matrix operand, expected suffix .d");
6410 case Match_InvalidMatrixIndexGPR32_12_15:
6411 return Error(L: Loc, Msg: "operand must be a register in range [w12, w15]");
6412 case Match_InvalidMatrixIndexGPR32_8_11:
6413 return Error(L: Loc, Msg: "operand must be a register in range [w8, w11]");
6414 case Match_InvalidSVEVectorList2x8Mul2:
6415 case Match_InvalidSVEVectorList2x16Mul2:
6416 case Match_InvalidSVEVectorList2x32Mul2:
6417 case Match_InvalidSVEVectorList2x64Mul2:
6418 case Match_InvalidSVEVectorList2x128Mul2:
6419 return Error(L: Loc, Msg: "Invalid vector list, expected list with 2 consecutive "
6420 "SVE vectors, where the first vector is a multiple of 2 "
6421 "and with matching element types");
6422 case Match_InvalidSVEVectorList2x8Mul2_Lo:
6423 case Match_InvalidSVEVectorList2x16Mul2_Lo:
6424 case Match_InvalidSVEVectorList2x32Mul2_Lo:
6425 case Match_InvalidSVEVectorList2x64Mul2_Lo:
6426 return Error(L: Loc, Msg: "Invalid vector list, expected list with 2 consecutive "
6427 "SVE vectors in the range z0-z14, where the first vector "
6428 "is a multiple of 2 "
6429 "and with matching element types");
6430 case Match_InvalidSVEVectorList2x8Mul2_Hi:
6431 case Match_InvalidSVEVectorList2x16Mul2_Hi:
6432 case Match_InvalidSVEVectorList2x32Mul2_Hi:
6433 case Match_InvalidSVEVectorList2x64Mul2_Hi:
6434 return Error(L: Loc,
6435 Msg: "Invalid vector list, expected list with 2 consecutive "
6436 "SVE vectors in the range z16-z30, where the first vector "
6437 "is a multiple of 2 "
6438 "and with matching element types");
6439 case Match_InvalidSVEVectorList4x8Mul4:
6440 case Match_InvalidSVEVectorList4x16Mul4:
6441 case Match_InvalidSVEVectorList4x32Mul4:
6442 case Match_InvalidSVEVectorList4x64Mul4:
6443 case Match_InvalidSVEVectorList4x128Mul4:
6444 return Error(L: Loc, Msg: "Invalid vector list, expected list with 4 consecutive "
6445 "SVE vectors, where the first vector is a multiple of 4 "
6446 "and with matching element types");
6447 case Match_InvalidSVEVectorList3x0_3b:
6448 return Error(L: Loc, Msg: "Invalid vector list, expected list with 3 consecutive "
6449 "SVE vectors starting at z0-z7");
6450 case Match_InvalidLookupTable:
6451 return Error(L: Loc, Msg: "Invalid lookup table, expected zt0");
6452 case Match_InvalidSVEVectorListStrided2x8:
6453 case Match_InvalidSVEVectorListStrided2x16:
6454 case Match_InvalidSVEVectorListStrided2x32:
6455 case Match_InvalidSVEVectorListStrided2x64:
6456 return Error(
6457 L: Loc,
6458 Msg: "Invalid vector list, expected list with each SVE vector in the list "
6459 "8 registers apart, and the first register in the range [z0, z7] or "
6460 "[z16, z23] and with correct element type");
6461 case Match_InvalidSVEVectorListStrided4x8:
6462 case Match_InvalidSVEVectorListStrided4x16:
6463 case Match_InvalidSVEVectorListStrided4x32:
6464 case Match_InvalidSVEVectorListStrided4x64:
6465 return Error(
6466 L: Loc,
6467 Msg: "Invalid vector list, expected list with each SVE vector in the list "
6468 "4 registers apart, and the first register in the range [z0, z3] or "
6469 "[z16, z19] and with correct element type");
6470 case Match_AddSubLSLImm3ShiftLarge:
6471 return Error(L: Loc,
6472 Msg: "expected 'lsl' with optional integer in range [0, 7]");
6473 default:
6474 llvm_unreachable("unexpected error code!");
6475 }
6476}
6477
6478static const char *getSubtargetFeatureName(uint64_t Val);
6479
6480bool AArch64AsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
6481 OperandVector &Operands,
6482 MCStreamer &Out,
6483 uint64_t &ErrorInfo,
6484 bool MatchingInlineAsm) {
6485 assert(!Operands.empty() && "Unexpected empty operand list!");
6486 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
6487 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
6488
6489 StringRef Tok = Op.getToken();
6490 unsigned NumOperands = Operands.size();
6491
6492 if (NumOperands == 4 && Tok == "lsl") {
6493 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6494 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6495 if (Op2.isScalarReg() && Op3.isImm()) {
6496 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Val: Op3.getImm());
6497 if (Op3CE) {
6498 uint64_t Op3Val = Op3CE->getValue();
6499 uint64_t NewOp3Val = 0;
6500 uint64_t NewOp4Val = 0;
6501 if (getAArch64MCRegisterClass(RC: AArch64::GPR32allRegClassID)
6502 .contains(Reg: Op2.getReg())) {
6503 NewOp3Val = (32 - Op3Val) & 0x1f;
6504 NewOp4Val = 31 - Op3Val;
6505 } else {
6506 NewOp3Val = (64 - Op3Val) & 0x3f;
6507 NewOp4Val = 63 - Op3Val;
6508 }
6509
6510 const MCExpr *NewOp3 = MCConstantExpr::create(Value: NewOp3Val, Ctx&: getContext());
6511 const MCExpr *NewOp4 = MCConstantExpr::create(Value: NewOp4Val, Ctx&: getContext());
6512
6513 Operands[0] =
6514 AArch64Operand::CreateToken(Str: "ubfm", S: Op.getStartLoc(), Ctx&: getContext());
6515 Operands.push_back(Elt: AArch64Operand::CreateImm(
6516 Val: NewOp4, S: Op3.getStartLoc(), E: Op3.getEndLoc(), Ctx&: getContext()));
6517 Operands[3] = AArch64Operand::CreateImm(Val: NewOp3, S: Op3.getStartLoc(),
6518 E: Op3.getEndLoc(), Ctx&: getContext());
6519 }
6520 }
6521 } else if (NumOperands == 4 && Tok == "bfc") {
6522 // FIXME: Horrible hack to handle BFC->BFM alias.
6523 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6524 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
6525 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
6526
6527 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
6528 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(Val: LSBOp.getImm());
6529 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(Val: WidthOp.getImm());
6530
6531 if (LSBCE && WidthCE) {
6532 uint64_t LSB = LSBCE->getValue();
6533 uint64_t Width = WidthCE->getValue();
6534
6535 uint64_t RegWidth = 0;
6536 if (getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
6537 .contains(Reg: Op1.getReg()))
6538 RegWidth = 64;
6539 else
6540 RegWidth = 32;
6541
6542 if (LSB >= RegWidth)
6543 return Error(L: LSBOp.getStartLoc(),
6544 Msg: "expected integer in range [0, 31]");
6545 if (Width < 1 || Width > RegWidth)
6546 return Error(L: WidthOp.getStartLoc(),
6547 Msg: "expected integer in range [1, 32]");
6548
6549 uint64_t ImmR = 0;
6550 if (RegWidth == 32)
6551 ImmR = (32 - LSB) & 0x1f;
6552 else
6553 ImmR = (64 - LSB) & 0x3f;
6554
6555 uint64_t ImmS = Width - 1;
6556
6557 if (ImmR != 0 && ImmS >= ImmR)
6558 return Error(L: WidthOp.getStartLoc(),
6559 Msg: "requested insert overflows register");
6560
6561 const MCExpr *ImmRExpr = MCConstantExpr::create(Value: ImmR, Ctx&: getContext());
6562 const MCExpr *ImmSExpr = MCConstantExpr::create(Value: ImmS, Ctx&: getContext());
6563 Operands[0] =
6564 AArch64Operand::CreateToken(Str: "bfm", S: Op.getStartLoc(), Ctx&: getContext());
6565 Operands[2] = AArch64Operand::CreateReg(
6566 Reg: RegWidth == 32 ? AArch64::WZR : AArch64::XZR, Kind: RegKind::Scalar,
6567 S: SMLoc(), E: SMLoc(), Ctx&: getContext());
6568 Operands[3] = AArch64Operand::CreateImm(
6569 Val: ImmRExpr, S: LSBOp.getStartLoc(), E: LSBOp.getEndLoc(), Ctx&: getContext());
6570 Operands.emplace_back(
6571 Args: AArch64Operand::CreateImm(Val: ImmSExpr, S: WidthOp.getStartLoc(),
6572 E: WidthOp.getEndLoc(), Ctx&: getContext()));
6573 }
6574 }
6575 } else if (NumOperands == 5) {
6576 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
6577 // UBFIZ -> UBFM aliases.
6578 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
6579 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6580 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6581 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6582
6583 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6584 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Val: Op3.getImm());
6585 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Val: Op4.getImm());
6586
6587 if (Op3CE && Op4CE) {
6588 uint64_t Op3Val = Op3CE->getValue();
6589 uint64_t Op4Val = Op4CE->getValue();
6590
6591 uint64_t RegWidth = 0;
6592 if (getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
6593 .contains(Reg: Op1.getReg()))
6594 RegWidth = 64;
6595 else
6596 RegWidth = 32;
6597
6598 if (Op3Val >= RegWidth)
6599 return Error(L: Op3.getStartLoc(),
6600 Msg: "expected integer in range [0, 31]");
6601 if (Op4Val < 1 || Op4Val > RegWidth)
6602 return Error(L: Op4.getStartLoc(),
6603 Msg: "expected integer in range [1, 32]");
6604
6605 uint64_t NewOp3Val = 0;
6606 if (RegWidth == 32)
6607 NewOp3Val = (32 - Op3Val) & 0x1f;
6608 else
6609 NewOp3Val = (64 - Op3Val) & 0x3f;
6610
6611 uint64_t NewOp4Val = Op4Val - 1;
6612
6613 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
6614 return Error(L: Op4.getStartLoc(),
6615 Msg: "requested insert overflows register");
6616
6617 const MCExpr *NewOp3 =
6618 MCConstantExpr::create(Value: NewOp3Val, Ctx&: getContext());
6619 const MCExpr *NewOp4 =
6620 MCConstantExpr::create(Value: NewOp4Val, Ctx&: getContext());
6621 Operands[3] = AArch64Operand::CreateImm(
6622 Val: NewOp3, S: Op3.getStartLoc(), E: Op3.getEndLoc(), Ctx&: getContext());
6623 Operands[4] = AArch64Operand::CreateImm(
6624 Val: NewOp4, S: Op4.getStartLoc(), E: Op4.getEndLoc(), Ctx&: getContext());
6625 if (Tok == "bfi")
6626 Operands[0] = AArch64Operand::CreateToken(Str: "bfm", S: Op.getStartLoc(),
6627 Ctx&: getContext());
6628 else if (Tok == "sbfiz")
6629 Operands[0] = AArch64Operand::CreateToken(Str: "sbfm", S: Op.getStartLoc(),
6630 Ctx&: getContext());
6631 else if (Tok == "ubfiz")
6632 Operands[0] = AArch64Operand::CreateToken(Str: "ubfm", S: Op.getStartLoc(),
6633 Ctx&: getContext());
6634 else
6635 llvm_unreachable("No valid mnemonic for alias?");
6636 }
6637 }
6638
6639 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
6640 // UBFX -> UBFM aliases.
6641 } else if (NumOperands == 5 &&
6642 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
6643 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6644 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6645 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
6646
6647 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
6648 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Val: Op3.getImm());
6649 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Val: Op4.getImm());
6650
6651 if (Op3CE && Op4CE) {
6652 uint64_t Op3Val = Op3CE->getValue();
6653 uint64_t Op4Val = Op4CE->getValue();
6654
6655 uint64_t RegWidth = 0;
6656 if (getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
6657 .contains(Reg: Op1.getReg()))
6658 RegWidth = 64;
6659 else
6660 RegWidth = 32;
6661
6662 if (Op3Val >= RegWidth)
6663 return Error(L: Op3.getStartLoc(),
6664 Msg: "expected integer in range [0, 31]");
6665 if (Op4Val < 1 || Op4Val > RegWidth)
6666 return Error(L: Op4.getStartLoc(),
6667 Msg: "expected integer in range [1, 32]");
6668
6669 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
6670
6671 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
6672 return Error(L: Op4.getStartLoc(),
6673 Msg: "requested extract overflows register");
6674
6675 const MCExpr *NewOp4 =
6676 MCConstantExpr::create(Value: NewOp4Val, Ctx&: getContext());
6677 Operands[4] = AArch64Operand::CreateImm(
6678 Val: NewOp4, S: Op4.getStartLoc(), E: Op4.getEndLoc(), Ctx&: getContext());
6679 if (Tok == "bfxil")
6680 Operands[0] = AArch64Operand::CreateToken(Str: "bfm", S: Op.getStartLoc(),
6681 Ctx&: getContext());
6682 else if (Tok == "sbfx")
6683 Operands[0] = AArch64Operand::CreateToken(Str: "sbfm", S: Op.getStartLoc(),
6684 Ctx&: getContext());
6685 else if (Tok == "ubfx")
6686 Operands[0] = AArch64Operand::CreateToken(Str: "ubfm", S: Op.getStartLoc(),
6687 Ctx&: getContext());
6688 else
6689 llvm_unreachable("No valid mnemonic for alias?");
6690 }
6691 }
6692 }
6693 }
6694
6695 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
6696 // instruction for FP registers correctly in some rare circumstances. Convert
6697 // it to a safe instruction and warn (because silently changing someone's
6698 // assembly is rude).
6699 if (getSTI().hasFeature(Feature: AArch64::FeatureZCZeroingFPWorkaround) &&
6700 NumOperands == 4 && Tok == "movi") {
6701 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
6702 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
6703 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
6704 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
6705 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
6706 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
6707 if (Suffix.lower() == ".2d" &&
6708 cast<MCConstantExpr>(Val: Op3.getImm())->getValue() == 0) {
6709 Warning(L: IDLoc, Msg: "instruction movi.2d with immediate #0 may not function"
6710 " correctly on this CPU, converting to equivalent movi.16b");
6711 // Switch the suffix to .16b.
6712 unsigned Idx = Op1.isToken() ? 1 : 2;
6713 Operands[Idx] =
6714 AArch64Operand::CreateToken(Str: ".16b", S: IDLoc, Ctx&: getContext());
6715 }
6716 }
6717 }
6718
6719 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
6720 // InstAlias can't quite handle this since the reg classes aren't
6721 // subclasses.
6722 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
6723 // The source register can be Wn here, but the matcher expects a
6724 // GPR64. Twiddle it here if necessary.
6725 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6726 if (Op.isScalarReg()) {
6727 MCRegister Reg = getXRegFromWReg(Reg: Op.getReg());
6728 Operands[2] = AArch64Operand::CreateReg(Reg, Kind: RegKind::Scalar,
6729 S: Op.getStartLoc(), E: Op.getEndLoc(),
6730 Ctx&: getContext());
6731 }
6732 }
6733 // FIXME: Likewise for sxt[bh] with a Xd dst operand
6734 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
6735 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6736 if (Op.isScalarReg() &&
6737 getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
6738 .contains(Reg: Op.getReg())) {
6739 // The source register can be Wn here, but the matcher expects a
6740 // GPR64. Twiddle it here if necessary.
6741 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
6742 if (Op.isScalarReg()) {
6743 MCRegister Reg = getXRegFromWReg(Reg: Op.getReg());
6744 Operands[2] = AArch64Operand::CreateReg(Reg, Kind: RegKind::Scalar,
6745 S: Op.getStartLoc(),
6746 E: Op.getEndLoc(), Ctx&: getContext());
6747 }
6748 }
6749 }
6750 // FIXME: Likewise for uxt[bh] with a Xd dst operand
6751 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
6752 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6753 if (Op.isScalarReg() &&
6754 getAArch64MCRegisterClass(RC: AArch64::GPR64allRegClassID)
6755 .contains(Reg: Op.getReg())) {
6756 // The source register can be Wn here, but the matcher expects a
6757 // GPR32. Twiddle it here if necessary.
6758 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
6759 if (Op.isScalarReg()) {
6760 MCRegister Reg = getWRegFromXReg(Reg: Op.getReg());
6761 Operands[1] = AArch64Operand::CreateReg(Reg, Kind: RegKind::Scalar,
6762 S: Op.getStartLoc(),
6763 E: Op.getEndLoc(), Ctx&: getContext());
6764 }
6765 }
6766 }
6767
6768 MCInst Inst;
6769 FeatureBitset MissingFeatures;
6770 // First try to match against the secondary set of tables containing the
6771 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
6772 unsigned MatchResult =
6773 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6774 matchingInlineAsm: MatchingInlineAsm, VariantID: 1);
6775
6776 // If that fails, try against the alternate table containing long-form NEON:
6777 // "fadd v0.2s, v1.2s, v2.2s"
6778 if (MatchResult != Match_Success) {
6779 // But first, save the short-form match result: we can use it in case the
6780 // long-form match also fails.
6781 auto ShortFormNEONErrorInfo = ErrorInfo;
6782 auto ShortFormNEONMatchResult = MatchResult;
6783 auto ShortFormNEONMissingFeatures = MissingFeatures;
6784
6785 MatchResult =
6786 MatchInstructionImpl(Operands, Inst, ErrorInfo, MissingFeatures,
6787 matchingInlineAsm: MatchingInlineAsm, VariantID: 0);
6788
6789 // Now, both matches failed, and the long-form match failed on the mnemonic
6790 // suffix token operand. The short-form match failure is probably more
6791 // relevant: use it instead.
6792 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
6793 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
6794 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
6795 MatchResult = ShortFormNEONMatchResult;
6796 ErrorInfo = ShortFormNEONErrorInfo;
6797 MissingFeatures = ShortFormNEONMissingFeatures;
6798 }
6799 }
6800
6801 switch (MatchResult) {
6802 case Match_Success: {
6803 // Perform range checking and other semantic validations
6804 SmallVector<SMLoc, 8> OperandLocs;
6805 NumOperands = Operands.size();
6806 for (unsigned i = 1; i < NumOperands; ++i)
6807 OperandLocs.push_back(Elt: Operands[i]->getStartLoc());
6808 if (validateInstruction(Inst, IDLoc, Loc&: OperandLocs))
6809 return true;
6810
6811 Inst.setLoc(IDLoc);
6812 Out.emitInstruction(Inst, STI: getSTI());
6813 return false;
6814 }
6815 case Match_MissingFeature: {
6816 assert(MissingFeatures.any() && "Unknown missing feature!");
6817 // Special case the error message for the very common case where only
6818 // a single subtarget feature is missing (neon, e.g.).
6819 std::string Msg = "instruction requires:";
6820 for (unsigned Feature : MissingFeatures) {
6821 Msg += " ";
6822 Msg += getSubtargetFeatureName(Val: Feature);
6823 }
6824 return Error(L: IDLoc, Msg);
6825 }
6826 case Match_MnemonicFail:
6827 return showMatchError(Loc: IDLoc, ErrCode: MatchResult, ErrorInfo, Operands);
6828 case Match_InvalidOperand: {
6829 SMLoc ErrorLoc = IDLoc;
6830
6831 if (ErrorInfo != ~0ULL) {
6832 if (ErrorInfo >= Operands.size())
6833 return Error(L: IDLoc, Msg: "too few operands for instruction",
6834 Range: SMRange(IDLoc, getTok().getLoc()));
6835
6836 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
6837 if (ErrorLoc == SMLoc())
6838 ErrorLoc = IDLoc;
6839 }
6840 // If the match failed on a suffix token operand, tweak the diagnostic
6841 // accordingly.
6842 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
6843 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
6844 MatchResult = Match_InvalidSuffix;
6845
6846 return showMatchError(Loc: ErrorLoc, ErrCode: MatchResult, ErrorInfo, Operands);
6847 }
6848 case Match_InvalidTiedOperand:
6849 case Match_InvalidMemoryIndexed1:
6850 case Match_InvalidMemoryIndexed2:
6851 case Match_InvalidMemoryIndexed4:
6852 case Match_InvalidMemoryIndexed8:
6853 case Match_InvalidMemoryIndexed16:
6854 case Match_InvalidCondCode:
6855 case Match_AddSubLSLImm3ShiftLarge:
6856 case Match_AddSubRegExtendSmall:
6857 case Match_AddSubRegExtendLarge:
6858 case Match_AddSubSecondSource:
6859 case Match_LogicalSecondSource:
6860 case Match_AddSubRegShift32:
6861 case Match_AddSubRegShift64:
6862 case Match_InvalidMovImm32Shift:
6863 case Match_InvalidMovImm64Shift:
6864 case Match_InvalidFPImm:
6865 case Match_InvalidMemoryWExtend8:
6866 case Match_InvalidMemoryWExtend16:
6867 case Match_InvalidMemoryWExtend32:
6868 case Match_InvalidMemoryWExtend64:
6869 case Match_InvalidMemoryWExtend128:
6870 case Match_InvalidMemoryXExtend8:
6871 case Match_InvalidMemoryXExtend16:
6872 case Match_InvalidMemoryXExtend32:
6873 case Match_InvalidMemoryXExtend64:
6874 case Match_InvalidMemoryXExtend128:
6875 case Match_InvalidMemoryIndexed1SImm4:
6876 case Match_InvalidMemoryIndexed2SImm4:
6877 case Match_InvalidMemoryIndexed3SImm4:
6878 case Match_InvalidMemoryIndexed4SImm4:
6879 case Match_InvalidMemoryIndexed1SImm6:
6880 case Match_InvalidMemoryIndexed16SImm4:
6881 case Match_InvalidMemoryIndexed32SImm4:
6882 case Match_InvalidMemoryIndexed4SImm7:
6883 case Match_InvalidMemoryIndexed8SImm7:
6884 case Match_InvalidMemoryIndexed16SImm7:
6885 case Match_InvalidMemoryIndexed8UImm5:
6886 case Match_InvalidMemoryIndexed8UImm3:
6887 case Match_InvalidMemoryIndexed4UImm5:
6888 case Match_InvalidMemoryIndexed2UImm5:
6889 case Match_InvalidMemoryIndexed1UImm6:
6890 case Match_InvalidMemoryIndexed2UImm6:
6891 case Match_InvalidMemoryIndexed4UImm6:
6892 case Match_InvalidMemoryIndexed8UImm6:
6893 case Match_InvalidMemoryIndexed16UImm6:
6894 case Match_InvalidMemoryIndexed32UImm8:
6895 case Match_InvalidMemoryIndexedSImm6:
6896 case Match_InvalidMemoryIndexedSImm5:
6897 case Match_InvalidMemoryIndexedSImm8:
6898 case Match_InvalidMemoryIndexedSImm9:
6899 case Match_InvalidMemoryIndexed16SImm9:
6900 case Match_InvalidMemoryIndexed8SImm10:
6901 case Match_InvalidImm0_0:
6902 case Match_InvalidImm0_1:
6903 case Match_InvalidImm0_3:
6904 case Match_InvalidImm0_7:
6905 case Match_InvalidImm0_15:
6906 case Match_InvalidImm0_31:
6907 case Match_InvalidImm0_63:
6908 case Match_InvalidImm0_127:
6909 case Match_InvalidImm0_255:
6910 case Match_InvalidImm0_511:
6911 case Match_InvalidImm0_65535:
6912 case Match_InvalidHinteUImm16:
6913 case Match_InvalidImm1_8:
6914 case Match_InvalidImm1_16:
6915 case Match_InvalidImm1_32:
6916 case Match_InvalidImm1_64:
6917 case Match_InvalidImm1_512:
6918 case Match_InvalidImmM1_62:
6919 case Match_InvalidImmM1_510:
6920 case Match_InvalidImmM255_256:
6921 case Match_InvalidImmM257_254:
6922 case Match_InvalidMemoryIndexedRange2UImm0:
6923 case Match_InvalidMemoryIndexedRange2UImm1:
6924 case Match_InvalidMemoryIndexedRange2UImm2:
6925 case Match_InvalidMemoryIndexedRange2UImm3:
6926 case Match_InvalidMemoryIndexedRange4UImm0:
6927 case Match_InvalidMemoryIndexedRange4UImm1:
6928 case Match_InvalidMemoryIndexedRange4UImm2:
6929 case Match_InvalidSVEAddSubImm8:
6930 case Match_InvalidSVEAddSubImm16:
6931 case Match_InvalidSVEAddSubImm32:
6932 case Match_InvalidSVEAddSubImm64:
6933 case Match_InvalidSVECpyImm8:
6934 case Match_InvalidSVECpyImm16:
6935 case Match_InvalidSVECpyImm32:
6936 case Match_InvalidSVECpyImm64:
6937 case Match_InvalidIndexRange0_0:
6938 case Match_InvalidIndexRange1_1:
6939 case Match_InvalidIndexRange0_15:
6940 case Match_InvalidIndexRange0_7:
6941 case Match_InvalidIndexRange0_3:
6942 case Match_InvalidIndexRange0_1:
6943 case Match_InvalidSVEIndexRange0_63:
6944 case Match_InvalidSVEIndexRange0_31:
6945 case Match_InvalidSVEIndexRange0_15:
6946 case Match_InvalidSVEIndexRange0_7:
6947 case Match_InvalidSVEIndexRange0_3:
6948 case Match_InvalidLabel:
6949 case Match_InvalidComplexRotationEven:
6950 case Match_InvalidComplexRotationOdd:
6951 case Match_InvalidGPR64shifted8:
6952 case Match_InvalidGPR64shifted16:
6953 case Match_InvalidGPR64shifted32:
6954 case Match_InvalidGPR64shifted64:
6955 case Match_InvalidGPR64shifted128:
6956 case Match_InvalidGPR64NoXZRshifted8:
6957 case Match_InvalidGPR64NoXZRshifted16:
6958 case Match_InvalidGPR64NoXZRshifted32:
6959 case Match_InvalidGPR64NoXZRshifted64:
6960 case Match_InvalidGPR64NoXZRshifted128:
6961 case Match_InvalidZPR32UXTW8:
6962 case Match_InvalidZPR32UXTW16:
6963 case Match_InvalidZPR32UXTW32:
6964 case Match_InvalidZPR32UXTW64:
6965 case Match_InvalidZPR32SXTW8:
6966 case Match_InvalidZPR32SXTW16:
6967 case Match_InvalidZPR32SXTW32:
6968 case Match_InvalidZPR32SXTW64:
6969 case Match_InvalidZPR64UXTW8:
6970 case Match_InvalidZPR64SXTW8:
6971 case Match_InvalidZPR64UXTW16:
6972 case Match_InvalidZPR64SXTW16:
6973 case Match_InvalidZPR64UXTW32:
6974 case Match_InvalidZPR64SXTW32:
6975 case Match_InvalidZPR64UXTW64:
6976 case Match_InvalidZPR64SXTW64:
6977 case Match_InvalidZPR32LSL8:
6978 case Match_InvalidZPR32LSL16:
6979 case Match_InvalidZPR32LSL32:
6980 case Match_InvalidZPR32LSL64:
6981 case Match_InvalidZPR64LSL8:
6982 case Match_InvalidZPR64LSL16:
6983 case Match_InvalidZPR64LSL32:
6984 case Match_InvalidZPR64LSL64:
6985 case Match_InvalidZPR0:
6986 case Match_InvalidZPR8:
6987 case Match_InvalidZPR16:
6988 case Match_InvalidZPR32:
6989 case Match_InvalidZPR64:
6990 case Match_InvalidZPR128:
6991 case Match_InvalidZPR_3b8:
6992 case Match_InvalidZPR_3b16:
6993 case Match_InvalidZPR_3b32:
6994 case Match_InvalidZPR_4b8:
6995 case Match_InvalidZPR_4b16:
6996 case Match_InvalidZPR_4b32:
6997 case Match_InvalidZPR_4b64:
6998 case Match_InvalidSVEPPRorPNRAnyReg:
6999 case Match_InvalidSVEPPRorPNRBReg:
7000 case Match_InvalidSVEPredicateAnyReg:
7001 case Match_InvalidSVEPattern:
7002 case Match_InvalidSVEVecLenSpecifier:
7003 case Match_InvalidSVEPredicateBReg:
7004 case Match_InvalidSVEPredicateHReg:
7005 case Match_InvalidSVEPredicateSReg:
7006 case Match_InvalidSVEPredicateDReg:
7007 case Match_InvalidSVEPredicate3bAnyReg:
7008 case Match_InvalidSVEPNPredicateB_p8to15Reg:
7009 case Match_InvalidSVEPNPredicateH_p8to15Reg:
7010 case Match_InvalidSVEPNPredicateS_p8to15Reg:
7011 case Match_InvalidSVEPNPredicateD_p8to15Reg:
7012 case Match_InvalidSVEPNPredicateAny_p8to15Reg:
7013 case Match_InvalidSVEPNPredicateBReg:
7014 case Match_InvalidSVEPNPredicateHReg:
7015 case Match_InvalidSVEPNPredicateSReg:
7016 case Match_InvalidSVEPNPredicateDReg:
7017 case Match_InvalidSVEPredicateListMul2x8:
7018 case Match_InvalidSVEPredicateListMul2x16:
7019 case Match_InvalidSVEPredicateListMul2x32:
7020 case Match_InvalidSVEPredicateListMul2x64:
7021 case Match_InvalidSVEExactFPImmOperandHalfOne:
7022 case Match_InvalidSVEExactFPImmOperandHalfTwo:
7023 case Match_InvalidSVEExactFPImmOperandZeroOne:
7024 case Match_InvalidMatrixTile16:
7025 case Match_InvalidMatrixTile32:
7026 case Match_InvalidMatrixTile64:
7027 case Match_InvalidMatrix:
7028 case Match_InvalidMatrix8:
7029 case Match_InvalidMatrix16:
7030 case Match_InvalidMatrix32:
7031 case Match_InvalidMatrix64:
7032 case Match_InvalidMatrixTileVectorH8:
7033 case Match_InvalidMatrixTileVectorH16:
7034 case Match_InvalidMatrixTileVectorH32:
7035 case Match_InvalidMatrixTileVectorH64:
7036 case Match_InvalidMatrixTileVectorH128:
7037 case Match_InvalidMatrixTileVectorV8:
7038 case Match_InvalidMatrixTileVectorV16:
7039 case Match_InvalidMatrixTileVectorV32:
7040 case Match_InvalidMatrixTileVectorV64:
7041 case Match_InvalidMatrixTileVectorV128:
7042 case Match_InvalidSVCR:
7043 case Match_InvalidMatrixIndexGPR32_12_15:
7044 case Match_InvalidMatrixIndexGPR32_8_11:
7045 case Match_InvalidLookupTable:
7046 case Match_InvalidZPRMul2_Lo8:
7047 case Match_InvalidZPRMul2_Hi8:
7048 case Match_InvalidZPRMul2_Lo16:
7049 case Match_InvalidZPRMul2_Hi16:
7050 case Match_InvalidZPRMul2_Lo32:
7051 case Match_InvalidZPRMul2_Hi32:
7052 case Match_InvalidZPRMul2_Lo64:
7053 case Match_InvalidZPRMul2_Hi64:
7054 case Match_InvalidZPR_K0:
7055 case Match_InvalidSVEVectorList2x8Mul2:
7056 case Match_InvalidSVEVectorList2x16Mul2:
7057 case Match_InvalidSVEVectorList2x32Mul2:
7058 case Match_InvalidSVEVectorList2x64Mul2:
7059 case Match_InvalidSVEVectorList2x128Mul2:
7060 case Match_InvalidSVEVectorList4x8Mul4:
7061 case Match_InvalidSVEVectorList4x16Mul4:
7062 case Match_InvalidSVEVectorList4x32Mul4:
7063 case Match_InvalidSVEVectorList4x64Mul4:
7064 case Match_InvalidSVEVectorList4x128Mul4:
7065 case Match_InvalidSVEVectorList2x8Mul2_Lo:
7066 case Match_InvalidSVEVectorList2x16Mul2_Lo:
7067 case Match_InvalidSVEVectorList2x32Mul2_Lo:
7068 case Match_InvalidSVEVectorList2x64Mul2_Lo:
7069 case Match_InvalidSVEVectorList2x8Mul2_Hi:
7070 case Match_InvalidSVEVectorList2x16Mul2_Hi:
7071 case Match_InvalidSVEVectorList2x32Mul2_Hi:
7072 case Match_InvalidSVEVectorList2x64Mul2_Hi:
7073 case Match_InvalidSVEVectorList3x0_3b:
7074 case Match_InvalidSVEVectorListStrided2x8:
7075 case Match_InvalidSVEVectorListStrided2x16:
7076 case Match_InvalidSVEVectorListStrided2x32:
7077 case Match_InvalidSVEVectorListStrided2x64:
7078 case Match_InvalidSVEVectorListStrided4x8:
7079 case Match_InvalidSVEVectorListStrided4x16:
7080 case Match_InvalidSVEVectorListStrided4x32:
7081 case Match_InvalidSVEVectorListStrided4x64:
7082 case Match_MSR:
7083 case Match_MRS: {
7084 if (ErrorInfo >= Operands.size())
7085 return Error(L: IDLoc, Msg: "too few operands for instruction",
7086 Range: SMRange(IDLoc, (*Operands.back()).getEndLoc()));
7087 // Any time we get here, there's nothing fancy to do. Just get the
7088 // operand SMLoc and display the diagnostic.
7089 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
7090 if (ErrorLoc == SMLoc())
7091 ErrorLoc = IDLoc;
7092 return showMatchError(Loc: ErrorLoc, ErrCode: MatchResult, ErrorInfo, Operands);
7093 }
7094 }
7095
7096 llvm_unreachable("Implement any new match types added!");
7097}
7098
7099/// ParseDirective parses the arm specific directives
7100bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
7101 const MCContext::Environment Format = getContext().getObjectFileType();
7102 bool IsMachO = Format == MCContext::IsMachO;
7103 bool IsCOFF = Format == MCContext::IsCOFF;
7104 bool IsELF = Format == MCContext::IsELF;
7105
7106 auto IDVal = DirectiveID.getIdentifier().lower();
7107 SMLoc Loc = DirectiveID.getLoc();
7108 if (IDVal == ".arch")
7109 parseDirectiveArch(L: Loc);
7110 else if (IDVal == ".cpu")
7111 parseDirectiveCPU(L: Loc);
7112 else if (IDVal == ".tlsdesccall")
7113 parseDirectiveTLSDescCall(L: Loc, /*IsAuth=*/false);
7114 else if (IDVal == ".tlsauthdesccall")
7115 parseDirectiveTLSDescCall(L: Loc, /*IsAuth=*/true);
7116 else if (IDVal == ".ltorg" || IDVal == ".pool")
7117 parseDirectiveLtorg(L: Loc);
7118 else if (IDVal == ".unreq")
7119 parseDirectiveUnreq(L: Loc);
7120 else if (IDVal == ".inst")
7121 parseDirectiveInst(L: Loc);
7122 else if (IDVal == ".cfi_negate_ra_state")
7123 parseDirectiveCFINegateRAState();
7124 else if (IDVal == ".cfi_negate_ra_state_with_pc")
7125 parseDirectiveCFINegateRAStateWithPC();
7126 else if (IDVal == ".cfi_set_ra_state")
7127 parseDirectiveCFILLVMSetRAState();
7128 else if (IDVal == ".cfi_b_key_frame")
7129 parseDirectiveCFIBKeyFrame();
7130 else if (IDVal == ".cfi_mte_tagged_frame")
7131 parseDirectiveCFIMTETaggedFrame();
7132 else if (IDVal == ".arch_extension")
7133 parseDirectiveArchExtension(L: Loc);
7134 else if (IDVal == ".variant_pcs")
7135 parseDirectiveVariantPCS(L: Loc);
7136 else if (IsMachO) {
7137 if (IDVal == MCLOHDirectiveName())
7138 parseDirectiveLOH(LOH: IDVal, L: Loc);
7139 else
7140 return true;
7141 } else if (IsCOFF) {
7142 if (IDVal == ".seh_stackalloc")
7143 parseDirectiveSEHAllocStack(L: Loc);
7144 else if (IDVal == ".seh_endprologue")
7145 parseDirectiveSEHPrologEnd(L: Loc);
7146 else if (IDVal == ".seh_end_c")
7147 parseDirectiveSEHEndC(L: Loc);
7148 else if (IDVal == ".seh_save_r19r20_x")
7149 parseDirectiveSEHSaveR19R20X(L: Loc);
7150 else if (IDVal == ".seh_save_fplr")
7151 parseDirectiveSEHSaveFPLR(L: Loc);
7152 else if (IDVal == ".seh_save_fplr_x")
7153 parseDirectiveSEHSaveFPLRX(L: Loc);
7154 else if (IDVal == ".seh_save_reg")
7155 parseDirectiveSEHSaveReg(L: Loc);
7156 else if (IDVal == ".seh_save_reg_x")
7157 parseDirectiveSEHSaveRegX(L: Loc);
7158 else if (IDVal == ".seh_save_regp")
7159 parseDirectiveSEHSaveRegP(L: Loc);
7160 else if (IDVal == ".seh_save_regp_x")
7161 parseDirectiveSEHSaveRegPX(L: Loc);
7162 else if (IDVal == ".seh_save_lrpair")
7163 parseDirectiveSEHSaveLRPair(L: Loc);
7164 else if (IDVal == ".seh_save_freg")
7165 parseDirectiveSEHSaveFReg(L: Loc);
7166 else if (IDVal == ".seh_save_freg_x")
7167 parseDirectiveSEHSaveFRegX(L: Loc);
7168 else if (IDVal == ".seh_save_fregp")
7169 parseDirectiveSEHSaveFRegP(L: Loc);
7170 else if (IDVal == ".seh_save_fregp_x")
7171 parseDirectiveSEHSaveFRegPX(L: Loc);
7172 else if (IDVal == ".seh_set_fp")
7173 parseDirectiveSEHSetFP(L: Loc);
7174 else if (IDVal == ".seh_add_fp")
7175 parseDirectiveSEHAddFP(L: Loc);
7176 else if (IDVal == ".seh_nop")
7177 parseDirectiveSEHNop(L: Loc);
7178 else if (IDVal == ".seh_save_next")
7179 parseDirectiveSEHSaveNext(L: Loc);
7180 else if (IDVal == ".seh_startepilogue")
7181 parseDirectiveSEHEpilogStart(L: Loc);
7182 else if (IDVal == ".seh_endepilogue")
7183 parseDirectiveSEHEpilogEnd(L: Loc);
7184 else if (IDVal == ".seh_trap_frame")
7185 parseDirectiveSEHTrapFrame(L: Loc);
7186 else if (IDVal == ".seh_pushframe")
7187 parseDirectiveSEHMachineFrame(L: Loc);
7188 else if (IDVal == ".seh_context")
7189 parseDirectiveSEHContext(L: Loc);
7190 else if (IDVal == ".seh_ec_context")
7191 parseDirectiveSEHECContext(L: Loc);
7192 else if (IDVal == ".seh_clear_unwound_to_call")
7193 parseDirectiveSEHClearUnwoundToCall(L: Loc);
7194 else if (IDVal == ".seh_pac_sign_lr")
7195 parseDirectiveSEHPACSignLR(L: Loc);
7196 else if (IDVal == ".seh_save_any_reg")
7197 parseDirectiveSEHSaveAnyReg(L: Loc, Paired: false, Writeback: false);
7198 else if (IDVal == ".seh_save_any_reg_p")
7199 parseDirectiveSEHSaveAnyReg(L: Loc, Paired: true, Writeback: false);
7200 else if (IDVal == ".seh_save_any_reg_x")
7201 parseDirectiveSEHSaveAnyReg(L: Loc, Paired: false, Writeback: true);
7202 else if (IDVal == ".seh_save_any_reg_px")
7203 parseDirectiveSEHSaveAnyReg(L: Loc, Paired: true, Writeback: true);
7204 else if (IDVal == ".seh_allocz")
7205 parseDirectiveSEHAllocZ(L: Loc);
7206 else if (IDVal == ".seh_save_zreg")
7207 parseDirectiveSEHSaveZReg(L: Loc);
7208 else if (IDVal == ".seh_save_preg")
7209 parseDirectiveSEHSavePReg(L: Loc);
7210 else
7211 return true;
7212 } else if (IsELF) {
7213 if (IDVal == ".aeabi_subsection")
7214 parseDirectiveAeabiSubSectionHeader(L: Loc);
7215 else if (IDVal == ".aeabi_attribute")
7216 parseDirectiveAeabiAArch64Attr(L: Loc);
7217 else
7218 return true;
7219 } else
7220 return true;
7221 return false;
7222}
7223
7224static void ExpandCryptoAEK(const AArch64::ArchInfo &ArchInfo,
7225 SmallVector<StringRef, 4> &RequestedExtensions) {
7226 const bool NoCrypto = llvm::is_contained(Range&: RequestedExtensions, Element: "nocrypto");
7227 const bool Crypto = llvm::is_contained(Range&: RequestedExtensions, Element: "crypto");
7228
7229 if (!NoCrypto && Crypto) {
7230 // Map 'generic' (and others) to sha2 and aes, because
7231 // that was the traditional meaning of crypto.
7232 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
7233 ArchInfo == AArch64::ARMV8_3A) {
7234 RequestedExtensions.push_back(Elt: "sha2");
7235 RequestedExtensions.push_back(Elt: "aes");
7236 }
7237 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
7238 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
7239 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
7240 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
7241 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
7242 ArchInfo == AArch64::ARMV9_4A || ArchInfo == AArch64::ARMV8R) {
7243 RequestedExtensions.push_back(Elt: "sm4");
7244 RequestedExtensions.push_back(Elt: "sha3");
7245 RequestedExtensions.push_back(Elt: "sha2");
7246 RequestedExtensions.push_back(Elt: "aes");
7247 }
7248 } else if (NoCrypto) {
7249 // Map 'generic' (and others) to sha2 and aes, because
7250 // that was the traditional meaning of crypto.
7251 if (ArchInfo == AArch64::ARMV8_1A || ArchInfo == AArch64::ARMV8_2A ||
7252 ArchInfo == AArch64::ARMV8_3A) {
7253 RequestedExtensions.push_back(Elt: "nosha2");
7254 RequestedExtensions.push_back(Elt: "noaes");
7255 }
7256 if (ArchInfo == AArch64::ARMV8_4A || ArchInfo == AArch64::ARMV8_5A ||
7257 ArchInfo == AArch64::ARMV8_6A || ArchInfo == AArch64::ARMV8_7A ||
7258 ArchInfo == AArch64::ARMV8_8A || ArchInfo == AArch64::ARMV8_9A ||
7259 ArchInfo == AArch64::ARMV9A || ArchInfo == AArch64::ARMV9_1A ||
7260 ArchInfo == AArch64::ARMV9_2A || ArchInfo == AArch64::ARMV9_3A ||
7261 ArchInfo == AArch64::ARMV9_4A) {
7262 RequestedExtensions.push_back(Elt: "nosm4");
7263 RequestedExtensions.push_back(Elt: "nosha3");
7264 RequestedExtensions.push_back(Elt: "nosha2");
7265 RequestedExtensions.push_back(Elt: "noaes");
7266 }
7267 }
7268}
7269
7270static SMLoc incrementLoc(SMLoc L, int Offset) {
7271 return SMLoc::getFromPointer(Ptr: L.getPointer() + Offset);
7272}
7273
7274/// parseDirectiveArch
7275/// ::= .arch token
7276bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
7277 SMLoc CurLoc = getLoc();
7278
7279 StringRef Name = getParser().parseStringToEndOfStatement().trim();
7280 StringRef Arch, ExtensionString;
7281 std::tie(args&: Arch, args&: ExtensionString) = Name.split(Separator: '+');
7282
7283 const AArch64::ArchInfo *ArchInfo = AArch64::parseArch(Arch);
7284 if (!ArchInfo)
7285 return Error(L: CurLoc, Msg: "unknown arch name");
7286
7287 if (parseToken(T: AsmToken::EndOfStatement))
7288 return true;
7289
7290 // Get the architecture and extension features.
7291 std::vector<StringRef> AArch64Features;
7292 AArch64Features.push_back(x: AArch64::StrTab[ArchInfo->ArchFeature]);
7293 AArch64::getExtensionFeatures(Extensions: ArchInfo->DefaultExts, Features&: AArch64Features);
7294
7295 MCSubtargetInfo &STI = copySTI();
7296 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
7297 STI.setDefaultFeatures(CPU: "generic", /*TuneCPU*/ "generic",
7298 FS: join(Begin: ArchFeatures.begin(), End: ArchFeatures.end(), Separator: ","));
7299
7300 SmallVector<StringRef, 4> RequestedExtensions;
7301 if (!ExtensionString.empty())
7302 ExtensionString.split(A&: RequestedExtensions, Separator: '+');
7303
7304 ExpandCryptoAEK(ArchInfo: *ArchInfo, RequestedExtensions);
7305 CurLoc = incrementLoc(L: CurLoc, Offset: Arch.size());
7306
7307 for (auto Name : RequestedExtensions) {
7308 // Advance source location past '+'.
7309 CurLoc = incrementLoc(L: CurLoc, Offset: 1);
7310
7311 bool EnableFeature = !Name.consume_front_insensitive(Prefix: "no");
7312
7313 auto It = llvm::find_if(Range: ExtensionMap, P: [&Name](const auto &Extension) {
7314 return Extension.name() == Name;
7315 });
7316
7317 if (It == std::end(cont: ExtensionMap))
7318 return Error(L: CurLoc, Msg: "unsupported architectural extension: " + Name);
7319
7320 if (EnableFeature)
7321 STI.SetFeatureBitsTransitively(It->value());
7322 else
7323 STI.ClearFeatureBitsTransitively(FB: It->value());
7324 CurLoc = incrementLoc(L: CurLoc, Offset: Name.size());
7325 }
7326 FeatureBitset Features = ComputeAvailableFeatures(FB: STI.getFeatureBits());
7327 setAvailableFeatures(Features);
7328
7329 getTargetStreamer().emitDirectiveArch(Name);
7330 return false;
7331}
7332
7333/// parseDirectiveArchExtension
7334/// ::= .arch_extension [no]feature
7335bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
7336 SMLoc ExtLoc = getLoc();
7337
7338 StringRef FullName = getParser().parseStringToEndOfStatement().trim();
7339
7340 if (parseEOL())
7341 return true;
7342
7343 bool EnableFeature = true;
7344 StringRef Name = FullName;
7345 if (Name.starts_with_insensitive(Prefix: "no")) {
7346 EnableFeature = false;
7347 Name = Name.substr(Start: 2);
7348 }
7349
7350 auto It = llvm::find_if(Range: ExtensionMap, P: [&Name](const auto &Extension) {
7351 return Extension.name() == Name;
7352 });
7353
7354 if (It == std::end(cont: ExtensionMap))
7355 return Error(L: ExtLoc, Msg: "unsupported architectural extension: " + Name);
7356
7357 MCSubtargetInfo &STI = copySTI();
7358 if (EnableFeature)
7359 STI.SetFeatureBitsTransitively(It->value());
7360 else
7361 STI.ClearFeatureBitsTransitively(FB: It->value());
7362 FeatureBitset Features = ComputeAvailableFeatures(FB: STI.getFeatureBits());
7363 setAvailableFeatures(Features);
7364
7365 getTargetStreamer().emitDirectiveArchExtension(Name: FullName);
7366 return false;
7367}
7368
7369/// parseDirectiveCPU
7370/// ::= .cpu id
7371bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
7372 SMLoc CurLoc = getLoc();
7373
7374 StringRef CPU, ExtensionString;
7375 std::tie(args&: CPU, args&: ExtensionString) =
7376 getParser().parseStringToEndOfStatement().trim().split(Separator: '+');
7377
7378 if (parseToken(T: AsmToken::EndOfStatement))
7379 return true;
7380
7381 SmallVector<StringRef, 4> RequestedExtensions;
7382 if (!ExtensionString.empty())
7383 ExtensionString.split(A&: RequestedExtensions, Separator: '+');
7384
7385 const llvm::AArch64::ArchInfo *CpuArch = llvm::AArch64::getArchForCpu(CPU);
7386 if (!CpuArch) {
7387 Error(L: CurLoc, Msg: "unknown CPU name");
7388 return false;
7389 }
7390 ExpandCryptoAEK(ArchInfo: *CpuArch, RequestedExtensions);
7391
7392 MCSubtargetInfo &STI = copySTI();
7393 STI.setDefaultFeatures(CPU, /*TuneCPU*/ CPU, FS: "");
7394 CurLoc = incrementLoc(L: CurLoc, Offset: CPU.size());
7395
7396 for (auto Name : RequestedExtensions) {
7397 // Advance source location past '+'.
7398 CurLoc = incrementLoc(L: CurLoc, Offset: 1);
7399
7400 bool EnableFeature = !Name.consume_front_insensitive(Prefix: "no");
7401
7402 auto It = llvm::find_if(Range: ExtensionMap, P: [&Name](const auto &Extension) {
7403 return Extension.name() == Name;
7404 });
7405
7406 if (It == std::end(cont: ExtensionMap))
7407 return Error(L: CurLoc, Msg: "unsupported architectural extension: " + Name);
7408
7409 if (EnableFeature)
7410 STI.SetFeatureBitsTransitively(It->value());
7411 else
7412 STI.ClearFeatureBitsTransitively(FB: It->value());
7413 CurLoc = incrementLoc(L: CurLoc, Offset: Name.size());
7414 }
7415 FeatureBitset Features = ComputeAvailableFeatures(FB: STI.getFeatureBits());
7416 setAvailableFeatures(Features);
7417 return false;
7418}
7419
7420/// parseDirectiveInst
7421/// ::= .inst opcode [, ...]
7422bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
7423 if (getLexer().is(K: AsmToken::EndOfStatement))
7424 return Error(L: Loc, Msg: "expected expression following '.inst' directive");
7425
7426 auto parseOp = [&]() -> bool {
7427 SMLoc L = getLoc();
7428 const MCExpr *Expr = nullptr;
7429 if (check(P: getParser().parseExpression(Res&: Expr), Loc: L, Msg: "expected expression"))
7430 return true;
7431 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Val: Expr);
7432 if (check(P: !Value, Loc: L, Msg: "expected constant expression"))
7433 return true;
7434 getTargetStreamer().emitInst(Inst: Value->getValue());
7435 return false;
7436 };
7437
7438 return parseMany(parseOne: parseOp);
7439}
7440
7441// parseDirectiveTLSDescCall:
7442// ::= .tlsdesccall symbol (if IsAuth is false)
7443// ::= .tlsauthdesccall symbol (if IsAuth is true)
7444bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L, bool IsAuth) {
7445 StringRef Name;
7446 if (check(P: getParser().parseIdentifier(Res&: Name), Loc: L, Msg: "expected symbol") ||
7447 parseToken(T: AsmToken::EndOfStatement))
7448 return true;
7449
7450 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
7451 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol: Sym, Ctx&: getContext());
7452 Expr = MCSpecifierExpr::create(
7453 Expr, S: IsAuth ? AArch64::S_TLSDESC_AUTH : AArch64::S_TLSDESC,
7454 Ctx&: getContext());
7455
7456 MCInst Inst;
7457 Inst.setOpcode(IsAuth ? AArch64::TLSAUTHDESCCALL : AArch64::TLSDESCCALL);
7458 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
7459
7460 getParser().getStreamer().emitInstruction(Inst, STI: getSTI());
7461 return false;
7462}
7463
7464/// ::= .loh <lohName | lohId> label1, ..., labelN
7465/// The number of arguments depends on the loh identifier.
7466bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
7467 MCLOHType Kind;
7468 if (getTok().isNot(K: AsmToken::Identifier)) {
7469 if (getTok().isNot(K: AsmToken::Integer))
7470 return TokError(Msg: "expected an identifier or a number in directive");
7471 // We successfully get a numeric value for the identifier.
7472 // Check if it is valid.
7473 int64_t Id = getTok().getIntVal();
7474 if (Id <= -1U && !isValidMCLOHType(Kind: Id))
7475 return TokError(Msg: "invalid numeric identifier in directive");
7476 Kind = (MCLOHType)Id;
7477 } else {
7478 StringRef Name = getTok().getIdentifier();
7479 // We successfully parse an identifier.
7480 // Check if it is a recognized one.
7481 int Id = MCLOHNameToId(Name);
7482
7483 if (Id == -1)
7484 return TokError(Msg: "invalid identifier in directive");
7485 Kind = (MCLOHType)Id;
7486 }
7487 // Consume the identifier.
7488 Lex();
7489 // Get the number of arguments of this LOH.
7490 int NbArgs = MCLOHIdToNbArgs(Kind);
7491
7492 assert(NbArgs != -1 && "Invalid number of arguments");
7493
7494 SmallVector<MCSymbol *, 3> Args;
7495 for (int Idx = 0; Idx < NbArgs; ++Idx) {
7496 StringRef Name;
7497 if (getParser().parseIdentifier(Res&: Name))
7498 return TokError(Msg: "expected identifier in directive");
7499 Args.push_back(Elt: getContext().getOrCreateSymbol(Name));
7500
7501 if (Idx + 1 == NbArgs)
7502 break;
7503 if (parseComma())
7504 return true;
7505 }
7506 if (parseEOL())
7507 return true;
7508
7509 getStreamer().emitLOHDirective(Kind, Args);
7510 return false;
7511}
7512
7513/// parseDirectiveLtorg
7514/// ::= .ltorg | .pool
7515bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
7516 if (parseEOL())
7517 return true;
7518 getTargetStreamer().emitCurrentConstantPool();
7519 return false;
7520}
7521
7522/// parseDirectiveReq
7523/// ::= name .req registername
7524bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7525 Lex(); // Eat the '.req' token.
7526 SMLoc SRegLoc = getLoc();
7527 RegKind RegisterKind = RegKind::Scalar;
7528 MCRegister RegNum;
7529 ParseStatus ParseRes = tryParseScalarRegister(RegNum);
7530
7531 if (!ParseRes.isSuccess()) {
7532 StringRef Kind;
7533 RegisterKind = RegKind::NeonVector;
7534 ParseRes = tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::NeonVector);
7535
7536 if (ParseRes.isFailure())
7537 return true;
7538
7539 if (ParseRes.isSuccess() && !Kind.empty())
7540 return Error(L: SRegLoc, Msg: "vector register without type specifier expected");
7541 }
7542
7543 if (!ParseRes.isSuccess()) {
7544 StringRef Kind;
7545 RegisterKind = RegKind::SVEDataVector;
7546 ParseRes =
7547 tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::SVEDataVector);
7548
7549 if (ParseRes.isFailure())
7550 return true;
7551
7552 if (ParseRes.isSuccess() && !Kind.empty())
7553 return Error(L: SRegLoc,
7554 Msg: "sve vector register without type specifier expected");
7555 }
7556
7557 if (!ParseRes.isSuccess()) {
7558 StringRef Kind;
7559 RegisterKind = RegKind::SVEPredicateVector;
7560 ParseRes = tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::SVEPredicateVector);
7561
7562 if (ParseRes.isFailure())
7563 return true;
7564
7565 if (ParseRes.isSuccess() && !Kind.empty())
7566 return Error(L: SRegLoc,
7567 Msg: "sve predicate register without type specifier expected");
7568 }
7569
7570 if (!ParseRes.isSuccess())
7571 return Error(L: SRegLoc, Msg: "register name or alias expected");
7572
7573 // Shouldn't be anything else.
7574 if (parseEOL())
7575 return true;
7576
7577 auto pair = std::make_pair(x&: RegisterKind, y&: RegNum);
7578 if (RegisterReqs.insert(KV: std::make_pair(x&: Name, y&: pair)).first->second != pair)
7579 Warning(L, Msg: "ignoring redefinition of register alias '" + Name + "'");
7580
7581 return false;
7582}
7583
7584/// parseDirectiveUneq
7585/// ::= .unreq registername
7586bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
7587 if (getTok().isNot(K: AsmToken::Identifier))
7588 return TokError(Msg: "unexpected input in .unreq directive.");
7589 RegisterReqs.erase(Key: getTok().getIdentifier().lower());
7590 Lex(); // Eat the identifier.
7591 return parseToken(T: AsmToken::EndOfStatement);
7592}
7593
7594bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
7595 if (parseEOL())
7596 return true;
7597 getStreamer().emitCFINegateRAState();
7598 return false;
7599}
7600
7601bool AArch64AsmParser::parseDirectiveCFINegateRAStateWithPC() {
7602 if (parseEOL())
7603 return true;
7604 getStreamer().emitCFINegateRAStateWithPC();
7605 return false;
7606}
7607
7608/// parseDirectiveCFILLVMSetRAState
7609/// ::= .cfi_set_ra_state ra_state, offset
7610/// ::= .cfi_set_ra_state ra_state, pac_sym
7611bool AArch64AsmParser::parseDirectiveCFILLVMSetRAState() {
7612 int64_t State;
7613 if (getParser().parseAbsoluteExpression(Res&: State))
7614 return true;
7615 if (parseToken(T: AsmToken::Comma, Msg: "expected ','"))
7616 return true;
7617 const MCExpr *Expr;
7618 SMLoc ExprLoc = getLoc();
7619 if (getParser().parseExpression(Res&: Expr))
7620 return true;
7621 if (parseEOL())
7622 return true;
7623 if (auto *SymRef = dyn_cast<MCSymbolRefExpr>(Val: Expr)) {
7624 getStreamer().emitCFILLVMSetRAState(
7625 State: (unsigned)State, PACSym: const_cast<MCSymbol *>(&SymRef->getSymbol()));
7626 } else if (auto *CE = dyn_cast<MCConstantExpr>(Val: Expr)) {
7627 getStreamer().emitCFILLVMSetRAState(State: (unsigned)State, Offset: CE->getValue());
7628 } else {
7629 return Error(
7630 L: ExprLoc,
7631 Msg: "expected an integer offset or a symbol for .cfi_set_ra_state");
7632 }
7633 return false;
7634}
7635
7636/// parseDirectiveCFIBKeyFrame
7637/// ::= .cfi_b_key
7638bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
7639 if (parseEOL())
7640 return true;
7641 getStreamer().emitCFIBKeyFrame();
7642 return false;
7643}
7644
7645/// parseDirectiveCFIMTETaggedFrame
7646/// ::= .cfi_mte_tagged_frame
7647bool AArch64AsmParser::parseDirectiveCFIMTETaggedFrame() {
7648 if (parseEOL())
7649 return true;
7650 getStreamer().emitCFIMTETaggedFrame();
7651 return false;
7652}
7653
7654/// parseDirectiveVariantPCS
7655/// ::= .variant_pcs symbolname
7656bool AArch64AsmParser::parseDirectiveVariantPCS(SMLoc L) {
7657 StringRef Name;
7658 if (getParser().parseIdentifier(Res&: Name))
7659 return TokError(Msg: "expected symbol name");
7660 if (parseEOL())
7661 return true;
7662 getTargetStreamer().emitDirectiveVariantPCS(
7663 Symbol: getContext().getOrCreateSymbol(Name));
7664 return false;
7665}
7666
7667/// parseDirectiveSEHAllocStack
7668/// ::= .seh_stackalloc
7669bool AArch64AsmParser::parseDirectiveSEHAllocStack(SMLoc L) {
7670 int64_t Size;
7671 if (parseImmExpr(Out&: Size))
7672 return true;
7673 getTargetStreamer().emitARM64WinCFIAllocStack(Size);
7674 return false;
7675}
7676
7677/// parseDirectiveSEHPrologEnd
7678/// ::= .seh_endprologue
7679bool AArch64AsmParser::parseDirectiveSEHPrologEnd(SMLoc L) {
7680 getTargetStreamer().emitARM64WinCFIPrologEnd();
7681 return false;
7682}
7683
7684bool AArch64AsmParser::parseDirectiveSEHEndC(SMLoc L) {
7685 getTargetStreamer().emitARM64WinCFIEndC();
7686 return false;
7687}
7688
7689/// parseDirectiveSEHSaveR19R20X
7690/// ::= .seh_save_r19r20_x
7691bool AArch64AsmParser::parseDirectiveSEHSaveR19R20X(SMLoc L) {
7692 int64_t Offset;
7693 if (parseImmExpr(Out&: Offset))
7694 return true;
7695 getTargetStreamer().emitARM64WinCFISaveR19R20X(Offset);
7696 return false;
7697}
7698
7699/// parseDirectiveSEHSaveFPLR
7700/// ::= .seh_save_fplr
7701bool AArch64AsmParser::parseDirectiveSEHSaveFPLR(SMLoc L) {
7702 int64_t Offset;
7703 if (parseImmExpr(Out&: Offset))
7704 return true;
7705 getTargetStreamer().emitARM64WinCFISaveFPLR(Offset);
7706 return false;
7707}
7708
7709/// parseDirectiveSEHSaveFPLRX
7710/// ::= .seh_save_fplr_x
7711bool AArch64AsmParser::parseDirectiveSEHSaveFPLRX(SMLoc L) {
7712 int64_t Offset;
7713 if (parseImmExpr(Out&: Offset))
7714 return true;
7715 getTargetStreamer().emitARM64WinCFISaveFPLRX(Offset);
7716 return false;
7717}
7718
7719/// parseDirectiveSEHSaveReg
7720/// ::= .seh_save_reg
7721bool AArch64AsmParser::parseDirectiveSEHSaveReg(SMLoc L) {
7722 unsigned Reg;
7723 int64_t Offset;
7724 if (parseRegisterInRange(Out&: Reg, Base: AArch64::X0, First: AArch64::X19, Last: AArch64::LR) ||
7725 parseComma() || parseImmExpr(Out&: Offset))
7726 return true;
7727 getTargetStreamer().emitARM64WinCFISaveReg(Reg, Offset);
7728 return false;
7729}
7730
7731/// parseDirectiveSEHSaveRegX
7732/// ::= .seh_save_reg_x
7733bool AArch64AsmParser::parseDirectiveSEHSaveRegX(SMLoc L) {
7734 unsigned Reg;
7735 int64_t Offset;
7736 if (parseRegisterInRange(Out&: Reg, Base: AArch64::X0, First: AArch64::X19, Last: AArch64::LR) ||
7737 parseComma() || parseImmExpr(Out&: Offset))
7738 return true;
7739 getTargetStreamer().emitARM64WinCFISaveRegX(Reg, Offset);
7740 return false;
7741}
7742
7743/// parseDirectiveSEHSaveRegP
7744/// ::= .seh_save_regp
7745bool AArch64AsmParser::parseDirectiveSEHSaveRegP(SMLoc L) {
7746 unsigned Reg;
7747 int64_t Offset;
7748 if (parseRegisterInRange(Out&: Reg, Base: AArch64::X0, First: AArch64::X19, Last: AArch64::FP) ||
7749 parseComma() || parseImmExpr(Out&: Offset))
7750 return true;
7751 getTargetStreamer().emitARM64WinCFISaveRegP(Reg, Offset);
7752 return false;
7753}
7754
7755/// parseDirectiveSEHSaveRegPX
7756/// ::= .seh_save_regp_x
7757bool AArch64AsmParser::parseDirectiveSEHSaveRegPX(SMLoc L) {
7758 unsigned Reg;
7759 int64_t Offset;
7760 if (parseRegisterInRange(Out&: Reg, Base: AArch64::X0, First: AArch64::X19, Last: AArch64::FP) ||
7761 parseComma() || parseImmExpr(Out&: Offset))
7762 return true;
7763 getTargetStreamer().emitARM64WinCFISaveRegPX(Reg, Offset);
7764 return false;
7765}
7766
7767/// parseDirectiveSEHSaveLRPair
7768/// ::= .seh_save_lrpair
7769bool AArch64AsmParser::parseDirectiveSEHSaveLRPair(SMLoc L) {
7770 unsigned Reg;
7771 int64_t Offset;
7772 L = getLoc();
7773 if (parseRegisterInRange(Out&: Reg, Base: AArch64::X0, First: AArch64::X19, Last: AArch64::LR) ||
7774 parseComma() || parseImmExpr(Out&: Offset))
7775 return true;
7776 if (check(P: ((Reg - 19) % 2 != 0), Loc: L,
7777 Msg: "expected register with even offset from x19"))
7778 return true;
7779 getTargetStreamer().emitARM64WinCFISaveLRPair(Reg, Offset);
7780 return false;
7781}
7782
7783/// parseDirectiveSEHSaveFReg
7784/// ::= .seh_save_freg
7785bool AArch64AsmParser::parseDirectiveSEHSaveFReg(SMLoc L) {
7786 unsigned Reg;
7787 int64_t Offset;
7788 if (parseRegisterInRange(Out&: Reg, Base: AArch64::D0, First: AArch64::D8, Last: AArch64::D15) ||
7789 parseComma() || parseImmExpr(Out&: Offset))
7790 return true;
7791 getTargetStreamer().emitARM64WinCFISaveFReg(Reg, Offset);
7792 return false;
7793}
7794
7795/// parseDirectiveSEHSaveFRegX
7796/// ::= .seh_save_freg_x
7797bool AArch64AsmParser::parseDirectiveSEHSaveFRegX(SMLoc L) {
7798 unsigned Reg;
7799 int64_t Offset;
7800 if (parseRegisterInRange(Out&: Reg, Base: AArch64::D0, First: AArch64::D8, Last: AArch64::D15) ||
7801 parseComma() || parseImmExpr(Out&: Offset))
7802 return true;
7803 getTargetStreamer().emitARM64WinCFISaveFRegX(Reg, Offset);
7804 return false;
7805}
7806
7807/// parseDirectiveSEHSaveFRegP
7808/// ::= .seh_save_fregp
7809bool AArch64AsmParser::parseDirectiveSEHSaveFRegP(SMLoc L) {
7810 unsigned Reg;
7811 int64_t Offset;
7812 if (parseRegisterInRange(Out&: Reg, Base: AArch64::D0, First: AArch64::D8, Last: AArch64::D14) ||
7813 parseComma() || parseImmExpr(Out&: Offset))
7814 return true;
7815 getTargetStreamer().emitARM64WinCFISaveFRegP(Reg, Offset);
7816 return false;
7817}
7818
7819/// parseDirectiveSEHSaveFRegPX
7820/// ::= .seh_save_fregp_x
7821bool AArch64AsmParser::parseDirectiveSEHSaveFRegPX(SMLoc L) {
7822 unsigned Reg;
7823 int64_t Offset;
7824 if (parseRegisterInRange(Out&: Reg, Base: AArch64::D0, First: AArch64::D8, Last: AArch64::D14) ||
7825 parseComma() || parseImmExpr(Out&: Offset))
7826 return true;
7827 getTargetStreamer().emitARM64WinCFISaveFRegPX(Reg, Offset);
7828 return false;
7829}
7830
7831/// parseDirectiveSEHSetFP
7832/// ::= .seh_set_fp
7833bool AArch64AsmParser::parseDirectiveSEHSetFP(SMLoc L) {
7834 getTargetStreamer().emitARM64WinCFISetFP();
7835 return false;
7836}
7837
7838/// parseDirectiveSEHAddFP
7839/// ::= .seh_add_fp
7840bool AArch64AsmParser::parseDirectiveSEHAddFP(SMLoc L) {
7841 int64_t Size;
7842 if (parseImmExpr(Out&: Size))
7843 return true;
7844 getTargetStreamer().emitARM64WinCFIAddFP(Size);
7845 return false;
7846}
7847
7848/// parseDirectiveSEHNop
7849/// ::= .seh_nop
7850bool AArch64AsmParser::parseDirectiveSEHNop(SMLoc L) {
7851 getTargetStreamer().emitARM64WinCFINop();
7852 return false;
7853}
7854
7855/// parseDirectiveSEHSaveNext
7856/// ::= .seh_save_next
7857bool AArch64AsmParser::parseDirectiveSEHSaveNext(SMLoc L) {
7858 getTargetStreamer().emitARM64WinCFISaveNext();
7859 return false;
7860}
7861
7862/// parseDirectiveSEHEpilogStart
7863/// ::= .seh_startepilogue
7864bool AArch64AsmParser::parseDirectiveSEHEpilogStart(SMLoc L) {
7865 getTargetStreamer().emitARM64WinCFIEpilogStart();
7866 return false;
7867}
7868
7869/// parseDirectiveSEHEpilogEnd
7870/// ::= .seh_endepilogue
7871bool AArch64AsmParser::parseDirectiveSEHEpilogEnd(SMLoc L) {
7872 getTargetStreamer().emitARM64WinCFIEpilogEnd();
7873 return false;
7874}
7875
7876/// parseDirectiveSEHTrapFrame
7877/// ::= .seh_trap_frame
7878bool AArch64AsmParser::parseDirectiveSEHTrapFrame(SMLoc L) {
7879 getTargetStreamer().emitARM64WinCFITrapFrame();
7880 return false;
7881}
7882
7883/// parseDirectiveSEHMachineFrame
7884/// ::= .seh_pushframe
7885bool AArch64AsmParser::parseDirectiveSEHMachineFrame(SMLoc L) {
7886 getTargetStreamer().emitARM64WinCFIMachineFrame();
7887 return false;
7888}
7889
7890/// parseDirectiveSEHContext
7891/// ::= .seh_context
7892bool AArch64AsmParser::parseDirectiveSEHContext(SMLoc L) {
7893 getTargetStreamer().emitARM64WinCFIContext();
7894 return false;
7895}
7896
7897/// parseDirectiveSEHECContext
7898/// ::= .seh_ec_context
7899bool AArch64AsmParser::parseDirectiveSEHECContext(SMLoc L) {
7900 getTargetStreamer().emitARM64WinCFIECContext();
7901 return false;
7902}
7903
7904/// parseDirectiveSEHClearUnwoundToCall
7905/// ::= .seh_clear_unwound_to_call
7906bool AArch64AsmParser::parseDirectiveSEHClearUnwoundToCall(SMLoc L) {
7907 getTargetStreamer().emitARM64WinCFIClearUnwoundToCall();
7908 return false;
7909}
7910
7911/// parseDirectiveSEHPACSignLR
7912/// ::= .seh_pac_sign_lr
7913bool AArch64AsmParser::parseDirectiveSEHPACSignLR(SMLoc L) {
7914 getTargetStreamer().emitARM64WinCFIPACSignLR();
7915 return false;
7916}
7917
7918/// parseDirectiveSEHSaveAnyReg
7919/// ::= .seh_save_any_reg
7920/// ::= .seh_save_any_reg_p
7921/// ::= .seh_save_any_reg_x
7922/// ::= .seh_save_any_reg_px
7923bool AArch64AsmParser::parseDirectiveSEHSaveAnyReg(SMLoc L, bool Paired,
7924 bool Writeback) {
7925 MCRegister Reg;
7926 SMLoc Start, End;
7927 int64_t Offset;
7928 if (check(P: parseRegister(Reg, StartLoc&: Start, EndLoc&: End), Loc: getLoc(), Msg: "expected register") ||
7929 parseComma() || parseImmExpr(Out&: Offset))
7930 return true;
7931
7932 if (Reg == AArch64::FP || Reg == AArch64::LR ||
7933 (Reg >= AArch64::X0 && Reg <= AArch64::X28)) {
7934 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7935 return Error(L, Msg: "invalid save_any_reg offset");
7936 unsigned EncodedReg;
7937 if (Reg == AArch64::FP)
7938 EncodedReg = 29;
7939 else if (Reg == AArch64::LR)
7940 EncodedReg = 30;
7941 else
7942 EncodedReg = Reg - AArch64::X0;
7943 if (Paired) {
7944 if (Reg == AArch64::LR)
7945 return Error(L: Start, Msg: "lr cannot be paired with another register");
7946 if (Writeback)
7947 getTargetStreamer().emitARM64WinCFISaveAnyRegIPX(Reg: EncodedReg, Offset);
7948 else
7949 getTargetStreamer().emitARM64WinCFISaveAnyRegIP(Reg: EncodedReg, Offset);
7950 } else {
7951 if (Writeback)
7952 getTargetStreamer().emitARM64WinCFISaveAnyRegIX(Reg: EncodedReg, Offset);
7953 else
7954 getTargetStreamer().emitARM64WinCFISaveAnyRegI(Reg: EncodedReg, Offset);
7955 }
7956 } else if (Reg >= AArch64::D0 && Reg <= AArch64::D31) {
7957 unsigned EncodedReg = Reg - AArch64::D0;
7958 if (Offset < 0 || Offset % (Paired || Writeback ? 16 : 8))
7959 return Error(L, Msg: "invalid save_any_reg offset");
7960 if (Paired) {
7961 if (Reg == AArch64::D31)
7962 return Error(L: Start, Msg: "d31 cannot be paired with another register");
7963 if (Writeback)
7964 getTargetStreamer().emitARM64WinCFISaveAnyRegDPX(Reg: EncodedReg, Offset);
7965 else
7966 getTargetStreamer().emitARM64WinCFISaveAnyRegDP(Reg: EncodedReg, Offset);
7967 } else {
7968 if (Writeback)
7969 getTargetStreamer().emitARM64WinCFISaveAnyRegDX(Reg: EncodedReg, Offset);
7970 else
7971 getTargetStreamer().emitARM64WinCFISaveAnyRegD(Reg: EncodedReg, Offset);
7972 }
7973 } else if (Reg >= AArch64::Q0 && Reg <= AArch64::Q31) {
7974 unsigned EncodedReg = Reg - AArch64::Q0;
7975 if (Offset < 0 || Offset % 16)
7976 return Error(L, Msg: "invalid save_any_reg offset");
7977 if (Paired) {
7978 if (Reg == AArch64::Q31)
7979 return Error(L: Start, Msg: "q31 cannot be paired with another register");
7980 if (Writeback)
7981 getTargetStreamer().emitARM64WinCFISaveAnyRegQPX(Reg: EncodedReg, Offset);
7982 else
7983 getTargetStreamer().emitARM64WinCFISaveAnyRegQP(Reg: EncodedReg, Offset);
7984 } else {
7985 if (Writeback)
7986 getTargetStreamer().emitARM64WinCFISaveAnyRegQX(Reg: EncodedReg, Offset);
7987 else
7988 getTargetStreamer().emitARM64WinCFISaveAnyRegQ(Reg: EncodedReg, Offset);
7989 }
7990 } else {
7991 return Error(L: Start, Msg: "save_any_reg register must be x, q or d register");
7992 }
7993 return false;
7994}
7995
7996/// parseDirectiveAllocZ
7997/// ::= .seh_allocz
7998bool AArch64AsmParser::parseDirectiveSEHAllocZ(SMLoc L) {
7999 int64_t Offset;
8000 if (parseImmExpr(Out&: Offset))
8001 return true;
8002 getTargetStreamer().emitARM64WinCFIAllocZ(Offset);
8003 return false;
8004}
8005
8006/// parseDirectiveSEHSaveZReg
8007/// ::= .seh_save_zreg
8008bool AArch64AsmParser::parseDirectiveSEHSaveZReg(SMLoc L) {
8009 MCRegister RegNum;
8010 StringRef Kind;
8011 int64_t Offset;
8012 ParseStatus Res =
8013 tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::SVEDataVector);
8014 if (!Res.isSuccess())
8015 return true;
8016 if (check(P: RegNum < AArch64::Z8 || RegNum > AArch64::Z23, Loc: L,
8017 Msg: "expected register in range z8 to z23"))
8018 return true;
8019 if (parseComma() || parseImmExpr(Out&: Offset))
8020 return true;
8021 getTargetStreamer().emitARM64WinCFISaveZReg(Reg: RegNum - AArch64::Z0, Offset);
8022 return false;
8023}
8024
8025/// parseDirectiveSEHSavePReg
8026/// ::= .seh_save_preg
8027bool AArch64AsmParser::parseDirectiveSEHSavePReg(SMLoc L) {
8028 MCRegister RegNum;
8029 StringRef Kind;
8030 int64_t Offset;
8031 ParseStatus Res =
8032 tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::SVEPredicateVector);
8033 if (!Res.isSuccess())
8034 return true;
8035 if (check(P: RegNum < AArch64::P4 || RegNum > AArch64::P15, Loc: L,
8036 Msg: "expected register in range p4 to p15"))
8037 return true;
8038 if (parseComma() || parseImmExpr(Out&: Offset))
8039 return true;
8040 getTargetStreamer().emitARM64WinCFISavePReg(Reg: RegNum - AArch64::P0, Offset);
8041 return false;
8042}
8043
8044bool AArch64AsmParser::parseDirectiveAeabiSubSectionHeader(SMLoc L) {
8045 // Handle parsing of .aeabi_subsection directives
8046 // - On first declaration of a subsection, expect exactly three identifiers
8047 // after `.aeabi_subsection`: the subsection name and two parameters.
8048 // - When switching to an existing subsection, it is valid to provide only
8049 // the subsection name, or the name together with the two parameters.
8050 MCAsmParser &Parser = getParser();
8051
8052 // Consume the name (subsection name)
8053 StringRef SubsectionName;
8054 AArch64BuildAttributes::VendorID SubsectionNameID;
8055 if (Parser.getTok().is(K: AsmToken::Identifier)) {
8056 SubsectionName = Parser.getTok().getIdentifier();
8057 SubsectionNameID = AArch64BuildAttributes::getVendorID(Vendor: SubsectionName);
8058 } else {
8059 Error(L: Parser.getTok().getLoc(), Msg: "subsection name not found");
8060 return true;
8061 }
8062 Parser.Lex();
8063
8064 std::unique_ptr<MCELFStreamer::AttributeSubSection> SubsectionExists =
8065 getTargetStreamer().getAttributesSubsectionByName(Name: SubsectionName);
8066 // Check whether only the subsection name was provided.
8067 // If so, the user is trying to switch to a subsection that should have been
8068 // declared before.
8069 if (Parser.getTok().is(K: llvm::AsmToken::EndOfStatement)) {
8070 if (SubsectionExists) {
8071 getTargetStreamer().emitAttributesSubsection(
8072 VendorName: SubsectionName,
8073 IsOptional: static_cast<AArch64BuildAttributes::SubsectionOptional>(
8074 SubsectionExists->IsOptional),
8075 ParameterType: static_cast<AArch64BuildAttributes::SubsectionType>(
8076 SubsectionExists->ParameterType));
8077 return false;
8078 }
8079 // If subsection does not exists, report error.
8080 else {
8081 Error(L: Parser.getTok().getLoc(),
8082 Msg: "Could not switch to subsection '" + SubsectionName +
8083 "' using subsection name, subsection has not been defined");
8084 return true;
8085 }
8086 }
8087
8088 // Otherwise, expecting 2 more parameters: consume a comma
8089 // parseComma() return *false* on success, and call Lex(), no need to call
8090 // Lex() again.
8091 if (Parser.parseComma()) {
8092 return true;
8093 }
8094
8095 // Consume the first parameter (optionality parameter)
8096 AArch64BuildAttributes::SubsectionOptional IsOptional;
8097 // options: optional/required
8098 if (Parser.getTok().is(K: AsmToken::Identifier)) {
8099 StringRef Optionality = Parser.getTok().getIdentifier();
8100 IsOptional = AArch64BuildAttributes::getOptionalID(Optional: Optionality);
8101 if (AArch64BuildAttributes::OPTIONAL_NOT_FOUND == IsOptional) {
8102 Error(L: Parser.getTok().getLoc(),
8103 Msg: AArch64BuildAttributes::getSubsectionOptionalUnknownError());
8104 return true;
8105 }
8106 if (SubsectionExists) {
8107 if (IsOptional != SubsectionExists->IsOptional) {
8108 Error(L: Parser.getTok().getLoc(),
8109 Msg: "optionality mismatch! subsection '" + SubsectionName +
8110 "' already exists with optionality defined as '" +
8111 AArch64BuildAttributes::getOptionalStr(
8112 Optional: SubsectionExists->IsOptional) +
8113 "' and not '" +
8114 AArch64BuildAttributes::getOptionalStr(Optional: IsOptional) + "'");
8115 return true;
8116 }
8117 }
8118 } else {
8119 Error(L: Parser.getTok().getLoc(),
8120 Msg: "optionality parameter not found, expected required|optional");
8121 return true;
8122 }
8123 // Check for possible IsOptional unaccepted values for known subsections
8124 if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID) {
8125 if (AArch64BuildAttributes::REQUIRED == IsOptional) {
8126 Error(L: Parser.getTok().getLoc(),
8127 Msg: "aeabi_feature_and_bits must be marked as optional");
8128 return true;
8129 }
8130 }
8131 if (AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) {
8132 if (AArch64BuildAttributes::OPTIONAL == IsOptional) {
8133 Error(L: Parser.getTok().getLoc(),
8134 Msg: "aeabi_pauthabi must be marked as required");
8135 return true;
8136 }
8137 }
8138 Parser.Lex();
8139 // consume a comma
8140 if (Parser.parseComma()) {
8141 return true;
8142 }
8143
8144 // Consume the second parameter (type parameter)
8145 AArch64BuildAttributes::SubsectionType Type;
8146 if (Parser.getTok().is(K: AsmToken::Identifier)) {
8147 StringRef Name = Parser.getTok().getIdentifier();
8148 Type = AArch64BuildAttributes::getTypeID(Type: Name);
8149 if (AArch64BuildAttributes::TYPE_NOT_FOUND == Type) {
8150 Error(L: Parser.getTok().getLoc(),
8151 Msg: AArch64BuildAttributes::getSubsectionTypeUnknownError());
8152 return true;
8153 }
8154 if (SubsectionExists) {
8155 if (Type != SubsectionExists->ParameterType) {
8156 Error(L: Parser.getTok().getLoc(),
8157 Msg: "type mismatch! subsection '" + SubsectionName +
8158 "' already exists with type defined as '" +
8159 AArch64BuildAttributes::getTypeStr(
8160 Type: SubsectionExists->ParameterType) +
8161 "' and not '" + AArch64BuildAttributes::getTypeStr(Type) +
8162 "'");
8163 return true;
8164 }
8165 }
8166 } else {
8167 Error(L: Parser.getTok().getLoc(),
8168 Msg: "type parameter not found, expected uleb128|ntbs");
8169 return true;
8170 }
8171 // Check for possible unaccepted 'type' values for known subsections
8172 if (AArch64BuildAttributes::AEABI_FEATURE_AND_BITS == SubsectionNameID ||
8173 AArch64BuildAttributes::AEABI_PAUTHABI == SubsectionNameID) {
8174 if (AArch64BuildAttributes::NTBS == Type) {
8175 Error(L: Parser.getTok().getLoc(),
8176 Msg: SubsectionName + " must be marked as ULEB128");
8177 return true;
8178 }
8179 }
8180 Parser.Lex();
8181
8182 // Parsing finished, check for trailing tokens.
8183 if (Parser.getTok().isNot(K: llvm::AsmToken::EndOfStatement)) {
8184 Error(L: Parser.getTok().getLoc(), Msg: "unexpected token for AArch64 build "
8185 "attributes subsection header directive");
8186 return true;
8187 }
8188
8189 getTargetStreamer().emitAttributesSubsection(VendorName: SubsectionName, IsOptional, ParameterType: Type);
8190
8191 return false;
8192}
8193
8194bool AArch64AsmParser::parseDirectiveAeabiAArch64Attr(SMLoc L) {
8195 // Expecting 2 Tokens: after '.aeabi_attribute', e.g.:
8196 // .aeabi_attribute (1)Tag_Feature_BTI, (2)[uleb128|ntbs]
8197 // separated by a comma.
8198 MCAsmParser &Parser = getParser();
8199
8200 std::unique_ptr<MCELFStreamer::AttributeSubSection> ActiveSubsection =
8201 getTargetStreamer().getActiveAttributesSubsection();
8202 if (nullptr == ActiveSubsection) {
8203 Error(L: Parser.getTok().getLoc(),
8204 Msg: "no active subsection, build attribute can not be added");
8205 return true;
8206 }
8207 StringRef ActiveSubsectionName = ActiveSubsection->VendorName;
8208 unsigned ActiveSubsectionType = ActiveSubsection->ParameterType;
8209
8210 unsigned ActiveSubsectionID = AArch64BuildAttributes::VENDOR_UNKNOWN;
8211 if (AArch64BuildAttributes::getVendorName(
8212 Vendor: AArch64BuildAttributes::AEABI_PAUTHABI) == ActiveSubsectionName)
8213 ActiveSubsectionID = AArch64BuildAttributes::AEABI_PAUTHABI;
8214 if (AArch64BuildAttributes::getVendorName(
8215 Vendor: AArch64BuildAttributes::AEABI_FEATURE_AND_BITS) ==
8216 ActiveSubsectionName)
8217 ActiveSubsectionID = AArch64BuildAttributes::AEABI_FEATURE_AND_BITS;
8218
8219 StringRef TagStr = "";
8220 unsigned Tag;
8221 if (Parser.getTok().is(K: AsmToken::Integer)) {
8222 Tag = getTok().getIntVal();
8223 } else if (Parser.getTok().is(K: AsmToken::Identifier)) {
8224 TagStr = Parser.getTok().getIdentifier();
8225 switch (ActiveSubsectionID) {
8226 case AArch64BuildAttributes::VENDOR_UNKNOWN:
8227 // Tag was provided as an unrecognized string instead of an unsigned
8228 // integer
8229 Error(L: Parser.getTok().getLoc(), Msg: "unrecognized Tag: '" + TagStr +
8230 "' \nExcept for public subsections, "
8231 "tags have to be an unsigned int.");
8232 return true;
8233 break;
8234 case AArch64BuildAttributes::AEABI_PAUTHABI:
8235 Tag = AArch64BuildAttributes::getPauthABITagsID(PauthABITag: TagStr);
8236 if (AArch64BuildAttributes::PAUTHABI_TAG_NOT_FOUND == Tag) {
8237 Error(L: Parser.getTok().getLoc(), Msg: "unknown AArch64 build attribute '" +
8238 TagStr + "' for subsection '" +
8239 ActiveSubsectionName + "'");
8240 return true;
8241 }
8242 break;
8243 case AArch64BuildAttributes::AEABI_FEATURE_AND_BITS:
8244 Tag = AArch64BuildAttributes::getFeatureAndBitsTagsID(FeatureAndBitsTag: TagStr);
8245 if (AArch64BuildAttributes::FEATURE_AND_BITS_TAG_NOT_FOUND == Tag) {
8246 Error(L: Parser.getTok().getLoc(), Msg: "unknown AArch64 build attribute '" +
8247 TagStr + "' for subsection '" +
8248 ActiveSubsectionName + "'");
8249 return true;
8250 }
8251 break;
8252 }
8253 } else {
8254 Error(L: Parser.getTok().getLoc(), Msg: "AArch64 build attributes tag not found");
8255 return true;
8256 }
8257 Parser.Lex();
8258 // consume a comma
8259 // parseComma() return *false* on success, and call Lex(), no need to call
8260 // Lex() again.
8261 if (Parser.parseComma()) {
8262 return true;
8263 }
8264
8265 // Consume the second parameter (attribute value)
8266 unsigned ValueInt = unsigned(-1);
8267 std::string ValueStr = "";
8268 if (Parser.getTok().is(K: AsmToken::Integer)) {
8269 if (AArch64BuildAttributes::NTBS == ActiveSubsectionType) {
8270 Error(
8271 L: Parser.getTok().getLoc(),
8272 Msg: "active subsection type is NTBS (string), found ULEB128 (unsigned)");
8273 return true;
8274 }
8275 ValueInt = getTok().getIntVal();
8276 } else if (Parser.getTok().is(K: AsmToken::Identifier)) {
8277 if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) {
8278 Error(
8279 L: Parser.getTok().getLoc(),
8280 Msg: "active subsection type is ULEB128 (unsigned), found NTBS (string)");
8281 return true;
8282 }
8283 ValueStr = Parser.getTok().getIdentifier();
8284 } else if (Parser.getTok().is(K: AsmToken::String)) {
8285 if (AArch64BuildAttributes::ULEB128 == ActiveSubsectionType) {
8286 Error(
8287 L: Parser.getTok().getLoc(),
8288 Msg: "active subsection type is ULEB128 (unsigned), found NTBS (string)");
8289 return true;
8290 }
8291 ValueStr = Parser.getTok().getString();
8292 } else {
8293 Error(L: Parser.getTok().getLoc(), Msg: "AArch64 build attributes value not found");
8294 return true;
8295 }
8296 // Check for possible unaccepted values for known tags
8297 // (AEABI_FEATURE_AND_BITS)
8298 if (ActiveSubsectionID == AArch64BuildAttributes::AEABI_FEATURE_AND_BITS) {
8299 if (0 != ValueInt && 1 != ValueInt) {
8300 Error(L: Parser.getTok().getLoc(),
8301 Msg: "unknown AArch64 build attributes Value for Tag '" + TagStr +
8302 "' options are 0|1");
8303 return true;
8304 }
8305 }
8306 Parser.Lex();
8307
8308 // Parsing finished. Check for trailing tokens.
8309 if (Parser.getTok().isNot(K: llvm::AsmToken::EndOfStatement)) {
8310 Error(L: Parser.getTok().getLoc(),
8311 Msg: "unexpected token for AArch64 build attributes tag and value "
8312 "attribute directive");
8313 return true;
8314 }
8315
8316 if (unsigned(-1) != ValueInt) {
8317 getTargetStreamer().emitAttribute(VendorName: ActiveSubsectionName, Tag, Value: ValueInt, String: "");
8318 }
8319 if ("" != ValueStr) {
8320 getTargetStreamer().emitAttribute(VendorName: ActiveSubsectionName, Tag, Value: unsigned(-1),
8321 String: ValueStr);
8322 }
8323 return false;
8324}
8325
8326bool AArch64AsmParser::parseExprWithSpecifier(const MCExpr *&Res, SMLoc &E) {
8327 SMLoc Loc = getLoc();
8328 if (getLexer().getKind() != AsmToken::Identifier)
8329 return TokError(Msg: "expected '%' relocation specifier");
8330 StringRef Identifier = getParser().getTok().getIdentifier();
8331 auto Spec = AArch64::parsePercentSpecifierName(Identifier);
8332 if (!Spec)
8333 return TokError(Msg: "invalid relocation specifier");
8334
8335 getParser().Lex(); // Eat the identifier
8336 if (parseToken(T: AsmToken::LParen, Msg: "expected '('"))
8337 return true;
8338
8339 const MCExpr *SubExpr;
8340 if (getParser().parseParenExpression(Res&: SubExpr, EndLoc&: E))
8341 return true;
8342
8343 Res = MCSpecifierExpr::create(Expr: SubExpr, S: Spec, Ctx&: getContext(), Loc);
8344 return false;
8345}
8346
8347bool AArch64AsmParser::parseDataExpr(const MCExpr *&Res) {
8348 SMLoc EndLoc;
8349 if (parseOptionalToken(T: AsmToken::Percent))
8350 return parseExprWithSpecifier(Res, E&: EndLoc);
8351
8352 if (getParser().parseExpression(Res))
8353 return true;
8354 MCAsmParser &Parser = getParser();
8355 if (!parseOptionalToken(T: AsmToken::At))
8356 return false;
8357 if (getLexer().getKind() != AsmToken::Identifier)
8358 return Error(L: getLoc(), Msg: "expected relocation specifier");
8359
8360 std::string Identifier = Parser.getTok().getIdentifier().lower();
8361 SMLoc Loc = getLoc();
8362 Lex();
8363 if (Identifier == "auth")
8364 return parseAuthExpr(Res, EndLoc);
8365
8366 auto Spec = AArch64::S_None;
8367 if (STI->getTargetTriple().isOSBinFormatMachO()) {
8368 if (Identifier == "got")
8369 Spec = AArch64::S_MACHO_GOT;
8370 }
8371 if (Spec == AArch64::S_None)
8372 return Error(L: Loc, Msg: "invalid relocation specifier");
8373 if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Val: Res))
8374 Res = MCSymbolRefExpr::create(Symbol: &SRE->getSymbol(), specifier: Spec, Ctx&: getContext(),
8375 Loc: SRE->getLoc());
8376 else
8377 return Error(L: Loc, Msg: "@ specifier only allowed after a symbol");
8378
8379 for (;;) {
8380 std::optional<MCBinaryExpr::Opcode> Opcode;
8381 if (parseOptionalToken(T: AsmToken::Plus))
8382 Opcode = MCBinaryExpr::Add;
8383 else if (parseOptionalToken(T: AsmToken::Minus))
8384 Opcode = MCBinaryExpr::Sub;
8385 else
8386 break;
8387 const MCExpr *Term;
8388 if (getParser().parsePrimaryExpr(Res&: Term, EndLoc, TypeInfo: nullptr))
8389 return true;
8390 Res = MCBinaryExpr::create(Op: *Opcode, LHS: Res, RHS: Term, Ctx&: getContext(), Loc: Res->getLoc());
8391 }
8392 return false;
8393}
8394
8395/// parseAuthExpr
8396/// ::= _sym@AUTH(ib,123[,addr])
8397/// ::= (_sym + 5)@AUTH(ib,123[,addr])
8398/// ::= (_sym - 5)@AUTH(ib,123[,addr])
8399bool AArch64AsmParser::parseAuthExpr(const MCExpr *&Res, SMLoc &EndLoc) {
8400 MCAsmParser &Parser = getParser();
8401 MCContext &Ctx = getContext();
8402 AsmToken Tok = Parser.getTok();
8403
8404 // At this point, we encountered "<id>@AUTH". There is no fallback anymore.
8405 if (parseToken(T: AsmToken::LParen, Msg: "expected '('"))
8406 return true;
8407
8408 if (Parser.getTok().isNot(K: AsmToken::Identifier))
8409 return TokError(Msg: "expected key name");
8410
8411 StringRef KeyStr = Parser.getTok().getIdentifier();
8412 auto KeyIDOrNone = AArch64StringToPACKeyID(Name: KeyStr);
8413 if (!KeyIDOrNone)
8414 return TokError(Msg: "invalid key '" + KeyStr + "'");
8415 Parser.Lex();
8416
8417 if (parseToken(T: AsmToken::Comma, Msg: "expected ','"))
8418 return true;
8419
8420 if (Parser.getTok().isNot(K: AsmToken::Integer))
8421 return TokError(Msg: "expected integer discriminator");
8422 int64_t Discriminator = Parser.getTok().getIntVal();
8423
8424 if (!isUInt<16>(x: Discriminator))
8425 return TokError(Msg: "integer discriminator " + Twine(Discriminator) +
8426 " out of range [0, 0xFFFF]");
8427 Parser.Lex();
8428
8429 bool UseAddressDiversity = false;
8430 if (Parser.getTok().is(K: AsmToken::Comma)) {
8431 Parser.Lex();
8432 if (Parser.getTok().isNot(K: AsmToken::Identifier) ||
8433 Parser.getTok().getIdentifier() != "addr")
8434 return TokError(Msg: "expected 'addr'");
8435 UseAddressDiversity = true;
8436 Parser.Lex();
8437 }
8438
8439 EndLoc = Parser.getTok().getEndLoc();
8440 if (parseToken(T: AsmToken::RParen, Msg: "expected ')'"))
8441 return true;
8442
8443 Res = AArch64AuthMCExpr::create(Expr: Res, Discriminator, Key: *KeyIDOrNone,
8444 HasAddressDiversity: UseAddressDiversity, Ctx, Loc: Res->getLoc());
8445 return false;
8446}
8447
8448bool AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
8449 AArch64::Specifier &ELFSpec,
8450 AArch64::Specifier &DarwinSpec,
8451 int64_t &Addend) {
8452 ELFSpec = AArch64::S_INVALID;
8453 DarwinSpec = AArch64::S_None;
8454 Addend = 0;
8455
8456 if (auto *AE = dyn_cast<MCSpecifierExpr>(Val: Expr)) {
8457 ELFSpec = AE->getSpecifier();
8458 Expr = AE->getSubExpr();
8459 }
8460
8461 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Val: Expr);
8462 if (SE) {
8463 // It's a simple symbol reference with no addend.
8464 DarwinSpec = AArch64::Specifier(SE->getKind());
8465 return true;
8466 }
8467
8468 // Check that it looks like a symbol + an addend
8469 MCValue Res;
8470 bool Relocatable = Expr->evaluateAsRelocatable(Res, Asm: nullptr);
8471 if (!Relocatable || Res.getSubSym())
8472 return false;
8473
8474 // Treat expressions with an ELFSpec (like ":abs_g1:3", or
8475 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
8476 if (!Res.getAddSym() && ELFSpec == AArch64::S_INVALID)
8477 return false;
8478
8479 if (Res.getAddSym())
8480 DarwinSpec = AArch64::Specifier(Res.getSpecifier());
8481 Addend = Res.getConstant();
8482
8483 // It's some symbol reference + a constant addend, but really
8484 // shouldn't use both Darwin and ELF syntax.
8485 return ELFSpec == AArch64::S_INVALID || DarwinSpec == AArch64::S_None;
8486}
8487
8488/// Force static initialization.
8489extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
8490LLVMInitializeAArch64AsmParser() {
8491 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
8492 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
8493 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
8494 RegisterMCAsmParser<AArch64AsmParser> W(getTheARM64_32Target());
8495 RegisterMCAsmParser<AArch64AsmParser> V(getTheAArch64_32Target());
8496}
8497
8498#define GET_REGISTER_MATCHER
8499#define GET_SUBTARGET_FEATURE_NAME
8500#define GET_MATCHER_IMPLEMENTATION
8501#define GET_MNEMONIC_SPELL_CHECKER
8502#include "AArch64GenAsmMatcher.inc"
8503
8504// Define this matcher function after the auto-generated include so we
8505// have the match class enum definitions.
8506unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
8507 unsigned Kind) {
8508 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
8509
8510 auto MatchesOpImmediate = [&](int64_t ExpectedVal) -> MatchResultTy {
8511 if (!Op.isImm())
8512 return Match_InvalidOperand;
8513 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Op.getImm());
8514 if (!CE)
8515 return Match_InvalidOperand;
8516 if (CE->getValue() == ExpectedVal)
8517 return Match_Success;
8518 return Match_InvalidOperand;
8519 };
8520
8521 switch (Kind) {
8522 default:
8523 return Match_InvalidOperand;
8524 case MCK_MPR:
8525 // If the Kind is a token for the MPR register class which has the "za"
8526 // register (SME accumulator array), check if the asm is a literal "za"
8527 // token. This is for the "smstart za" alias that defines the register
8528 // as a literal token.
8529 if (Op.isTokenEqual(Str: "za"))
8530 return Match_Success;
8531 return Match_InvalidOperand;
8532
8533 // If the kind is a token for a literal immediate, check if our asm operand
8534 // matches. This is for InstAliases which have a fixed-value immediate in
8535 // the asm string, such as hints which are parsed into a specific
8536 // instruction definition.
8537#define MATCH_HASH(N) \
8538 case MCK__HASH_##N: \
8539 return MatchesOpImmediate(N);
8540 MATCH_HASH(0)
8541 MATCH_HASH(1)
8542 MATCH_HASH(2)
8543 MATCH_HASH(3)
8544 MATCH_HASH(4)
8545 MATCH_HASH(6)
8546 MATCH_HASH(7)
8547 MATCH_HASH(8)
8548 MATCH_HASH(10)
8549 MATCH_HASH(12)
8550 MATCH_HASH(14)
8551 MATCH_HASH(16)
8552 MATCH_HASH(24)
8553 MATCH_HASH(25)
8554 MATCH_HASH(26)
8555 MATCH_HASH(27)
8556 MATCH_HASH(28)
8557 MATCH_HASH(29)
8558 MATCH_HASH(30)
8559 MATCH_HASH(31)
8560 MATCH_HASH(32)
8561 MATCH_HASH(40)
8562 MATCH_HASH(48)
8563 MATCH_HASH(64)
8564#undef MATCH_HASH
8565#define MATCH_HASH_MINUS(N) \
8566 case MCK__HASH__MINUS_##N: \
8567 return MatchesOpImmediate(-N);
8568 MATCH_HASH_MINUS(4)
8569 MATCH_HASH_MINUS(8)
8570 MATCH_HASH_MINUS(16)
8571#undef MATCH_HASH_MINUS
8572 }
8573}
8574
8575ParseStatus AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
8576
8577 SMLoc S = getLoc();
8578
8579 if (getTok().isNot(K: AsmToken::Identifier))
8580 return Error(L: S, Msg: "expected register");
8581
8582 MCRegister FirstReg;
8583 ParseStatus Res = tryParseScalarRegister(RegNum&: FirstReg);
8584 if (!Res.isSuccess())
8585 return Error(L: S, Msg: "expected first even register of a consecutive same-size "
8586 "even/odd register pair");
8587
8588 const MCRegisterClass &WRegClass =
8589 getAArch64MCRegisterClass(RC: AArch64::GPR32RegClassID);
8590 const MCRegisterClass &XRegClass =
8591 getAArch64MCRegisterClass(RC: AArch64::GPR64RegClassID);
8592
8593 bool isXReg = XRegClass.contains(Reg: FirstReg),
8594 isWReg = WRegClass.contains(Reg: FirstReg);
8595 if (!isXReg && !isWReg)
8596 return Error(L: S, Msg: "expected first even register of a consecutive same-size "
8597 "even/odd register pair");
8598
8599 const MCRegisterInfo *RI = getContext().getRegisterInfo();
8600 unsigned FirstEncoding = RI->getEncodingValue(Reg: FirstReg);
8601
8602 if (FirstEncoding & 0x1)
8603 return Error(L: S, Msg: "expected first even register of a consecutive same-size "
8604 "even/odd register pair");
8605
8606 if (getTok().isNot(K: AsmToken::Comma))
8607 return Error(L: getLoc(), Msg: "expected comma");
8608 // Eat the comma
8609 Lex();
8610
8611 SMLoc E = getLoc();
8612 MCRegister SecondReg;
8613 Res = tryParseScalarRegister(RegNum&: SecondReg);
8614 if (!Res.isSuccess())
8615 return Error(L: E, Msg: "expected second odd register of a consecutive same-size "
8616 "even/odd register pair");
8617
8618 if (RI->getEncodingValue(Reg: SecondReg) != FirstEncoding + 1 ||
8619 (isXReg && !XRegClass.contains(Reg: SecondReg)) ||
8620 (isWReg && !WRegClass.contains(Reg: SecondReg)))
8621 return Error(L: E, Msg: "expected second odd register of a consecutive same-size "
8622 "even/odd register pair");
8623
8624 MCRegister Pair;
8625 if (isXReg) {
8626 Pair = RI->getMatchingSuperReg(
8627 Reg: FirstReg, SubIdx: AArch64::sube64,
8628 RC: &getAArch64MCRegisterClass(RC: AArch64::XSeqPairsClassRegClassID));
8629 } else {
8630 Pair = RI->getMatchingSuperReg(
8631 Reg: FirstReg, SubIdx: AArch64::sube32,
8632 RC: &getAArch64MCRegisterClass(RC: AArch64::WSeqPairsClassRegClassID));
8633 }
8634
8635 Operands.push_back(Elt: AArch64Operand::CreateReg(Reg: Pair, Kind: RegKind::Scalar, S,
8636 E: getLoc(), Ctx&: getContext()));
8637
8638 return ParseStatus::Success;
8639}
8640
8641template <bool ParseShiftExtend, bool ParseSuffix>
8642ParseStatus AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
8643 const SMLoc S = getLoc();
8644 // Check for a SVE vector register specifier first.
8645 MCRegister RegNum;
8646 StringRef Kind;
8647
8648 ParseStatus Res =
8649 tryParseVectorRegister(Reg&: RegNum, Kind, MatchKind: RegKind::SVEDataVector);
8650
8651 if (!Res.isSuccess())
8652 return Res;
8653
8654 if (ParseSuffix && Kind.empty())
8655 return ParseStatus::NoMatch;
8656
8657 const auto &KindRes = parseVectorKind(Suffix: Kind, VectorKind: RegKind::SVEDataVector);
8658 if (!KindRes)
8659 return ParseStatus::NoMatch;
8660
8661 unsigned ElementWidth = KindRes->second;
8662
8663 // No shift/extend is the default.
8664 if (!ParseShiftExtend || getTok().isNot(K: AsmToken::Comma)) {
8665 Operands.push_back(Elt: AArch64Operand::CreateVectorReg(
8666 Reg: RegNum, Kind: RegKind::SVEDataVector, ElementWidth, S, E: S, Ctx&: getContext()));
8667
8668 ParseStatus Res = tryParseVectorIndex(Operands);
8669 if (Res.isFailure())
8670 return ParseStatus::Failure;
8671 return ParseStatus::Success;
8672 }
8673
8674 // Eat the comma
8675 Lex();
8676
8677 // Match the shift
8678 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
8679 Res = tryParseOptionalShiftExtend(Operands&: ExtOpnd);
8680 if (!Res.isSuccess())
8681 return Res;
8682
8683 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
8684 Operands.push_back(Elt: AArch64Operand::CreateVectorReg(
8685 Reg: RegNum, Kind: RegKind::SVEDataVector, ElementWidth, S, E: Ext->getEndLoc(),
8686 Ctx&: getContext(), ExtTy: Ext->getShiftExtendType(), ShiftAmount: Ext->getShiftExtendAmount(),
8687 HasExplicitAmount: Ext->hasShiftExtendAmount()));
8688
8689 return ParseStatus::Success;
8690}
8691
8692ParseStatus AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
8693 SMLoc SS = getLoc();
8694 const AsmToken &TokE = getTok();
8695
8696 if (TokE.isNot(K: AsmToken::Identifier))
8697 return ParseStatus::NoMatch;
8698
8699 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(Name: TokE.getString());
8700 if (!Pat)
8701 return ParseStatus::NoMatch;
8702
8703 Lex();
8704 int64_t Pattern = Pat->Encoding;
8705 assert(Pattern >= 0 && Pattern < 32);
8706
8707 Operands.push_back(
8708 Elt: AArch64Operand::CreateImm(Val: MCConstantExpr::create(Value: Pattern, Ctx&: getContext()),
8709 S: SS, E: getLoc(), Ctx&: getContext()));
8710
8711 return ParseStatus::Success;
8712}
8713
8714ParseStatus
8715AArch64AsmParser::tryParseSVEVecLenSpecifier(OperandVector &Operands) {
8716 int64_t Pattern;
8717 SMLoc SS = getLoc();
8718 const AsmToken &TokE = getTok();
8719 // Parse the pattern
8720 auto Pat = AArch64SVEVecLenSpecifier::lookupSVEVECLENSPECIFIERByName(
8721 Name: TokE.getString());
8722 if (!Pat)
8723 return ParseStatus::NoMatch;
8724
8725 Lex();
8726 Pattern = Pat->Encoding;
8727 assert(Pattern >= 0 && Pattern <= 1 && "Pattern does not exist");
8728
8729 Operands.push_back(
8730 Elt: AArch64Operand::CreateImm(Val: MCConstantExpr::create(Value: Pattern, Ctx&: getContext()),
8731 S: SS, E: getLoc(), Ctx&: getContext()));
8732
8733 return ParseStatus::Success;
8734}
8735
8736ParseStatus AArch64AsmParser::tryParseGPR64x8(OperandVector &Operands) {
8737 SMLoc SS = getLoc();
8738
8739 MCRegister XReg;
8740 if (!tryParseScalarRegister(RegNum&: XReg).isSuccess())
8741 return ParseStatus::NoMatch;
8742
8743 MCContext &ctx = getContext();
8744 const MCRegisterInfo *RI = ctx.getRegisterInfo();
8745 MCRegister X8Reg = RI->getMatchingSuperReg(
8746 Reg: XReg, SubIdx: AArch64::x8sub_0,
8747 RC: &getAArch64MCRegisterClass(RC: AArch64::GPR64x8ClassRegClassID));
8748 if (!X8Reg)
8749 return Error(L: SS,
8750 Msg: "expected an even-numbered x-register in the range [x0,x22]");
8751
8752 Operands.push_back(
8753 Elt: AArch64Operand::CreateReg(Reg: X8Reg, Kind: RegKind::Scalar, S: SS, E: getLoc(), Ctx&: ctx));
8754 return ParseStatus::Success;
8755}
8756
8757ParseStatus AArch64AsmParser::tryParseImmRange(OperandVector &Operands) {
8758 SMLoc S = getLoc();
8759
8760 if (getTok().isNot(K: AsmToken::Integer))
8761 return ParseStatus::NoMatch;
8762
8763 if (getLexer().peekTok().isNot(K: AsmToken::Colon))
8764 return ParseStatus::NoMatch;
8765
8766 const MCExpr *ImmF;
8767 if (getParser().parseExpression(Res&: ImmF))
8768 return ParseStatus::NoMatch;
8769
8770 if (getTok().isNot(K: AsmToken::Colon))
8771 return ParseStatus::NoMatch;
8772
8773 Lex(); // Eat ':'
8774 if (getTok().isNot(K: AsmToken::Integer))
8775 return ParseStatus::NoMatch;
8776
8777 SMLoc E = getTok().getLoc();
8778 const MCExpr *ImmL;
8779 if (getParser().parseExpression(Res&: ImmL))
8780 return ParseStatus::NoMatch;
8781
8782 unsigned ImmFVal = cast<MCConstantExpr>(Val: ImmF)->getValue();
8783 unsigned ImmLVal = cast<MCConstantExpr>(Val: ImmL)->getValue();
8784
8785 Operands.push_back(
8786 Elt: AArch64Operand::CreateImmRange(First: ImmFVal, Last: ImmLVal, S, E, Ctx&: getContext()));
8787 return ParseStatus::Success;
8788}
8789