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