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