1 //==- AArch64AsmParser.cpp - Parse AArch64 assembly to MCInst instructions -==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "MCTargetDesc/AArch64AddressingModes.h"
11 #include "MCTargetDesc/AArch64MCExpr.h"
12 #include "MCTargetDesc/AArch64MCTargetDesc.h"
13 #include "MCTargetDesc/AArch64TargetStreamer.h"
14 #include "AArch64InstrInfo.h"
15 #include "Utils/AArch64BaseInfo.h"
16 #include "llvm/ADT/APFloat.h"
17 #include "llvm/ADT/APInt.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringExtras.h"
22 #include "llvm/ADT/StringMap.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/MC/MCContext.h"
27 #include "llvm/MC/MCExpr.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCLinkerOptimizationHint.h"
30 #include "llvm/MC/MCObjectFileInfo.h"
31 #include "llvm/MC/MCParser/MCAsmLexer.h"
32 #include "llvm/MC/MCParser/MCAsmParser.h"
33 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
34 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
35 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
36 #include "llvm/MC/MCRegisterInfo.h"
37 #include "llvm/MC/MCStreamer.h"
38 #include "llvm/MC/MCSubtargetInfo.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/MC/MCTargetOptions.h"
41 #include "llvm/MC/SubtargetFeature.h"
42 #include "llvm/MC/MCValue.h"
43 #include "llvm/Support/Casting.h"
44 #include "llvm/Support/Compiler.h"
45 #include "llvm/Support/ErrorHandling.h"
46 #include "llvm/Support/MathExtras.h"
47 #include "llvm/Support/SMLoc.h"
48 #include "llvm/Support/TargetParser.h"
49 #include "llvm/Support/TargetRegistry.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include <cassert>
52 #include <cctype>
53 #include <cstdint>
54 #include <cstdio>
55 #include <string>
56 #include <tuple>
57 #include <utility>
58 #include <vector>
59
60 using namespace llvm;
61
62 namespace {
63
64 enum class RegKind {
65 Scalar,
66 NeonVector,
67 SVEDataVector,
68 SVEPredicateVector
69 };
70
71 enum RegConstraintEqualityTy {
72 EqualsReg,
73 EqualsSuperReg,
74 EqualsSubReg
75 };
76
77 class AArch64AsmParser : public MCTargetAsmParser {
78 private:
79 StringRef Mnemonic; ///< Instruction mnemonic.
80
81 // Map of register aliases registers via the .req directive.
82 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
83
84 class PrefixInfo {
85 public:
CreateFromInst(const MCInst & Inst,uint64_t TSFlags)86 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
87 PrefixInfo Prefix;
88 switch (Inst.getOpcode()) {
89 case AArch64::MOVPRFX_ZZ:
90 Prefix.Active = true;
91 Prefix.Dst = Inst.getOperand(0).getReg();
92 break;
93 case AArch64::MOVPRFX_ZPmZ_B:
94 case AArch64::MOVPRFX_ZPmZ_H:
95 case AArch64::MOVPRFX_ZPmZ_S:
96 case AArch64::MOVPRFX_ZPmZ_D:
97 Prefix.Active = true;
98 Prefix.Predicated = true;
99 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
100 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
101 "No destructive element size set for movprfx");
102 Prefix.Dst = Inst.getOperand(0).getReg();
103 Prefix.Pg = Inst.getOperand(2).getReg();
104 break;
105 case AArch64::MOVPRFX_ZPzZ_B:
106 case AArch64::MOVPRFX_ZPzZ_H:
107 case AArch64::MOVPRFX_ZPzZ_S:
108 case AArch64::MOVPRFX_ZPzZ_D:
109 Prefix.Active = true;
110 Prefix.Predicated = true;
111 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
112 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
113 "No destructive element size set for movprfx");
114 Prefix.Dst = Inst.getOperand(0).getReg();
115 Prefix.Pg = Inst.getOperand(1).getReg();
116 break;
117 default:
118 break;
119 }
120
121 return Prefix;
122 }
123
PrefixInfo()124 PrefixInfo() : Active(false), Predicated(false) {}
isActive() const125 bool isActive() const { return Active; }
isPredicated() const126 bool isPredicated() const { return Predicated; }
getElementSize() const127 unsigned getElementSize() const {
128 assert(Predicated);
129 return ElementSize;
130 }
getDstReg() const131 unsigned getDstReg() const { return Dst; }
getPgReg() const132 unsigned getPgReg() const {
133 assert(Predicated);
134 return Pg;
135 }
136
137 private:
138 bool Active;
139 bool Predicated;
140 unsigned ElementSize;
141 unsigned Dst;
142 unsigned Pg;
143 } NextPrefix;
144
getTargetStreamer()145 AArch64TargetStreamer &getTargetStreamer() {
146 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
147 return static_cast<AArch64TargetStreamer &>(TS);
148 }
149
getLoc() const150 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
151
152 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
153 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
154 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
155 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
156 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
157 bool parseRegister(OperandVector &Operands);
158 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
159 bool parseNeonVectorList(OperandVector &Operands);
160 bool parseOptionalMulOperand(OperandVector &Operands);
161 bool parseOperand(OperandVector &Operands, bool isCondCode,
162 bool invertCondCode);
163
164 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
165 OperandVector &Operands);
166
167 bool parseDirectiveArch(SMLoc L);
168 bool parseDirectiveArchExtension(SMLoc L);
169 bool parseDirectiveCPU(SMLoc L);
170 bool parseDirectiveInst(SMLoc L);
171
172 bool parseDirectiveTLSDescCall(SMLoc L);
173
174 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
175 bool parseDirectiveLtorg(SMLoc L);
176
177 bool parseDirectiveReq(StringRef Name, SMLoc L);
178 bool parseDirectiveUnreq(SMLoc L);
179 bool parseDirectiveCFINegateRAState();
180 bool parseDirectiveCFIBKeyFrame();
181
182 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
183 SmallVectorImpl<SMLoc> &Loc);
184 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
185 OperandVector &Operands, MCStreamer &Out,
186 uint64_t &ErrorInfo,
187 bool MatchingInlineAsm) override;
188 /// @name Auto-generated Match Functions
189 /// {
190
191 #define GET_ASSEMBLER_HEADER
192 #include "AArch64GenAsmMatcher.inc"
193
194 /// }
195
196 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
197 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
198 RegKind MatchKind);
199 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
200 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
201 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
202 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
203 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
204 template <bool IsSVEPrefetch = false>
205 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
206 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
207 OperandMatchResultTy tryParseBTIHint(OperandVector &Operands);
208 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
209 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
210 template<bool AddFPZeroAsLiteral>
211 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
212 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
213 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
214 bool tryParseNeonVectorRegister(OperandVector &Operands);
215 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
216 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
217 template <bool ParseShiftExtend,
218 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
219 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
220 template <bool ParseShiftExtend, bool ParseSuffix>
221 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
222 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
223 template <RegKind VectorKind>
224 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
225 bool ExpectMatch = false);
226 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
227
228 public:
229 enum AArch64MatchResultTy {
230 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
231 #define GET_OPERAND_DIAGNOSTIC_TYPES
232 #include "AArch64GenAsmMatcher.inc"
233 };
234 bool IsILP32;
235
AArch64AsmParser(const MCSubtargetInfo & STI,MCAsmParser & Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)236 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
237 const MCInstrInfo &MII, const MCTargetOptions &Options)
238 : MCTargetAsmParser(Options, STI, MII) {
239 IsILP32 = Options.getABIName() == "ilp32";
240 MCAsmParserExtension::Initialize(Parser);
241 MCStreamer &S = getParser().getStreamer();
242 if (S.getTargetStreamer() == nullptr)
243 new AArch64TargetStreamer(S);
244
245 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
246 // directives as they have the same form and semantics:
247 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
248 Parser.addAliasForDirective(".hword", ".2byte");
249 Parser.addAliasForDirective(".word", ".4byte");
250 Parser.addAliasForDirective(".xword", ".8byte");
251
252 // Initialize the set of available features.
253 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
254 }
255
256 bool regsEqual(const MCParsedAsmOperand &Op1,
257 const MCParsedAsmOperand &Op2) const override;
258 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
259 SMLoc NameLoc, OperandVector &Operands) override;
260 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
261 bool ParseDirective(AsmToken DirectiveID) override;
262 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
263 unsigned Kind) override;
264
265 static bool classifySymbolRef(const MCExpr *Expr,
266 AArch64MCExpr::VariantKind &ELFRefKind,
267 MCSymbolRefExpr::VariantKind &DarwinRefKind,
268 int64_t &Addend);
269 };
270
271 /// AArch64Operand - Instances of this class represent a parsed AArch64 machine
272 /// instruction.
273 class AArch64Operand : public MCParsedAsmOperand {
274 private:
275 enum KindTy {
276 k_Immediate,
277 k_ShiftedImm,
278 k_CondCode,
279 k_Register,
280 k_VectorList,
281 k_VectorIndex,
282 k_Token,
283 k_SysReg,
284 k_SysCR,
285 k_Prefetch,
286 k_ShiftExtend,
287 k_FPImm,
288 k_Barrier,
289 k_PSBHint,
290 k_BTIHint,
291 } Kind;
292
293 SMLoc StartLoc, EndLoc;
294
295 struct TokOp {
296 const char *Data;
297 unsigned Length;
298 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
299 };
300
301 // Separate shift/extend operand.
302 struct ShiftExtendOp {
303 AArch64_AM::ShiftExtendType Type;
304 unsigned Amount;
305 bool HasExplicitAmount;
306 };
307
308 struct RegOp {
309 unsigned RegNum;
310 RegKind Kind;
311 int ElementWidth;
312
313 // The register may be allowed as a different register class,
314 // e.g. for GPR64as32 or GPR32as64.
315 RegConstraintEqualityTy EqualityTy;
316
317 // In some cases the shift/extend needs to be explicitly parsed together
318 // with the register, rather than as a separate operand. This is needed
319 // for addressing modes where the instruction as a whole dictates the
320 // scaling/extend, rather than specific bits in the instruction.
321 // By parsing them as a single operand, we avoid the need to pass an
322 // extra operand in all CodeGen patterns (because all operands need to
323 // have an associated value), and we avoid the need to update TableGen to
324 // accept operands that have no associated bits in the instruction.
325 //
326 // An added benefit of parsing them together is that the assembler
327 // can give a sensible diagnostic if the scaling is not correct.
328 //
329 // The default is 'lsl #0' (HasExplicitAmount = false) if no
330 // ShiftExtend is specified.
331 ShiftExtendOp ShiftExtend;
332 };
333
334 struct VectorListOp {
335 unsigned RegNum;
336 unsigned Count;
337 unsigned NumElements;
338 unsigned ElementWidth;
339 RegKind RegisterKind;
340 };
341
342 struct VectorIndexOp {
343 unsigned Val;
344 };
345
346 struct ImmOp {
347 const MCExpr *Val;
348 };
349
350 struct ShiftedImmOp {
351 const MCExpr *Val;
352 unsigned ShiftAmount;
353 };
354
355 struct CondCodeOp {
356 AArch64CC::CondCode Code;
357 };
358
359 struct FPImmOp {
360 uint64_t Val; // APFloat value bitcasted to uint64_t.
361 bool IsExact; // describes whether parsed value was exact.
362 };
363
364 struct BarrierOp {
365 const char *Data;
366 unsigned Length;
367 unsigned Val; // Not the enum since not all values have names.
368 };
369
370 struct SysRegOp {
371 const char *Data;
372 unsigned Length;
373 uint32_t MRSReg;
374 uint32_t MSRReg;
375 uint32_t PStateField;
376 };
377
378 struct SysCRImmOp {
379 unsigned Val;
380 };
381
382 struct PrefetchOp {
383 const char *Data;
384 unsigned Length;
385 unsigned Val;
386 };
387
388 struct PSBHintOp {
389 const char *Data;
390 unsigned Length;
391 unsigned Val;
392 };
393
394 struct BTIHintOp {
395 const char *Data;
396 unsigned Length;
397 unsigned Val;
398 };
399
400 struct ExtendOp {
401 unsigned Val;
402 };
403
404 union {
405 struct TokOp Tok;
406 struct RegOp Reg;
407 struct VectorListOp VectorList;
408 struct VectorIndexOp VectorIndex;
409 struct ImmOp Imm;
410 struct ShiftedImmOp ShiftedImm;
411 struct CondCodeOp CondCode;
412 struct FPImmOp FPImm;
413 struct BarrierOp Barrier;
414 struct SysRegOp SysReg;
415 struct SysCRImmOp SysCRImm;
416 struct PrefetchOp Prefetch;
417 struct PSBHintOp PSBHint;
418 struct BTIHintOp BTIHint;
419 struct ShiftExtendOp ShiftExtend;
420 };
421
422 // Keep the MCContext around as the MCExprs may need manipulated during
423 // the add<>Operands() calls.
424 MCContext &Ctx;
425
426 public:
AArch64Operand(KindTy K,MCContext & Ctx)427 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
428
AArch64Operand(const AArch64Operand & o)429 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
430 Kind = o.Kind;
431 StartLoc = o.StartLoc;
432 EndLoc = o.EndLoc;
433 switch (Kind) {
434 case k_Token:
435 Tok = o.Tok;
436 break;
437 case k_Immediate:
438 Imm = o.Imm;
439 break;
440 case k_ShiftedImm:
441 ShiftedImm = o.ShiftedImm;
442 break;
443 case k_CondCode:
444 CondCode = o.CondCode;
445 break;
446 case k_FPImm:
447 FPImm = o.FPImm;
448 break;
449 case k_Barrier:
450 Barrier = o.Barrier;
451 break;
452 case k_Register:
453 Reg = o.Reg;
454 break;
455 case k_VectorList:
456 VectorList = o.VectorList;
457 break;
458 case k_VectorIndex:
459 VectorIndex = o.VectorIndex;
460 break;
461 case k_SysReg:
462 SysReg = o.SysReg;
463 break;
464 case k_SysCR:
465 SysCRImm = o.SysCRImm;
466 break;
467 case k_Prefetch:
468 Prefetch = o.Prefetch;
469 break;
470 case k_PSBHint:
471 PSBHint = o.PSBHint;
472 break;
473 case k_BTIHint:
474 BTIHint = o.BTIHint;
475 break;
476 case k_ShiftExtend:
477 ShiftExtend = o.ShiftExtend;
478 break;
479 }
480 }
481
482 /// getStartLoc - Get the location of the first token of this operand.
getStartLoc() const483 SMLoc getStartLoc() const override { return StartLoc; }
484 /// getEndLoc - Get the location of the last token of this operand.
getEndLoc() const485 SMLoc getEndLoc() const override { return EndLoc; }
486
getToken() const487 StringRef getToken() const {
488 assert(Kind == k_Token && "Invalid access!");
489 return StringRef(Tok.Data, Tok.Length);
490 }
491
isTokenSuffix() const492 bool isTokenSuffix() const {
493 assert(Kind == k_Token && "Invalid access!");
494 return Tok.IsSuffix;
495 }
496
getImm() const497 const MCExpr *getImm() const {
498 assert(Kind == k_Immediate && "Invalid access!");
499 return Imm.Val;
500 }
501
getShiftedImmVal() const502 const MCExpr *getShiftedImmVal() const {
503 assert(Kind == k_ShiftedImm && "Invalid access!");
504 return ShiftedImm.Val;
505 }
506
getShiftedImmShift() const507 unsigned getShiftedImmShift() const {
508 assert(Kind == k_ShiftedImm && "Invalid access!");
509 return ShiftedImm.ShiftAmount;
510 }
511
getCondCode() const512 AArch64CC::CondCode getCondCode() const {
513 assert(Kind == k_CondCode && "Invalid access!");
514 return CondCode.Code;
515 }
516
getFPImm() const517 APFloat getFPImm() const {
518 assert (Kind == k_FPImm && "Invalid access!");
519 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
520 }
521
getFPImmIsExact() const522 bool getFPImmIsExact() const {
523 assert (Kind == k_FPImm && "Invalid access!");
524 return FPImm.IsExact;
525 }
526
getBarrier() const527 unsigned getBarrier() const {
528 assert(Kind == k_Barrier && "Invalid access!");
529 return Barrier.Val;
530 }
531
getBarrierName() const532 StringRef getBarrierName() const {
533 assert(Kind == k_Barrier && "Invalid access!");
534 return StringRef(Barrier.Data, Barrier.Length);
535 }
536
getReg() const537 unsigned getReg() const override {
538 assert(Kind == k_Register && "Invalid access!");
539 return Reg.RegNum;
540 }
541
getRegEqualityTy() const542 RegConstraintEqualityTy getRegEqualityTy() const {
543 assert(Kind == k_Register && "Invalid access!");
544 return Reg.EqualityTy;
545 }
546
getVectorListStart() const547 unsigned getVectorListStart() const {
548 assert(Kind == k_VectorList && "Invalid access!");
549 return VectorList.RegNum;
550 }
551
getVectorListCount() const552 unsigned getVectorListCount() const {
553 assert(Kind == k_VectorList && "Invalid access!");
554 return VectorList.Count;
555 }
556
getVectorIndex() const557 unsigned getVectorIndex() const {
558 assert(Kind == k_VectorIndex && "Invalid access!");
559 return VectorIndex.Val;
560 }
561
getSysReg() const562 StringRef getSysReg() const {
563 assert(Kind == k_SysReg && "Invalid access!");
564 return StringRef(SysReg.Data, SysReg.Length);
565 }
566
getSysCR() const567 unsigned getSysCR() const {
568 assert(Kind == k_SysCR && "Invalid access!");
569 return SysCRImm.Val;
570 }
571
getPrefetch() const572 unsigned getPrefetch() const {
573 assert(Kind == k_Prefetch && "Invalid access!");
574 return Prefetch.Val;
575 }
576
getPSBHint() const577 unsigned getPSBHint() const {
578 assert(Kind == k_PSBHint && "Invalid access!");
579 return PSBHint.Val;
580 }
581
getPSBHintName() const582 StringRef getPSBHintName() const {
583 assert(Kind == k_PSBHint && "Invalid access!");
584 return StringRef(PSBHint.Data, PSBHint.Length);
585 }
586
getBTIHint() const587 unsigned getBTIHint() const {
588 assert(Kind == k_BTIHint && "Invalid access!");
589 return BTIHint.Val;
590 }
591
getBTIHintName() const592 StringRef getBTIHintName() const {
593 assert(Kind == k_BTIHint && "Invalid access!");
594 return StringRef(BTIHint.Data, BTIHint.Length);
595 }
596
getPrefetchName() const597 StringRef getPrefetchName() const {
598 assert(Kind == k_Prefetch && "Invalid access!");
599 return StringRef(Prefetch.Data, Prefetch.Length);
600 }
601
getShiftExtendType() const602 AArch64_AM::ShiftExtendType getShiftExtendType() const {
603 if (Kind == k_ShiftExtend)
604 return ShiftExtend.Type;
605 if (Kind == k_Register)
606 return Reg.ShiftExtend.Type;
607 llvm_unreachable("Invalid access!");
608 }
609
getShiftExtendAmount() const610 unsigned getShiftExtendAmount() const {
611 if (Kind == k_ShiftExtend)
612 return ShiftExtend.Amount;
613 if (Kind == k_Register)
614 return Reg.ShiftExtend.Amount;
615 llvm_unreachable("Invalid access!");
616 }
617
hasShiftExtendAmount() const618 bool hasShiftExtendAmount() const {
619 if (Kind == k_ShiftExtend)
620 return ShiftExtend.HasExplicitAmount;
621 if (Kind == k_Register)
622 return Reg.ShiftExtend.HasExplicitAmount;
623 llvm_unreachable("Invalid access!");
624 }
625
isImm() const626 bool isImm() const override { return Kind == k_Immediate; }
isMem() const627 bool isMem() const override { return false; }
628
isUImm6() const629 bool isUImm6() const {
630 if (!isImm())
631 return false;
632 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
633 if (!MCE)
634 return false;
635 int64_t Val = MCE->getValue();
636 return (Val >= 0 && Val < 64);
637 }
638
isSImm() const639 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
640
isSImmScaled() const641 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
642 return isImmScaled<Bits, Scale>(true);
643 }
644
isUImmScaled() const645 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
646 return isImmScaled<Bits, Scale>(false);
647 }
648
649 template <int Bits, int Scale>
isImmScaled(bool Signed) const650 DiagnosticPredicate isImmScaled(bool Signed) const {
651 if (!isImm())
652 return DiagnosticPredicateTy::NoMatch;
653
654 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
655 if (!MCE)
656 return DiagnosticPredicateTy::NoMatch;
657
658 int64_t MinVal, MaxVal;
659 if (Signed) {
660 int64_t Shift = Bits - 1;
661 MinVal = (int64_t(1) << Shift) * -Scale;
662 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
663 } else {
664 MinVal = 0;
665 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
666 }
667
668 int64_t Val = MCE->getValue();
669 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
670 return DiagnosticPredicateTy::Match;
671
672 return DiagnosticPredicateTy::NearMatch;
673 }
674
isSVEPattern() const675 DiagnosticPredicate isSVEPattern() const {
676 if (!isImm())
677 return DiagnosticPredicateTy::NoMatch;
678 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
679 if (!MCE)
680 return DiagnosticPredicateTy::NoMatch;
681 int64_t Val = MCE->getValue();
682 if (Val >= 0 && Val < 32)
683 return DiagnosticPredicateTy::Match;
684 return DiagnosticPredicateTy::NearMatch;
685 }
686
isSymbolicUImm12Offset(const MCExpr * Expr) const687 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
688 AArch64MCExpr::VariantKind ELFRefKind;
689 MCSymbolRefExpr::VariantKind DarwinRefKind;
690 int64_t Addend;
691 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
692 Addend)) {
693 // If we don't understand the expression, assume the best and
694 // let the fixup and relocation code deal with it.
695 return true;
696 }
697
698 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
699 ELFRefKind == AArch64MCExpr::VK_LO12 ||
700 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
701 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
702 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
703 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
704 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
705 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
706 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
707 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
708 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
709 // Note that we don't range-check the addend. It's adjusted modulo page
710 // size when converted, so there is no "out of range" condition when using
711 // @pageoff.
712 return true;
713 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
714 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
715 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
716 return Addend == 0;
717 }
718
719 return false;
720 }
721
isUImm12Offset() const722 template <int Scale> bool isUImm12Offset() const {
723 if (!isImm())
724 return false;
725
726 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
727 if (!MCE)
728 return isSymbolicUImm12Offset(getImm());
729
730 int64_t Val = MCE->getValue();
731 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
732 }
733
734 template <int N, int M>
isImmInRange() const735 bool isImmInRange() const {
736 if (!isImm())
737 return false;
738 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
739 if (!MCE)
740 return false;
741 int64_t Val = MCE->getValue();
742 return (Val >= N && Val <= M);
743 }
744
745 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
746 // a logical immediate can always be represented when inverted.
747 template <typename T>
isLogicalImm() const748 bool isLogicalImm() const {
749 if (!isImm())
750 return false;
751 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
752 if (!MCE)
753 return false;
754
755 int64_t Val = MCE->getValue();
756 int64_t SVal = typename std::make_signed<T>::type(Val);
757 int64_t UVal = typename std::make_unsigned<T>::type(Val);
758 if (Val != SVal && Val != UVal)
759 return false;
760
761 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
762 }
763
isShiftedImm() const764 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
765
766 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
767 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
768 /// immediate that can be shifted by 'Shift'.
769 template <unsigned Width>
getShiftedVal() const770 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
771 if (isShiftedImm() && Width == getShiftedImmShift())
772 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
773 return std::make_pair(CE->getValue(), Width);
774
775 if (isImm())
776 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
777 int64_t Val = CE->getValue();
778 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
779 return std::make_pair(Val >> Width, Width);
780 else
781 return std::make_pair(Val, 0u);
782 }
783
784 return {};
785 }
786
isAddSubImm() const787 bool isAddSubImm() const {
788 if (!isShiftedImm() && !isImm())
789 return false;
790
791 const MCExpr *Expr;
792
793 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
794 if (isShiftedImm()) {
795 unsigned Shift = ShiftedImm.ShiftAmount;
796 Expr = ShiftedImm.Val;
797 if (Shift != 0 && Shift != 12)
798 return false;
799 } else {
800 Expr = getImm();
801 }
802
803 AArch64MCExpr::VariantKind ELFRefKind;
804 MCSymbolRefExpr::VariantKind DarwinRefKind;
805 int64_t Addend;
806 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
807 DarwinRefKind, Addend)) {
808 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
809 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
810 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
811 || ELFRefKind == AArch64MCExpr::VK_LO12
812 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
813 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
814 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
815 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
816 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
817 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
818 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
819 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
820 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
821 }
822
823 // If it's a constant, it should be a real immediate in range.
824 if (auto ShiftedVal = getShiftedVal<12>())
825 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
826
827 // If it's an expression, we hope for the best and let the fixup/relocation
828 // code deal with it.
829 return true;
830 }
831
isAddSubImmNeg() const832 bool isAddSubImmNeg() const {
833 if (!isShiftedImm() && !isImm())
834 return false;
835
836 // Otherwise it should be a real negative immediate in range.
837 if (auto ShiftedVal = getShiftedVal<12>())
838 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
839
840 return false;
841 }
842
843 // Signed value in the range -128 to +127. For element widths of
844 // 16 bits or higher it may also be a signed multiple of 256 in the
845 // range -32768 to +32512.
846 // For element-width of 8 bits a range of -128 to 255 is accepted,
847 // since a copy of a byte can be either signed/unsigned.
848 template <typename T>
isSVECpyImm() const849 DiagnosticPredicate isSVECpyImm() const {
850 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
851 return DiagnosticPredicateTy::NoMatch;
852
853 bool IsByte =
854 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
855 if (auto ShiftedImm = getShiftedVal<8>())
856 if (!(IsByte && ShiftedImm->second) &&
857 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
858 << ShiftedImm->second))
859 return DiagnosticPredicateTy::Match;
860
861 return DiagnosticPredicateTy::NearMatch;
862 }
863
864 // Unsigned value in the range 0 to 255. For element widths of
865 // 16 bits or higher it may also be a signed multiple of 256 in the
866 // range 0 to 65280.
isSVEAddSubImm() const867 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
868 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
869 return DiagnosticPredicateTy::NoMatch;
870
871 bool IsByte =
872 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
873 if (auto ShiftedImm = getShiftedVal<8>())
874 if (!(IsByte && ShiftedImm->second) &&
875 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
876 << ShiftedImm->second))
877 return DiagnosticPredicateTy::Match;
878
879 return DiagnosticPredicateTy::NearMatch;
880 }
881
isSVEPreferredLogicalImm() const882 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
883 if (isLogicalImm<T>() && !isSVECpyImm<T>())
884 return DiagnosticPredicateTy::Match;
885 return DiagnosticPredicateTy::NoMatch;
886 }
887
isCondCode() const888 bool isCondCode() const { return Kind == k_CondCode; }
889
isSIMDImmType10() const890 bool isSIMDImmType10() const {
891 if (!isImm())
892 return false;
893 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
894 if (!MCE)
895 return false;
896 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
897 }
898
899 template<int N>
isBranchTarget() const900 bool isBranchTarget() const {
901 if (!isImm())
902 return false;
903 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
904 if (!MCE)
905 return true;
906 int64_t Val = MCE->getValue();
907 if (Val & 0x3)
908 return false;
909 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
910 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
911 }
912
913 bool
isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const914 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
915 if (!isImm())
916 return false;
917
918 AArch64MCExpr::VariantKind ELFRefKind;
919 MCSymbolRefExpr::VariantKind DarwinRefKind;
920 int64_t Addend;
921 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
922 DarwinRefKind, Addend)) {
923 return false;
924 }
925 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
926 return false;
927
928 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
929 if (ELFRefKind == AllowedModifiers[i])
930 return true;
931 }
932
933 return false;
934 }
935
isMovZSymbolG3() const936 bool isMovZSymbolG3() const {
937 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
938 }
939
isMovZSymbolG2() const940 bool isMovZSymbolG2() const {
941 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
942 AArch64MCExpr::VK_TPREL_G2,
943 AArch64MCExpr::VK_DTPREL_G2});
944 }
945
isMovZSymbolG1() const946 bool isMovZSymbolG1() const {
947 return isMovWSymbol({
948 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
949 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
950 AArch64MCExpr::VK_DTPREL_G1,
951 });
952 }
953
isMovZSymbolG0() const954 bool isMovZSymbolG0() const {
955 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
956 AArch64MCExpr::VK_TPREL_G0,
957 AArch64MCExpr::VK_DTPREL_G0});
958 }
959
isMovKSymbolG3() const960 bool isMovKSymbolG3() const {
961 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
962 }
963
isMovKSymbolG2() const964 bool isMovKSymbolG2() const {
965 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
966 }
967
isMovKSymbolG1() const968 bool isMovKSymbolG1() const {
969 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
970 AArch64MCExpr::VK_TPREL_G1_NC,
971 AArch64MCExpr::VK_DTPREL_G1_NC});
972 }
973
isMovKSymbolG0() const974 bool isMovKSymbolG0() const {
975 return isMovWSymbol(
976 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
977 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
978 }
979
980 template<int RegWidth, int Shift>
isMOVZMovAlias() const981 bool isMOVZMovAlias() const {
982 if (!isImm()) return false;
983
984 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
985 if (!CE) return false;
986 uint64_t Value = CE->getValue();
987
988 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
989 }
990
991 template<int RegWidth, int Shift>
isMOVNMovAlias() const992 bool isMOVNMovAlias() const {
993 if (!isImm()) return false;
994
995 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
996 if (!CE) return false;
997 uint64_t Value = CE->getValue();
998
999 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
1000 }
1001
isFPImm() const1002 bool isFPImm() const {
1003 return Kind == k_FPImm &&
1004 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1005 }
1006
isBarrier() const1007 bool isBarrier() const { return Kind == k_Barrier; }
isSysReg() const1008 bool isSysReg() const { return Kind == k_SysReg; }
1009
isMRSSystemRegister() const1010 bool isMRSSystemRegister() const {
1011 if (!isSysReg()) return false;
1012
1013 return SysReg.MRSReg != -1U;
1014 }
1015
isMSRSystemRegister() const1016 bool isMSRSystemRegister() const {
1017 if (!isSysReg()) return false;
1018 return SysReg.MSRReg != -1U;
1019 }
1020
isSystemPStateFieldWithImm0_1() const1021 bool isSystemPStateFieldWithImm0_1() const {
1022 if (!isSysReg()) return false;
1023 return (SysReg.PStateField == AArch64PState::PAN ||
1024 SysReg.PStateField == AArch64PState::DIT ||
1025 SysReg.PStateField == AArch64PState::UAO ||
1026 SysReg.PStateField == AArch64PState::SSBS);
1027 }
1028
isSystemPStateFieldWithImm0_15() const1029 bool isSystemPStateFieldWithImm0_15() const {
1030 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
1031 return SysReg.PStateField != -1U;
1032 }
1033
isReg() const1034 bool isReg() const override {
1035 return Kind == k_Register;
1036 }
1037
isScalarReg() const1038 bool isScalarReg() const {
1039 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1040 }
1041
isNeonVectorReg() const1042 bool isNeonVectorReg() const {
1043 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1044 }
1045
isNeonVectorRegLo() const1046 bool isNeonVectorRegLo() const {
1047 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
1048 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1049 Reg.RegNum);
1050 }
1051
isSVEVectorReg() const1052 template <unsigned Class> bool isSVEVectorReg() const {
1053 RegKind RK;
1054 switch (Class) {
1055 case AArch64::ZPRRegClassID:
1056 case AArch64::ZPR_3bRegClassID:
1057 case AArch64::ZPR_4bRegClassID:
1058 RK = RegKind::SVEDataVector;
1059 break;
1060 case AArch64::PPRRegClassID:
1061 case AArch64::PPR_3bRegClassID:
1062 RK = RegKind::SVEPredicateVector;
1063 break;
1064 default:
1065 llvm_unreachable("Unsupport register class");
1066 }
1067
1068 return (Kind == k_Register && Reg.Kind == RK) &&
1069 AArch64MCRegisterClasses[Class].contains(getReg());
1070 }
1071
isFPRasZPR() const1072 template <unsigned Class> bool isFPRasZPR() const {
1073 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1074 AArch64MCRegisterClasses[Class].contains(getReg());
1075 }
1076
1077 template <int ElementWidth, unsigned Class>
isSVEPredicateVectorRegOfWidth() const1078 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1079 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1080 return DiagnosticPredicateTy::NoMatch;
1081
1082 if (isSVEVectorReg<Class>() &&
1083 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1084 return DiagnosticPredicateTy::Match;
1085
1086 return DiagnosticPredicateTy::NearMatch;
1087 }
1088
1089 template <int ElementWidth, unsigned Class>
isSVEDataVectorRegOfWidth() const1090 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1091 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1092 return DiagnosticPredicateTy::NoMatch;
1093
1094 if (isSVEVectorReg<Class>() &&
1095 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1096 return DiagnosticPredicateTy::Match;
1097
1098 return DiagnosticPredicateTy::NearMatch;
1099 }
1100
1101 template <int ElementWidth, unsigned Class,
1102 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1103 bool ShiftWidthAlwaysSame>
isSVEDataVectorRegWithShiftExtend() const1104 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1105 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1106 if (!VectorMatch.isMatch())
1107 return DiagnosticPredicateTy::NoMatch;
1108
1109 // Give a more specific diagnostic when the user has explicitly typed in
1110 // a shift-amount that does not match what is expected, but for which
1111 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1112 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1113 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1114 ShiftExtendTy == AArch64_AM::SXTW) &&
1115 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1116 return DiagnosticPredicateTy::NoMatch;
1117
1118 if (MatchShift && ShiftExtendTy == getShiftExtendType())
1119 return DiagnosticPredicateTy::Match;
1120
1121 return DiagnosticPredicateTy::NearMatch;
1122 }
1123
isGPR32as64() const1124 bool isGPR32as64() const {
1125 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1126 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1127 }
1128
isGPR64as32() const1129 bool isGPR64as32() const {
1130 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1131 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1132 }
1133
isWSeqPair() const1134 bool isWSeqPair() const {
1135 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1136 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1137 Reg.RegNum);
1138 }
1139
isXSeqPair() const1140 bool isXSeqPair() const {
1141 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1142 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1143 Reg.RegNum);
1144 }
1145
1146 template<int64_t Angle, int64_t Remainder>
isComplexRotation() const1147 DiagnosticPredicate isComplexRotation() const {
1148 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
1149
1150 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1151 if (!CE) return DiagnosticPredicateTy::NoMatch;
1152 uint64_t Value = CE->getValue();
1153
1154 if (Value % Angle == Remainder && Value <= 270)
1155 return DiagnosticPredicateTy::Match;
1156 return DiagnosticPredicateTy::NearMatch;
1157 }
1158
isGPR64() const1159 template <unsigned RegClassID> bool isGPR64() const {
1160 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1161 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1162 }
1163
1164 template <unsigned RegClassID, int ExtWidth>
isGPR64WithShiftExtend() const1165 DiagnosticPredicate isGPR64WithShiftExtend() const {
1166 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1167 return DiagnosticPredicateTy::NoMatch;
1168
1169 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1170 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1171 return DiagnosticPredicateTy::Match;
1172 return DiagnosticPredicateTy::NearMatch;
1173 }
1174
1175 /// Is this a vector list with the type implicit (presumably attached to the
1176 /// instruction itself)?
1177 template <RegKind VectorKind, unsigned NumRegs>
isImplicitlyTypedVectorList() const1178 bool isImplicitlyTypedVectorList() const {
1179 return Kind == k_VectorList && VectorList.Count == NumRegs &&
1180 VectorList.NumElements == 0 &&
1181 VectorList.RegisterKind == VectorKind;
1182 }
1183
1184 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1185 unsigned ElementWidth>
isTypedVectorList() const1186 bool isTypedVectorList() const {
1187 if (Kind != k_VectorList)
1188 return false;
1189 if (VectorList.Count != NumRegs)
1190 return false;
1191 if (VectorList.RegisterKind != VectorKind)
1192 return false;
1193 if (VectorList.ElementWidth != ElementWidth)
1194 return false;
1195 return VectorList.NumElements == NumElements;
1196 }
1197
1198 template <int Min, int Max>
isVectorIndex() const1199 DiagnosticPredicate isVectorIndex() const {
1200 if (Kind != k_VectorIndex)
1201 return DiagnosticPredicateTy::NoMatch;
1202 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1203 return DiagnosticPredicateTy::Match;
1204 return DiagnosticPredicateTy::NearMatch;
1205 }
1206
isToken() const1207 bool isToken() const override { return Kind == k_Token; }
1208
isTokenEqual(StringRef Str) const1209 bool isTokenEqual(StringRef Str) const {
1210 return Kind == k_Token && getToken() == Str;
1211 }
isSysCR() const1212 bool isSysCR() const { return Kind == k_SysCR; }
isPrefetch() const1213 bool isPrefetch() const { return Kind == k_Prefetch; }
isPSBHint() const1214 bool isPSBHint() const { return Kind == k_PSBHint; }
isBTIHint() const1215 bool isBTIHint() const { return Kind == k_BTIHint; }
isShiftExtend() const1216 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
isShifter() const1217 bool isShifter() const {
1218 if (!isShiftExtend())
1219 return false;
1220
1221 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1222 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1223 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1224 ST == AArch64_AM::MSL);
1225 }
1226
isExactFPImm() const1227 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1228 if (Kind != k_FPImm)
1229 return DiagnosticPredicateTy::NoMatch;
1230
1231 if (getFPImmIsExact()) {
1232 // Lookup the immediate from table of supported immediates.
1233 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1234 assert(Desc && "Unknown enum value");
1235
1236 // Calculate its FP value.
1237 APFloat RealVal(APFloat::IEEEdouble());
1238 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1239 APFloat::opOK)
1240 llvm_unreachable("FP immediate is not exact");
1241
1242 if (getFPImm().bitwiseIsEqual(RealVal))
1243 return DiagnosticPredicateTy::Match;
1244 }
1245
1246 return DiagnosticPredicateTy::NearMatch;
1247 }
1248
1249 template <unsigned ImmA, unsigned ImmB>
isExactFPImm() const1250 DiagnosticPredicate isExactFPImm() const {
1251 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1252 if ((Res = isExactFPImm<ImmA>()))
1253 return DiagnosticPredicateTy::Match;
1254 if ((Res = isExactFPImm<ImmB>()))
1255 return DiagnosticPredicateTy::Match;
1256 return Res;
1257 }
1258
isExtend() const1259 bool isExtend() const {
1260 if (!isShiftExtend())
1261 return false;
1262
1263 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1264 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1265 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1266 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1267 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1268 ET == AArch64_AM::LSL) &&
1269 getShiftExtendAmount() <= 4;
1270 }
1271
isExtend64() const1272 bool isExtend64() const {
1273 if (!isExtend())
1274 return false;
1275 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1276 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1277 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1278 }
1279
isExtendLSL64() const1280 bool isExtendLSL64() const {
1281 if (!isExtend())
1282 return false;
1283 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1284 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1285 ET == AArch64_AM::LSL) &&
1286 getShiftExtendAmount() <= 4;
1287 }
1288
isMemXExtend() const1289 template<int Width> bool isMemXExtend() const {
1290 if (!isExtend())
1291 return false;
1292 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1293 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1294 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1295 getShiftExtendAmount() == 0);
1296 }
1297
isMemWExtend() const1298 template<int Width> bool isMemWExtend() const {
1299 if (!isExtend())
1300 return false;
1301 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1302 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1303 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1304 getShiftExtendAmount() == 0);
1305 }
1306
1307 template <unsigned width>
isArithmeticShifter() const1308 bool isArithmeticShifter() const {
1309 if (!isShifter())
1310 return false;
1311
1312 // An arithmetic shifter is LSL, LSR, or ASR.
1313 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1314 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1315 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1316 }
1317
1318 template <unsigned width>
isLogicalShifter() const1319 bool isLogicalShifter() const {
1320 if (!isShifter())
1321 return false;
1322
1323 // A logical shifter is LSL, LSR, ASR or ROR.
1324 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1325 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1326 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1327 getShiftExtendAmount() < width;
1328 }
1329
isMovImm32Shifter() const1330 bool isMovImm32Shifter() const {
1331 if (!isShifter())
1332 return false;
1333
1334 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1335 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1336 if (ST != AArch64_AM::LSL)
1337 return false;
1338 uint64_t Val = getShiftExtendAmount();
1339 return (Val == 0 || Val == 16);
1340 }
1341
isMovImm64Shifter() const1342 bool isMovImm64Shifter() const {
1343 if (!isShifter())
1344 return false;
1345
1346 // A MOVi shifter is LSL of 0 or 16.
1347 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1348 if (ST != AArch64_AM::LSL)
1349 return false;
1350 uint64_t Val = getShiftExtendAmount();
1351 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1352 }
1353
isLogicalVecShifter() const1354 bool isLogicalVecShifter() const {
1355 if (!isShifter())
1356 return false;
1357
1358 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1359 unsigned Shift = getShiftExtendAmount();
1360 return getShiftExtendType() == AArch64_AM::LSL &&
1361 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1362 }
1363
isLogicalVecHalfWordShifter() const1364 bool isLogicalVecHalfWordShifter() const {
1365 if (!isLogicalVecShifter())
1366 return false;
1367
1368 // A logical vector shifter is a left shift by 0 or 8.
1369 unsigned Shift = getShiftExtendAmount();
1370 return getShiftExtendType() == AArch64_AM::LSL &&
1371 (Shift == 0 || Shift == 8);
1372 }
1373
isMoveVecShifter() const1374 bool isMoveVecShifter() const {
1375 if (!isShiftExtend())
1376 return false;
1377
1378 // A logical vector shifter is a left shift by 8 or 16.
1379 unsigned Shift = getShiftExtendAmount();
1380 return getShiftExtendType() == AArch64_AM::MSL &&
1381 (Shift == 8 || Shift == 16);
1382 }
1383
1384 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1385 // to LDUR/STUR when the offset is not legal for the former but is for
1386 // the latter. As such, in addition to checking for being a legal unscaled
1387 // address, also check that it is not a legal scaled address. This avoids
1388 // ambiguity in the matcher.
1389 template<int Width>
isSImm9OffsetFB() const1390 bool isSImm9OffsetFB() const {
1391 return isSImm<9>() && !isUImm12Offset<Width / 8>();
1392 }
1393
isAdrpLabel() const1394 bool isAdrpLabel() const {
1395 // Validation was handled during parsing, so we just sanity check that
1396 // something didn't go haywire.
1397 if (!isImm())
1398 return false;
1399
1400 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1401 int64_t Val = CE->getValue();
1402 int64_t Min = - (4096 * (1LL << (21 - 1)));
1403 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1404 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1405 }
1406
1407 return true;
1408 }
1409
isAdrLabel() const1410 bool isAdrLabel() const {
1411 // Validation was handled during parsing, so we just sanity check that
1412 // something didn't go haywire.
1413 if (!isImm())
1414 return false;
1415
1416 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1417 int64_t Val = CE->getValue();
1418 int64_t Min = - (1LL << (21 - 1));
1419 int64_t Max = ((1LL << (21 - 1)) - 1);
1420 return Val >= Min && Val <= Max;
1421 }
1422
1423 return true;
1424 }
1425
addExpr(MCInst & Inst,const MCExpr * Expr) const1426 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1427 // Add as immediates when possible. Null MCExpr = 0.
1428 if (!Expr)
1429 Inst.addOperand(MCOperand::createImm(0));
1430 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1431 Inst.addOperand(MCOperand::createImm(CE->getValue()));
1432 else
1433 Inst.addOperand(MCOperand::createExpr(Expr));
1434 }
1435
addRegOperands(MCInst & Inst,unsigned N) const1436 void addRegOperands(MCInst &Inst, unsigned N) const {
1437 assert(N == 1 && "Invalid number of operands!");
1438 Inst.addOperand(MCOperand::createReg(getReg()));
1439 }
1440
addGPR32as64Operands(MCInst & Inst,unsigned N) const1441 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1442 assert(N == 1 && "Invalid number of operands!");
1443 assert(
1444 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1445
1446 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1447 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1448 RI->getEncodingValue(getReg()));
1449
1450 Inst.addOperand(MCOperand::createReg(Reg));
1451 }
1452
addGPR64as32Operands(MCInst & Inst,unsigned N) const1453 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 assert(
1456 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1457
1458 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1459 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1460 RI->getEncodingValue(getReg()));
1461
1462 Inst.addOperand(MCOperand::createReg(Reg));
1463 }
1464
1465 template <int Width>
addFPRasZPRRegOperands(MCInst & Inst,unsigned N) const1466 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1467 unsigned Base;
1468 switch (Width) {
1469 case 8: Base = AArch64::B0; break;
1470 case 16: Base = AArch64::H0; break;
1471 case 32: Base = AArch64::S0; break;
1472 case 64: Base = AArch64::D0; break;
1473 case 128: Base = AArch64::Q0; break;
1474 default:
1475 llvm_unreachable("Unsupported width");
1476 }
1477 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1478 }
1479
addVectorReg64Operands(MCInst & Inst,unsigned N) const1480 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1481 assert(N == 1 && "Invalid number of operands!");
1482 assert(
1483 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1484 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
1485 }
1486
addVectorReg128Operands(MCInst & Inst,unsigned N) const1487 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1488 assert(N == 1 && "Invalid number of operands!");
1489 assert(
1490 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
1491 Inst.addOperand(MCOperand::createReg(getReg()));
1492 }
1493
addVectorRegLoOperands(MCInst & Inst,unsigned N) const1494 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::createReg(getReg()));
1497 }
1498
1499 enum VecListIndexType {
1500 VecListIdx_DReg = 0,
1501 VecListIdx_QReg = 1,
1502 VecListIdx_ZReg = 2,
1503 };
1504
1505 template <VecListIndexType RegTy, unsigned NumRegs>
addVectorListOperands(MCInst & Inst,unsigned N) const1506 void addVectorListOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 static const unsigned FirstRegs[][5] = {
1509 /* DReg */ { AArch64::Q0,
1510 AArch64::D0, AArch64::D0_D1,
1511 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1512 /* QReg */ { AArch64::Q0,
1513 AArch64::Q0, AArch64::Q0_Q1,
1514 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1515 /* ZReg */ { AArch64::Z0,
1516 AArch64::Z0, AArch64::Z0_Z1,
1517 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
1518 };
1519
1520 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1521 " NumRegs must be <= 4 for ZRegs");
1522
1523 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1524 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1525 FirstRegs[(unsigned)RegTy][0]));
1526 }
1527
addVectorIndexOperands(MCInst & Inst,unsigned N) const1528 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
1529 assert(N == 1 && "Invalid number of operands!");
1530 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
1531 }
1532
1533 template <unsigned ImmIs0, unsigned ImmIs1>
addExactFPImmOperands(MCInst & Inst,unsigned N) const1534 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1535 assert(N == 1 && "Invalid number of operands!");
1536 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1537 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1538 }
1539
addImmOperands(MCInst & Inst,unsigned N) const1540 void addImmOperands(MCInst &Inst, unsigned N) const {
1541 assert(N == 1 && "Invalid number of operands!");
1542 // If this is a pageoff symrefexpr with an addend, adjust the addend
1543 // to be only the page-offset portion. Otherwise, just add the expr
1544 // as-is.
1545 addExpr(Inst, getImm());
1546 }
1547
1548 template <int Shift>
addImmWithOptionalShiftOperands(MCInst & Inst,unsigned N) const1549 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1550 assert(N == 2 && "Invalid number of operands!");
1551 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1552 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1553 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1554 } else if (isShiftedImm()) {
1555 addExpr(Inst, getShiftedImmVal());
1556 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
1557 } else {
1558 addExpr(Inst, getImm());
1559 Inst.addOperand(MCOperand::createImm(0));
1560 }
1561 }
1562
1563 template <int Shift>
addImmNegWithOptionalShiftOperands(MCInst & Inst,unsigned N) const1564 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 2 && "Invalid number of operands!");
1566 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1567 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1568 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1569 } else
1570 llvm_unreachable("Not a shifted negative immediate");
1571 }
1572
addCondCodeOperands(MCInst & Inst,unsigned N) const1573 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1574 assert(N == 1 && "Invalid number of operands!");
1575 Inst.addOperand(MCOperand::createImm(getCondCode()));
1576 }
1577
addAdrpLabelOperands(MCInst & Inst,unsigned N) const1578 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1579 assert(N == 1 && "Invalid number of operands!");
1580 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1581 if (!MCE)
1582 addExpr(Inst, getImm());
1583 else
1584 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
1585 }
1586
addAdrLabelOperands(MCInst & Inst,unsigned N) const1587 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1588 addImmOperands(Inst, N);
1589 }
1590
1591 template<int Scale>
addUImm12OffsetOperands(MCInst & Inst,unsigned N) const1592 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1593 assert(N == 1 && "Invalid number of operands!");
1594 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1595
1596 if (!MCE) {
1597 Inst.addOperand(MCOperand::createExpr(getImm()));
1598 return;
1599 }
1600 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1601 }
1602
addUImm6Operands(MCInst & Inst,unsigned N) const1603 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1604 assert(N == 1 && "Invalid number of operands!");
1605 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1606 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1607 }
1608
1609 template <int Scale>
addImmScaledOperands(MCInst & Inst,unsigned N) const1610 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1611 assert(N == 1 && "Invalid number of operands!");
1612 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1613 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1614 }
1615
1616 template <typename T>
addLogicalImmOperands(MCInst & Inst,unsigned N) const1617 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
1618 assert(N == 1 && "Invalid number of operands!");
1619 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1620 typename std::make_unsigned<T>::type Val = MCE->getValue();
1621 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
1622 Inst.addOperand(MCOperand::createImm(encoding));
1623 }
1624
1625 template <typename T>
addLogicalImmNotOperands(MCInst & Inst,unsigned N) const1626 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
1627 assert(N == 1 && "Invalid number of operands!");
1628 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1629 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1630 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
1631 Inst.addOperand(MCOperand::createImm(encoding));
1632 }
1633
addSIMDImmType10Operands(MCInst & Inst,unsigned N) const1634 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
1636 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1637 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
1638 Inst.addOperand(MCOperand::createImm(encoding));
1639 }
1640
addBranchTarget26Operands(MCInst & Inst,unsigned N) const1641 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1642 // Branch operands don't encode the low bits, so shift them off
1643 // here. If it's a label, however, just put it on directly as there's
1644 // not enough information now to do anything.
1645 assert(N == 1 && "Invalid number of operands!");
1646 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1647 if (!MCE) {
1648 addExpr(Inst, getImm());
1649 return;
1650 }
1651 assert(MCE && "Invalid constant immediate operand!");
1652 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1653 }
1654
addPCRelLabel19Operands(MCInst & Inst,unsigned N) const1655 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1656 // Branch operands don't encode the low bits, so shift them off
1657 // here. If it's a label, however, just put it on directly as there's
1658 // not enough information now to do anything.
1659 assert(N == 1 && "Invalid number of operands!");
1660 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1661 if (!MCE) {
1662 addExpr(Inst, getImm());
1663 return;
1664 }
1665 assert(MCE && "Invalid constant immediate operand!");
1666 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1667 }
1668
addBranchTarget14Operands(MCInst & Inst,unsigned N) const1669 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1670 // Branch operands don't encode the low bits, so shift them off
1671 // here. If it's a label, however, just put it on directly as there's
1672 // not enough information now to do anything.
1673 assert(N == 1 && "Invalid number of operands!");
1674 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1675 if (!MCE) {
1676 addExpr(Inst, getImm());
1677 return;
1678 }
1679 assert(MCE && "Invalid constant immediate operand!");
1680 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
1681 }
1682
addFPImmOperands(MCInst & Inst,unsigned N) const1683 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1684 assert(N == 1 && "Invalid number of operands!");
1685 Inst.addOperand(MCOperand::createImm(
1686 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
1687 }
1688
addBarrierOperands(MCInst & Inst,unsigned N) const1689 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1690 assert(N == 1 && "Invalid number of operands!");
1691 Inst.addOperand(MCOperand::createImm(getBarrier()));
1692 }
1693
addMRSSystemRegisterOperands(MCInst & Inst,unsigned N) const1694 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1695 assert(N == 1 && "Invalid number of operands!");
1696
1697 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
1698 }
1699
addMSRSystemRegisterOperands(MCInst & Inst,unsigned N) const1700 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 1 && "Invalid number of operands!");
1702
1703 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
1704 }
1705
addSystemPStateFieldWithImm0_1Operands(MCInst & Inst,unsigned N) const1706 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708
1709 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1710 }
1711
addSystemPStateFieldWithImm0_15Operands(MCInst & Inst,unsigned N) const1712 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
1713 assert(N == 1 && "Invalid number of operands!");
1714
1715 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1716 }
1717
addSysCROperands(MCInst & Inst,unsigned N) const1718 void addSysCROperands(MCInst &Inst, unsigned N) const {
1719 assert(N == 1 && "Invalid number of operands!");
1720 Inst.addOperand(MCOperand::createImm(getSysCR()));
1721 }
1722
addPrefetchOperands(MCInst & Inst,unsigned N) const1723 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1724 assert(N == 1 && "Invalid number of operands!");
1725 Inst.addOperand(MCOperand::createImm(getPrefetch()));
1726 }
1727
addPSBHintOperands(MCInst & Inst,unsigned N) const1728 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1729 assert(N == 1 && "Invalid number of operands!");
1730 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1731 }
1732
addBTIHintOperands(MCInst & Inst,unsigned N) const1733 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1734 assert(N == 1 && "Invalid number of operands!");
1735 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1736 }
1737
addShifterOperands(MCInst & Inst,unsigned N) const1738 void addShifterOperands(MCInst &Inst, unsigned N) const {
1739 assert(N == 1 && "Invalid number of operands!");
1740 unsigned Imm =
1741 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
1742 Inst.addOperand(MCOperand::createImm(Imm));
1743 }
1744
addExtendOperands(MCInst & Inst,unsigned N) const1745 void addExtendOperands(MCInst &Inst, unsigned N) const {
1746 assert(N == 1 && "Invalid number of operands!");
1747 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1748 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1749 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
1750 Inst.addOperand(MCOperand::createImm(Imm));
1751 }
1752
addExtend64Operands(MCInst & Inst,unsigned N) const1753 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1754 assert(N == 1 && "Invalid number of operands!");
1755 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1756 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1757 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
1758 Inst.addOperand(MCOperand::createImm(Imm));
1759 }
1760
addMemExtendOperands(MCInst & Inst,unsigned N) const1761 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 2 && "Invalid number of operands!");
1763 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1764 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
1765 Inst.addOperand(MCOperand::createImm(IsSigned));
1766 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
1767 }
1768
1769 // For 8-bit load/store instructions with a register offset, both the
1770 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1771 // they're disambiguated by whether the shift was explicit or implicit rather
1772 // than its size.
addMemExtend8Operands(MCInst & Inst,unsigned N) const1773 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1774 assert(N == 2 && "Invalid number of operands!");
1775 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1776 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
1777 Inst.addOperand(MCOperand::createImm(IsSigned));
1778 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
1779 }
1780
1781 template<int Shift>
addMOVZMovAliasOperands(MCInst & Inst,unsigned N) const1782 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1783 assert(N == 1 && "Invalid number of operands!");
1784
1785 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1786 uint64_t Value = CE->getValue();
1787 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
1788 }
1789
1790 template<int Shift>
addMOVNMovAliasOperands(MCInst & Inst,unsigned N) const1791 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1792 assert(N == 1 && "Invalid number of operands!");
1793
1794 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1795 uint64_t Value = CE->getValue();
1796 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
1797 }
1798
addComplexRotationEvenOperands(MCInst & Inst,unsigned N) const1799 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 1 && "Invalid number of operands!");
1801 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1802 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1803 }
1804
addComplexRotationOddOperands(MCInst & Inst,unsigned N) const1805 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1806 assert(N == 1 && "Invalid number of operands!");
1807 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1808 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1809 }
1810
1811 void print(raw_ostream &OS) const override;
1812
1813 static std::unique_ptr<AArch64Operand>
CreateToken(StringRef Str,bool IsSuffix,SMLoc S,MCContext & Ctx)1814 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1815 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
1816 Op->Tok.Data = Str.data();
1817 Op->Tok.Length = Str.size();
1818 Op->Tok.IsSuffix = IsSuffix;
1819 Op->StartLoc = S;
1820 Op->EndLoc = S;
1821 return Op;
1822 }
1823
1824 static std::unique_ptr<AArch64Operand>
CreateReg(unsigned RegNum,RegKind Kind,SMLoc S,SMLoc E,MCContext & Ctx,RegConstraintEqualityTy EqTy=RegConstraintEqualityTy::EqualsReg,AArch64_AM::ShiftExtendType ExtTy=AArch64_AM::LSL,unsigned ShiftAmount=0,unsigned HasExplicitAmount=false)1825 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
1826 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
1827 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1828 unsigned ShiftAmount = 0,
1829 unsigned HasExplicitAmount = false) {
1830 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1831 Op->Reg.RegNum = RegNum;
1832 Op->Reg.Kind = Kind;
1833 Op->Reg.ElementWidth = 0;
1834 Op->Reg.EqualityTy = EqTy;
1835 Op->Reg.ShiftExtend.Type = ExtTy;
1836 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1837 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1838 Op->StartLoc = S;
1839 Op->EndLoc = E;
1840 return Op;
1841 }
1842
1843 static std::unique_ptr<AArch64Operand>
CreateVectorReg(unsigned RegNum,RegKind Kind,unsigned ElementWidth,SMLoc S,SMLoc E,MCContext & Ctx,AArch64_AM::ShiftExtendType ExtTy=AArch64_AM::LSL,unsigned ShiftAmount=0,unsigned HasExplicitAmount=false)1844 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1845 SMLoc S, SMLoc E, MCContext &Ctx,
1846 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1847 unsigned ShiftAmount = 0,
1848 unsigned HasExplicitAmount = false) {
1849 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1850 Kind == RegKind::SVEPredicateVector) &&
1851 "Invalid vector kind");
1852 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
1853 HasExplicitAmount);
1854 Op->Reg.ElementWidth = ElementWidth;
1855 return Op;
1856 }
1857
1858 static std::unique_ptr<AArch64Operand>
CreateVectorList(unsigned RegNum,unsigned Count,unsigned NumElements,unsigned ElementWidth,RegKind RegisterKind,SMLoc S,SMLoc E,MCContext & Ctx)1859 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
1860 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1861 MCContext &Ctx) {
1862 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
1863 Op->VectorList.RegNum = RegNum;
1864 Op->VectorList.Count = Count;
1865 Op->VectorList.NumElements = NumElements;
1866 Op->VectorList.ElementWidth = ElementWidth;
1867 Op->VectorList.RegisterKind = RegisterKind;
1868 Op->StartLoc = S;
1869 Op->EndLoc = E;
1870 return Op;
1871 }
1872
1873 static std::unique_ptr<AArch64Operand>
CreateVectorIndex(unsigned Idx,SMLoc S,SMLoc E,MCContext & Ctx)1874 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1875 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
1876 Op->VectorIndex.Val = Idx;
1877 Op->StartLoc = S;
1878 Op->EndLoc = E;
1879 return Op;
1880 }
1881
CreateImm(const MCExpr * Val,SMLoc S,SMLoc E,MCContext & Ctx)1882 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1883 SMLoc E, MCContext &Ctx) {
1884 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
1885 Op->Imm.Val = Val;
1886 Op->StartLoc = S;
1887 Op->EndLoc = E;
1888 return Op;
1889 }
1890
CreateShiftedImm(const MCExpr * Val,unsigned ShiftAmount,SMLoc S,SMLoc E,MCContext & Ctx)1891 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1892 unsigned ShiftAmount,
1893 SMLoc S, SMLoc E,
1894 MCContext &Ctx) {
1895 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
1896 Op->ShiftedImm .Val = Val;
1897 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1898 Op->StartLoc = S;
1899 Op->EndLoc = E;
1900 return Op;
1901 }
1902
1903 static std::unique_ptr<AArch64Operand>
CreateCondCode(AArch64CC::CondCode Code,SMLoc S,SMLoc E,MCContext & Ctx)1904 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1905 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
1906 Op->CondCode.Code = Code;
1907 Op->StartLoc = S;
1908 Op->EndLoc = E;
1909 return Op;
1910 }
1911
1912 static std::unique_ptr<AArch64Operand>
CreateFPImm(APFloat Val,bool IsExact,SMLoc S,MCContext & Ctx)1913 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
1914 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
1915 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1916 Op->FPImm.IsExact = IsExact;
1917 Op->StartLoc = S;
1918 Op->EndLoc = S;
1919 return Op;
1920 }
1921
CreateBarrier(unsigned Val,StringRef Str,SMLoc S,MCContext & Ctx)1922 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1923 StringRef Str,
1924 SMLoc S,
1925 MCContext &Ctx) {
1926 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
1927 Op->Barrier.Val = Val;
1928 Op->Barrier.Data = Str.data();
1929 Op->Barrier.Length = Str.size();
1930 Op->StartLoc = S;
1931 Op->EndLoc = S;
1932 return Op;
1933 }
1934
CreateSysReg(StringRef Str,SMLoc S,uint32_t MRSReg,uint32_t MSRReg,uint32_t PStateField,MCContext & Ctx)1935 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1936 uint32_t MRSReg,
1937 uint32_t MSRReg,
1938 uint32_t PStateField,
1939 MCContext &Ctx) {
1940 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
1941 Op->SysReg.Data = Str.data();
1942 Op->SysReg.Length = Str.size();
1943 Op->SysReg.MRSReg = MRSReg;
1944 Op->SysReg.MSRReg = MSRReg;
1945 Op->SysReg.PStateField = PStateField;
1946 Op->StartLoc = S;
1947 Op->EndLoc = S;
1948 return Op;
1949 }
1950
CreateSysCR(unsigned Val,SMLoc S,SMLoc E,MCContext & Ctx)1951 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1952 SMLoc E, MCContext &Ctx) {
1953 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
1954 Op->SysCRImm.Val = Val;
1955 Op->StartLoc = S;
1956 Op->EndLoc = E;
1957 return Op;
1958 }
1959
CreatePrefetch(unsigned Val,StringRef Str,SMLoc S,MCContext & Ctx)1960 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1961 StringRef Str,
1962 SMLoc S,
1963 MCContext &Ctx) {
1964 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
1965 Op->Prefetch.Val = Val;
1966 Op->Barrier.Data = Str.data();
1967 Op->Barrier.Length = Str.size();
1968 Op->StartLoc = S;
1969 Op->EndLoc = S;
1970 return Op;
1971 }
1972
CreatePSBHint(unsigned Val,StringRef Str,SMLoc S,MCContext & Ctx)1973 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1974 StringRef Str,
1975 SMLoc S,
1976 MCContext &Ctx) {
1977 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1978 Op->PSBHint.Val = Val;
1979 Op->PSBHint.Data = Str.data();
1980 Op->PSBHint.Length = Str.size();
1981 Op->StartLoc = S;
1982 Op->EndLoc = S;
1983 return Op;
1984 }
1985
CreateBTIHint(unsigned Val,StringRef Str,SMLoc S,MCContext & Ctx)1986 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1987 StringRef Str,
1988 SMLoc S,
1989 MCContext &Ctx) {
1990 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1991 Op->BTIHint.Val = Val << 1 | 32;
1992 Op->BTIHint.Data = Str.data();
1993 Op->BTIHint.Length = Str.size();
1994 Op->StartLoc = S;
1995 Op->EndLoc = S;
1996 return Op;
1997 }
1998
1999 static std::unique_ptr<AArch64Operand>
CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp,unsigned Val,bool HasExplicitAmount,SMLoc S,SMLoc E,MCContext & Ctx)2000 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
2001 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
2002 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
2003 Op->ShiftExtend.Type = ShOp;
2004 Op->ShiftExtend.Amount = Val;
2005 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2006 Op->StartLoc = S;
2007 Op->EndLoc = E;
2008 return Op;
2009 }
2010 };
2011
2012 } // end anonymous namespace.
2013
print(raw_ostream & OS) const2014 void AArch64Operand::print(raw_ostream &OS) const {
2015 switch (Kind) {
2016 case k_FPImm:
2017 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2018 if (!getFPImmIsExact())
2019 OS << " (inexact)";
2020 OS << ">";
2021 break;
2022 case k_Barrier: {
2023 StringRef Name = getBarrierName();
2024 if (!Name.empty())
2025 OS << "<barrier " << Name << ">";
2026 else
2027 OS << "<barrier invalid #" << getBarrier() << ">";
2028 break;
2029 }
2030 case k_Immediate:
2031 OS << *getImm();
2032 break;
2033 case k_ShiftedImm: {
2034 unsigned Shift = getShiftedImmShift();
2035 OS << "<shiftedimm ";
2036 OS << *getShiftedImmVal();
2037 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2038 break;
2039 }
2040 case k_CondCode:
2041 OS << "<condcode " << getCondCode() << ">";
2042 break;
2043 case k_VectorList: {
2044 OS << "<vectorlist ";
2045 unsigned Reg = getVectorListStart();
2046 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2047 OS << Reg + i << " ";
2048 OS << ">";
2049 break;
2050 }
2051 case k_VectorIndex:
2052 OS << "<vectorindex " << getVectorIndex() << ">";
2053 break;
2054 case k_SysReg:
2055 OS << "<sysreg: " << getSysReg() << '>';
2056 break;
2057 case k_Token:
2058 OS << "'" << getToken() << "'";
2059 break;
2060 case k_SysCR:
2061 OS << "c" << getSysCR();
2062 break;
2063 case k_Prefetch: {
2064 StringRef Name = getPrefetchName();
2065 if (!Name.empty())
2066 OS << "<prfop " << Name << ">";
2067 else
2068 OS << "<prfop invalid #" << getPrefetch() << ">";
2069 break;
2070 }
2071 case k_PSBHint:
2072 OS << getPSBHintName();
2073 break;
2074 case k_Register:
2075 OS << "<register " << getReg() << ">";
2076 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2077 break;
2078 LLVM_FALLTHROUGH;
2079 case k_BTIHint:
2080 OS << getBTIHintName();
2081 break;
2082 case k_ShiftExtend:
2083 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2084 << getShiftExtendAmount();
2085 if (!hasShiftExtendAmount())
2086 OS << "<imp>";
2087 OS << '>';
2088 break;
2089 }
2090 }
2091
2092 /// @name Auto-generated Match Functions
2093 /// {
2094
2095 static unsigned MatchRegisterName(StringRef Name);
2096
2097 /// }
2098
MatchNeonVectorRegName(StringRef Name)2099 static unsigned MatchNeonVectorRegName(StringRef Name) {
2100 return StringSwitch<unsigned>(Name.lower())
2101 .Case("v0", AArch64::Q0)
2102 .Case("v1", AArch64::Q1)
2103 .Case("v2", AArch64::Q2)
2104 .Case("v3", AArch64::Q3)
2105 .Case("v4", AArch64::Q4)
2106 .Case("v5", AArch64::Q5)
2107 .Case("v6", AArch64::Q6)
2108 .Case("v7", AArch64::Q7)
2109 .Case("v8", AArch64::Q8)
2110 .Case("v9", AArch64::Q9)
2111 .Case("v10", AArch64::Q10)
2112 .Case("v11", AArch64::Q11)
2113 .Case("v12", AArch64::Q12)
2114 .Case("v13", AArch64::Q13)
2115 .Case("v14", AArch64::Q14)
2116 .Case("v15", AArch64::Q15)
2117 .Case("v16", AArch64::Q16)
2118 .Case("v17", AArch64::Q17)
2119 .Case("v18", AArch64::Q18)
2120 .Case("v19", AArch64::Q19)
2121 .Case("v20", AArch64::Q20)
2122 .Case("v21", AArch64::Q21)
2123 .Case("v22", AArch64::Q22)
2124 .Case("v23", AArch64::Q23)
2125 .Case("v24", AArch64::Q24)
2126 .Case("v25", AArch64::Q25)
2127 .Case("v26", AArch64::Q26)
2128 .Case("v27", AArch64::Q27)
2129 .Case("v28", AArch64::Q28)
2130 .Case("v29", AArch64::Q29)
2131 .Case("v30", AArch64::Q30)
2132 .Case("v31", AArch64::Q31)
2133 .Default(0);
2134 }
2135
2136 /// Returns an optional pair of (#elements, element-width) if Suffix
2137 /// is a valid vector kind. Where the number of elements in a vector
2138 /// or the vector width is implicit or explicitly unknown (but still a
2139 /// valid suffix kind), 0 is used.
parseVectorKind(StringRef Suffix,RegKind VectorKind)2140 static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2141 RegKind VectorKind) {
2142 std::pair<int, int> Res = {-1, -1};
2143
2144 switch (VectorKind) {
2145 case RegKind::NeonVector:
2146 Res =
2147 StringSwitch<std::pair<int, int>>(Suffix.lower())
2148 .Case("", {0, 0})
2149 .Case(".1d", {1, 64})
2150 .Case(".1q", {1, 128})
2151 // '.2h' needed for fp16 scalar pairwise reductions
2152 .Case(".2h", {2, 16})
2153 .Case(".2s", {2, 32})
2154 .Case(".2d", {2, 64})
2155 // '.4b' is another special case for the ARMv8.2a dot product
2156 // operand
2157 .Case(".4b", {4, 8})
2158 .Case(".4h", {4, 16})
2159 .Case(".4s", {4, 32})
2160 .Case(".8b", {8, 8})
2161 .Case(".8h", {8, 16})
2162 .Case(".16b", {16, 8})
2163 // Accept the width neutral ones, too, for verbose syntax. If those
2164 // aren't used in the right places, the token operand won't match so
2165 // all will work out.
2166 .Case(".b", {0, 8})
2167 .Case(".h", {0, 16})
2168 .Case(".s", {0, 32})
2169 .Case(".d", {0, 64})
2170 .Default({-1, -1});
2171 break;
2172 case RegKind::SVEPredicateVector:
2173 case RegKind::SVEDataVector:
2174 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2175 .Case("", {0, 0})
2176 .Case(".b", {0, 8})
2177 .Case(".h", {0, 16})
2178 .Case(".s", {0, 32})
2179 .Case(".d", {0, 64})
2180 .Case(".q", {0, 128})
2181 .Default({-1, -1});
2182 break;
2183 default:
2184 llvm_unreachable("Unsupported RegKind");
2185 }
2186
2187 if (Res == std::make_pair(-1, -1))
2188 return Optional<std::pair<int, int>>();
2189
2190 return Optional<std::pair<int, int>>(Res);
2191 }
2192
isValidVectorKind(StringRef Suffix,RegKind VectorKind)2193 static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2194 return parseVectorKind(Suffix, VectorKind).hasValue();
2195 }
2196
matchSVEDataVectorRegName(StringRef Name)2197 static unsigned matchSVEDataVectorRegName(StringRef Name) {
2198 return StringSwitch<unsigned>(Name.lower())
2199 .Case("z0", AArch64::Z0)
2200 .Case("z1", AArch64::Z1)
2201 .Case("z2", AArch64::Z2)
2202 .Case("z3", AArch64::Z3)
2203 .Case("z4", AArch64::Z4)
2204 .Case("z5", AArch64::Z5)
2205 .Case("z6", AArch64::Z6)
2206 .Case("z7", AArch64::Z7)
2207 .Case("z8", AArch64::Z8)
2208 .Case("z9", AArch64::Z9)
2209 .Case("z10", AArch64::Z10)
2210 .Case("z11", AArch64::Z11)
2211 .Case("z12", AArch64::Z12)
2212 .Case("z13", AArch64::Z13)
2213 .Case("z14", AArch64::Z14)
2214 .Case("z15", AArch64::Z15)
2215 .Case("z16", AArch64::Z16)
2216 .Case("z17", AArch64::Z17)
2217 .Case("z18", AArch64::Z18)
2218 .Case("z19", AArch64::Z19)
2219 .Case("z20", AArch64::Z20)
2220 .Case("z21", AArch64::Z21)
2221 .Case("z22", AArch64::Z22)
2222 .Case("z23", AArch64::Z23)
2223 .Case("z24", AArch64::Z24)
2224 .Case("z25", AArch64::Z25)
2225 .Case("z26", AArch64::Z26)
2226 .Case("z27", AArch64::Z27)
2227 .Case("z28", AArch64::Z28)
2228 .Case("z29", AArch64::Z29)
2229 .Case("z30", AArch64::Z30)
2230 .Case("z31", AArch64::Z31)
2231 .Default(0);
2232 }
2233
matchSVEPredicateVectorRegName(StringRef Name)2234 static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2235 return StringSwitch<unsigned>(Name.lower())
2236 .Case("p0", AArch64::P0)
2237 .Case("p1", AArch64::P1)
2238 .Case("p2", AArch64::P2)
2239 .Case("p3", AArch64::P3)
2240 .Case("p4", AArch64::P4)
2241 .Case("p5", AArch64::P5)
2242 .Case("p6", AArch64::P6)
2243 .Case("p7", AArch64::P7)
2244 .Case("p8", AArch64::P8)
2245 .Case("p9", AArch64::P9)
2246 .Case("p10", AArch64::P10)
2247 .Case("p11", AArch64::P11)
2248 .Case("p12", AArch64::P12)
2249 .Case("p13", AArch64::P13)
2250 .Case("p14", AArch64::P14)
2251 .Case("p15", AArch64::P15)
2252 .Default(0);
2253 }
2254
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)2255 bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2256 SMLoc &EndLoc) {
2257 StartLoc = getLoc();
2258 auto Res = tryParseScalarRegister(RegNo);
2259 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2260 return Res != MatchOperand_Success;
2261 }
2262
2263 // Matches a register name or register alias previously defined by '.req'
matchRegisterNameAlias(StringRef Name,RegKind Kind)2264 unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
2265 RegKind Kind) {
2266 unsigned RegNum = 0;
2267 if ((RegNum = matchSVEDataVectorRegName(Name)))
2268 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2269
2270 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2271 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2272
2273 if ((RegNum = MatchNeonVectorRegName(Name)))
2274 return Kind == RegKind::NeonVector ? RegNum : 0;
2275
2276 // The parsed register must be of RegKind Scalar
2277 if ((RegNum = MatchRegisterName(Name)))
2278 return Kind == RegKind::Scalar ? RegNum : 0;
2279
2280 if (!RegNum) {
2281 // Handle a few common aliases of registers.
2282 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2283 .Case("fp", AArch64::FP)
2284 .Case("lr", AArch64::LR)
2285 .Case("x31", AArch64::XZR)
2286 .Case("w31", AArch64::WZR)
2287 .Default(0))
2288 return Kind == RegKind::Scalar ? RegNum : 0;
2289
2290 // Check for aliases registered via .req. Canonicalize to lower case.
2291 // That's more consistent since register names are case insensitive, and
2292 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2293 auto Entry = RegisterReqs.find(Name.lower());
2294 if (Entry == RegisterReqs.end())
2295 return 0;
2296
2297 // set RegNum if the match is the right kind of register
2298 if (Kind == Entry->getValue().first)
2299 RegNum = Entry->getValue().second;
2300 }
2301 return RegNum;
2302 }
2303
2304 /// tryParseScalarRegister - Try to parse a register name. The token must be an
2305 /// Identifier when called, and if it is a register name the token is eaten and
2306 /// the register is added to the operand list.
2307 OperandMatchResultTy
tryParseScalarRegister(unsigned & RegNum)2308 AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
2309 MCAsmParser &Parser = getParser();
2310 const AsmToken &Tok = Parser.getTok();
2311 if (Tok.isNot(AsmToken::Identifier))
2312 return MatchOperand_NoMatch;
2313
2314 std::string lowerCase = Tok.getString().lower();
2315 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2316 if (Reg == 0)
2317 return MatchOperand_NoMatch;
2318
2319 RegNum = Reg;
2320 Parser.Lex(); // Eat identifier token.
2321 return MatchOperand_Success;
2322 }
2323
2324 /// tryParseSysCROperand - Try to parse a system instruction CR operand name.
2325 OperandMatchResultTy
tryParseSysCROperand(OperandVector & Operands)2326 AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
2327 MCAsmParser &Parser = getParser();
2328 SMLoc S = getLoc();
2329
2330 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2331 Error(S, "Expected cN operand where 0 <= N <= 15");
2332 return MatchOperand_ParseFail;
2333 }
2334
2335 StringRef Tok = Parser.getTok().getIdentifier();
2336 if (Tok[0] != 'c' && Tok[0] != 'C') {
2337 Error(S, "Expected cN operand where 0 <= N <= 15");
2338 return MatchOperand_ParseFail;
2339 }
2340
2341 uint32_t CRNum;
2342 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2343 if (BadNum || CRNum > 15) {
2344 Error(S, "Expected cN operand where 0 <= N <= 15");
2345 return MatchOperand_ParseFail;
2346 }
2347
2348 Parser.Lex(); // Eat identifier token.
2349 Operands.push_back(
2350 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2351 return MatchOperand_Success;
2352 }
2353
2354 /// tryParsePrefetch - Try to parse a prefetch operand.
2355 template <bool IsSVEPrefetch>
2356 OperandMatchResultTy
tryParsePrefetch(OperandVector & Operands)2357 AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
2358 MCAsmParser &Parser = getParser();
2359 SMLoc S = getLoc();
2360 const AsmToken &Tok = Parser.getTok();
2361
2362 auto LookupByName = [](StringRef N) {
2363 if (IsSVEPrefetch) {
2364 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2365 return Optional<unsigned>(Res->Encoding);
2366 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2367 return Optional<unsigned>(Res->Encoding);
2368 return Optional<unsigned>();
2369 };
2370
2371 auto LookupByEncoding = [](unsigned E) {
2372 if (IsSVEPrefetch) {
2373 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2374 return Optional<StringRef>(Res->Name);
2375 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2376 return Optional<StringRef>(Res->Name);
2377 return Optional<StringRef>();
2378 };
2379 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2380
2381 // Either an identifier for named values or a 5-bit immediate.
2382 // Eat optional hash.
2383 if (parseOptionalToken(AsmToken::Hash) ||
2384 Tok.is(AsmToken::Integer)) {
2385 const MCExpr *ImmVal;
2386 if (getParser().parseExpression(ImmVal))
2387 return MatchOperand_ParseFail;
2388
2389 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2390 if (!MCE) {
2391 TokError("immediate value expected for prefetch operand");
2392 return MatchOperand_ParseFail;
2393 }
2394 unsigned prfop = MCE->getValue();
2395 if (prfop > MaxVal) {
2396 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2397 "] expected");
2398 return MatchOperand_ParseFail;
2399 }
2400
2401 auto PRFM = LookupByEncoding(MCE->getValue());
2402 Operands.push_back(AArch64Operand::CreatePrefetch(
2403 prfop, PRFM.getValueOr(""), S, getContext()));
2404 return MatchOperand_Success;
2405 }
2406
2407 if (Tok.isNot(AsmToken::Identifier)) {
2408 TokError("prefetch hint expected");
2409 return MatchOperand_ParseFail;
2410 }
2411
2412 auto PRFM = LookupByName(Tok.getString());
2413 if (!PRFM) {
2414 TokError("prefetch hint expected");
2415 return MatchOperand_ParseFail;
2416 }
2417
2418 Parser.Lex(); // Eat identifier token.
2419 Operands.push_back(AArch64Operand::CreatePrefetch(
2420 *PRFM, Tok.getString(), S, getContext()));
2421 return MatchOperand_Success;
2422 }
2423
2424 /// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
2425 OperandMatchResultTy
tryParsePSBHint(OperandVector & Operands)2426 AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2427 MCAsmParser &Parser = getParser();
2428 SMLoc S = getLoc();
2429 const AsmToken &Tok = Parser.getTok();
2430 if (Tok.isNot(AsmToken::Identifier)) {
2431 TokError("invalid operand for instruction");
2432 return MatchOperand_ParseFail;
2433 }
2434
2435 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2436 if (!PSB) {
2437 TokError("invalid operand for instruction");
2438 return MatchOperand_ParseFail;
2439 }
2440
2441 Parser.Lex(); // Eat identifier token.
2442 Operands.push_back(AArch64Operand::CreatePSBHint(
2443 PSB->Encoding, Tok.getString(), S, getContext()));
2444 return MatchOperand_Success;
2445 }
2446
2447 /// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2448 OperandMatchResultTy
tryParseBTIHint(OperandVector & Operands)2449 AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2450 MCAsmParser &Parser = getParser();
2451 SMLoc S = getLoc();
2452 const AsmToken &Tok = Parser.getTok();
2453 if (Tok.isNot(AsmToken::Identifier)) {
2454 TokError("invalid operand for instruction");
2455 return MatchOperand_ParseFail;
2456 }
2457
2458 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2459 if (!BTI) {
2460 TokError("invalid operand for instruction");
2461 return MatchOperand_ParseFail;
2462 }
2463
2464 Parser.Lex(); // Eat identifier token.
2465 Operands.push_back(AArch64Operand::CreateBTIHint(
2466 BTI->Encoding, Tok.getString(), S, getContext()));
2467 return MatchOperand_Success;
2468 }
2469
2470 /// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2471 /// instruction.
2472 OperandMatchResultTy
tryParseAdrpLabel(OperandVector & Operands)2473 AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
2474 MCAsmParser &Parser = getParser();
2475 SMLoc S = getLoc();
2476 const MCExpr *Expr;
2477
2478 if (Parser.getTok().is(AsmToken::Hash)) {
2479 Parser.Lex(); // Eat hash token.
2480 }
2481
2482 if (parseSymbolicImmVal(Expr))
2483 return MatchOperand_ParseFail;
2484
2485 AArch64MCExpr::VariantKind ELFRefKind;
2486 MCSymbolRefExpr::VariantKind DarwinRefKind;
2487 int64_t Addend;
2488 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2489 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2490 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2491 // No modifier was specified at all; this is the syntax for an ELF basic
2492 // ADRP relocation (unfortunately).
2493 Expr =
2494 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
2495 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2496 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2497 Addend != 0) {
2498 Error(S, "gotpage label reference not allowed an addend");
2499 return MatchOperand_ParseFail;
2500 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2501 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2502 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2503 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2504 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2505 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2506 // The operand must be an @page or @gotpage qualified symbolref.
2507 Error(S, "page or gotpage label reference expected");
2508 return MatchOperand_ParseFail;
2509 }
2510 }
2511
2512 // We have either a label reference possibly with addend or an immediate. The
2513 // addend is a raw value here. The linker will adjust it to only reference the
2514 // page.
2515 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2516 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2517
2518 return MatchOperand_Success;
2519 }
2520
2521 /// tryParseAdrLabel - Parse and validate a source label for the ADR
2522 /// instruction.
2523 OperandMatchResultTy
tryParseAdrLabel(OperandVector & Operands)2524 AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2525 SMLoc S = getLoc();
2526 const MCExpr *Expr;
2527
2528 // Leave anything with a bracket to the default for SVE
2529 if (getParser().getTok().is(AsmToken::LBrac))
2530 return MatchOperand_NoMatch;
2531
2532 if (getParser().getTok().is(AsmToken::Hash))
2533 getParser().Lex(); // Eat hash token.
2534
2535 if (parseSymbolicImmVal(Expr))
2536 return MatchOperand_ParseFail;
2537
2538 AArch64MCExpr::VariantKind ELFRefKind;
2539 MCSymbolRefExpr::VariantKind DarwinRefKind;
2540 int64_t Addend;
2541 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2542 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2543 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2544 // No modifier was specified at all; this is the syntax for an ELF basic
2545 // ADR relocation (unfortunately).
2546 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2547 } else {
2548 Error(S, "unexpected adr label");
2549 return MatchOperand_ParseFail;
2550 }
2551 }
2552
2553 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2554 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2555 return MatchOperand_Success;
2556 }
2557
2558 /// tryParseFPImm - A floating point immediate expression operand.
2559 template<bool AddFPZeroAsLiteral>
2560 OperandMatchResultTy
tryParseFPImm(OperandVector & Operands)2561 AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
2562 MCAsmParser &Parser = getParser();
2563 SMLoc S = getLoc();
2564
2565 bool Hash = parseOptionalToken(AsmToken::Hash);
2566
2567 // Handle negation, as that still comes through as a separate token.
2568 bool isNegative = parseOptionalToken(AsmToken::Minus);
2569
2570 const AsmToken &Tok = Parser.getTok();
2571 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2572 if (!Hash)
2573 return MatchOperand_NoMatch;
2574 TokError("invalid floating point immediate");
2575 return MatchOperand_ParseFail;
2576 }
2577
2578 // Parse hexadecimal representation.
2579 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2580 if (Tok.getIntVal() > 255 || isNegative) {
2581 TokError("encoded floating point value out of range");
2582 return MatchOperand_ParseFail;
2583 }
2584
2585 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2586 Operands.push_back(
2587 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2588 } else {
2589 // Parse FP representation.
2590 APFloat RealVal(APFloat::IEEEdouble());
2591 auto Status =
2592 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2593 if (isNegative)
2594 RealVal.changeSign();
2595
2596 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2597 Operands.push_back(
2598 AArch64Operand::CreateToken("#0", false, S, getContext()));
2599 Operands.push_back(
2600 AArch64Operand::CreateToken(".0", false, S, getContext()));
2601 } else
2602 Operands.push_back(AArch64Operand::CreateFPImm(
2603 RealVal, Status == APFloat::opOK, S, getContext()));
2604 }
2605
2606 Parser.Lex(); // Eat the token.
2607
2608 return MatchOperand_Success;
2609 }
2610
2611 /// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2612 /// a shift suffix, for example '#1, lsl #12'.
2613 OperandMatchResultTy
tryParseImmWithOptionalShift(OperandVector & Operands)2614 AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
2615 MCAsmParser &Parser = getParser();
2616 SMLoc S = getLoc();
2617
2618 if (Parser.getTok().is(AsmToken::Hash))
2619 Parser.Lex(); // Eat '#'
2620 else if (Parser.getTok().isNot(AsmToken::Integer))
2621 // Operand should start from # or should be integer, emit error otherwise.
2622 return MatchOperand_NoMatch;
2623
2624 const MCExpr *Imm;
2625 if (parseSymbolicImmVal(Imm))
2626 return MatchOperand_ParseFail;
2627 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2628 SMLoc E = Parser.getTok().getLoc();
2629 Operands.push_back(
2630 AArch64Operand::CreateImm(Imm, S, E, getContext()));
2631 return MatchOperand_Success;
2632 }
2633
2634 // Eat ','
2635 Parser.Lex();
2636
2637 // The optional operand must be "lsl #N" where N is non-negative.
2638 if (!Parser.getTok().is(AsmToken::Identifier) ||
2639 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2640 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2641 return MatchOperand_ParseFail;
2642 }
2643
2644 // Eat 'lsl'
2645 Parser.Lex();
2646
2647 parseOptionalToken(AsmToken::Hash);
2648
2649 if (Parser.getTok().isNot(AsmToken::Integer)) {
2650 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2651 return MatchOperand_ParseFail;
2652 }
2653
2654 int64_t ShiftAmount = Parser.getTok().getIntVal();
2655
2656 if (ShiftAmount < 0) {
2657 Error(Parser.getTok().getLoc(), "positive shift amount required");
2658 return MatchOperand_ParseFail;
2659 }
2660 Parser.Lex(); // Eat the number
2661
2662 // Just in case the optional lsl #0 is used for immediates other than zero.
2663 if (ShiftAmount == 0 && Imm != 0) {
2664 SMLoc E = Parser.getTok().getLoc();
2665 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2666 return MatchOperand_Success;
2667 }
2668
2669 SMLoc E = Parser.getTok().getLoc();
2670 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2671 S, E, getContext()));
2672 return MatchOperand_Success;
2673 }
2674
2675 /// parseCondCodeString - Parse a Condition Code string.
parseCondCodeString(StringRef Cond)2676 AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2677 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2678 .Case("eq", AArch64CC::EQ)
2679 .Case("ne", AArch64CC::NE)
2680 .Case("cs", AArch64CC::HS)
2681 .Case("hs", AArch64CC::HS)
2682 .Case("cc", AArch64CC::LO)
2683 .Case("lo", AArch64CC::LO)
2684 .Case("mi", AArch64CC::MI)
2685 .Case("pl", AArch64CC::PL)
2686 .Case("vs", AArch64CC::VS)
2687 .Case("vc", AArch64CC::VC)
2688 .Case("hi", AArch64CC::HI)
2689 .Case("ls", AArch64CC::LS)
2690 .Case("ge", AArch64CC::GE)
2691 .Case("lt", AArch64CC::LT)
2692 .Case("gt", AArch64CC::GT)
2693 .Case("le", AArch64CC::LE)
2694 .Case("al", AArch64CC::AL)
2695 .Case("nv", AArch64CC::NV)
2696 .Default(AArch64CC::Invalid);
2697
2698 if (CC == AArch64CC::Invalid &&
2699 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2700 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2701 .Case("none", AArch64CC::EQ)
2702 .Case("any", AArch64CC::NE)
2703 .Case("nlast", AArch64CC::HS)
2704 .Case("last", AArch64CC::LO)
2705 .Case("first", AArch64CC::MI)
2706 .Case("nfrst", AArch64CC::PL)
2707 .Case("pmore", AArch64CC::HI)
2708 .Case("plast", AArch64CC::LS)
2709 .Case("tcont", AArch64CC::GE)
2710 .Case("tstop", AArch64CC::LT)
2711 .Default(AArch64CC::Invalid);
2712
2713 return CC;
2714 }
2715
2716 /// parseCondCode - Parse a Condition Code operand.
parseCondCode(OperandVector & Operands,bool invertCondCode)2717 bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2718 bool invertCondCode) {
2719 MCAsmParser &Parser = getParser();
2720 SMLoc S = getLoc();
2721 const AsmToken &Tok = Parser.getTok();
2722 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2723
2724 StringRef Cond = Tok.getString();
2725 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2726 if (CC == AArch64CC::Invalid)
2727 return TokError("invalid condition code");
2728 Parser.Lex(); // Eat identifier token.
2729
2730 if (invertCondCode) {
2731 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2732 return TokError("condition codes AL and NV are invalid for this instruction");
2733 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
2734 }
2735
2736 Operands.push_back(
2737 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2738 return false;
2739 }
2740
2741 /// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2742 /// them if present.
2743 OperandMatchResultTy
tryParseOptionalShiftExtend(OperandVector & Operands)2744 AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
2745 MCAsmParser &Parser = getParser();
2746 const AsmToken &Tok = Parser.getTok();
2747 std::string LowerID = Tok.getString().lower();
2748 AArch64_AM::ShiftExtendType ShOp =
2749 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2750 .Case("lsl", AArch64_AM::LSL)
2751 .Case("lsr", AArch64_AM::LSR)
2752 .Case("asr", AArch64_AM::ASR)
2753 .Case("ror", AArch64_AM::ROR)
2754 .Case("msl", AArch64_AM::MSL)
2755 .Case("uxtb", AArch64_AM::UXTB)
2756 .Case("uxth", AArch64_AM::UXTH)
2757 .Case("uxtw", AArch64_AM::UXTW)
2758 .Case("uxtx", AArch64_AM::UXTX)
2759 .Case("sxtb", AArch64_AM::SXTB)
2760 .Case("sxth", AArch64_AM::SXTH)
2761 .Case("sxtw", AArch64_AM::SXTW)
2762 .Case("sxtx", AArch64_AM::SXTX)
2763 .Default(AArch64_AM::InvalidShiftExtend);
2764
2765 if (ShOp == AArch64_AM::InvalidShiftExtend)
2766 return MatchOperand_NoMatch;
2767
2768 SMLoc S = Tok.getLoc();
2769 Parser.Lex();
2770
2771 bool Hash = parseOptionalToken(AsmToken::Hash);
2772
2773 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2774 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2775 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2776 ShOp == AArch64_AM::MSL) {
2777 // We expect a number here.
2778 TokError("expected #imm after shift specifier");
2779 return MatchOperand_ParseFail;
2780 }
2781
2782 // "extend" type operations don't need an immediate, #0 is implicit.
2783 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2784 Operands.push_back(
2785 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2786 return MatchOperand_Success;
2787 }
2788
2789 // Make sure we do actually have a number, identifier or a parenthesized
2790 // expression.
2791 SMLoc E = Parser.getTok().getLoc();
2792 if (!Parser.getTok().is(AsmToken::Integer) &&
2793 !Parser.getTok().is(AsmToken::LParen) &&
2794 !Parser.getTok().is(AsmToken::Identifier)) {
2795 Error(E, "expected integer shift amount");
2796 return MatchOperand_ParseFail;
2797 }
2798
2799 const MCExpr *ImmVal;
2800 if (getParser().parseExpression(ImmVal))
2801 return MatchOperand_ParseFail;
2802
2803 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2804 if (!MCE) {
2805 Error(E, "expected constant '#imm' after shift specifier");
2806 return MatchOperand_ParseFail;
2807 }
2808
2809 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2810 Operands.push_back(AArch64Operand::CreateShiftExtend(
2811 ShOp, MCE->getValue(), true, S, E, getContext()));
2812 return MatchOperand_Success;
2813 }
2814
2815 static const struct Extension {
2816 const char *Name;
2817 const FeatureBitset Features;
2818 } ExtensionMap[] = {
2819 {"crc", {AArch64::FeatureCRC}},
2820 {"sm4", {AArch64::FeatureSM4}},
2821 {"sha3", {AArch64::FeatureSHA3}},
2822 {"sha2", {AArch64::FeatureSHA2}},
2823 {"aes", {AArch64::FeatureAES}},
2824 {"crypto", {AArch64::FeatureCrypto}},
2825 {"fp", {AArch64::FeatureFPARMv8}},
2826 {"simd", {AArch64::FeatureNEON}},
2827 {"ras", {AArch64::FeatureRAS}},
2828 {"lse", {AArch64::FeatureLSE}},
2829 {"predres", {AArch64::FeaturePredRes}},
2830 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2831 {"mte", {AArch64::FeatureMTE}},
2832 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2833 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2834 {"ccpp", {AArch64::FeatureCCPP}},
2835 {"sve", {AArch64::FeatureSVE}},
2836 // FIXME: Unsupported extensions
2837 {"pan", {}},
2838 {"lor", {}},
2839 {"rdma", {}},
2840 {"profile", {}},
2841 };
2842
setRequiredFeatureString(FeatureBitset FBS,std::string & Str)2843 static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2844 if (FBS[AArch64::HasV8_1aOps])
2845 Str += "ARMv8.1a";
2846 else if (FBS[AArch64::HasV8_2aOps])
2847 Str += "ARMv8.2a";
2848 else if (FBS[AArch64::HasV8_3aOps])
2849 Str += "ARMv8.3a";
2850 else if (FBS[AArch64::HasV8_4aOps])
2851 Str += "ARMv8.4a";
2852 else if (FBS[AArch64::HasV8_5aOps])
2853 Str += "ARMv8.5a";
2854 else {
2855 auto ext = std::find_if(std::begin(ExtensionMap),
2856 std::end(ExtensionMap),
2857 [&](const Extension& e)
2858 // Use & in case multiple features are enabled
2859 { return (FBS & e.Features) != FeatureBitset(); }
2860 );
2861
2862 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2863 }
2864 }
2865
createSysAlias(uint16_t Encoding,OperandVector & Operands,SMLoc S)2866 void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2867 SMLoc S) {
2868 const uint16_t Op2 = Encoding & 7;
2869 const uint16_t Cm = (Encoding & 0x78) >> 3;
2870 const uint16_t Cn = (Encoding & 0x780) >> 7;
2871 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2872
2873 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2874
2875 Operands.push_back(
2876 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2877 Operands.push_back(
2878 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2879 Operands.push_back(
2880 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2881 Expr = MCConstantExpr::create(Op2, getContext());
2882 Operands.push_back(
2883 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2884 }
2885
2886 /// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2887 /// the SYS instruction. Parse them specially so that we create a SYS MCInst.
parseSysAlias(StringRef Name,SMLoc NameLoc,OperandVector & Operands)2888 bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2889 OperandVector &Operands) {
2890 if (Name.find('.') != StringRef::npos)
2891 return TokError("invalid operand");
2892
2893 Mnemonic = Name;
2894 Operands.push_back(
2895 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2896
2897 MCAsmParser &Parser = getParser();
2898 const AsmToken &Tok = Parser.getTok();
2899 StringRef Op = Tok.getString();
2900 SMLoc S = Tok.getLoc();
2901
2902 if (Mnemonic == "ic") {
2903 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2904 if (!IC)
2905 return TokError("invalid operand for IC instruction");
2906 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2907 std::string Str("IC " + std::string(IC->Name) + " requires ");
2908 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2909 return TokError(Str.c_str());
2910 }
2911 createSysAlias(IC->Encoding, Operands, S);
2912 } else if (Mnemonic == "dc") {
2913 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2914 if (!DC)
2915 return TokError("invalid operand for DC instruction");
2916 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2917 std::string Str("DC " + std::string(DC->Name) + " requires ");
2918 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2919 return TokError(Str.c_str());
2920 }
2921 createSysAlias(DC->Encoding, Operands, S);
2922 } else if (Mnemonic == "at") {
2923 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2924 if (!AT)
2925 return TokError("invalid operand for AT instruction");
2926 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2927 std::string Str("AT " + std::string(AT->Name) + " requires ");
2928 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2929 return TokError(Str.c_str());
2930 }
2931 createSysAlias(AT->Encoding, Operands, S);
2932 } else if (Mnemonic == "tlbi") {
2933 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2934 if (!TLBI)
2935 return TokError("invalid operand for TLBI instruction");
2936 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2937 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2938 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2939 return TokError(Str.c_str());
2940 }
2941 createSysAlias(TLBI->Encoding, Operands, S);
2942 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2943 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2944 if (!PRCTX)
2945 return TokError("invalid operand for prediction restriction instruction");
2946 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2947 std::string Str(
2948 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2949 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2950 return TokError(Str.c_str());
2951 }
2952 uint16_t PRCTX_Op2 =
2953 Mnemonic == "cfp" ? 4 :
2954 Mnemonic == "dvp" ? 5 :
2955 Mnemonic == "cpp" ? 7 :
2956 0;
2957 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2958 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
2959 }
2960
2961 Parser.Lex(); // Eat operand.
2962
2963 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2964 bool HasRegister = false;
2965
2966 // Check for the optional register operand.
2967 if (parseOptionalToken(AsmToken::Comma)) {
2968 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2969 return TokError("expected register operand");
2970 HasRegister = true;
2971 }
2972
2973 if (ExpectRegister && !HasRegister)
2974 return TokError("specified " + Mnemonic + " op requires a register");
2975 else if (!ExpectRegister && HasRegister)
2976 return TokError("specified " + Mnemonic + " op does not use a register");
2977
2978 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2979 return true;
2980
2981 return false;
2982 }
2983
2984 OperandMatchResultTy
tryParseBarrierOperand(OperandVector & Operands)2985 AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
2986 MCAsmParser &Parser = getParser();
2987 const AsmToken &Tok = Parser.getTok();
2988
2989 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2990 TokError("'csync' operand expected");
2991 return MatchOperand_ParseFail;
2992 // Can be either a #imm style literal or an option name
2993 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
2994 // Immediate operand.
2995 const MCExpr *ImmVal;
2996 SMLoc ExprLoc = getLoc();
2997 if (getParser().parseExpression(ImmVal))
2998 return MatchOperand_ParseFail;
2999 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3000 if (!MCE) {
3001 Error(ExprLoc, "immediate value expected for barrier operand");
3002 return MatchOperand_ParseFail;
3003 }
3004 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3005 Error(ExprLoc, "barrier operand out of range");
3006 return MatchOperand_ParseFail;
3007 }
3008 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3009 Operands.push_back(AArch64Operand::CreateBarrier(
3010 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
3011 return MatchOperand_Success;
3012 }
3013
3014 if (Tok.isNot(AsmToken::Identifier)) {
3015 TokError("invalid operand for instruction");
3016 return MatchOperand_ParseFail;
3017 }
3018
3019 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
3020 // The only valid named option for ISB is 'sy'
3021 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3022 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
3023 TokError("'sy' or #imm operand expected");
3024 return MatchOperand_ParseFail;
3025 // The only valid named option for TSB is 'csync'
3026 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3027 TokError("'csync' operand expected");
3028 return MatchOperand_ParseFail;
3029 } else if (!DB && !TSB) {
3030 TokError("invalid barrier option name");
3031 return MatchOperand_ParseFail;
3032 }
3033
3034 Operands.push_back(AArch64Operand::CreateBarrier(
3035 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
3036 Parser.Lex(); // Consume the option
3037
3038 return MatchOperand_Success;
3039 }
3040
3041 OperandMatchResultTy
tryParseSysReg(OperandVector & Operands)3042 AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
3043 MCAsmParser &Parser = getParser();
3044 const AsmToken &Tok = Parser.getTok();
3045
3046 if (Tok.isNot(AsmToken::Identifier))
3047 return MatchOperand_NoMatch;
3048
3049 int MRSReg, MSRReg;
3050 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3051 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3052 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3053 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3054 } else
3055 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
3056
3057 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3058 unsigned PStateImm = -1;
3059 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3060 PStateImm = PState->Encoding;
3061
3062 Operands.push_back(
3063 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3064 PStateImm, getContext()));
3065 Parser.Lex(); // Eat identifier
3066
3067 return MatchOperand_Success;
3068 }
3069
3070 /// tryParseNeonVectorRegister - Parse a vector register operand.
tryParseNeonVectorRegister(OperandVector & Operands)3071 bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
3072 MCAsmParser &Parser = getParser();
3073 if (Parser.getTok().isNot(AsmToken::Identifier))
3074 return true;
3075
3076 SMLoc S = getLoc();
3077 // Check for a vector register specifier first.
3078 StringRef Kind;
3079 unsigned Reg;
3080 OperandMatchResultTy Res =
3081 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3082 if (Res != MatchOperand_Success)
3083 return true;
3084
3085 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3086 if (!KindRes)
3087 return true;
3088
3089 unsigned ElementWidth = KindRes->second;
3090 Operands.push_back(
3091 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3092 S, getLoc(), getContext()));
3093
3094 // If there was an explicit qualifier, that goes on as a literal text
3095 // operand.
3096 if (!Kind.empty())
3097 Operands.push_back(
3098 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3099
3100 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3101 }
3102
3103 OperandMatchResultTy
tryParseVectorIndex(OperandVector & Operands)3104 AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
3105 SMLoc SIdx = getLoc();
3106 if (parseOptionalToken(AsmToken::LBrac)) {
3107 const MCExpr *ImmVal;
3108 if (getParser().parseExpression(ImmVal))
3109 return MatchOperand_NoMatch;
3110 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3111 if (!MCE) {
3112 TokError("immediate value expected for vector index");
3113 return MatchOperand_ParseFail;;
3114 }
3115
3116 SMLoc E = getLoc();
3117
3118 if (parseToken(AsmToken::RBrac, "']' expected"))
3119 return MatchOperand_ParseFail;;
3120
3121 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3122 E, getContext()));
3123 return MatchOperand_Success;
3124 }
3125
3126 return MatchOperand_NoMatch;
3127 }
3128
3129 // tryParseVectorRegister - Try to parse a vector register name with
3130 // optional kind specifier. If it is a register specifier, eat the token
3131 // and return it.
3132 OperandMatchResultTy
tryParseVectorRegister(unsigned & Reg,StringRef & Kind,RegKind MatchKind)3133 AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
3134 RegKind MatchKind) {
3135 MCAsmParser &Parser = getParser();
3136 const AsmToken &Tok = Parser.getTok();
3137
3138 if (Tok.isNot(AsmToken::Identifier))
3139 return MatchOperand_NoMatch;
3140
3141 StringRef Name = Tok.getString();
3142 // If there is a kind specifier, it's separated from the register name by
3143 // a '.'.
3144 size_t Start = 0, Next = Name.find('.');
3145 StringRef Head = Name.slice(Start, Next);
3146 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
3147
3148 if (RegNum) {
3149 if (Next != StringRef::npos) {
3150 Kind = Name.slice(Next, StringRef::npos);
3151 if (!isValidVectorKind(Kind, MatchKind)) {
3152 TokError("invalid vector kind qualifier");
3153 return MatchOperand_ParseFail;
3154 }
3155 }
3156 Parser.Lex(); // Eat the register token.
3157
3158 Reg = RegNum;
3159 return MatchOperand_Success;
3160 }
3161
3162 return MatchOperand_NoMatch;
3163 }
3164
3165 /// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3166 OperandMatchResultTy
tryParseSVEPredicateVector(OperandVector & Operands)3167 AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3168 // Check for a SVE predicate register specifier first.
3169 const SMLoc S = getLoc();
3170 StringRef Kind;
3171 unsigned RegNum;
3172 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
3173 if (Res != MatchOperand_Success)
3174 return Res;
3175
3176 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3177 if (!KindRes)
3178 return MatchOperand_NoMatch;
3179
3180 unsigned ElementWidth = KindRes->second;
3181 Operands.push_back(AArch64Operand::CreateVectorReg(
3182 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3183 getLoc(), getContext()));
3184
3185 // Not all predicates are followed by a '/m' or '/z'.
3186 MCAsmParser &Parser = getParser();
3187 if (Parser.getTok().isNot(AsmToken::Slash))
3188 return MatchOperand_Success;
3189
3190 // But when they do they shouldn't have an element type suffix.
3191 if (!Kind.empty()) {
3192 Error(S, "not expecting size suffix");
3193 return MatchOperand_ParseFail;
3194 }
3195
3196 // Add a literal slash as operand
3197 Operands.push_back(
3198 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3199
3200 Parser.Lex(); // Eat the slash.
3201
3202 // Zeroing or merging?
3203 auto Pred = Parser.getTok().getString().lower();
3204 if (Pred != "z" && Pred != "m") {
3205 Error(getLoc(), "expecting 'm' or 'z' predication");
3206 return MatchOperand_ParseFail;
3207 }
3208
3209 // Add zero/merge token.
3210 const char *ZM = Pred == "z" ? "z" : "m";
3211 Operands.push_back(
3212 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3213
3214 Parser.Lex(); // Eat zero/merge token.
3215 return MatchOperand_Success;
3216 }
3217
3218 /// parseRegister - Parse a register operand.
parseRegister(OperandVector & Operands)3219 bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
3220 // Try for a Neon vector register.
3221 if (!tryParseNeonVectorRegister(Operands))
3222 return false;
3223
3224 // Otherwise try for a scalar register.
3225 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3226 return false;
3227
3228 return true;
3229 }
3230
parseSymbolicImmVal(const MCExpr * & ImmVal)3231 bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
3232 MCAsmParser &Parser = getParser();
3233 bool HasELFModifier = false;
3234 AArch64MCExpr::VariantKind RefKind;
3235
3236 if (parseOptionalToken(AsmToken::Colon)) {
3237 HasELFModifier = true;
3238
3239 if (Parser.getTok().isNot(AsmToken::Identifier))
3240 return TokError("expect relocation specifier in operand after ':'");
3241
3242 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3243 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3244 .Case("lo12", AArch64MCExpr::VK_LO12)
3245 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3246 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3247 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3248 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3249 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3250 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3251 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3252 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3253 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3254 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3255 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3256 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3257 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3258 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3259 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3260 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3261 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3262 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3263 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3264 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3265 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3266 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3267 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3268 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3269 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3270 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3271 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3272 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3273 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3274 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3275 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3276 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3277 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3278 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
3279 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3280 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
3281 .Default(AArch64MCExpr::VK_INVALID);
3282
3283 if (RefKind == AArch64MCExpr::VK_INVALID)
3284 return TokError("expect relocation specifier in operand after ':'");
3285
3286 Parser.Lex(); // Eat identifier
3287
3288 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
3289 return true;
3290 }
3291
3292 if (getParser().parseExpression(ImmVal))
3293 return true;
3294
3295 if (HasELFModifier)
3296 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
3297
3298 return false;
3299 }
3300
3301 template <RegKind VectorKind>
3302 OperandMatchResultTy
tryParseVectorList(OperandVector & Operands,bool ExpectMatch)3303 AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3304 bool ExpectMatch) {
3305 MCAsmParser &Parser = getParser();
3306 if (!Parser.getTok().is(AsmToken::LCurly))
3307 return MatchOperand_NoMatch;
3308
3309 // Wrapper around parse function
3310 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
3311 bool NoMatchIsError) {
3312 auto RegTok = Parser.getTok();
3313 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3314 if (ParseRes == MatchOperand_Success) {
3315 if (parseVectorKind(Kind, VectorKind))
3316 return ParseRes;
3317 llvm_unreachable("Expected a valid vector kind");
3318 }
3319
3320 if (RegTok.isNot(AsmToken::Identifier) ||
3321 ParseRes == MatchOperand_ParseFail ||
3322 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3323 Error(Loc, "vector register expected");
3324 return MatchOperand_ParseFail;
3325 }
3326
3327 return MatchOperand_NoMatch;
3328 };
3329
3330 SMLoc S = getLoc();
3331 auto LCurly = Parser.getTok();
3332 Parser.Lex(); // Eat left bracket token.
3333
3334 StringRef Kind;
3335 unsigned FirstReg;
3336 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3337
3338 // Put back the original left bracket if there was no match, so that
3339 // different types of list-operands can be matched (e.g. SVE, Neon).
3340 if (ParseRes == MatchOperand_NoMatch)
3341 Parser.getLexer().UnLex(LCurly);
3342
3343 if (ParseRes != MatchOperand_Success)
3344 return ParseRes;
3345
3346 int64_t PrevReg = FirstReg;
3347 unsigned Count = 1;
3348
3349 if (parseOptionalToken(AsmToken::Minus)) {
3350 SMLoc Loc = getLoc();
3351 StringRef NextKind;
3352
3353 unsigned Reg;
3354 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3355 if (ParseRes != MatchOperand_Success)
3356 return ParseRes;
3357
3358 // Any Kind suffices must match on all regs in the list.
3359 if (Kind != NextKind) {
3360 Error(Loc, "mismatched register size suffix");
3361 return MatchOperand_ParseFail;
3362 }
3363
3364 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3365
3366 if (Space == 0 || Space > 3) {
3367 Error(Loc, "invalid number of vectors");
3368 return MatchOperand_ParseFail;
3369 }
3370
3371 Count += Space;
3372 }
3373 else {
3374 while (parseOptionalToken(AsmToken::Comma)) {
3375 SMLoc Loc = getLoc();
3376 StringRef NextKind;
3377 unsigned Reg;
3378 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3379 if (ParseRes != MatchOperand_Success)
3380 return ParseRes;
3381
3382 // Any Kind suffices must match on all regs in the list.
3383 if (Kind != NextKind) {
3384 Error(Loc, "mismatched register size suffix");
3385 return MatchOperand_ParseFail;
3386 }
3387
3388 // Registers must be incremental (with wraparound at 31)
3389 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
3390 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3391 Error(Loc, "registers must be sequential");
3392 return MatchOperand_ParseFail;
3393 }
3394
3395 PrevReg = Reg;
3396 ++Count;
3397 }
3398 }
3399
3400 if (parseToken(AsmToken::RCurly, "'}' expected"))
3401 return MatchOperand_ParseFail;
3402
3403 if (Count > 4) {
3404 Error(S, "invalid number of vectors");
3405 return MatchOperand_ParseFail;
3406 }
3407
3408 unsigned NumElements = 0;
3409 unsigned ElementWidth = 0;
3410 if (!Kind.empty()) {
3411 if (const auto &VK = parseVectorKind(Kind, VectorKind))
3412 std::tie(NumElements, ElementWidth) = *VK;
3413 }
3414
3415 Operands.push_back(AArch64Operand::CreateVectorList(
3416 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3417 getContext()));
3418
3419 return MatchOperand_Success;
3420 }
3421
3422 /// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
parseNeonVectorList(OperandVector & Operands)3423 bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
3424 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3425 if (ParseRes != MatchOperand_Success)
3426 return true;
3427
3428 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3429 }
3430
3431 OperandMatchResultTy
tryParseGPR64sp0Operand(OperandVector & Operands)3432 AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
3433 SMLoc StartLoc = getLoc();
3434
3435 unsigned RegNum;
3436 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3437 if (Res != MatchOperand_Success)
3438 return Res;
3439
3440 if (!parseOptionalToken(AsmToken::Comma)) {
3441 Operands.push_back(AArch64Operand::CreateReg(
3442 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3443 return MatchOperand_Success;
3444 }
3445
3446 parseOptionalToken(AsmToken::Hash);
3447
3448 if (getParser().getTok().isNot(AsmToken::Integer)) {
3449 Error(getLoc(), "index must be absent or #0");
3450 return MatchOperand_ParseFail;
3451 }
3452
3453 const MCExpr *ImmVal;
3454 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3455 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3456 Error(getLoc(), "index must be absent or #0");
3457 return MatchOperand_ParseFail;
3458 }
3459
3460 Operands.push_back(AArch64Operand::CreateReg(
3461 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
3462 return MatchOperand_Success;
3463 }
3464
3465 template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
3466 OperandMatchResultTy
tryParseGPROperand(OperandVector & Operands)3467 AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3468 SMLoc StartLoc = getLoc();
3469
3470 unsigned RegNum;
3471 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3472 if (Res != MatchOperand_Success)
3473 return Res;
3474
3475 // No shift/extend is the default.
3476 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3477 Operands.push_back(AArch64Operand::CreateReg(
3478 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
3479 return MatchOperand_Success;
3480 }
3481
3482 // Eat the comma
3483 getParser().Lex();
3484
3485 // Match the shift
3486 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3487 Res = tryParseOptionalShiftExtend(ExtOpnd);
3488 if (Res != MatchOperand_Success)
3489 return Res;
3490
3491 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
3492 Operands.push_back(AArch64Operand::CreateReg(
3493 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3494 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3495 Ext->hasShiftExtendAmount()));
3496
3497 return MatchOperand_Success;
3498 }
3499
parseOptionalMulOperand(OperandVector & Operands)3500 bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
3501 MCAsmParser &Parser = getParser();
3502
3503 // Some SVE instructions have a decoration after the immediate, i.e.
3504 // "mul vl". We parse them here and add tokens, which must be present in the
3505 // asm string in the tablegen instruction.
3506 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3507 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
3508 if (!Parser.getTok().getString().equals_lower("mul") ||
3509 !(NextIsVL || NextIsHash))
3510 return true;
3511
3512 Operands.push_back(
3513 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
3514 Parser.Lex(); // Eat the "mul"
3515
3516 if (NextIsVL) {
3517 Operands.push_back(
3518 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3519 Parser.Lex(); // Eat the "vl"
3520 return false;
3521 }
3522
3523 if (NextIsHash) {
3524 Parser.Lex(); // Eat the #
3525 SMLoc S = getLoc();
3526
3527 // Parse immediate operand.
3528 const MCExpr *ImmVal;
3529 if (!Parser.parseExpression(ImmVal))
3530 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3531 Operands.push_back(AArch64Operand::CreateImm(
3532 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3533 getContext()));
3534 return MatchOperand_Success;
3535 }
3536 }
3537
3538 return Error(getLoc(), "expected 'vl' or '#<imm>'");
3539 }
3540
3541 /// parseOperand - Parse a arm instruction operand. For now this parses the
3542 /// operand regardless of the mnemonic.
parseOperand(OperandVector & Operands,bool isCondCode,bool invertCondCode)3543 bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3544 bool invertCondCode) {
3545 MCAsmParser &Parser = getParser();
3546
3547 OperandMatchResultTy ResTy =
3548 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3549
3550 // Check if the current operand has a custom associated parser, if so, try to
3551 // custom parse the operand, or fallback to the general approach.
3552 if (ResTy == MatchOperand_Success)
3553 return false;
3554 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3555 // there was a match, but an error occurred, in which case, just return that
3556 // the operand parsing failed.
3557 if (ResTy == MatchOperand_ParseFail)
3558 return true;
3559
3560 // Nothing custom, so do general case parsing.
3561 SMLoc S, E;
3562 switch (getLexer().getKind()) {
3563 default: {
3564 SMLoc S = getLoc();
3565 const MCExpr *Expr;
3566 if (parseSymbolicImmVal(Expr))
3567 return Error(S, "invalid operand");
3568
3569 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3570 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3571 return false;
3572 }
3573 case AsmToken::LBrac: {
3574 SMLoc Loc = Parser.getTok().getLoc();
3575 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3576 getContext()));
3577 Parser.Lex(); // Eat '['
3578
3579 // There's no comma after a '[', so we can parse the next operand
3580 // immediately.
3581 return parseOperand(Operands, false, false);
3582 }
3583 case AsmToken::LCurly:
3584 return parseNeonVectorList(Operands);
3585 case AsmToken::Identifier: {
3586 // If we're expecting a Condition Code operand, then just parse that.
3587 if (isCondCode)
3588 return parseCondCode(Operands, invertCondCode);
3589
3590 // If it's a register name, parse it.
3591 if (!parseRegister(Operands))
3592 return false;
3593
3594 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3595 // by SVE instructions.
3596 if (!parseOptionalMulOperand(Operands))
3597 return false;
3598
3599 // This could be an optional "shift" or "extend" operand.
3600 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3601 // We can only continue if no tokens were eaten.
3602 if (GotShift != MatchOperand_NoMatch)
3603 return GotShift;
3604
3605 // This was not a register so parse other operands that start with an
3606 // identifier (like labels) as expressions and create them as immediates.
3607 const MCExpr *IdVal;
3608 S = getLoc();
3609 if (getParser().parseExpression(IdVal))
3610 return true;
3611 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3612 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3613 return false;
3614 }
3615 case AsmToken::Integer:
3616 case AsmToken::Real:
3617 case AsmToken::Hash: {
3618 // #42 -> immediate.
3619 S = getLoc();
3620
3621 parseOptionalToken(AsmToken::Hash);
3622
3623 // Parse a negative sign
3624 bool isNegative = false;
3625 if (Parser.getTok().is(AsmToken::Minus)) {
3626 isNegative = true;
3627 // We need to consume this token only when we have a Real, otherwise
3628 // we let parseSymbolicImmVal take care of it
3629 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3630 Parser.Lex();
3631 }
3632
3633 // The only Real that should come through here is a literal #0.0 for
3634 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3635 // so convert the value.
3636 const AsmToken &Tok = Parser.getTok();
3637 if (Tok.is(AsmToken::Real)) {
3638 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
3639 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3640 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3641 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3642 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
3643 return TokError("unexpected floating point literal");
3644 else if (IntVal != 0 || isNegative)
3645 return TokError("expected floating-point constant #0.0");
3646 Parser.Lex(); // Eat the token.
3647
3648 Operands.push_back(
3649 AArch64Operand::CreateToken("#0", false, S, getContext()));
3650 Operands.push_back(
3651 AArch64Operand::CreateToken(".0", false, S, getContext()));
3652 return false;
3653 }
3654
3655 const MCExpr *ImmVal;
3656 if (parseSymbolicImmVal(ImmVal))
3657 return true;
3658
3659 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3660 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3661 return false;
3662 }
3663 case AsmToken::Equal: {
3664 SMLoc Loc = getLoc();
3665 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
3666 return TokError("unexpected token in operand");
3667 Parser.Lex(); // Eat '='
3668 const MCExpr *SubExprVal;
3669 if (getParser().parseExpression(SubExprVal))
3670 return true;
3671
3672 if (Operands.size() < 2 ||
3673 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
3674 return Error(Loc, "Only valid when first operand is register");
3675
3676 bool IsXReg =
3677 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3678 Operands[1]->getReg());
3679
3680 MCContext& Ctx = getContext();
3681 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3682 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
3683 if (isa<MCConstantExpr>(SubExprVal)) {
3684 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3685 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3686 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3687 ShiftAmt += 16;
3688 Imm >>= 16;
3689 }
3690 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3691 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3692 Operands.push_back(AArch64Operand::CreateImm(
3693 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
3694 if (ShiftAmt)
3695 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3696 ShiftAmt, true, S, E, Ctx));
3697 return false;
3698 }
3699 APInt Simm = APInt(64, Imm << ShiftAmt);
3700 // check if the immediate is an unsigned or signed 32-bit int for W regs
3701 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3702 return Error(Loc, "Immediate too large for register");
3703 }
3704 // If it is a label or an imm that cannot fit in a movz, put it into CP.
3705 const MCExpr *CPLoc =
3706 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
3707 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3708 return false;
3709 }
3710 }
3711 }
3712
regsEqual(const MCParsedAsmOperand & Op1,const MCParsedAsmOperand & Op2) const3713 bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3714 const MCParsedAsmOperand &Op2) const {
3715 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3716 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3717 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3718 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3719 return MCTargetAsmParser::regsEqual(Op1, Op2);
3720
3721 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3722 "Testing equality of non-scalar registers not supported");
3723
3724 // Check if a registers match their sub/super register classes.
3725 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3726 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3727 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3728 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3729 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3730 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3731 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3732 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3733
3734 return false;
3735 }
3736
3737 /// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3738 /// operands.
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)3739 bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3740 StringRef Name, SMLoc NameLoc,
3741 OperandVector &Operands) {
3742 MCAsmParser &Parser = getParser();
3743 Name = StringSwitch<StringRef>(Name.lower())
3744 .Case("beq", "b.eq")
3745 .Case("bne", "b.ne")
3746 .Case("bhs", "b.hs")
3747 .Case("bcs", "b.cs")
3748 .Case("blo", "b.lo")
3749 .Case("bcc", "b.cc")
3750 .Case("bmi", "b.mi")
3751 .Case("bpl", "b.pl")
3752 .Case("bvs", "b.vs")
3753 .Case("bvc", "b.vc")
3754 .Case("bhi", "b.hi")
3755 .Case("bls", "b.ls")
3756 .Case("bge", "b.ge")
3757 .Case("blt", "b.lt")
3758 .Case("bgt", "b.gt")
3759 .Case("ble", "b.le")
3760 .Case("bal", "b.al")
3761 .Case("bnv", "b.nv")
3762 .Default(Name);
3763
3764 // First check for the AArch64-specific .req directive.
3765 if (Parser.getTok().is(AsmToken::Identifier) &&
3766 Parser.getTok().getIdentifier() == ".req") {
3767 parseDirectiveReq(Name, NameLoc);
3768 // We always return 'error' for this, as we're done with this
3769 // statement and don't need to match the 'instruction."
3770 return true;
3771 }
3772
3773 // Create the leading tokens for the mnemonic, split by '.' characters.
3774 size_t Start = 0, Next = Name.find('.');
3775 StringRef Head = Name.slice(Start, Next);
3776
3777 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3778 // the SYS instruction.
3779 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3780 Head == "cfp" || Head == "dvp" || Head == "cpp")
3781 return parseSysAlias(Head, NameLoc, Operands);
3782
3783 Operands.push_back(
3784 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3785 Mnemonic = Head;
3786
3787 // Handle condition codes for a branch mnemonic
3788 if (Head == "b" && Next != StringRef::npos) {
3789 Start = Next;
3790 Next = Name.find('.', Start + 1);
3791 Head = Name.slice(Start + 1, Next);
3792
3793 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3794 (Head.data() - Name.data()));
3795 AArch64CC::CondCode CC = parseCondCodeString(Head);
3796 if (CC == AArch64CC::Invalid)
3797 return Error(SuffixLoc, "invalid condition code");
3798 Operands.push_back(
3799 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3800 Operands.push_back(
3801 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3802 }
3803
3804 // Add the remaining tokens in the mnemonic.
3805 while (Next != StringRef::npos) {
3806 Start = Next;
3807 Next = Name.find('.', Start + 1);
3808 Head = Name.slice(Start, Next);
3809 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3810 (Head.data() - Name.data()) + 1);
3811 Operands.push_back(
3812 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3813 }
3814
3815 // Conditional compare instructions have a Condition Code operand, which needs
3816 // to be parsed and an immediate operand created.
3817 bool condCodeFourthOperand =
3818 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3819 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3820 Head == "csinc" || Head == "csinv" || Head == "csneg");
3821
3822 // These instructions are aliases to some of the conditional select
3823 // instructions. However, the condition code is inverted in the aliased
3824 // instruction.
3825 //
3826 // FIXME: Is this the correct way to handle these? Or should the parser
3827 // generate the aliased instructions directly?
3828 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3829 bool condCodeThirdOperand =
3830 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3831
3832 // Read the remaining operands.
3833 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3834
3835 unsigned N = 1;
3836 do {
3837 // Parse and remember the operand.
3838 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3839 (N == 3 && condCodeThirdOperand) ||
3840 (N == 2 && condCodeSecondOperand),
3841 condCodeSecondOperand || condCodeThirdOperand)) {
3842 return true;
3843 }
3844
3845 // After successfully parsing some operands there are two special cases to
3846 // consider (i.e. notional operands not separated by commas). Both are due
3847 // to memory specifiers:
3848 // + An RBrac will end an address for load/store/prefetch
3849 // + An '!' will indicate a pre-indexed operation.
3850 //
3851 // It's someone else's responsibility to make sure these tokens are sane
3852 // in the given context!
3853
3854 SMLoc RLoc = Parser.getTok().getLoc();
3855 if (parseOptionalToken(AsmToken::RBrac))
3856 Operands.push_back(
3857 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3858 SMLoc ELoc = Parser.getTok().getLoc();
3859 if (parseOptionalToken(AsmToken::Exclaim))
3860 Operands.push_back(
3861 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
3862
3863 ++N;
3864 } while (parseOptionalToken(AsmToken::Comma));
3865 }
3866
3867 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3868 return true;
3869
3870 return false;
3871 }
3872
isMatchingOrAlias(unsigned ZReg,unsigned Reg)3873 static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3874 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3875 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3877 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3878 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3879 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3880 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3881 }
3882
3883 // FIXME: This entire function is a giant hack to provide us with decent
3884 // operand range validation/diagnostics until TableGen/MC can be extended
3885 // to support autogeneration of this kind of validation.
validateInstruction(MCInst & Inst,SMLoc & IDLoc,SmallVectorImpl<SMLoc> & Loc)3886 bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3887 SmallVectorImpl<SMLoc> &Loc) {
3888 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3889 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3890
3891 // A prefix only applies to the instruction following it. Here we extract
3892 // prefix information for the next instruction before validating the current
3893 // one so that in the case of failure we don't erronously continue using the
3894 // current prefix.
3895 PrefixInfo Prefix = NextPrefix;
3896 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3897
3898 // Before validating the instruction in isolation we run through the rules
3899 // applicable when it follows a prefix instruction.
3900 // NOTE: brk & hlt can be prefixed but require no additional validation.
3901 if (Prefix.isActive() &&
3902 (Inst.getOpcode() != AArch64::BRK) &&
3903 (Inst.getOpcode() != AArch64::HLT)) {
3904
3905 // Prefixed intructions must have a destructive operand.
3906 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3907 AArch64::NotDestructive)
3908 return Error(IDLoc, "instruction is unpredictable when following a"
3909 " movprfx, suggest replacing movprfx with mov");
3910
3911 // Destination operands must match.
3912 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3913 return Error(Loc[0], "instruction is unpredictable when following a"
3914 " movprfx writing to a different destination");
3915
3916 // Destination operand must not be used in any other location.
3917 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3918 if (Inst.getOperand(i).isReg() &&
3919 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3920 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3921 return Error(Loc[0], "instruction is unpredictable when following a"
3922 " movprfx and destination also used as non-destructive"
3923 " source");
3924 }
3925
3926 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3927 if (Prefix.isPredicated()) {
3928 int PgIdx = -1;
3929
3930 // Find the instructions general predicate.
3931 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3932 if (Inst.getOperand(i).isReg() &&
3933 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3934 PgIdx = i;
3935 break;
3936 }
3937
3938 // Instruction must be predicated if the movprfx is predicated.
3939 if (PgIdx == -1 ||
3940 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3941 return Error(IDLoc, "instruction is unpredictable when following a"
3942 " predicated movprfx, suggest using unpredicated movprfx");
3943
3944 // Instruction must use same general predicate as the movprfx.
3945 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3946 return Error(IDLoc, "instruction is unpredictable when following a"
3947 " predicated movprfx using a different general predicate");
3948
3949 // Instruction element type must match the movprfx.
3950 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3951 return Error(IDLoc, "instruction is unpredictable when following a"
3952 " predicated movprfx with a different element size");
3953 }
3954 }
3955
3956 // Check for indexed addressing modes w/ the base register being the
3957 // same as a destination/source register or pair load where
3958 // the Rt == Rt2. All of those are undefined behaviour.
3959 switch (Inst.getOpcode()) {
3960 case AArch64::LDPSWpre:
3961 case AArch64::LDPWpost:
3962 case AArch64::LDPWpre:
3963 case AArch64::LDPXpost:
3964 case AArch64::LDPXpre: {
3965 unsigned Rt = Inst.getOperand(1).getReg();
3966 unsigned Rt2 = Inst.getOperand(2).getReg();
3967 unsigned Rn = Inst.getOperand(3).getReg();
3968 if (RI->isSubRegisterEq(Rn, Rt))
3969 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3970 "is also a destination");
3971 if (RI->isSubRegisterEq(Rn, Rt2))
3972 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3973 "is also a destination");
3974 LLVM_FALLTHROUGH;
3975 }
3976 case AArch64::LDPDi:
3977 case AArch64::LDPQi:
3978 case AArch64::LDPSi:
3979 case AArch64::LDPSWi:
3980 case AArch64::LDPWi:
3981 case AArch64::LDPXi: {
3982 unsigned Rt = Inst.getOperand(0).getReg();
3983 unsigned Rt2 = Inst.getOperand(1).getReg();
3984 if (Rt == Rt2)
3985 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3986 break;
3987 }
3988 case AArch64::LDPDpost:
3989 case AArch64::LDPDpre:
3990 case AArch64::LDPQpost:
3991 case AArch64::LDPQpre:
3992 case AArch64::LDPSpost:
3993 case AArch64::LDPSpre:
3994 case AArch64::LDPSWpost: {
3995 unsigned Rt = Inst.getOperand(1).getReg();
3996 unsigned Rt2 = Inst.getOperand(2).getReg();
3997 if (Rt == Rt2)
3998 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3999 break;
4000 }
4001 case AArch64::STPDpost:
4002 case AArch64::STPDpre:
4003 case AArch64::STPQpost:
4004 case AArch64::STPQpre:
4005 case AArch64::STPSpost:
4006 case AArch64::STPSpre:
4007 case AArch64::STPWpost:
4008 case AArch64::STPWpre:
4009 case AArch64::STPXpost:
4010 case AArch64::STPXpre: {
4011 unsigned Rt = Inst.getOperand(1).getReg();
4012 unsigned Rt2 = Inst.getOperand(2).getReg();
4013 unsigned Rn = Inst.getOperand(3).getReg();
4014 if (RI->isSubRegisterEq(Rn, Rt))
4015 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4016 "is also a source");
4017 if (RI->isSubRegisterEq(Rn, Rt2))
4018 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4019 "is also a source");
4020 break;
4021 }
4022 case AArch64::LDRBBpre:
4023 case AArch64::LDRBpre:
4024 case AArch64::LDRHHpre:
4025 case AArch64::LDRHpre:
4026 case AArch64::LDRSBWpre:
4027 case AArch64::LDRSBXpre:
4028 case AArch64::LDRSHWpre:
4029 case AArch64::LDRSHXpre:
4030 case AArch64::LDRSWpre:
4031 case AArch64::LDRWpre:
4032 case AArch64::LDRXpre:
4033 case AArch64::LDRBBpost:
4034 case AArch64::LDRBpost:
4035 case AArch64::LDRHHpost:
4036 case AArch64::LDRHpost:
4037 case AArch64::LDRSBWpost:
4038 case AArch64::LDRSBXpost:
4039 case AArch64::LDRSHWpost:
4040 case AArch64::LDRSHXpost:
4041 case AArch64::LDRSWpost:
4042 case AArch64::LDRWpost:
4043 case AArch64::LDRXpost: {
4044 unsigned Rt = Inst.getOperand(1).getReg();
4045 unsigned Rn = Inst.getOperand(2).getReg();
4046 if (RI->isSubRegisterEq(Rn, Rt))
4047 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4048 "is also a source");
4049 break;
4050 }
4051 case AArch64::STRBBpost:
4052 case AArch64::STRBpost:
4053 case AArch64::STRHHpost:
4054 case AArch64::STRHpost:
4055 case AArch64::STRWpost:
4056 case AArch64::STRXpost:
4057 case AArch64::STRBBpre:
4058 case AArch64::STRBpre:
4059 case AArch64::STRHHpre:
4060 case AArch64::STRHpre:
4061 case AArch64::STRWpre:
4062 case AArch64::STRXpre: {
4063 unsigned Rt = Inst.getOperand(1).getReg();
4064 unsigned Rn = Inst.getOperand(2).getReg();
4065 if (RI->isSubRegisterEq(Rn, Rt))
4066 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4067 "is also a source");
4068 break;
4069 }
4070 case AArch64::STXRB:
4071 case AArch64::STXRH:
4072 case AArch64::STXRW:
4073 case AArch64::STXRX:
4074 case AArch64::STLXRB:
4075 case AArch64::STLXRH:
4076 case AArch64::STLXRW:
4077 case AArch64::STLXRX: {
4078 unsigned Rs = Inst.getOperand(0).getReg();
4079 unsigned Rt = Inst.getOperand(1).getReg();
4080 unsigned Rn = Inst.getOperand(2).getReg();
4081 if (RI->isSubRegisterEq(Rt, Rs) ||
4082 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4083 return Error(Loc[0],
4084 "unpredictable STXR instruction, status is also a source");
4085 break;
4086 }
4087 case AArch64::STXPW:
4088 case AArch64::STXPX:
4089 case AArch64::STLXPW:
4090 case AArch64::STLXPX: {
4091 unsigned Rs = Inst.getOperand(0).getReg();
4092 unsigned Rt1 = Inst.getOperand(1).getReg();
4093 unsigned Rt2 = Inst.getOperand(2).getReg();
4094 unsigned Rn = Inst.getOperand(3).getReg();
4095 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4096 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4097 return Error(Loc[0],
4098 "unpredictable STXP instruction, status is also a source");
4099 break;
4100 }
4101 case AArch64::LDGV: {
4102 unsigned Rt = Inst.getOperand(0).getReg();
4103 unsigned Rn = Inst.getOperand(1).getReg();
4104 if (RI->isSubRegisterEq(Rt, Rn)) {
4105 return Error(Loc[0],
4106 "unpredictable LDGV instruction, writeback register is also "
4107 "the target register");
4108 }
4109 }
4110 }
4111
4112
4113 // Now check immediate ranges. Separate from the above as there is overlap
4114 // in the instructions being checked and this keeps the nested conditionals
4115 // to a minimum.
4116 switch (Inst.getOpcode()) {
4117 case AArch64::ADDSWri:
4118 case AArch64::ADDSXri:
4119 case AArch64::ADDWri:
4120 case AArch64::ADDXri:
4121 case AArch64::SUBSWri:
4122 case AArch64::SUBSXri:
4123 case AArch64::SUBWri:
4124 case AArch64::SUBXri: {
4125 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4126 // some slight duplication here.
4127 if (Inst.getOperand(2).isExpr()) {
4128 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4129 AArch64MCExpr::VariantKind ELFRefKind;
4130 MCSymbolRefExpr::VariantKind DarwinRefKind;
4131 int64_t Addend;
4132 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4133
4134 // Only allow these with ADDXri.
4135 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4136 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4137 Inst.getOpcode() == AArch64::ADDXri)
4138 return false;
4139
4140 // Only allow these with ADDXri/ADDWri
4141 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4142 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4143 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4144 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4145 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4146 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4147 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
4148 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4149 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4150 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
4151 (Inst.getOpcode() == AArch64::ADDXri ||
4152 Inst.getOpcode() == AArch64::ADDWri))
4153 return false;
4154
4155 // Don't allow symbol refs in the immediate field otherwise
4156 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4157 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4158 // 'cmp w0, 'borked')
4159 return Error(Loc.back(), "invalid immediate expression");
4160 }
4161 // We don't validate more complex expressions here
4162 }
4163 return false;
4164 }
4165 default:
4166 return false;
4167 }
4168 }
4169
4170 static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4171 unsigned VariantID = 0);
4172
showMatchError(SMLoc Loc,unsigned ErrCode,uint64_t ErrorInfo,OperandVector & Operands)4173 bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
4174 uint64_t ErrorInfo,
4175 OperandVector &Operands) {
4176 switch (ErrCode) {
4177 case Match_InvalidTiedOperand: {
4178 RegConstraintEqualityTy EqTy =
4179 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4180 .getRegEqualityTy();
4181 switch (EqTy) {
4182 case RegConstraintEqualityTy::EqualsSubReg:
4183 return Error(Loc, "operand must be 64-bit form of destination register");
4184 case RegConstraintEqualityTy::EqualsSuperReg:
4185 return Error(Loc, "operand must be 32-bit form of destination register");
4186 case RegConstraintEqualityTy::EqualsReg:
4187 return Error(Loc, "operand must match destination register");
4188 }
4189 llvm_unreachable("Unknown RegConstraintEqualityTy");
4190 }
4191 case Match_MissingFeature:
4192 return Error(Loc,
4193 "instruction requires a CPU feature not currently enabled");
4194 case Match_InvalidOperand:
4195 return Error(Loc, "invalid operand for instruction");
4196 case Match_InvalidSuffix:
4197 return Error(Loc, "invalid type suffix for instruction");
4198 case Match_InvalidCondCode:
4199 return Error(Loc, "expected AArch64 condition code");
4200 case Match_AddSubRegExtendSmall:
4201 return Error(Loc,
4202 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4203 case Match_AddSubRegExtendLarge:
4204 return Error(Loc,
4205 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4206 case Match_AddSubSecondSource:
4207 return Error(Loc,
4208 "expected compatible register, symbol or integer in range [0, 4095]");
4209 case Match_LogicalSecondSource:
4210 return Error(Loc, "expected compatible register or logical immediate");
4211 case Match_InvalidMovImm32Shift:
4212 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4213 case Match_InvalidMovImm64Shift:
4214 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4215 case Match_AddSubRegShift32:
4216 return Error(Loc,
4217 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4218 case Match_AddSubRegShift64:
4219 return Error(Loc,
4220 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4221 case Match_InvalidFPImm:
4222 return Error(Loc,
4223 "expected compatible register or floating-point constant");
4224 case Match_InvalidMemoryIndexedSImm6:
4225 return Error(Loc, "index must be an integer in range [-32, 31].");
4226 case Match_InvalidMemoryIndexedSImm5:
4227 return Error(Loc, "index must be an integer in range [-16, 15].");
4228 case Match_InvalidMemoryIndexed1SImm4:
4229 return Error(Loc, "index must be an integer in range [-8, 7].");
4230 case Match_InvalidMemoryIndexed2SImm4:
4231 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
4232 case Match_InvalidMemoryIndexed3SImm4:
4233 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
4234 case Match_InvalidMemoryIndexed4SImm4:
4235 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
4236 case Match_InvalidMemoryIndexed16SImm4:
4237 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
4238 case Match_InvalidMemoryIndexed1SImm6:
4239 return Error(Loc, "index must be an integer in range [-32, 31].");
4240 case Match_InvalidMemoryIndexedSImm8:
4241 return Error(Loc, "index must be an integer in range [-128, 127].");
4242 case Match_InvalidMemoryIndexedSImm9:
4243 return Error(Loc, "index must be an integer in range [-256, 255].");
4244 case Match_InvalidMemoryIndexed16SImm9:
4245 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
4246 case Match_InvalidMemoryIndexed8SImm10:
4247 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
4248 case Match_InvalidMemoryIndexed4SImm7:
4249 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4250 case Match_InvalidMemoryIndexed8SImm7:
4251 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4252 case Match_InvalidMemoryIndexed16SImm7:
4253 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
4254 case Match_InvalidMemoryIndexed8UImm5:
4255 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4256 case Match_InvalidMemoryIndexed4UImm5:
4257 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4258 case Match_InvalidMemoryIndexed2UImm5:
4259 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
4260 case Match_InvalidMemoryIndexed8UImm6:
4261 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
4262 case Match_InvalidMemoryIndexed16UImm6:
4263 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
4264 case Match_InvalidMemoryIndexed4UImm6:
4265 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4266 case Match_InvalidMemoryIndexed2UImm6:
4267 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4268 case Match_InvalidMemoryIndexed1UImm6:
4269 return Error(Loc, "index must be in range [0, 63].");
4270 case Match_InvalidMemoryWExtend8:
4271 return Error(Loc,
4272 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4273 case Match_InvalidMemoryWExtend16:
4274 return Error(Loc,
4275 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4276 case Match_InvalidMemoryWExtend32:
4277 return Error(Loc,
4278 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4279 case Match_InvalidMemoryWExtend64:
4280 return Error(Loc,
4281 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4282 case Match_InvalidMemoryWExtend128:
4283 return Error(Loc,
4284 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4285 case Match_InvalidMemoryXExtend8:
4286 return Error(Loc,
4287 "expected 'lsl' or 'sxtx' with optional shift of #0");
4288 case Match_InvalidMemoryXExtend16:
4289 return Error(Loc,
4290 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4291 case Match_InvalidMemoryXExtend32:
4292 return Error(Loc,
4293 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4294 case Match_InvalidMemoryXExtend64:
4295 return Error(Loc,
4296 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4297 case Match_InvalidMemoryXExtend128:
4298 return Error(Loc,
4299 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4300 case Match_InvalidMemoryIndexed1:
4301 return Error(Loc, "index must be an integer in range [0, 4095].");
4302 case Match_InvalidMemoryIndexed2:
4303 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4304 case Match_InvalidMemoryIndexed4:
4305 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4306 case Match_InvalidMemoryIndexed8:
4307 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4308 case Match_InvalidMemoryIndexed16:
4309 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
4310 case Match_InvalidImm0_1:
4311 return Error(Loc, "immediate must be an integer in range [0, 1].");
4312 case Match_InvalidImm0_7:
4313 return Error(Loc, "immediate must be an integer in range [0, 7].");
4314 case Match_InvalidImm0_15:
4315 return Error(Loc, "immediate must be an integer in range [0, 15].");
4316 case Match_InvalidImm0_31:
4317 return Error(Loc, "immediate must be an integer in range [0, 31].");
4318 case Match_InvalidImm0_63:
4319 return Error(Loc, "immediate must be an integer in range [0, 63].");
4320 case Match_InvalidImm0_127:
4321 return Error(Loc, "immediate must be an integer in range [0, 127].");
4322 case Match_InvalidImm0_255:
4323 return Error(Loc, "immediate must be an integer in range [0, 255].");
4324 case Match_InvalidImm0_65535:
4325 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4326 case Match_InvalidImm1_8:
4327 return Error(Loc, "immediate must be an integer in range [1, 8].");
4328 case Match_InvalidImm1_16:
4329 return Error(Loc, "immediate must be an integer in range [1, 16].");
4330 case Match_InvalidImm1_32:
4331 return Error(Loc, "immediate must be an integer in range [1, 32].");
4332 case Match_InvalidImm1_64:
4333 return Error(Loc, "immediate must be an integer in range [1, 64].");
4334 case Match_InvalidSVEAddSubImm8:
4335 return Error(Loc, "immediate must be an integer in range [0, 255]"
4336 " with a shift amount of 0");
4337 case Match_InvalidSVEAddSubImm16:
4338 case Match_InvalidSVEAddSubImm32:
4339 case Match_InvalidSVEAddSubImm64:
4340 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4341 "multiple of 256 in range [256, 65280]");
4342 case Match_InvalidSVECpyImm8:
4343 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4344 " with a shift amount of 0");
4345 case Match_InvalidSVECpyImm16:
4346 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4347 "multiple of 256 in range [-32768, 65280]");
4348 case Match_InvalidSVECpyImm32:
4349 case Match_InvalidSVECpyImm64:
4350 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4351 "multiple of 256 in range [-32768, 32512]");
4352 case Match_InvalidIndexRange1_1:
4353 return Error(Loc, "expected lane specifier '[1]'");
4354 case Match_InvalidIndexRange0_15:
4355 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4356 case Match_InvalidIndexRange0_7:
4357 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4358 case Match_InvalidIndexRange0_3:
4359 return Error(Loc, "vector lane must be an integer in range [0, 3].");
4360 case Match_InvalidIndexRange0_1:
4361 return Error(Loc, "vector lane must be an integer in range [0, 1].");
4362 case Match_InvalidSVEIndexRange0_63:
4363 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4364 case Match_InvalidSVEIndexRange0_31:
4365 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4366 case Match_InvalidSVEIndexRange0_15:
4367 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4368 case Match_InvalidSVEIndexRange0_7:
4369 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4370 case Match_InvalidSVEIndexRange0_3:
4371 return Error(Loc, "vector lane must be an integer in range [0, 3].");
4372 case Match_InvalidLabel:
4373 return Error(Loc, "expected label or encodable integer pc offset");
4374 case Match_MRS:
4375 return Error(Loc, "expected readable system register");
4376 case Match_MSR:
4377 return Error(Loc, "expected writable system register or pstate");
4378 case Match_InvalidComplexRotationEven:
4379 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4380 case Match_InvalidComplexRotationOdd:
4381 return Error(Loc, "complex rotation must be 90 or 270.");
4382 case Match_MnemonicFail: {
4383 std::string Suggestion = AArch64MnemonicSpellCheck(
4384 ((AArch64Operand &)*Operands[0]).getToken(),
4385 ComputeAvailableFeatures(STI->getFeatureBits()));
4386 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4387 }
4388 case Match_InvalidGPR64shifted8:
4389 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4390 case Match_InvalidGPR64shifted16:
4391 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4392 case Match_InvalidGPR64shifted32:
4393 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4394 case Match_InvalidGPR64shifted64:
4395 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4396 case Match_InvalidGPR64NoXZRshifted8:
4397 return Error(Loc, "register must be x0..x30 without shift");
4398 case Match_InvalidGPR64NoXZRshifted16:
4399 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4400 case Match_InvalidGPR64NoXZRshifted32:
4401 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4402 case Match_InvalidGPR64NoXZRshifted64:
4403 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
4404 case Match_InvalidZPR32UXTW8:
4405 case Match_InvalidZPR32SXTW8:
4406 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4407 case Match_InvalidZPR32UXTW16:
4408 case Match_InvalidZPR32SXTW16:
4409 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4410 case Match_InvalidZPR32UXTW32:
4411 case Match_InvalidZPR32SXTW32:
4412 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4413 case Match_InvalidZPR32UXTW64:
4414 case Match_InvalidZPR32SXTW64:
4415 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4416 case Match_InvalidZPR64UXTW8:
4417 case Match_InvalidZPR64SXTW8:
4418 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4419 case Match_InvalidZPR64UXTW16:
4420 case Match_InvalidZPR64SXTW16:
4421 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4422 case Match_InvalidZPR64UXTW32:
4423 case Match_InvalidZPR64SXTW32:
4424 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4425 case Match_InvalidZPR64UXTW64:
4426 case Match_InvalidZPR64SXTW64:
4427 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
4428 case Match_InvalidZPR32LSL8:
4429 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4430 case Match_InvalidZPR32LSL16:
4431 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4432 case Match_InvalidZPR32LSL32:
4433 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4434 case Match_InvalidZPR32LSL64:
4435 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
4436 case Match_InvalidZPR64LSL8:
4437 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4438 case Match_InvalidZPR64LSL16:
4439 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4440 case Match_InvalidZPR64LSL32:
4441 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4442 case Match_InvalidZPR64LSL64:
4443 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
4444 case Match_InvalidZPR0:
4445 return Error(Loc, "expected register without element width sufix");
4446 case Match_InvalidZPR8:
4447 case Match_InvalidZPR16:
4448 case Match_InvalidZPR32:
4449 case Match_InvalidZPR64:
4450 case Match_InvalidZPR128:
4451 return Error(Loc, "invalid element width");
4452 case Match_InvalidZPR_3b8:
4453 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4454 case Match_InvalidZPR_3b16:
4455 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4456 case Match_InvalidZPR_3b32:
4457 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4458 case Match_InvalidZPR_4b16:
4459 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4460 case Match_InvalidZPR_4b32:
4461 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4462 case Match_InvalidZPR_4b64:
4463 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
4464 case Match_InvalidSVEPattern:
4465 return Error(Loc, "invalid predicate pattern");
4466 case Match_InvalidSVEPredicateAnyReg:
4467 case Match_InvalidSVEPredicateBReg:
4468 case Match_InvalidSVEPredicateHReg:
4469 case Match_InvalidSVEPredicateSReg:
4470 case Match_InvalidSVEPredicateDReg:
4471 return Error(Loc, "invalid predicate register.");
4472 case Match_InvalidSVEPredicate3bAnyReg:
4473 case Match_InvalidSVEPredicate3bBReg:
4474 case Match_InvalidSVEPredicate3bHReg:
4475 case Match_InvalidSVEPredicate3bSReg:
4476 case Match_InvalidSVEPredicate3bDReg:
4477 return Error(Loc, "restricted predicate has range [0, 7].");
4478 case Match_InvalidSVEExactFPImmOperandHalfOne:
4479 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4480 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4481 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4482 case Match_InvalidSVEExactFPImmOperandZeroOne:
4483 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
4484 default:
4485 llvm_unreachable("unexpected error code!");
4486 }
4487 }
4488
4489 static const char *getSubtargetFeatureName(uint64_t Val);
4490
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)4491 bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4492 OperandVector &Operands,
4493 MCStreamer &Out,
4494 uint64_t &ErrorInfo,
4495 bool MatchingInlineAsm) {
4496 assert(!Operands.empty() && "Unexpect empty operand list!");
4497 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4498 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
4499
4500 StringRef Tok = Op.getToken();
4501 unsigned NumOperands = Operands.size();
4502
4503 if (NumOperands == 4 && Tok == "lsl") {
4504 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4505 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4506 if (Op2.isScalarReg() && Op3.isImm()) {
4507 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4508 if (Op3CE) {
4509 uint64_t Op3Val = Op3CE->getValue();
4510 uint64_t NewOp3Val = 0;
4511 uint64_t NewOp4Val = 0;
4512 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
4513 Op2.getReg())) {
4514 NewOp3Val = (32 - Op3Val) & 0x1f;
4515 NewOp4Val = 31 - Op3Val;
4516 } else {
4517 NewOp3Val = (64 - Op3Val) & 0x3f;
4518 NewOp4Val = 63 - Op3Val;
4519 }
4520
4521 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4522 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
4523
4524 Operands[0] = AArch64Operand::CreateToken(
4525 "ubfm", false, Op.getStartLoc(), getContext());
4526 Operands.push_back(AArch64Operand::CreateImm(
4527 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4528 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4529 Op3.getEndLoc(), getContext());
4530 }
4531 }
4532 } else if (NumOperands == 4 && Tok == "bfc") {
4533 // FIXME: Horrible hack to handle BFC->BFM alias.
4534 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4535 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4536 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4537
4538 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
4539 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4540 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4541
4542 if (LSBCE && WidthCE) {
4543 uint64_t LSB = LSBCE->getValue();
4544 uint64_t Width = WidthCE->getValue();
4545
4546 uint64_t RegWidth = 0;
4547 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4548 Op1.getReg()))
4549 RegWidth = 64;
4550 else
4551 RegWidth = 32;
4552
4553 if (LSB >= RegWidth)
4554 return Error(LSBOp.getStartLoc(),
4555 "expected integer in range [0, 31]");
4556 if (Width < 1 || Width > RegWidth)
4557 return Error(WidthOp.getStartLoc(),
4558 "expected integer in range [1, 32]");
4559
4560 uint64_t ImmR = 0;
4561 if (RegWidth == 32)
4562 ImmR = (32 - LSB) & 0x1f;
4563 else
4564 ImmR = (64 - LSB) & 0x3f;
4565
4566 uint64_t ImmS = Width - 1;
4567
4568 if (ImmR != 0 && ImmS >= ImmR)
4569 return Error(WidthOp.getStartLoc(),
4570 "requested insert overflows register");
4571
4572 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4573 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
4574 Operands[0] = AArch64Operand::CreateToken(
4575 "bfm", false, Op.getStartLoc(), getContext());
4576 Operands[2] = AArch64Operand::CreateReg(
4577 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4578 SMLoc(), SMLoc(), getContext());
4579 Operands[3] = AArch64Operand::CreateImm(
4580 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4581 Operands.emplace_back(
4582 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4583 WidthOp.getEndLoc(), getContext()));
4584 }
4585 }
4586 } else if (NumOperands == 5) {
4587 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4588 // UBFIZ -> UBFM aliases.
4589 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
4590 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4591 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4592 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
4593
4594 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
4595 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4596 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
4597
4598 if (Op3CE && Op4CE) {
4599 uint64_t Op3Val = Op3CE->getValue();
4600 uint64_t Op4Val = Op4CE->getValue();
4601
4602 uint64_t RegWidth = 0;
4603 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4604 Op1.getReg()))
4605 RegWidth = 64;
4606 else
4607 RegWidth = 32;
4608
4609 if (Op3Val >= RegWidth)
4610 return Error(Op3.getStartLoc(),
4611 "expected integer in range [0, 31]");
4612 if (Op4Val < 1 || Op4Val > RegWidth)
4613 return Error(Op4.getStartLoc(),
4614 "expected integer in range [1, 32]");
4615
4616 uint64_t NewOp3Val = 0;
4617 if (RegWidth == 32)
4618 NewOp3Val = (32 - Op3Val) & 0x1f;
4619 else
4620 NewOp3Val = (64 - Op3Val) & 0x3f;
4621
4622 uint64_t NewOp4Val = Op4Val - 1;
4623
4624 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
4625 return Error(Op4.getStartLoc(),
4626 "requested insert overflows register");
4627
4628 const MCExpr *NewOp3 =
4629 MCConstantExpr::create(NewOp3Val, getContext());
4630 const MCExpr *NewOp4 =
4631 MCConstantExpr::create(NewOp4Val, getContext());
4632 Operands[3] = AArch64Operand::CreateImm(
4633 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
4634 Operands[4] = AArch64Operand::CreateImm(
4635 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
4636 if (Tok == "bfi")
4637 Operands[0] = AArch64Operand::CreateToken(
4638 "bfm", false, Op.getStartLoc(), getContext());
4639 else if (Tok == "sbfiz")
4640 Operands[0] = AArch64Operand::CreateToken(
4641 "sbfm", false, Op.getStartLoc(), getContext());
4642 else if (Tok == "ubfiz")
4643 Operands[0] = AArch64Operand::CreateToken(
4644 "ubfm", false, Op.getStartLoc(), getContext());
4645 else
4646 llvm_unreachable("No valid mnemonic for alias?");
4647 }
4648 }
4649
4650 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4651 // UBFX -> UBFM aliases.
4652 } else if (NumOperands == 5 &&
4653 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
4654 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4655 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4656 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
4657
4658 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
4659 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4660 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
4661
4662 if (Op3CE && Op4CE) {
4663 uint64_t Op3Val = Op3CE->getValue();
4664 uint64_t Op4Val = Op4CE->getValue();
4665
4666 uint64_t RegWidth = 0;
4667 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4668 Op1.getReg()))
4669 RegWidth = 64;
4670 else
4671 RegWidth = 32;
4672
4673 if (Op3Val >= RegWidth)
4674 return Error(Op3.getStartLoc(),
4675 "expected integer in range [0, 31]");
4676 if (Op4Val < 1 || Op4Val > RegWidth)
4677 return Error(Op4.getStartLoc(),
4678 "expected integer in range [1, 32]");
4679
4680 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4681
4682 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
4683 return Error(Op4.getStartLoc(),
4684 "requested extract overflows register");
4685
4686 const MCExpr *NewOp4 =
4687 MCConstantExpr::create(NewOp4Val, getContext());
4688 Operands[4] = AArch64Operand::CreateImm(
4689 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
4690 if (Tok == "bfxil")
4691 Operands[0] = AArch64Operand::CreateToken(
4692 "bfm", false, Op.getStartLoc(), getContext());
4693 else if (Tok == "sbfx")
4694 Operands[0] = AArch64Operand::CreateToken(
4695 "sbfm", false, Op.getStartLoc(), getContext());
4696 else if (Tok == "ubfx")
4697 Operands[0] = AArch64Operand::CreateToken(
4698 "ubfm", false, Op.getStartLoc(), getContext());
4699 else
4700 llvm_unreachable("No valid mnemonic for alias?");
4701 }
4702 }
4703 }
4704 }
4705
4706 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4707 // instruction for FP registers correctly in some rare circumstances. Convert
4708 // it to a safe instruction and warn (because silently changing someone's
4709 // assembly is rude).
4710 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4711 NumOperands == 4 && Tok == "movi") {
4712 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4713 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4714 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4715 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4716 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4717 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4718 if (Suffix.lower() == ".2d" &&
4719 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4720 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4721 " correctly on this CPU, converting to equivalent movi.16b");
4722 // Switch the suffix to .16b.
4723 unsigned Idx = Op1.isToken() ? 1 : 2;
4724 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4725 getContext());
4726 }
4727 }
4728 }
4729
4730 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4731 // InstAlias can't quite handle this since the reg classes aren't
4732 // subclasses.
4733 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4734 // The source register can be Wn here, but the matcher expects a
4735 // GPR64. Twiddle it here if necessary.
4736 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
4737 if (Op.isScalarReg()) {
4738 unsigned Reg = getXRegFromWReg(Op.getReg());
4739 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4740 Op.getStartLoc(), Op.getEndLoc(),
4741 getContext());
4742 }
4743 }
4744 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4745 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
4746 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4747 if (Op.isScalarReg() &&
4748 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4749 Op.getReg())) {
4750 // The source register can be Wn here, but the matcher expects a
4751 // GPR64. Twiddle it here if necessary.
4752 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
4753 if (Op.isScalarReg()) {
4754 unsigned Reg = getXRegFromWReg(Op.getReg());
4755 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4756 Op.getStartLoc(),
4757 Op.getEndLoc(), getContext());
4758 }
4759 }
4760 }
4761 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4762 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
4763 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4764 if (Op.isScalarReg() &&
4765 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4766 Op.getReg())) {
4767 // The source register can be Wn here, but the matcher expects a
4768 // GPR32. Twiddle it here if necessary.
4769 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
4770 if (Op.isScalarReg()) {
4771 unsigned Reg = getWRegFromXReg(Op.getReg());
4772 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4773 Op.getStartLoc(),
4774 Op.getEndLoc(), getContext());
4775 }
4776 }
4777 }
4778
4779 MCInst Inst;
4780 // First try to match against the secondary set of tables containing the
4781 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4782 unsigned MatchResult =
4783 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
4784
4785 // If that fails, try against the alternate table containing long-form NEON:
4786 // "fadd v0.2s, v1.2s, v2.2s"
4787 if (MatchResult != Match_Success) {
4788 // But first, save the short-form match result: we can use it in case the
4789 // long-form match also fails.
4790 auto ShortFormNEONErrorInfo = ErrorInfo;
4791 auto ShortFormNEONMatchResult = MatchResult;
4792
4793 MatchResult =
4794 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
4795
4796 // Now, both matches failed, and the long-form match failed on the mnemonic
4797 // suffix token operand. The short-form match failure is probably more
4798 // relevant: use it instead.
4799 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
4800 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
4801 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4802 MatchResult = ShortFormNEONMatchResult;
4803 ErrorInfo = ShortFormNEONErrorInfo;
4804 }
4805 }
4806
4807 switch (MatchResult) {
4808 case Match_Success: {
4809 // Perform range checking and other semantic validations
4810 SmallVector<SMLoc, 8> OperandLocs;
4811 NumOperands = Operands.size();
4812 for (unsigned i = 1; i < NumOperands; ++i)
4813 OperandLocs.push_back(Operands[i]->getStartLoc());
4814 if (validateInstruction(Inst, IDLoc, OperandLocs))
4815 return true;
4816
4817 Inst.setLoc(IDLoc);
4818 Out.EmitInstruction(Inst, getSTI());
4819 return false;
4820 }
4821 case Match_MissingFeature: {
4822 assert(ErrorInfo && "Unknown missing feature!");
4823 // Special case the error message for the very common case where only
4824 // a single subtarget feature is missing (neon, e.g.).
4825 std::string Msg = "instruction requires:";
4826 uint64_t Mask = 1;
4827 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4828 if (ErrorInfo & Mask) {
4829 Msg += " ";
4830 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
4831 }
4832 Mask <<= 1;
4833 }
4834 return Error(IDLoc, Msg);
4835 }
4836 case Match_MnemonicFail:
4837 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
4838 case Match_InvalidOperand: {
4839 SMLoc ErrorLoc = IDLoc;
4840
4841 if (ErrorInfo != ~0ULL) {
4842 if (ErrorInfo >= Operands.size())
4843 return Error(IDLoc, "too few operands for instruction",
4844 SMRange(IDLoc, getTok().getLoc()));
4845
4846 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
4847 if (ErrorLoc == SMLoc())
4848 ErrorLoc = IDLoc;
4849 }
4850 // If the match failed on a suffix token operand, tweak the diagnostic
4851 // accordingly.
4852 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4853 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
4854 MatchResult = Match_InvalidSuffix;
4855
4856 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
4857 }
4858 case Match_InvalidTiedOperand:
4859 case Match_InvalidMemoryIndexed1:
4860 case Match_InvalidMemoryIndexed2:
4861 case Match_InvalidMemoryIndexed4:
4862 case Match_InvalidMemoryIndexed8:
4863 case Match_InvalidMemoryIndexed16:
4864 case Match_InvalidCondCode:
4865 case Match_AddSubRegExtendSmall:
4866 case Match_AddSubRegExtendLarge:
4867 case Match_AddSubSecondSource:
4868 case Match_LogicalSecondSource:
4869 case Match_AddSubRegShift32:
4870 case Match_AddSubRegShift64:
4871 case Match_InvalidMovImm32Shift:
4872 case Match_InvalidMovImm64Shift:
4873 case Match_InvalidFPImm:
4874 case Match_InvalidMemoryWExtend8:
4875 case Match_InvalidMemoryWExtend16:
4876 case Match_InvalidMemoryWExtend32:
4877 case Match_InvalidMemoryWExtend64:
4878 case Match_InvalidMemoryWExtend128:
4879 case Match_InvalidMemoryXExtend8:
4880 case Match_InvalidMemoryXExtend16:
4881 case Match_InvalidMemoryXExtend32:
4882 case Match_InvalidMemoryXExtend64:
4883 case Match_InvalidMemoryXExtend128:
4884 case Match_InvalidMemoryIndexed1SImm4:
4885 case Match_InvalidMemoryIndexed2SImm4:
4886 case Match_InvalidMemoryIndexed3SImm4:
4887 case Match_InvalidMemoryIndexed4SImm4:
4888 case Match_InvalidMemoryIndexed1SImm6:
4889 case Match_InvalidMemoryIndexed16SImm4:
4890 case Match_InvalidMemoryIndexed4SImm7:
4891 case Match_InvalidMemoryIndexed8SImm7:
4892 case Match_InvalidMemoryIndexed16SImm7:
4893 case Match_InvalidMemoryIndexed8UImm5:
4894 case Match_InvalidMemoryIndexed4UImm5:
4895 case Match_InvalidMemoryIndexed2UImm5:
4896 case Match_InvalidMemoryIndexed1UImm6:
4897 case Match_InvalidMemoryIndexed2UImm6:
4898 case Match_InvalidMemoryIndexed4UImm6:
4899 case Match_InvalidMemoryIndexed8UImm6:
4900 case Match_InvalidMemoryIndexed16UImm6:
4901 case Match_InvalidMemoryIndexedSImm6:
4902 case Match_InvalidMemoryIndexedSImm5:
4903 case Match_InvalidMemoryIndexedSImm8:
4904 case Match_InvalidMemoryIndexedSImm9:
4905 case Match_InvalidMemoryIndexed16SImm9:
4906 case Match_InvalidMemoryIndexed8SImm10:
4907 case Match_InvalidImm0_1:
4908 case Match_InvalidImm0_7:
4909 case Match_InvalidImm0_15:
4910 case Match_InvalidImm0_31:
4911 case Match_InvalidImm0_63:
4912 case Match_InvalidImm0_127:
4913 case Match_InvalidImm0_255:
4914 case Match_InvalidImm0_65535:
4915 case Match_InvalidImm1_8:
4916 case Match_InvalidImm1_16:
4917 case Match_InvalidImm1_32:
4918 case Match_InvalidImm1_64:
4919 case Match_InvalidSVEAddSubImm8:
4920 case Match_InvalidSVEAddSubImm16:
4921 case Match_InvalidSVEAddSubImm32:
4922 case Match_InvalidSVEAddSubImm64:
4923 case Match_InvalidSVECpyImm8:
4924 case Match_InvalidSVECpyImm16:
4925 case Match_InvalidSVECpyImm32:
4926 case Match_InvalidSVECpyImm64:
4927 case Match_InvalidIndexRange1_1:
4928 case Match_InvalidIndexRange0_15:
4929 case Match_InvalidIndexRange0_7:
4930 case Match_InvalidIndexRange0_3:
4931 case Match_InvalidIndexRange0_1:
4932 case Match_InvalidSVEIndexRange0_63:
4933 case Match_InvalidSVEIndexRange0_31:
4934 case Match_InvalidSVEIndexRange0_15:
4935 case Match_InvalidSVEIndexRange0_7:
4936 case Match_InvalidSVEIndexRange0_3:
4937 case Match_InvalidLabel:
4938 case Match_InvalidComplexRotationEven:
4939 case Match_InvalidComplexRotationOdd:
4940 case Match_InvalidGPR64shifted8:
4941 case Match_InvalidGPR64shifted16:
4942 case Match_InvalidGPR64shifted32:
4943 case Match_InvalidGPR64shifted64:
4944 case Match_InvalidGPR64NoXZRshifted8:
4945 case Match_InvalidGPR64NoXZRshifted16:
4946 case Match_InvalidGPR64NoXZRshifted32:
4947 case Match_InvalidGPR64NoXZRshifted64:
4948 case Match_InvalidZPR32UXTW8:
4949 case Match_InvalidZPR32UXTW16:
4950 case Match_InvalidZPR32UXTW32:
4951 case Match_InvalidZPR32UXTW64:
4952 case Match_InvalidZPR32SXTW8:
4953 case Match_InvalidZPR32SXTW16:
4954 case Match_InvalidZPR32SXTW32:
4955 case Match_InvalidZPR32SXTW64:
4956 case Match_InvalidZPR64UXTW8:
4957 case Match_InvalidZPR64SXTW8:
4958 case Match_InvalidZPR64UXTW16:
4959 case Match_InvalidZPR64SXTW16:
4960 case Match_InvalidZPR64UXTW32:
4961 case Match_InvalidZPR64SXTW32:
4962 case Match_InvalidZPR64UXTW64:
4963 case Match_InvalidZPR64SXTW64:
4964 case Match_InvalidZPR32LSL8:
4965 case Match_InvalidZPR32LSL16:
4966 case Match_InvalidZPR32LSL32:
4967 case Match_InvalidZPR32LSL64:
4968 case Match_InvalidZPR64LSL8:
4969 case Match_InvalidZPR64LSL16:
4970 case Match_InvalidZPR64LSL32:
4971 case Match_InvalidZPR64LSL64:
4972 case Match_InvalidZPR0:
4973 case Match_InvalidZPR8:
4974 case Match_InvalidZPR16:
4975 case Match_InvalidZPR32:
4976 case Match_InvalidZPR64:
4977 case Match_InvalidZPR128:
4978 case Match_InvalidZPR_3b8:
4979 case Match_InvalidZPR_3b16:
4980 case Match_InvalidZPR_3b32:
4981 case Match_InvalidZPR_4b16:
4982 case Match_InvalidZPR_4b32:
4983 case Match_InvalidZPR_4b64:
4984 case Match_InvalidSVEPredicateAnyReg:
4985 case Match_InvalidSVEPattern:
4986 case Match_InvalidSVEPredicateBReg:
4987 case Match_InvalidSVEPredicateHReg:
4988 case Match_InvalidSVEPredicateSReg:
4989 case Match_InvalidSVEPredicateDReg:
4990 case Match_InvalidSVEPredicate3bAnyReg:
4991 case Match_InvalidSVEPredicate3bBReg:
4992 case Match_InvalidSVEPredicate3bHReg:
4993 case Match_InvalidSVEPredicate3bSReg:
4994 case Match_InvalidSVEPredicate3bDReg:
4995 case Match_InvalidSVEExactFPImmOperandHalfOne:
4996 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4997 case Match_InvalidSVEExactFPImmOperandZeroOne:
4998 case Match_MSR:
4999 case Match_MRS: {
5000 if (ErrorInfo >= Operands.size())
5001 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
5002 // Any time we get here, there's nothing fancy to do. Just get the
5003 // operand SMLoc and display the diagnostic.
5004 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
5005 if (ErrorLoc == SMLoc())
5006 ErrorLoc = IDLoc;
5007 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
5008 }
5009 }
5010
5011 llvm_unreachable("Implement any new match types added!");
5012 }
5013
5014 /// ParseDirective parses the arm specific directives
ParseDirective(AsmToken DirectiveID)5015 bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
5016 const MCObjectFileInfo::Environment Format =
5017 getContext().getObjectFileInfo()->getObjectFileType();
5018 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
5019
5020 StringRef IDVal = DirectiveID.getIdentifier();
5021 SMLoc Loc = DirectiveID.getLoc();
5022 if (IDVal == ".arch")
5023 parseDirectiveArch(Loc);
5024 else if (IDVal == ".cpu")
5025 parseDirectiveCPU(Loc);
5026 else if (IDVal == ".tlsdesccall")
5027 parseDirectiveTLSDescCall(Loc);
5028 else if (IDVal == ".ltorg" || IDVal == ".pool")
5029 parseDirectiveLtorg(Loc);
5030 else if (IDVal == ".unreq")
5031 parseDirectiveUnreq(Loc);
5032 else if (IDVal == ".inst")
5033 parseDirectiveInst(Loc);
5034 else if (IDVal == ".cfi_negate_ra_state")
5035 parseDirectiveCFINegateRAState();
5036 else if (IDVal == ".cfi_b_key_frame")
5037 parseDirectiveCFIBKeyFrame();
5038 else if (IDVal == ".arch_extension")
5039 parseDirectiveArchExtension(Loc);
5040 else if (IsMachO) {
5041 if (IDVal == MCLOHDirectiveName())
5042 parseDirectiveLOH(IDVal, Loc);
5043 else
5044 return true;
5045 } else
5046 return true;
5047 return false;
5048 }
5049
ExpandCryptoAEK(AArch64::ArchKind ArchKind,SmallVector<StringRef,4> & RequestedExtensions)5050 static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5051 SmallVector<StringRef, 4> &RequestedExtensions) {
5052 const bool NoCrypto =
5053 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5054 "nocrypto") != std::end(RequestedExtensions));
5055 const bool Crypto =
5056 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5057 "crypto") != std::end(RequestedExtensions));
5058
5059 if (!NoCrypto && Crypto) {
5060 switch (ArchKind) {
5061 default:
5062 // Map 'generic' (and others) to sha2 and aes, because
5063 // that was the traditional meaning of crypto.
5064 case AArch64::ArchKind::ARMV8_1A:
5065 case AArch64::ArchKind::ARMV8_2A:
5066 case AArch64::ArchKind::ARMV8_3A:
5067 RequestedExtensions.push_back("sha2");
5068 RequestedExtensions.push_back("aes");
5069 break;
5070 case AArch64::ArchKind::ARMV8_4A:
5071 case AArch64::ArchKind::ARMV8_5A:
5072 RequestedExtensions.push_back("sm4");
5073 RequestedExtensions.push_back("sha3");
5074 RequestedExtensions.push_back("sha2");
5075 RequestedExtensions.push_back("aes");
5076 break;
5077 }
5078 } else if (NoCrypto) {
5079 switch (ArchKind) {
5080 default:
5081 // Map 'generic' (and others) to sha2 and aes, because
5082 // that was the traditional meaning of crypto.
5083 case AArch64::ArchKind::ARMV8_1A:
5084 case AArch64::ArchKind::ARMV8_2A:
5085 case AArch64::ArchKind::ARMV8_3A:
5086 RequestedExtensions.push_back("nosha2");
5087 RequestedExtensions.push_back("noaes");
5088 break;
5089 case AArch64::ArchKind::ARMV8_4A:
5090 case AArch64::ArchKind::ARMV8_5A:
5091 RequestedExtensions.push_back("nosm4");
5092 RequestedExtensions.push_back("nosha3");
5093 RequestedExtensions.push_back("nosha2");
5094 RequestedExtensions.push_back("noaes");
5095 break;
5096 }
5097 }
5098 }
5099
5100 /// parseDirectiveArch
5101 /// ::= .arch token
parseDirectiveArch(SMLoc L)5102 bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5103 SMLoc ArchLoc = getLoc();
5104
5105 StringRef Arch, ExtensionString;
5106 std::tie(Arch, ExtensionString) =
5107 getParser().parseStringToEndOfStatement().trim().split('+');
5108
5109 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5110 if (ID == AArch64::ArchKind::INVALID)
5111 return Error(ArchLoc, "unknown arch name");
5112
5113 if (parseToken(AsmToken::EndOfStatement))
5114 return true;
5115
5116 // Get the architecture and extension features.
5117 std::vector<StringRef> AArch64Features;
5118 AArch64::getArchFeatures(ID, AArch64Features);
5119 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5120 AArch64Features);
5121
5122 MCSubtargetInfo &STI = copySTI();
5123 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5124 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5125
5126 SmallVector<StringRef, 4> RequestedExtensions;
5127 if (!ExtensionString.empty())
5128 ExtensionString.split(RequestedExtensions, '+');
5129
5130 ExpandCryptoAEK(ID, RequestedExtensions);
5131
5132 FeatureBitset Features = STI.getFeatureBits();
5133 for (auto Name : RequestedExtensions) {
5134 bool EnableFeature = true;
5135
5136 if (Name.startswith_lower("no")) {
5137 EnableFeature = false;
5138 Name = Name.substr(2);
5139 }
5140
5141 for (const auto &Extension : ExtensionMap) {
5142 if (Extension.Name != Name)
5143 continue;
5144
5145 if (Extension.Features.none())
5146 report_fatal_error("unsupported architectural extension: " + Name);
5147
5148 FeatureBitset ToggleFeatures = EnableFeature
5149 ? (~Features & Extension.Features)
5150 : ( Features & Extension.Features);
5151 uint64_t Features =
5152 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5153 setAvailableFeatures(Features);
5154 break;
5155 }
5156 }
5157 return false;
5158 }
5159
5160 /// parseDirectiveArchExtension
5161 /// ::= .arch_extension [no]feature
parseDirectiveArchExtension(SMLoc L)5162 bool AArch64AsmParser::parseDirectiveArchExtension(SMLoc L) {
5163 MCAsmParser &Parser = getParser();
5164
5165 if (getLexer().isNot(AsmToken::Identifier))
5166 return Error(getLexer().getLoc(), "expected architecture extension name");
5167
5168 const AsmToken &Tok = Parser.getTok();
5169 StringRef Name = Tok.getString();
5170 SMLoc ExtLoc = Tok.getLoc();
5171 Lex();
5172
5173 if (parseToken(AsmToken::EndOfStatement,
5174 "unexpected token in '.arch_extension' directive"))
5175 return true;
5176
5177 bool EnableFeature = true;
5178 if (Name.startswith_lower("no")) {
5179 EnableFeature = false;
5180 Name = Name.substr(2);
5181 }
5182
5183 MCSubtargetInfo &STI = copySTI();
5184 FeatureBitset Features = STI.getFeatureBits();
5185 for (const auto &Extension : ExtensionMap) {
5186 if (Extension.Name != Name)
5187 continue;
5188
5189 if (Extension.Features.none())
5190 return Error(ExtLoc, "unsupported architectural extension: " + Name);
5191
5192 FeatureBitset ToggleFeatures = EnableFeature
5193 ? (~Features & Extension.Features)
5194 : (Features & Extension.Features);
5195 uint64_t Features =
5196 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5197 setAvailableFeatures(Features);
5198 return false;
5199 }
5200
5201 return Error(ExtLoc, "unknown architectural extension: " + Name);
5202 }
5203
incrementLoc(SMLoc L,int Offset)5204 static SMLoc incrementLoc(SMLoc L, int Offset) {
5205 return SMLoc::getFromPointer(L.getPointer() + Offset);
5206 }
5207
5208 /// parseDirectiveCPU
5209 /// ::= .cpu id
parseDirectiveCPU(SMLoc L)5210 bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
5211 SMLoc CurLoc = getLoc();
5212
5213 StringRef CPU, ExtensionString;
5214 std::tie(CPU, ExtensionString) =
5215 getParser().parseStringToEndOfStatement().trim().split('+');
5216
5217 if (parseToken(AsmToken::EndOfStatement))
5218 return true;
5219
5220 SmallVector<StringRef, 4> RequestedExtensions;
5221 if (!ExtensionString.empty())
5222 ExtensionString.split(RequestedExtensions, '+');
5223
5224 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5225 // once that is tablegen'ed
5226 if (!getSTI().isCPUStringValid(CPU)) {
5227 Error(CurLoc, "unknown CPU name");
5228 return false;
5229 }
5230
5231 MCSubtargetInfo &STI = copySTI();
5232 STI.setDefaultFeatures(CPU, "");
5233 CurLoc = incrementLoc(CurLoc, CPU.size());
5234
5235 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5236
5237 FeatureBitset Features = STI.getFeatureBits();
5238 for (auto Name : RequestedExtensions) {
5239 // Advance source location past '+'.
5240 CurLoc = incrementLoc(CurLoc, 1);
5241
5242 bool EnableFeature = true;
5243
5244 if (Name.startswith_lower("no")) {
5245 EnableFeature = false;
5246 Name = Name.substr(2);
5247 }
5248
5249 bool FoundExtension = false;
5250 for (const auto &Extension : ExtensionMap) {
5251 if (Extension.Name != Name)
5252 continue;
5253
5254 if (Extension.Features.none())
5255 report_fatal_error("unsupported architectural extension: " + Name);
5256
5257 FeatureBitset ToggleFeatures = EnableFeature
5258 ? (~Features & Extension.Features)
5259 : ( Features & Extension.Features);
5260 uint64_t Features =
5261 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5262 setAvailableFeatures(Features);
5263 FoundExtension = true;
5264
5265 break;
5266 }
5267
5268 if (!FoundExtension)
5269 Error(CurLoc, "unsupported architectural extension");
5270
5271 CurLoc = incrementLoc(CurLoc, Name.size());
5272 }
5273 return false;
5274 }
5275
5276 /// parseDirectiveInst
5277 /// ::= .inst opcode [, ...]
parseDirectiveInst(SMLoc Loc)5278 bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
5279 if (getLexer().is(AsmToken::EndOfStatement))
5280 return Error(Loc, "expected expression following '.inst' directive");
5281
5282 auto parseOp = [&]() -> bool {
5283 SMLoc L = getLoc();
5284 const MCExpr *Expr;
5285 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5286 return true;
5287 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
5288 if (check(!Value, L, "expected constant expression"))
5289 return true;
5290 getTargetStreamer().emitInst(Value->getValue());
5291 return false;
5292 };
5293
5294 if (parseMany(parseOp))
5295 return addErrorSuffix(" in '.inst' directive");
5296 return false;
5297 }
5298
5299 // parseDirectiveTLSDescCall:
5300 // ::= .tlsdesccall symbol
parseDirectiveTLSDescCall(SMLoc L)5301 bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5302 StringRef Name;
5303 if (check(getParser().parseIdentifier(Name), L,
5304 "expected symbol after directive") ||
5305 parseToken(AsmToken::EndOfStatement))
5306 return true;
5307
5308 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
5309 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5310 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
5311
5312 MCInst Inst;
5313 Inst.setOpcode(AArch64::TLSDESCCALL);
5314 Inst.addOperand(MCOperand::createExpr(Expr));
5315
5316 getParser().getStreamer().EmitInstruction(Inst, getSTI());
5317 return false;
5318 }
5319
5320 /// ::= .loh <lohName | lohId> label1, ..., labelN
5321 /// The number of arguments depends on the loh identifier.
parseDirectiveLOH(StringRef IDVal,SMLoc Loc)5322 bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
5323 MCLOHType Kind;
5324 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5325 if (getParser().getTok().isNot(AsmToken::Integer))
5326 return TokError("expected an identifier or a number in directive");
5327 // We successfully get a numeric value for the identifier.
5328 // Check if it is valid.
5329 int64_t Id = getParser().getTok().getIntVal();
5330 if (Id <= -1U && !isValidMCLOHType(Id))
5331 return TokError("invalid numeric identifier in directive");
5332 Kind = (MCLOHType)Id;
5333 } else {
5334 StringRef Name = getTok().getIdentifier();
5335 // We successfully parse an identifier.
5336 // Check if it is a recognized one.
5337 int Id = MCLOHNameToId(Name);
5338
5339 if (Id == -1)
5340 return TokError("invalid identifier in directive");
5341 Kind = (MCLOHType)Id;
5342 }
5343 // Consume the identifier.
5344 Lex();
5345 // Get the number of arguments of this LOH.
5346 int NbArgs = MCLOHIdToNbArgs(Kind);
5347
5348 assert(NbArgs != -1 && "Invalid number of arguments");
5349
5350 SmallVector<MCSymbol *, 3> Args;
5351 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5352 StringRef Name;
5353 if (getParser().parseIdentifier(Name))
5354 return TokError("expected identifier in directive");
5355 Args.push_back(getContext().getOrCreateSymbol(Name));
5356
5357 if (Idx + 1 == NbArgs)
5358 break;
5359 if (parseToken(AsmToken::Comma,
5360 "unexpected token in '" + Twine(IDVal) + "' directive"))
5361 return true;
5362 }
5363 if (parseToken(AsmToken::EndOfStatement,
5364 "unexpected token in '" + Twine(IDVal) + "' directive"))
5365 return true;
5366
5367 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5368 return false;
5369 }
5370
5371 /// parseDirectiveLtorg
5372 /// ::= .ltorg | .pool
parseDirectiveLtorg(SMLoc L)5373 bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
5374 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5375 return true;
5376 getTargetStreamer().emitCurrentConstantPool();
5377 return false;
5378 }
5379
5380 /// parseDirectiveReq
5381 /// ::= name .req registername
parseDirectiveReq(StringRef Name,SMLoc L)5382 bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
5383 MCAsmParser &Parser = getParser();
5384 Parser.Lex(); // Eat the '.req' token.
5385 SMLoc SRegLoc = getLoc();
5386 RegKind RegisterKind = RegKind::Scalar;
5387 unsigned RegNum;
5388 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
5389
5390 if (ParseRes != MatchOperand_Success) {
5391 StringRef Kind;
5392 RegisterKind = RegKind::NeonVector;
5393 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
5394
5395 if (ParseRes == MatchOperand_ParseFail)
5396 return true;
5397
5398 if (ParseRes == MatchOperand_Success && !Kind.empty())
5399 return Error(SRegLoc, "vector register without type specifier expected");
5400 }
5401
5402 if (ParseRes != MatchOperand_Success) {
5403 StringRef Kind;
5404 RegisterKind = RegKind::SVEDataVector;
5405 ParseRes =
5406 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
5407
5408 if (ParseRes == MatchOperand_ParseFail)
5409 return true;
5410
5411 if (ParseRes == MatchOperand_Success && !Kind.empty())
5412 return Error(SRegLoc,
5413 "sve vector register without type specifier expected");
5414 }
5415
5416 if (ParseRes != MatchOperand_Success) {
5417 StringRef Kind;
5418 RegisterKind = RegKind::SVEPredicateVector;
5419 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
5420
5421 if (ParseRes == MatchOperand_ParseFail)
5422 return true;
5423
5424 if (ParseRes == MatchOperand_Success && !Kind.empty())
5425 return Error(SRegLoc,
5426 "sve predicate register without type specifier expected");
5427 }
5428
5429 if (ParseRes != MatchOperand_Success)
5430 return Error(SRegLoc, "register name or alias expected");
5431
5432 // Shouldn't be anything else.
5433 if (parseToken(AsmToken::EndOfStatement,
5434 "unexpected input in .req directive"))
5435 return true;
5436
5437 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
5438 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
5439 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5440
5441 return false;
5442 }
5443
5444 /// parseDirectiveUneq
5445 /// ::= .unreq registername
parseDirectiveUnreq(SMLoc L)5446 bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
5447 MCAsmParser &Parser = getParser();
5448 if (getTok().isNot(AsmToken::Identifier))
5449 return TokError("unexpected input in .unreq directive.");
5450 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5451 Parser.Lex(); // Eat the identifier.
5452 if (parseToken(AsmToken::EndOfStatement))
5453 return addErrorSuffix("in '.unreq' directive");
5454 return false;
5455 }
5456
parseDirectiveCFINegateRAState()5457 bool AArch64AsmParser::parseDirectiveCFINegateRAState() {
5458 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5459 return true;
5460 getStreamer().EmitCFINegateRAState();
5461 return false;
5462 }
5463
5464 /// parseDirectiveCFIBKeyFrame
5465 /// ::= .cfi_b_key
parseDirectiveCFIBKeyFrame()5466 bool AArch64AsmParser::parseDirectiveCFIBKeyFrame() {
5467 if (parseToken(AsmToken::EndOfStatement,
5468 "unexpected token in '.cfi_b_key_frame'"))
5469 return true;
5470 getStreamer().EmitCFIBKeyFrame();
5471 return false;
5472 }
5473
5474 bool
classifySymbolRef(const MCExpr * Expr,AArch64MCExpr::VariantKind & ELFRefKind,MCSymbolRefExpr::VariantKind & DarwinRefKind,int64_t & Addend)5475 AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5476 AArch64MCExpr::VariantKind &ELFRefKind,
5477 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5478 int64_t &Addend) {
5479 ELFRefKind = AArch64MCExpr::VK_INVALID;
5480 DarwinRefKind = MCSymbolRefExpr::VK_None;
5481 Addend = 0;
5482
5483 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5484 ELFRefKind = AE->getKind();
5485 Expr = AE->getSubExpr();
5486 }
5487
5488 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5489 if (SE) {
5490 // It's a simple symbol reference with no addend.
5491 DarwinRefKind = SE->getKind();
5492 return true;
5493 }
5494
5495 // Check that it looks like a symbol + an addend
5496 MCValue Res;
5497 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
5498 if (!Relocatable || Res.getSymB())
5499 return false;
5500
5501 // Treat expressions with an ELFRefKind (like ":abs_g1:3", or
5502 // ":abs_g1:x" where x is constant) as symbolic even if there is no symbol.
5503 if (!Res.getSymA() && ELFRefKind == AArch64MCExpr::VK_INVALID)
5504 return false;
5505
5506 if (Res.getSymA())
5507 DarwinRefKind = Res.getSymA()->getKind();
5508 Addend = Res.getConstant();
5509
5510 // It's some symbol reference + a constant addend, but really
5511 // shouldn't use both Darwin and ELF syntax.
5512 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5513 DarwinRefKind == MCSymbolRefExpr::VK_None;
5514 }
5515
5516 /// Force static initialization.
LLVMInitializeAArch64AsmParser()5517 extern "C" void LLVMInitializeAArch64AsmParser() {
5518 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5519 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5520 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
5521 }
5522
5523 #define GET_REGISTER_MATCHER
5524 #define GET_SUBTARGET_FEATURE_NAME
5525 #define GET_MATCHER_IMPLEMENTATION
5526 #define GET_MNEMONIC_SPELL_CHECKER
5527 #include "AArch64GenAsmMatcher.inc"
5528
5529 // Define this matcher function after the auto-generated include so we
5530 // have the match class enum definitions.
validateTargetOperandClass(MCParsedAsmOperand & AsmOp,unsigned Kind)5531 unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
5532 unsigned Kind) {
5533 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
5534 // If the kind is a token for a literal immediate, check if our asm
5535 // operand matches. This is for InstAliases which have a fixed-value
5536 // immediate in the syntax.
5537 int64_t ExpectedVal;
5538 switch (Kind) {
5539 default:
5540 return Match_InvalidOperand;
5541 case MCK__35_0:
5542 ExpectedVal = 0;
5543 break;
5544 case MCK__35_1:
5545 ExpectedVal = 1;
5546 break;
5547 case MCK__35_12:
5548 ExpectedVal = 12;
5549 break;
5550 case MCK__35_16:
5551 ExpectedVal = 16;
5552 break;
5553 case MCK__35_2:
5554 ExpectedVal = 2;
5555 break;
5556 case MCK__35_24:
5557 ExpectedVal = 24;
5558 break;
5559 case MCK__35_3:
5560 ExpectedVal = 3;
5561 break;
5562 case MCK__35_32:
5563 ExpectedVal = 32;
5564 break;
5565 case MCK__35_4:
5566 ExpectedVal = 4;
5567 break;
5568 case MCK__35_48:
5569 ExpectedVal = 48;
5570 break;
5571 case MCK__35_6:
5572 ExpectedVal = 6;
5573 break;
5574 case MCK__35_64:
5575 ExpectedVal = 64;
5576 break;
5577 case MCK__35_8:
5578 ExpectedVal = 8;
5579 break;
5580 }
5581 if (!Op.isImm())
5582 return Match_InvalidOperand;
5583 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
5584 if (!CE)
5585 return Match_InvalidOperand;
5586 if (CE->getValue() == ExpectedVal)
5587 return Match_Success;
5588 return Match_InvalidOperand;
5589 }
5590
5591 OperandMatchResultTy
tryParseGPRSeqPair(OperandVector & Operands)5592 AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5593
5594 SMLoc S = getLoc();
5595
5596 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5597 Error(S, "expected register");
5598 return MatchOperand_ParseFail;
5599 }
5600
5601 unsigned FirstReg;
5602 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5603 if (Res != MatchOperand_Success)
5604 return MatchOperand_ParseFail;
5605
5606 const MCRegisterClass &WRegClass =
5607 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5608 const MCRegisterClass &XRegClass =
5609 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5610
5611 bool isXReg = XRegClass.contains(FirstReg),
5612 isWReg = WRegClass.contains(FirstReg);
5613 if (!isXReg && !isWReg) {
5614 Error(S, "expected first even register of a "
5615 "consecutive same-size even/odd register pair");
5616 return MatchOperand_ParseFail;
5617 }
5618
5619 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5620 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5621
5622 if (FirstEncoding & 0x1) {
5623 Error(S, "expected first even register of a "
5624 "consecutive same-size even/odd register pair");
5625 return MatchOperand_ParseFail;
5626 }
5627
5628 if (getParser().getTok().isNot(AsmToken::Comma)) {
5629 Error(getLoc(), "expected comma");
5630 return MatchOperand_ParseFail;
5631 }
5632 // Eat the comma
5633 getParser().Lex();
5634
5635 SMLoc E = getLoc();
5636 unsigned SecondReg;
5637 Res = tryParseScalarRegister(SecondReg);
5638 if (Res != MatchOperand_Success)
5639 return MatchOperand_ParseFail;
5640
5641 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
5642 (isXReg && !XRegClass.contains(SecondReg)) ||
5643 (isWReg && !WRegClass.contains(SecondReg))) {
5644 Error(E,"expected second odd register of a "
5645 "consecutive same-size even/odd register pair");
5646 return MatchOperand_ParseFail;
5647 }
5648
5649 unsigned Pair = 0;
5650 if (isXReg) {
5651 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5652 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5653 } else {
5654 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5655 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5656 }
5657
5658 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5659 getLoc(), getContext()));
5660
5661 return MatchOperand_Success;
5662 }
5663
5664 template <bool ParseShiftExtend, bool ParseSuffix>
5665 OperandMatchResultTy
tryParseSVEDataVector(OperandVector & Operands)5666 AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
5667 const SMLoc S = getLoc();
5668 // Check for a SVE vector register specifier first.
5669 unsigned RegNum;
5670 StringRef Kind;
5671
5672 OperandMatchResultTy Res =
5673 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
5674
5675 if (Res != MatchOperand_Success)
5676 return Res;
5677
5678 if (ParseSuffix && Kind.empty())
5679 return MatchOperand_NoMatch;
5680
5681 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5682 if (!KindRes)
5683 return MatchOperand_NoMatch;
5684
5685 unsigned ElementWidth = KindRes->second;
5686
5687 // No shift/extend is the default.
5688 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5689 Operands.push_back(AArch64Operand::CreateVectorReg(
5690 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5691
5692 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5693 if (Res == MatchOperand_ParseFail)
5694 return MatchOperand_ParseFail;
5695 return MatchOperand_Success;
5696 }
5697
5698 // Eat the comma
5699 getParser().Lex();
5700
5701 // Match the shift
5702 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5703 Res = tryParseOptionalShiftExtend(ExtOpnd);
5704 if (Res != MatchOperand_Success)
5705 return Res;
5706
5707 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
5708 Operands.push_back(AArch64Operand::CreateVectorReg(
5709 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5710 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5711 Ext->hasShiftExtendAmount()));
5712
5713 return MatchOperand_Success;
5714 }
5715
5716 OperandMatchResultTy
tryParseSVEPattern(OperandVector & Operands)5717 AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5718 MCAsmParser &Parser = getParser();
5719
5720 SMLoc SS = getLoc();
5721 const AsmToken &TokE = Parser.getTok();
5722 bool IsHash = TokE.is(AsmToken::Hash);
5723
5724 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5725 return MatchOperand_NoMatch;
5726
5727 int64_t Pattern;
5728 if (IsHash) {
5729 Parser.Lex(); // Eat hash
5730
5731 // Parse the immediate operand.
5732 const MCExpr *ImmVal;
5733 SS = getLoc();
5734 if (Parser.parseExpression(ImmVal))
5735 return MatchOperand_ParseFail;
5736
5737 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5738 if (!MCE)
5739 return MatchOperand_ParseFail;
5740
5741 Pattern = MCE->getValue();
5742 } else {
5743 // Parse the pattern
5744 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5745 if (!Pat)
5746 return MatchOperand_NoMatch;
5747
5748 Parser.Lex();
5749 Pattern = Pat->Encoding;
5750 assert(Pattern >= 0 && Pattern < 32);
5751 }
5752
5753 Operands.push_back(
5754 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5755 SS, getLoc(), getContext()));
5756
5757 return MatchOperand_Success;
5758 }
5759