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