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