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