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