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