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