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