1 //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ---------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "AMDKernelCodeT.h" 11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 12 #include "MCTargetDesc/AMDGPUTargetStreamer.h" 13 #include "SIDefines.h" 14 #include "Utils/AMDGPUBaseInfo.h" 15 #include "Utils/AMDKernelCodeTUtils.h" 16 #include "llvm/ADT/APFloat.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/ADT/StringSwitch.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstrInfo.h" 25 #include "llvm/MC/MCParser/MCAsmLexer.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 28 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 29 #include "llvm/MC/MCRegisterInfo.h" 30 #include "llvm/MC/MCStreamer.h" 31 #include "llvm/MC/MCSubtargetInfo.h" 32 #include "llvm/MC/MCSymbolELF.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/ELF.h" 35 #include "llvm/Support/SourceMgr.h" 36 #include "llvm/Support/TargetRegistry.h" 37 #include "llvm/Support/raw_ostream.h" 38 39 using namespace llvm; 40 41 namespace { 42 43 struct OptionalOperand; 44 45 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL }; 46 47 class AMDGPUOperand : public MCParsedAsmOperand { 48 enum KindTy { 49 Token, 50 Immediate, 51 Register, 52 Expression 53 } Kind; 54 55 SMLoc StartLoc, EndLoc; 56 57 public: 58 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {} 59 60 MCContext *Ctx; 61 62 enum ImmTy { 63 ImmTyNone, 64 ImmTyDSOffset0, 65 ImmTyDSOffset1, 66 ImmTyGDS, 67 ImmTyOffset, 68 ImmTyGLC, 69 ImmTySLC, 70 ImmTyTFE, 71 ImmTyClamp, 72 ImmTyOMod, 73 ImmTyDppCtrl, 74 ImmTyDppRowMask, 75 ImmTyDppBankMask, 76 ImmTyDppBoundCtrl, 77 ImmTySdwaSel, 78 ImmTySdwaDstUnused, 79 ImmTyDMask, 80 ImmTyUNorm, 81 ImmTyDA, 82 ImmTyR128, 83 ImmTyLWE, 84 ImmTyHwreg, 85 }; 86 87 struct TokOp { 88 const char *Data; 89 unsigned Length; 90 }; 91 92 struct ImmOp { 93 bool IsFPImm; 94 ImmTy Type; 95 int64_t Val; 96 int Modifiers; 97 }; 98 99 struct RegOp { 100 unsigned RegNo; 101 int Modifiers; 102 const MCRegisterInfo *TRI; 103 const MCSubtargetInfo *STI; 104 bool IsForcedVOP3; 105 }; 106 107 union { 108 TokOp Tok; 109 ImmOp Imm; 110 RegOp Reg; 111 const MCExpr *Expr; 112 }; 113 114 void addImmOperands(MCInst &Inst, unsigned N) const { 115 Inst.addOperand(MCOperand::createImm(getImm())); 116 } 117 118 StringRef getToken() const { 119 return StringRef(Tok.Data, Tok.Length); 120 } 121 122 void addRegOperands(MCInst &Inst, unsigned N) const { 123 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI))); 124 } 125 126 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 127 if (isRegKind()) 128 addRegOperands(Inst, N); 129 else 130 addImmOperands(Inst, N); 131 } 132 133 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 134 if (isRegKind()) { 135 Inst.addOperand(MCOperand::createImm(Reg.Modifiers)); 136 addRegOperands(Inst, N); 137 } else { 138 Inst.addOperand(MCOperand::createImm(Imm.Modifiers)); 139 addImmOperands(Inst, N); 140 } 141 } 142 143 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 144 if (isImm()) 145 addImmOperands(Inst, N); 146 else { 147 assert(isExpr()); 148 Inst.addOperand(MCOperand::createExpr(Expr)); 149 } 150 } 151 152 bool defaultTokenHasSuffix() const { 153 StringRef Token(Tok.Data, Tok.Length); 154 155 return Token.endswith("_e32") || Token.endswith("_e64") || 156 Token.endswith("_dpp"); 157 } 158 159 bool isToken() const override { 160 return Kind == Token; 161 } 162 163 bool isImm() const override { 164 return Kind == Immediate; 165 } 166 167 bool isInlinableImm() const { 168 if (!isImm() || Imm.Type != AMDGPUOperand::ImmTyNone /* Only plain 169 immediates are inlinable (e.g. "clamp" attribute is not) */ ) 170 return false; 171 // TODO: We should avoid using host float here. It would be better to 172 // check the float bit values which is what a few other places do. 173 // We've had bot failures before due to weird NaN support on mips hosts. 174 const float F = BitsToFloat(Imm.Val); 175 // TODO: Add 1/(2*pi) for VI 176 return (Imm.Val <= 64 && Imm.Val >= -16) || 177 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 || 178 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0); 179 } 180 181 bool isDSOffset0() const { 182 assert(isImm()); 183 return Imm.Type == ImmTyDSOffset0; 184 } 185 186 bool isDSOffset1() const { 187 assert(isImm()); 188 return Imm.Type == ImmTyDSOffset1; 189 } 190 191 int64_t getImm() const { 192 return Imm.Val; 193 } 194 195 enum ImmTy getImmTy() const { 196 assert(isImm()); 197 return Imm.Type; 198 } 199 200 bool isRegKind() const { 201 return Kind == Register; 202 } 203 204 bool isReg() const override { 205 return Kind == Register && Reg.Modifiers == 0; 206 } 207 208 bool isRegOrImmWithInputMods() const { 209 return Kind == Register || isInlinableImm(); 210 } 211 212 bool isImmTy(ImmTy ImmT) const { 213 return isImm() && Imm.Type == ImmT; 214 } 215 216 bool isClamp() const { 217 return isImmTy(ImmTyClamp); 218 } 219 220 bool isOMod() const { 221 return isImmTy(ImmTyOMod); 222 } 223 224 bool isImmModifier() const { 225 return Kind == Immediate && Imm.Type != ImmTyNone; 226 } 227 228 bool isDMask() const { 229 return isImmTy(ImmTyDMask); 230 } 231 232 bool isUNorm() const { return isImmTy(ImmTyUNorm); } 233 bool isDA() const { return isImmTy(ImmTyDA); } 234 bool isR128() const { return isImmTy(ImmTyUNorm); } 235 bool isLWE() const { return isImmTy(ImmTyLWE); } 236 237 bool isMod() const { 238 return isClamp() || isOMod(); 239 } 240 241 bool isGDS() const { return isImmTy(ImmTyGDS); } 242 bool isGLC() const { return isImmTy(ImmTyGLC); } 243 bool isSLC() const { return isImmTy(ImmTySLC); } 244 bool isTFE() const { return isImmTy(ImmTyTFE); } 245 246 bool isBankMask() const { 247 return isImmTy(ImmTyDppBankMask); 248 } 249 250 bool isRowMask() const { 251 return isImmTy(ImmTyDppRowMask); 252 } 253 254 bool isBoundCtrl() const { 255 return isImmTy(ImmTyDppBoundCtrl); 256 } 257 258 bool isSDWASel() const { 259 return isImmTy(ImmTySdwaSel); 260 } 261 262 bool isSDWADstUnused() const { 263 return isImmTy(ImmTySdwaDstUnused); 264 } 265 266 void setModifiers(unsigned Mods) { 267 assert(isReg() || (isImm() && Imm.Modifiers == 0)); 268 if (isReg()) 269 Reg.Modifiers = Mods; 270 else 271 Imm.Modifiers = Mods; 272 } 273 274 bool hasModifiers() const { 275 assert(isRegKind() || isImm()); 276 return isRegKind() ? Reg.Modifiers != 0 : Imm.Modifiers != 0; 277 } 278 279 unsigned getReg() const override { 280 return Reg.RegNo; 281 } 282 283 bool isRegOrImm() const { 284 return isReg() || isImm(); 285 } 286 287 bool isRegClass(unsigned RCID) const { 288 return isReg() && Reg.TRI->getRegClass(RCID).contains(getReg()); 289 } 290 291 bool isSCSrc32() const { 292 return isInlinableImm() || isRegClass(AMDGPU::SReg_32RegClassID); 293 } 294 295 bool isSCSrc64() const { 296 return isInlinableImm() || isRegClass(AMDGPU::SReg_64RegClassID); 297 } 298 299 bool isSSrc32() const { 300 return isImm() || isSCSrc32(); 301 } 302 303 bool isSSrc64() const { 304 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 305 // See isVSrc64(). 306 return isImm() || isSCSrc64(); 307 } 308 309 bool isVCSrc32() const { 310 return isInlinableImm() || isRegClass(AMDGPU::VS_32RegClassID); 311 } 312 313 bool isVCSrc64() const { 314 return isInlinableImm() || isRegClass(AMDGPU::VS_64RegClassID); 315 } 316 317 bool isVSrc32() const { 318 return isImm() || isVCSrc32(); 319 } 320 321 bool isVSrc64() const { 322 // TODO: Check if the 64-bit value (coming from assembly source) can be 323 // narrowed to 32 bits (in the instruction stream). That require knowledge 324 // of instruction type (unsigned/signed, floating or "untyped"/B64), 325 // see [AMD GCN3 ISA 6.3.1]. 326 // TODO: How 64-bit values are formed from 32-bit literals in _B64 insns? 327 return isImm() || isVCSrc64(); 328 } 329 330 bool isMem() const override { 331 return false; 332 } 333 334 bool isExpr() const { 335 return Kind == Expression; 336 } 337 338 bool isSoppBrTarget() const { 339 return isExpr() || isImm(); 340 } 341 342 SMLoc getStartLoc() const override { 343 return StartLoc; 344 } 345 346 SMLoc getEndLoc() const override { 347 return EndLoc; 348 } 349 350 void print(raw_ostream &OS) const override { 351 switch (Kind) { 352 case Register: 353 OS << "<register " << getReg() << " mods: " << Reg.Modifiers << '>'; 354 break; 355 case Immediate: 356 if (Imm.Type != AMDGPUOperand::ImmTyNone) 357 OS << getImm(); 358 else 359 OS << '<' << getImm() << " mods: " << Imm.Modifiers << '>'; 360 break; 361 case Token: 362 OS << '\'' << getToken() << '\''; 363 break; 364 case Expression: 365 OS << "<expr " << *Expr << '>'; 366 break; 367 } 368 } 369 370 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val, SMLoc Loc, 371 enum ImmTy Type = ImmTyNone, 372 bool IsFPImm = false) { 373 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate); 374 Op->Imm.Val = Val; 375 Op->Imm.IsFPImm = IsFPImm; 376 Op->Imm.Type = Type; 377 Op->Imm.Modifiers = 0; 378 Op->StartLoc = Loc; 379 Op->EndLoc = Loc; 380 return Op; 381 } 382 383 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc, 384 bool HasExplicitEncodingSize = true) { 385 auto Res = llvm::make_unique<AMDGPUOperand>(Token); 386 Res->Tok.Data = Str.data(); 387 Res->Tok.Length = Str.size(); 388 Res->StartLoc = Loc; 389 Res->EndLoc = Loc; 390 return Res; 391 } 392 393 static std::unique_ptr<AMDGPUOperand> CreateReg(unsigned RegNo, SMLoc S, 394 SMLoc E, 395 const MCRegisterInfo *TRI, 396 const MCSubtargetInfo *STI, 397 bool ForceVOP3) { 398 auto Op = llvm::make_unique<AMDGPUOperand>(Register); 399 Op->Reg.RegNo = RegNo; 400 Op->Reg.TRI = TRI; 401 Op->Reg.STI = STI; 402 Op->Reg.Modifiers = 0; 403 Op->Reg.IsForcedVOP3 = ForceVOP3; 404 Op->StartLoc = S; 405 Op->EndLoc = E; 406 return Op; 407 } 408 409 static std::unique_ptr<AMDGPUOperand> CreateExpr(const class MCExpr *Expr, SMLoc S) { 410 auto Op = llvm::make_unique<AMDGPUOperand>(Expression); 411 Op->Expr = Expr; 412 Op->StartLoc = S; 413 Op->EndLoc = S; 414 return Op; 415 } 416 417 bool isDSOffset() const; 418 bool isDSOffset01() const; 419 bool isSWaitCnt() const; 420 bool isHwreg() const; 421 bool isMubufOffset() const; 422 bool isSMRDOffset() const; 423 bool isSMRDLiteralOffset() const; 424 bool isDPPCtrl() const; 425 }; 426 427 class AMDGPUAsmParser : public MCTargetAsmParser { 428 const MCInstrInfo &MII; 429 MCAsmParser &Parser; 430 431 unsigned ForcedEncodingSize; 432 433 bool isSI() const { 434 return AMDGPU::isSI(getSTI()); 435 } 436 437 bool isCI() const { 438 return AMDGPU::isCI(getSTI()); 439 } 440 441 bool isVI() const { 442 return AMDGPU::isVI(getSTI()); 443 } 444 445 bool hasSGPR102_SGPR103() const { 446 return !isVI(); 447 } 448 449 /// @name Auto-generated Match Functions 450 /// { 451 452 #define GET_ASSEMBLER_HEADER 453 #include "AMDGPUGenAsmMatcher.inc" 454 455 /// } 456 457 private: 458 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 459 bool ParseDirectiveHSACodeObjectVersion(); 460 bool ParseDirectiveHSACodeObjectISA(); 461 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 462 bool ParseDirectiveAMDKernelCodeT(); 463 bool ParseSectionDirectiveHSAText(); 464 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; 465 bool ParseDirectiveAMDGPUHsaKernel(); 466 bool ParseDirectiveAMDGPUHsaModuleGlobal(); 467 bool ParseDirectiveAMDGPUHsaProgramGlobal(); 468 bool ParseSectionDirectiveHSADataGlobalAgent(); 469 bool ParseSectionDirectiveHSADataGlobalProgram(); 470 bool ParseSectionDirectiveHSARodataReadonlyAgent(); 471 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum); 472 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth); 473 474 public: 475 enum AMDGPUMatchResultTy { 476 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 477 }; 478 479 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 480 const MCInstrInfo &MII, 481 const MCTargetOptions &Options) 482 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser), 483 ForcedEncodingSize(0) { 484 MCAsmParserExtension::Initialize(Parser); 485 486 if (getSTI().getFeatureBits().none()) { 487 // Set default features. 488 copySTI().ToggleFeature("SOUTHERN_ISLANDS"); 489 } 490 491 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); 492 } 493 494 AMDGPUTargetStreamer &getTargetStreamer() { 495 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 496 return static_cast<AMDGPUTargetStreamer &>(TS); 497 } 498 499 unsigned getForcedEncodingSize() const { 500 return ForcedEncodingSize; 501 } 502 503 void setForcedEncodingSize(unsigned Size) { 504 ForcedEncodingSize = Size; 505 } 506 507 bool isForcedVOP3() const { 508 return ForcedEncodingSize == 64; 509 } 510 511 std::unique_ptr<AMDGPUOperand> parseRegister(); 512 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 513 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 514 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 515 OperandVector &Operands, MCStreamer &Out, 516 uint64_t &ErrorInfo, 517 bool MatchingInlineAsm) override; 518 bool ParseDirective(AsmToken DirectiveID) override; 519 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); 520 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 521 SMLoc NameLoc, OperandVector &Operands) override; 522 523 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int, 524 int64_t Default = 0); 525 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, 526 OperandVector &Operands, 527 enum AMDGPUOperand::ImmTy ImmTy = 528 AMDGPUOperand::ImmTyNone); 529 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands, 530 enum AMDGPUOperand::ImmTy ImmTy = 531 AMDGPUOperand::ImmTyNone); 532 OperandMatchResultTy parseOptionalOps( 533 const ArrayRef<OptionalOperand> &OptionalOps, 534 OperandVector &Operands); 535 OperandMatchResultTy parseStringWithPrefix(const char *Prefix, StringRef &Value); 536 537 538 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 539 void cvtDS(MCInst &Inst, const OperandVector &Operands); 540 OperandMatchResultTy parseDSOptionalOps(OperandVector &Operands); 541 OperandMatchResultTy parseDSOff01OptionalOps(OperandVector &Operands); 542 OperandMatchResultTy parseDSOffsetOptional(OperandVector &Operands); 543 544 bool parseCnt(int64_t &IntVal); 545 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 546 bool parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier); 547 OperandMatchResultTy parseHwregOp(OperandVector &Operands); 548 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 549 550 OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands); 551 OperandMatchResultTy parseFlatAtomicOptionalOps(OperandVector &Operands); 552 void cvtFlat(MCInst &Inst, const OperandVector &Operands); 553 void cvtFlatAtomic(MCInst &Inst, const OperandVector &Operands); 554 555 void cvtMubuf(MCInst &Inst, const OperandVector &Operands); 556 OperandMatchResultTy parseOffset(OperandVector &Operands); 557 OperandMatchResultTy parseMubufOptionalOps(OperandVector &Operands); 558 OperandMatchResultTy parseGLC(OperandVector &Operands); 559 OperandMatchResultTy parseSLC(OperandVector &Operands); 560 OperandMatchResultTy parseTFE(OperandVector &Operands); 561 562 OperandMatchResultTy parseDMask(OperandVector &Operands); 563 OperandMatchResultTy parseUNorm(OperandVector &Operands); 564 OperandMatchResultTy parseDA(OperandVector &Operands); 565 OperandMatchResultTy parseR128(OperandVector &Operands); 566 OperandMatchResultTy parseLWE(OperandVector &Operands); 567 568 void cvtId(MCInst &Inst, const OperandVector &Operands); 569 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands); 570 void cvtVOP3_2_nomod(MCInst &Inst, const OperandVector &Operands); 571 void cvtVOP3_only(MCInst &Inst, const OperandVector &Operands); 572 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 573 574 void cvtMIMG(MCInst &Inst, const OperandVector &Operands); 575 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands); 576 OperandMatchResultTy parseVOP3OptionalOps(OperandVector &Operands); 577 578 OperandMatchResultTy parseDPPCtrlOps(OperandVector &Operands); 579 OperandMatchResultTy parseDPPOptionalOps(OperandVector &Operands); 580 void cvtDPP_mod(MCInst &Inst, const OperandVector &Operands); 581 void cvtDPP_nomod(MCInst &Inst, const OperandVector &Operands); 582 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool HasMods); 583 584 OperandMatchResultTy parseSDWASel(OperandVector &Operands); 585 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); 586 }; 587 588 struct OptionalOperand { 589 const char *Name; 590 AMDGPUOperand::ImmTy Type; 591 bool IsBit; 592 int64_t Default; 593 bool (*ConvertResult)(int64_t&); 594 }; 595 596 } 597 598 static int getRegClass(RegisterKind Is, unsigned RegWidth) { 599 if (Is == IS_VGPR) { 600 switch (RegWidth) { 601 default: return -1; 602 case 1: return AMDGPU::VGPR_32RegClassID; 603 case 2: return AMDGPU::VReg_64RegClassID; 604 case 3: return AMDGPU::VReg_96RegClassID; 605 case 4: return AMDGPU::VReg_128RegClassID; 606 case 8: return AMDGPU::VReg_256RegClassID; 607 case 16: return AMDGPU::VReg_512RegClassID; 608 } 609 } else if (Is == IS_TTMP) { 610 switch (RegWidth) { 611 default: return -1; 612 case 1: return AMDGPU::TTMP_32RegClassID; 613 case 2: return AMDGPU::TTMP_64RegClassID; 614 case 4: return AMDGPU::TTMP_128RegClassID; 615 } 616 } else if (Is == IS_SGPR) { 617 switch (RegWidth) { 618 default: return -1; 619 case 1: return AMDGPU::SGPR_32RegClassID; 620 case 2: return AMDGPU::SGPR_64RegClassID; 621 case 4: return AMDGPU::SGPR_128RegClassID; 622 case 8: return AMDGPU::SReg_256RegClassID; 623 case 16: return AMDGPU::SReg_512RegClassID; 624 } 625 } 626 return -1; 627 } 628 629 static unsigned getSpecialRegForName(StringRef RegName) { 630 return StringSwitch<unsigned>(RegName) 631 .Case("exec", AMDGPU::EXEC) 632 .Case("vcc", AMDGPU::VCC) 633 .Case("flat_scratch", AMDGPU::FLAT_SCR) 634 .Case("m0", AMDGPU::M0) 635 .Case("scc", AMDGPU::SCC) 636 .Case("tba", AMDGPU::TBA) 637 .Case("tma", AMDGPU::TMA) 638 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 639 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 640 .Case("vcc_lo", AMDGPU::VCC_LO) 641 .Case("vcc_hi", AMDGPU::VCC_HI) 642 .Case("exec_lo", AMDGPU::EXEC_LO) 643 .Case("exec_hi", AMDGPU::EXEC_HI) 644 .Case("tma_lo", AMDGPU::TMA_LO) 645 .Case("tma_hi", AMDGPU::TMA_HI) 646 .Case("tba_lo", AMDGPU::TBA_LO) 647 .Case("tba_hi", AMDGPU::TBA_HI) 648 .Default(0); 649 } 650 651 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { 652 auto R = parseRegister(); 653 if (!R) return true; 654 assert(R->isReg()); 655 RegNo = R->getReg(); 656 StartLoc = R->getStartLoc(); 657 EndLoc = R->getEndLoc(); 658 return false; 659 } 660 661 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum) 662 { 663 switch (RegKind) { 664 case IS_SPECIAL: 665 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; } 666 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; } 667 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; } 668 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; } 669 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; } 670 return false; 671 case IS_VGPR: 672 case IS_SGPR: 673 case IS_TTMP: 674 if (Reg1 != Reg + RegWidth) { return false; } 675 RegWidth++; 676 return true; 677 default: 678 assert(false); return false; 679 } 680 } 681 682 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth) 683 { 684 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 685 if (getLexer().is(AsmToken::Identifier)) { 686 StringRef RegName = Parser.getTok().getString(); 687 if ((Reg = getSpecialRegForName(RegName))) { 688 Parser.Lex(); 689 RegKind = IS_SPECIAL; 690 } else { 691 unsigned RegNumIndex = 0; 692 if (RegName[0] == 'v') { RegNumIndex = 1; RegKind = IS_VGPR; } 693 else if (RegName[0] == 's') { RegNumIndex = 1; RegKind = IS_SGPR; } 694 else if (RegName.startswith("ttmp")) { RegNumIndex = strlen("ttmp"); RegKind = IS_TTMP; } 695 else { return false; } 696 if (RegName.size() > RegNumIndex) { 697 // Single 32-bit register: vXX. 698 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum)) { return false; } 699 Parser.Lex(); 700 RegWidth = 1; 701 } else { 702 // Range of registers: v[XX:YY]. 703 Parser.Lex(); 704 int64_t RegLo, RegHi; 705 if (getLexer().isNot(AsmToken::LBrac)) { return false; } 706 Parser.Lex(); 707 708 if (getParser().parseAbsoluteExpression(RegLo)) { return false; } 709 710 if (getLexer().isNot(AsmToken::Colon)) { return false; } 711 Parser.Lex(); 712 713 if (getParser().parseAbsoluteExpression(RegHi)) { return false; } 714 715 if (getLexer().isNot(AsmToken::RBrac)) { return false; } 716 Parser.Lex(); 717 718 RegNum = (unsigned) RegLo; 719 RegWidth = (RegHi - RegLo) + 1; 720 } 721 } 722 } else if (getLexer().is(AsmToken::LBrac)) { 723 // List of consecutive registers: [s0,s1,s2,s3] 724 Parser.Lex(); 725 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { return false; } 726 if (RegWidth != 1) { return false; } 727 RegisterKind RegKind1; 728 unsigned Reg1, RegNum1, RegWidth1; 729 do { 730 if (getLexer().is(AsmToken::Comma)) { 731 Parser.Lex(); 732 } else if (getLexer().is(AsmToken::RBrac)) { 733 Parser.Lex(); 734 break; 735 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1)) { 736 if (RegWidth1 != 1) { return false; } 737 if (RegKind1 != RegKind) { return false; } 738 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) { return false; } 739 } else { 740 return false; 741 } 742 } while (true); 743 } else { 744 return false; 745 } 746 switch (RegKind) { 747 case IS_SPECIAL: 748 RegNum = 0; 749 RegWidth = 1; 750 break; 751 case IS_VGPR: 752 case IS_SGPR: 753 case IS_TTMP: 754 { 755 unsigned Size = 1; 756 if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 757 // SGPR and TTMP registers must be are aligned. Max required alignment is 4 dwords. 758 Size = std::min(RegWidth, 4u); 759 } 760 if (RegNum % Size != 0) { return false; } 761 RegNum = RegNum / Size; 762 int RCID = getRegClass(RegKind, RegWidth); 763 if (RCID == -1) { return false; } 764 const MCRegisterClass RC = TRI->getRegClass(RCID); 765 if (RegNum >= RC.getNumRegs()) { return false; } 766 Reg = RC.getRegister(RegNum); 767 break; 768 } 769 770 default: 771 assert(false); return false; 772 } 773 774 if (!subtargetHasRegister(*TRI, Reg)) { return false; } 775 return true; 776 } 777 778 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() { 779 const auto &Tok = Parser.getTok(); 780 SMLoc StartLoc = Tok.getLoc(); 781 SMLoc EndLoc = Tok.getEndLoc(); 782 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 783 784 RegisterKind RegKind; 785 unsigned Reg, RegNum, RegWidth; 786 787 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { 788 return nullptr; 789 } 790 return AMDGPUOperand::CreateReg(Reg, StartLoc, EndLoc, 791 TRI, &getSTI(), false); 792 } 793 794 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 795 796 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 797 798 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 799 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3))) 800 return Match_InvalidOperand; 801 802 if ((TSFlags & SIInstrFlags::VOP3) && 803 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 804 getForcedEncodingSize() != 64) 805 return Match_PreferE32; 806 807 return Match_Success; 808 } 809 810 811 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 812 OperandVector &Operands, 813 MCStreamer &Out, 814 uint64_t &ErrorInfo, 815 bool MatchingInlineAsm) { 816 MCInst Inst; 817 818 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 819 default: break; 820 case Match_Success: 821 Inst.setLoc(IDLoc); 822 Out.EmitInstruction(Inst, getSTI()); 823 return false; 824 case Match_MissingFeature: 825 return Error(IDLoc, "instruction not supported on this GPU"); 826 827 case Match_MnemonicFail: 828 return Error(IDLoc, "unrecognized instruction mnemonic"); 829 830 case Match_InvalidOperand: { 831 SMLoc ErrorLoc = IDLoc; 832 if (ErrorInfo != ~0ULL) { 833 if (ErrorInfo >= Operands.size()) { 834 return Error(IDLoc, "too few operands for instruction"); 835 } 836 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 837 if (ErrorLoc == SMLoc()) 838 ErrorLoc = IDLoc; 839 } 840 return Error(ErrorLoc, "invalid operand for instruction"); 841 } 842 case Match_PreferE32: 843 return Error(IDLoc, "internal error: instruction without _e64 suffix " 844 "should be encoded as e32"); 845 } 846 llvm_unreachable("Implement any new match types added!"); 847 } 848 849 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 850 uint32_t &Minor) { 851 if (getLexer().isNot(AsmToken::Integer)) 852 return TokError("invalid major version"); 853 854 Major = getLexer().getTok().getIntVal(); 855 Lex(); 856 857 if (getLexer().isNot(AsmToken::Comma)) 858 return TokError("minor version number required, comma expected"); 859 Lex(); 860 861 if (getLexer().isNot(AsmToken::Integer)) 862 return TokError("invalid minor version"); 863 864 Minor = getLexer().getTok().getIntVal(); 865 Lex(); 866 867 return false; 868 } 869 870 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 871 872 uint32_t Major; 873 uint32_t Minor; 874 875 if (ParseDirectiveMajorMinor(Major, Minor)) 876 return true; 877 878 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 879 return false; 880 } 881 882 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 883 884 uint32_t Major; 885 uint32_t Minor; 886 uint32_t Stepping; 887 StringRef VendorName; 888 StringRef ArchName; 889 890 // If this directive has no arguments, then use the ISA version for the 891 // targeted GPU. 892 if (getLexer().is(AsmToken::EndOfStatement)) { 893 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits()); 894 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor, 895 Isa.Stepping, 896 "AMD", "AMDGPU"); 897 return false; 898 } 899 900 901 if (ParseDirectiveMajorMinor(Major, Minor)) 902 return true; 903 904 if (getLexer().isNot(AsmToken::Comma)) 905 return TokError("stepping version number required, comma expected"); 906 Lex(); 907 908 if (getLexer().isNot(AsmToken::Integer)) 909 return TokError("invalid stepping version"); 910 911 Stepping = getLexer().getTok().getIntVal(); 912 Lex(); 913 914 if (getLexer().isNot(AsmToken::Comma)) 915 return TokError("vendor name required, comma expected"); 916 Lex(); 917 918 if (getLexer().isNot(AsmToken::String)) 919 return TokError("invalid vendor name"); 920 921 VendorName = getLexer().getTok().getStringContents(); 922 Lex(); 923 924 if (getLexer().isNot(AsmToken::Comma)) 925 return TokError("arch name required, comma expected"); 926 Lex(); 927 928 if (getLexer().isNot(AsmToken::String)) 929 return TokError("invalid arch name"); 930 931 ArchName = getLexer().getTok().getStringContents(); 932 Lex(); 933 934 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 935 VendorName, ArchName); 936 return false; 937 } 938 939 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 940 amd_kernel_code_t &Header) { 941 SmallString<40> ErrStr; 942 raw_svector_ostream Err(ErrStr); 943 if (!parseAmdKernelCodeField(ID, getLexer(), Header, Err)) { 944 return TokError(Err.str()); 945 } 946 Lex(); 947 return false; 948 } 949 950 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 951 952 amd_kernel_code_t Header; 953 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits()); 954 955 while (true) { 956 957 if (getLexer().isNot(AsmToken::EndOfStatement)) 958 return TokError("amd_kernel_code_t values must begin on a new line"); 959 960 // Lex EndOfStatement. This is in a while loop, because lexing a comment 961 // will set the current token to EndOfStatement. 962 while(getLexer().is(AsmToken::EndOfStatement)) 963 Lex(); 964 965 if (getLexer().isNot(AsmToken::Identifier)) 966 return TokError("expected value identifier or .end_amd_kernel_code_t"); 967 968 StringRef ID = getLexer().getTok().getIdentifier(); 969 Lex(); 970 971 if (ID == ".end_amd_kernel_code_t") 972 break; 973 974 if (ParseAMDKernelCodeTValue(ID, Header)) 975 return true; 976 } 977 978 getTargetStreamer().EmitAMDKernelCodeT(Header); 979 980 return false; 981 } 982 983 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() { 984 getParser().getStreamer().SwitchSection( 985 AMDGPU::getHSATextSection(getContext())); 986 return false; 987 } 988 989 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 990 if (getLexer().isNot(AsmToken::Identifier)) 991 return TokError("expected symbol name"); 992 993 StringRef KernelName = Parser.getTok().getString(); 994 995 getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 996 ELF::STT_AMDGPU_HSA_KERNEL); 997 Lex(); 998 return false; 999 } 1000 1001 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() { 1002 if (getLexer().isNot(AsmToken::Identifier)) 1003 return TokError("expected symbol name"); 1004 1005 StringRef GlobalName = Parser.getTok().getIdentifier(); 1006 1007 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName); 1008 Lex(); 1009 return false; 1010 } 1011 1012 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() { 1013 if (getLexer().isNot(AsmToken::Identifier)) 1014 return TokError("expected symbol name"); 1015 1016 StringRef GlobalName = Parser.getTok().getIdentifier(); 1017 1018 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName); 1019 Lex(); 1020 return false; 1021 } 1022 1023 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() { 1024 getParser().getStreamer().SwitchSection( 1025 AMDGPU::getHSADataGlobalAgentSection(getContext())); 1026 return false; 1027 } 1028 1029 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() { 1030 getParser().getStreamer().SwitchSection( 1031 AMDGPU::getHSADataGlobalProgramSection(getContext())); 1032 return false; 1033 } 1034 1035 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() { 1036 getParser().getStreamer().SwitchSection( 1037 AMDGPU::getHSARodataReadonlyAgentSection(getContext())); 1038 return false; 1039 } 1040 1041 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 1042 StringRef IDVal = DirectiveID.getString(); 1043 1044 if (IDVal == ".hsa_code_object_version") 1045 return ParseDirectiveHSACodeObjectVersion(); 1046 1047 if (IDVal == ".hsa_code_object_isa") 1048 return ParseDirectiveHSACodeObjectISA(); 1049 1050 if (IDVal == ".amd_kernel_code_t") 1051 return ParseDirectiveAMDKernelCodeT(); 1052 1053 if (IDVal == ".hsatext" || IDVal == ".text") 1054 return ParseSectionDirectiveHSAText(); 1055 1056 if (IDVal == ".amdgpu_hsa_kernel") 1057 return ParseDirectiveAMDGPUHsaKernel(); 1058 1059 if (IDVal == ".amdgpu_hsa_module_global") 1060 return ParseDirectiveAMDGPUHsaModuleGlobal(); 1061 1062 if (IDVal == ".amdgpu_hsa_program_global") 1063 return ParseDirectiveAMDGPUHsaProgramGlobal(); 1064 1065 if (IDVal == ".hsadata_global_agent") 1066 return ParseSectionDirectiveHSADataGlobalAgent(); 1067 1068 if (IDVal == ".hsadata_global_program") 1069 return ParseSectionDirectiveHSADataGlobalProgram(); 1070 1071 if (IDVal == ".hsarodata_readonly_agent") 1072 return ParseSectionDirectiveHSARodataReadonlyAgent(); 1073 1074 return true; 1075 } 1076 1077 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 1078 unsigned RegNo) const { 1079 if (isCI()) 1080 return true; 1081 1082 if (isSI()) { 1083 // No flat_scr 1084 switch (RegNo) { 1085 case AMDGPU::FLAT_SCR: 1086 case AMDGPU::FLAT_SCR_LO: 1087 case AMDGPU::FLAT_SCR_HI: 1088 return false; 1089 default: 1090 return true; 1091 } 1092 } 1093 1094 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 1095 // SI/CI have. 1096 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true); 1097 R.isValid(); ++R) { 1098 if (*R == RegNo) 1099 return false; 1100 } 1101 1102 return true; 1103 } 1104 1105 static bool operandsHaveModifiers(const OperandVector &Operands) { 1106 1107 for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 1108 const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 1109 if (Op.isRegKind() && Op.hasModifiers()) 1110 return true; 1111 if (Op.isImm() && Op.hasModifiers()) 1112 return true; 1113 if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOMod || 1114 Op.getImmTy() == AMDGPUOperand::ImmTyClamp)) 1115 return true; 1116 } 1117 return false; 1118 } 1119 1120 AMDGPUAsmParser::OperandMatchResultTy 1121 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 1122 1123 // Try to parse with a custom parser 1124 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 1125 1126 // If we successfully parsed the operand or if there as an error parsing, 1127 // we are done. 1128 // 1129 // If we are parsing after we reach EndOfStatement then this means we 1130 // are appending default values to the Operands list. This is only done 1131 // by custom parser, so we shouldn't continue on to the generic parsing. 1132 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail|| 1133 getLexer().is(AsmToken::EndOfStatement)) 1134 return ResTy; 1135 1136 bool Negate = false, Abs = false, Abs2 = false; 1137 1138 if (getLexer().getKind()== AsmToken::Minus) { 1139 Parser.Lex(); 1140 Negate = true; 1141 } 1142 1143 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") { 1144 Parser.Lex(); 1145 Abs2 = true; 1146 if (getLexer().isNot(AsmToken::LParen)) { 1147 Error(Parser.getTok().getLoc(), "expected left paren after abs"); 1148 return MatchOperand_ParseFail; 1149 } 1150 Parser.Lex(); 1151 } 1152 1153 if (getLexer().getKind() == AsmToken::Pipe) { 1154 Parser.Lex(); 1155 Abs = true; 1156 } 1157 1158 switch(getLexer().getKind()) { 1159 case AsmToken::Integer: { 1160 SMLoc S = Parser.getTok().getLoc(); 1161 int64_t IntVal; 1162 if (getParser().parseAbsoluteExpression(IntVal)) 1163 return MatchOperand_ParseFail; 1164 if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) { 1165 Error(S, "invalid immediate: only 32-bit values are legal"); 1166 return MatchOperand_ParseFail; 1167 } 1168 1169 if (Negate) 1170 IntVal *= -1; 1171 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S)); 1172 return MatchOperand_Success; 1173 } 1174 case AsmToken::Real: { 1175 // FIXME: We should emit an error if a double precisions floating-point 1176 // value is used. I'm not sure the best way to detect this. 1177 SMLoc S = Parser.getTok().getLoc(); 1178 int64_t IntVal; 1179 if (getParser().parseAbsoluteExpression(IntVal)) 1180 return MatchOperand_ParseFail; 1181 1182 APFloat F((float)BitsToDouble(IntVal)); 1183 if (Negate) 1184 F.changeSign(); 1185 Operands.push_back( 1186 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); 1187 return MatchOperand_Success; 1188 } 1189 case AsmToken::LBrac: 1190 case AsmToken::Identifier: { 1191 if (auto R = parseRegister()) { 1192 unsigned Modifiers = 0; 1193 1194 if (Negate) 1195 Modifiers |= 0x1; 1196 1197 if (Abs) { 1198 if (getLexer().getKind() != AsmToken::Pipe) 1199 return MatchOperand_ParseFail; 1200 Parser.Lex(); 1201 Modifiers |= 0x2; 1202 } 1203 if (Abs2) { 1204 if (getLexer().isNot(AsmToken::RParen)) { 1205 return MatchOperand_ParseFail; 1206 } 1207 Parser.Lex(); 1208 Modifiers |= 0x2; 1209 } 1210 assert(R->isReg()); 1211 R->Reg.IsForcedVOP3 = isForcedVOP3(); 1212 if (Modifiers) { 1213 R->setModifiers(Modifiers); 1214 } 1215 Operands.push_back(std::move(R)); 1216 } else { 1217 ResTy = parseVOP3OptionalOps(Operands); 1218 if (ResTy == MatchOperand_NoMatch) { 1219 const auto &Tok = Parser.getTok(); 1220 Operands.push_back(AMDGPUOperand::CreateToken(Tok.getString(), 1221 Tok.getLoc())); 1222 Parser.Lex(); 1223 } 1224 } 1225 return MatchOperand_Success; 1226 } 1227 default: 1228 return MatchOperand_NoMatch; 1229 } 1230 } 1231 1232 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1233 StringRef Name, 1234 SMLoc NameLoc, OperandVector &Operands) { 1235 1236 // Clear any forced encodings from the previous instruction. 1237 setForcedEncodingSize(0); 1238 1239 if (Name.endswith("_e64")) 1240 setForcedEncodingSize(64); 1241 else if (Name.endswith("_e32")) 1242 setForcedEncodingSize(32); 1243 1244 // Add the instruction mnemonic 1245 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); 1246 1247 while (!getLexer().is(AsmToken::EndOfStatement)) { 1248 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); 1249 1250 // Eat the comma or space if there is one. 1251 if (getLexer().is(AsmToken::Comma)) 1252 Parser.Lex(); 1253 1254 switch (Res) { 1255 case MatchOperand_Success: break; 1256 case MatchOperand_ParseFail: return Error(getLexer().getLoc(), 1257 "failed parsing operand."); 1258 case MatchOperand_NoMatch: return Error(getLexer().getLoc(), 1259 "not a valid operand."); 1260 } 1261 } 1262 1263 return false; 1264 } 1265 1266 //===----------------------------------------------------------------------===// 1267 // Utility functions 1268 //===----------------------------------------------------------------------===// 1269 1270 AMDGPUAsmParser::OperandMatchResultTy 1271 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int, 1272 int64_t Default) { 1273 // We are at the end of the statement, and this is a default argument, so 1274 // use a default value. 1275 if (getLexer().is(AsmToken::EndOfStatement)) { 1276 Int = Default; 1277 return MatchOperand_Success; 1278 } 1279 1280 switch(getLexer().getKind()) { 1281 default: return MatchOperand_NoMatch; 1282 case AsmToken::Identifier: { 1283 StringRef OffsetName = Parser.getTok().getString(); 1284 if (!OffsetName.equals(Prefix)) 1285 return MatchOperand_NoMatch; 1286 1287 Parser.Lex(); 1288 if (getLexer().isNot(AsmToken::Colon)) 1289 return MatchOperand_ParseFail; 1290 1291 Parser.Lex(); 1292 if (getLexer().isNot(AsmToken::Integer)) 1293 return MatchOperand_ParseFail; 1294 1295 if (getParser().parseAbsoluteExpression(Int)) 1296 return MatchOperand_ParseFail; 1297 break; 1298 } 1299 } 1300 return MatchOperand_Success; 1301 } 1302 1303 AMDGPUAsmParser::OperandMatchResultTy 1304 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1305 enum AMDGPUOperand::ImmTy ImmTy) { 1306 1307 SMLoc S = Parser.getTok().getLoc(); 1308 int64_t Offset = 0; 1309 1310 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Offset); 1311 if (Res != MatchOperand_Success) 1312 return Res; 1313 1314 Operands.push_back(AMDGPUOperand::CreateImm(Offset, S, ImmTy)); 1315 return MatchOperand_Success; 1316 } 1317 1318 AMDGPUAsmParser::OperandMatchResultTy 1319 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 1320 enum AMDGPUOperand::ImmTy ImmTy) { 1321 int64_t Bit = 0; 1322 SMLoc S = Parser.getTok().getLoc(); 1323 1324 // We are at the end of the statement, and this is a default argument, so 1325 // use a default value. 1326 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1327 switch(getLexer().getKind()) { 1328 case AsmToken::Identifier: { 1329 StringRef Tok = Parser.getTok().getString(); 1330 if (Tok == Name) { 1331 Bit = 1; 1332 Parser.Lex(); 1333 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 1334 Bit = 0; 1335 Parser.Lex(); 1336 } else { 1337 return MatchOperand_NoMatch; 1338 } 1339 break; 1340 } 1341 default: 1342 return MatchOperand_NoMatch; 1343 } 1344 } 1345 1346 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy)); 1347 return MatchOperand_Success; 1348 } 1349 1350 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap; 1351 1352 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands, 1353 OptionalImmIndexMap& OptionalIdx, 1354 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) { 1355 auto i = OptionalIdx.find(ImmT); 1356 if (i != OptionalIdx.end()) { 1357 unsigned Idx = i->second; 1358 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 1359 } else { 1360 Inst.addOperand(MCOperand::createImm(Default)); 1361 } 1362 } 1363 1364 static bool operandsHasOptionalOp(const OperandVector &Operands, 1365 const OptionalOperand &OOp) { 1366 for (unsigned i = 0; i < Operands.size(); i++) { 1367 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]); 1368 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) || 1369 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name)) 1370 return true; 1371 1372 } 1373 return false; 1374 } 1375 1376 AMDGPUAsmParser::OperandMatchResultTy 1377 AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps, 1378 OperandVector &Operands) { 1379 SMLoc S = Parser.getTok().getLoc(); 1380 for (const OptionalOperand &Op : OptionalOps) { 1381 if (operandsHasOptionalOp(Operands, Op)) 1382 continue; 1383 AMDGPUAsmParser::OperandMatchResultTy Res; 1384 int64_t Value; 1385 if (Op.IsBit) { 1386 Res = parseNamedBit(Op.Name, Operands, Op.Type); 1387 if (Res == MatchOperand_NoMatch) 1388 continue; 1389 return Res; 1390 } 1391 1392 Res = parseIntWithPrefix(Op.Name, Value, Op.Default); 1393 1394 if (Res == MatchOperand_NoMatch) 1395 continue; 1396 1397 if (Res != MatchOperand_Success) 1398 return Res; 1399 1400 bool DefaultValue = (Value == Op.Default); 1401 1402 if (Op.ConvertResult && !Op.ConvertResult(Value)) { 1403 return MatchOperand_ParseFail; 1404 } 1405 1406 if (!DefaultValue) { 1407 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type)); 1408 } 1409 return MatchOperand_Success; 1410 } 1411 return MatchOperand_NoMatch; 1412 } 1413 1414 AMDGPUAsmParser::OperandMatchResultTy 1415 AMDGPUAsmParser::parseStringWithPrefix(const char *Prefix, StringRef &Value) { 1416 if (getLexer().isNot(AsmToken::Identifier)) { 1417 return MatchOperand_NoMatch; 1418 } 1419 StringRef Tok = Parser.getTok().getString(); 1420 if (Tok != Prefix) { 1421 return MatchOperand_NoMatch; 1422 } 1423 1424 Parser.Lex(); 1425 if (getLexer().isNot(AsmToken::Colon)) { 1426 return MatchOperand_ParseFail; 1427 } 1428 1429 Parser.Lex(); 1430 if (getLexer().isNot(AsmToken::Identifier)) { 1431 return MatchOperand_ParseFail; 1432 } 1433 1434 Value = Parser.getTok().getString(); 1435 return MatchOperand_Success; 1436 } 1437 1438 //===----------------------------------------------------------------------===// 1439 // ds 1440 //===----------------------------------------------------------------------===// 1441 1442 static const OptionalOperand DSOptionalOps [] = { 1443 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1444 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1445 }; 1446 1447 static const OptionalOperand DSOptionalOpsOff01 [] = { 1448 {"offset0", AMDGPUOperand::ImmTyDSOffset0, false, 0, nullptr}, 1449 {"offset1", AMDGPUOperand::ImmTyDSOffset1, false, 0, nullptr}, 1450 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1451 }; 1452 1453 AMDGPUAsmParser::OperandMatchResultTy 1454 AMDGPUAsmParser::parseDSOptionalOps(OperandVector &Operands) { 1455 return parseOptionalOps(DSOptionalOps, Operands); 1456 } 1457 AMDGPUAsmParser::OperandMatchResultTy 1458 AMDGPUAsmParser::parseDSOff01OptionalOps(OperandVector &Operands) { 1459 return parseOptionalOps(DSOptionalOpsOff01, Operands); 1460 } 1461 1462 AMDGPUAsmParser::OperandMatchResultTy 1463 AMDGPUAsmParser::parseDSOffsetOptional(OperandVector &Operands) { 1464 SMLoc S = Parser.getTok().getLoc(); 1465 AMDGPUAsmParser::OperandMatchResultTy Res = 1466 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset); 1467 if (Res == MatchOperand_NoMatch) { 1468 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 1469 AMDGPUOperand::ImmTyOffset)); 1470 Res = MatchOperand_Success; 1471 } 1472 return Res; 1473 } 1474 1475 bool AMDGPUOperand::isDSOffset() const { 1476 return isImm() && isUInt<16>(getImm()); 1477 } 1478 1479 bool AMDGPUOperand::isDSOffset01() const { 1480 return isImm() && isUInt<8>(getImm()); 1481 } 1482 1483 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 1484 const OperandVector &Operands) { 1485 1486 OptionalImmIndexMap OptionalIdx; 1487 1488 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1489 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1490 1491 // Add the register arguments 1492 if (Op.isReg()) { 1493 Op.addRegOperands(Inst, 1); 1494 continue; 1495 } 1496 1497 // Handle optional arguments 1498 OptionalIdx[Op.getImmTy()] = i; 1499 } 1500 1501 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDSOffset0); 1502 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDSOffset1); 1503 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1504 1505 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1506 } 1507 1508 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 1509 1510 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1511 bool GDSOnly = false; 1512 1513 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1514 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1515 1516 // Add the register arguments 1517 if (Op.isReg()) { 1518 Op.addRegOperands(Inst, 1); 1519 continue; 1520 } 1521 1522 if (Op.isToken() && Op.getToken() == "gds") { 1523 GDSOnly = true; 1524 continue; 1525 } 1526 1527 // Handle optional arguments 1528 OptionalIdx[Op.getImmTy()] = i; 1529 } 1530 1531 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 1532 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1533 1534 if (!GDSOnly) { 1535 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1536 } 1537 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1538 } 1539 1540 1541 //===----------------------------------------------------------------------===// 1542 // s_waitcnt 1543 //===----------------------------------------------------------------------===// 1544 1545 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 1546 StringRef CntName = Parser.getTok().getString(); 1547 int64_t CntVal; 1548 1549 Parser.Lex(); 1550 if (getLexer().isNot(AsmToken::LParen)) 1551 return true; 1552 1553 Parser.Lex(); 1554 if (getLexer().isNot(AsmToken::Integer)) 1555 return true; 1556 1557 if (getParser().parseAbsoluteExpression(CntVal)) 1558 return true; 1559 1560 if (getLexer().isNot(AsmToken::RParen)) 1561 return true; 1562 1563 Parser.Lex(); 1564 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 1565 Parser.Lex(); 1566 1567 int CntShift; 1568 int CntMask; 1569 1570 if (CntName == "vmcnt") { 1571 CntMask = 0xf; 1572 CntShift = 0; 1573 } else if (CntName == "expcnt") { 1574 CntMask = 0x7; 1575 CntShift = 4; 1576 } else if (CntName == "lgkmcnt") { 1577 CntMask = 0xf; 1578 CntShift = 8; 1579 } else { 1580 return true; 1581 } 1582 1583 IntVal &= ~(CntMask << CntShift); 1584 IntVal |= (CntVal << CntShift); 1585 return false; 1586 } 1587 1588 AMDGPUAsmParser::OperandMatchResultTy 1589 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 1590 // Disable all counters by default. 1591 // vmcnt [3:0] 1592 // expcnt [6:4] 1593 // lgkmcnt [11:8] 1594 int64_t CntVal = 0xf7f; 1595 SMLoc S = Parser.getTok().getLoc(); 1596 1597 switch(getLexer().getKind()) { 1598 default: return MatchOperand_ParseFail; 1599 case AsmToken::Integer: 1600 // The operand can be an integer value. 1601 if (getParser().parseAbsoluteExpression(CntVal)) 1602 return MatchOperand_ParseFail; 1603 break; 1604 1605 case AsmToken::Identifier: 1606 do { 1607 if (parseCnt(CntVal)) 1608 return MatchOperand_ParseFail; 1609 } while(getLexer().isNot(AsmToken::EndOfStatement)); 1610 break; 1611 } 1612 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S)); 1613 return MatchOperand_Success; 1614 } 1615 1616 bool AMDGPUAsmParser::parseHwreg(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier) { 1617 if (Parser.getTok().getString() != "hwreg") 1618 return true; 1619 Parser.Lex(); 1620 1621 if (getLexer().isNot(AsmToken::LParen)) 1622 return true; 1623 Parser.Lex(); 1624 1625 if (getLexer().is(AsmToken::Identifier)) { 1626 IsIdentifier = true; 1627 HwRegCode = StringSwitch<unsigned>(Parser.getTok().getString()) 1628 .Case("HW_REG_MODE" , 1) 1629 .Case("HW_REG_STATUS" , 2) 1630 .Case("HW_REG_TRAPSTS" , 3) 1631 .Case("HW_REG_HW_ID" , 4) 1632 .Case("HW_REG_GPR_ALLOC", 5) 1633 .Case("HW_REG_LDS_ALLOC", 6) 1634 .Case("HW_REG_IB_STS" , 7) 1635 .Default(-1); 1636 Parser.Lex(); 1637 } else { 1638 IsIdentifier = false; 1639 if (getLexer().isNot(AsmToken::Integer)) 1640 return true; 1641 if (getParser().parseAbsoluteExpression(HwRegCode)) 1642 return true; 1643 } 1644 1645 if (getLexer().is(AsmToken::RParen)) { 1646 Parser.Lex(); 1647 return false; 1648 } 1649 1650 // optional params 1651 if (getLexer().isNot(AsmToken::Comma)) 1652 return true; 1653 Parser.Lex(); 1654 1655 if (getLexer().isNot(AsmToken::Integer)) 1656 return true; 1657 if (getParser().parseAbsoluteExpression(Offset)) 1658 return true; 1659 1660 if (getLexer().isNot(AsmToken::Comma)) 1661 return true; 1662 Parser.Lex(); 1663 1664 if (getLexer().isNot(AsmToken::Integer)) 1665 return true; 1666 if (getParser().parseAbsoluteExpression(Width)) 1667 return true; 1668 1669 if (getLexer().isNot(AsmToken::RParen)) 1670 return true; 1671 Parser.Lex(); 1672 1673 return false; 1674 } 1675 1676 AMDGPUAsmParser::OperandMatchResultTy 1677 AMDGPUAsmParser::parseHwregOp(OperandVector &Operands) { 1678 int64_t Imm16Val = 0; 1679 SMLoc S = Parser.getTok().getLoc(); 1680 1681 switch(getLexer().getKind()) { 1682 default: return MatchOperand_ParseFail; 1683 case AsmToken::Integer: 1684 // The operand can be an integer value. 1685 if (getParser().parseAbsoluteExpression(Imm16Val)) 1686 return MatchOperand_ParseFail; 1687 if (!isInt<16>(Imm16Val) && !isUInt<16>(Imm16Val)) { 1688 Error(S, "invalid immediate: only 16-bit values are legal"); 1689 // Do not return error code, but create an imm operand anyway and proceed 1690 // to the next operand, if any. That avoids unneccessary error messages. 1691 } 1692 break; 1693 1694 case AsmToken::Identifier: { 1695 bool IsIdentifier = false; 1696 int64_t HwRegCode = -1; 1697 int64_t Offset = 0; // default 1698 int64_t Width = 32; // default 1699 if (parseHwreg(HwRegCode, Offset, Width, IsIdentifier)) 1700 return MatchOperand_ParseFail; 1701 // HwRegCode (6) [5:0] 1702 // Offset (5) [10:6] 1703 // WidthMinusOne (5) [15:11] 1704 if (HwRegCode < 0 || HwRegCode > 63) { 1705 if (IsIdentifier) 1706 Error(S, "invalid symbolic name of hardware register"); 1707 else 1708 Error(S, "invalid code of hardware register: only 6-bit values are legal"); 1709 } 1710 if (Offset < 0 || Offset > 31) 1711 Error(S, "invalid bit offset: only 5-bit values are legal"); 1712 if (Width < 1 || Width > 32) 1713 Error(S, "invalid bitfield width: only values from 1 to 32 are legal"); 1714 Imm16Val = HwRegCode | (Offset << 6) | ((Width-1) << 11); 1715 } 1716 break; 1717 } 1718 Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg)); 1719 return MatchOperand_Success; 1720 } 1721 1722 bool AMDGPUOperand::isSWaitCnt() const { 1723 return isImm(); 1724 } 1725 1726 bool AMDGPUOperand::isHwreg() const { 1727 return isImmTy(ImmTyHwreg); 1728 } 1729 1730 //===----------------------------------------------------------------------===// 1731 // sopp branch targets 1732 //===----------------------------------------------------------------------===// 1733 1734 AMDGPUAsmParser::OperandMatchResultTy 1735 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 1736 SMLoc S = Parser.getTok().getLoc(); 1737 1738 switch (getLexer().getKind()) { 1739 default: return MatchOperand_ParseFail; 1740 case AsmToken::Integer: { 1741 int64_t Imm; 1742 if (getParser().parseAbsoluteExpression(Imm)) 1743 return MatchOperand_ParseFail; 1744 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S)); 1745 return MatchOperand_Success; 1746 } 1747 1748 case AsmToken::Identifier: 1749 Operands.push_back(AMDGPUOperand::CreateExpr( 1750 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 1751 Parser.getTok().getString()), getContext()), S)); 1752 Parser.Lex(); 1753 return MatchOperand_Success; 1754 } 1755 } 1756 1757 //===----------------------------------------------------------------------===// 1758 // flat 1759 //===----------------------------------------------------------------------===// 1760 1761 static const OptionalOperand FlatOptionalOps [] = { 1762 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1763 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1764 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1765 }; 1766 1767 static const OptionalOperand FlatAtomicOptionalOps [] = { 1768 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1769 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1770 }; 1771 1772 AMDGPUAsmParser::OperandMatchResultTy 1773 AMDGPUAsmParser::parseFlatOptionalOps(OperandVector &Operands) { 1774 return parseOptionalOps(FlatOptionalOps, Operands); 1775 } 1776 1777 AMDGPUAsmParser::OperandMatchResultTy 1778 AMDGPUAsmParser::parseFlatAtomicOptionalOps(OperandVector &Operands) { 1779 return parseOptionalOps(FlatAtomicOptionalOps, Operands); 1780 } 1781 1782 void AMDGPUAsmParser::cvtFlat(MCInst &Inst, 1783 const OperandVector &Operands) { 1784 OptionalImmIndexMap OptionalIdx; 1785 1786 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1787 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1788 1789 // Add the register arguments 1790 if (Op.isReg()) { 1791 Op.addRegOperands(Inst, 1); 1792 continue; 1793 } 1794 1795 OptionalIdx[Op.getImmTy()] = i; 1796 } 1797 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 1798 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1799 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1800 } 1801 1802 1803 void AMDGPUAsmParser::cvtFlatAtomic(MCInst &Inst, 1804 const OperandVector &Operands) { 1805 OptionalImmIndexMap OptionalIdx; 1806 1807 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1808 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1809 1810 // Add the register arguments 1811 if (Op.isReg()) { 1812 Op.addRegOperands(Inst, 1); 1813 continue; 1814 } 1815 1816 // Handle 'glc' token for flat atomics. 1817 if (Op.isToken()) { 1818 continue; 1819 } 1820 1821 // Handle optional arguments 1822 OptionalIdx[Op.getImmTy()] = i; 1823 } 1824 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1825 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1826 } 1827 1828 //===----------------------------------------------------------------------===// 1829 // mubuf 1830 //===----------------------------------------------------------------------===// 1831 1832 static const OptionalOperand MubufOptionalOps [] = { 1833 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1834 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1835 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1836 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1837 }; 1838 1839 AMDGPUAsmParser::OperandMatchResultTy 1840 AMDGPUAsmParser::parseMubufOptionalOps(OperandVector &Operands) { 1841 return parseOptionalOps(MubufOptionalOps, Operands); 1842 } 1843 1844 AMDGPUAsmParser::OperandMatchResultTy 1845 AMDGPUAsmParser::parseOffset(OperandVector &Operands) { 1846 return parseIntWithPrefix("offset", Operands); 1847 } 1848 1849 AMDGPUAsmParser::OperandMatchResultTy 1850 AMDGPUAsmParser::parseGLC(OperandVector &Operands) { 1851 return parseNamedBit("glc", Operands); 1852 } 1853 1854 AMDGPUAsmParser::OperandMatchResultTy 1855 AMDGPUAsmParser::parseSLC(OperandVector &Operands) { 1856 return parseNamedBit("slc", Operands); 1857 } 1858 1859 AMDGPUAsmParser::OperandMatchResultTy 1860 AMDGPUAsmParser::parseTFE(OperandVector &Operands) { 1861 return parseNamedBit("tfe", Operands); 1862 } 1863 1864 bool AMDGPUOperand::isMubufOffset() const { 1865 return isImmTy(ImmTyOffset) && isUInt<12>(getImm()); 1866 } 1867 1868 void AMDGPUAsmParser::cvtMubuf(MCInst &Inst, 1869 const OperandVector &Operands) { 1870 OptionalImmIndexMap OptionalIdx; 1871 1872 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1873 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1874 1875 // Add the register arguments 1876 if (Op.isReg()) { 1877 Op.addRegOperands(Inst, 1); 1878 continue; 1879 } 1880 1881 // Handle the case where soffset is an immediate 1882 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 1883 Op.addImmOperands(Inst, 1); 1884 continue; 1885 } 1886 1887 // Handle tokens like 'offen' which are sometimes hard-coded into the 1888 // asm string. There are no MCInst operands for these. 1889 if (Op.isToken()) { 1890 continue; 1891 } 1892 assert(Op.isImm()); 1893 1894 // Handle optional arguments 1895 OptionalIdx[Op.getImmTy()] = i; 1896 } 1897 1898 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 1899 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 1900 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1901 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1902 } 1903 1904 //===----------------------------------------------------------------------===// 1905 // mimg 1906 //===----------------------------------------------------------------------===// 1907 1908 AMDGPUAsmParser::OperandMatchResultTy 1909 AMDGPUAsmParser::parseDMask(OperandVector &Operands) { 1910 return parseIntWithPrefix("dmask", Operands, AMDGPUOperand::ImmTyDMask); 1911 } 1912 1913 AMDGPUAsmParser::OperandMatchResultTy 1914 AMDGPUAsmParser::parseUNorm(OperandVector &Operands) { 1915 return parseNamedBit("unorm", Operands, AMDGPUOperand::ImmTyUNorm); 1916 } 1917 1918 AMDGPUAsmParser::OperandMatchResultTy 1919 AMDGPUAsmParser::parseDA(OperandVector &Operands) { 1920 return parseNamedBit("da", Operands, AMDGPUOperand::ImmTyDA); 1921 } 1922 1923 AMDGPUAsmParser::OperandMatchResultTy 1924 AMDGPUAsmParser::parseR128(OperandVector &Operands) { 1925 return parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128); 1926 } 1927 1928 AMDGPUAsmParser::OperandMatchResultTy 1929 AMDGPUAsmParser::parseLWE(OperandVector &Operands) { 1930 return parseNamedBit("lwe", Operands, AMDGPUOperand::ImmTyLWE); 1931 } 1932 1933 //===----------------------------------------------------------------------===// 1934 // smrd 1935 //===----------------------------------------------------------------------===// 1936 1937 bool AMDGPUOperand::isSMRDOffset() const { 1938 1939 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget 1940 // information here. 1941 return isImm() && isUInt<8>(getImm()); 1942 } 1943 1944 bool AMDGPUOperand::isSMRDLiteralOffset() const { 1945 // 32-bit literals are only supported on CI and we only want to use them 1946 // when the offset is > 8-bits. 1947 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 1948 } 1949 1950 //===----------------------------------------------------------------------===// 1951 // vop3 1952 //===----------------------------------------------------------------------===// 1953 1954 static bool ConvertOmodMul(int64_t &Mul) { 1955 if (Mul != 1 && Mul != 2 && Mul != 4) 1956 return false; 1957 1958 Mul >>= 1; 1959 return true; 1960 } 1961 1962 static bool ConvertOmodDiv(int64_t &Div) { 1963 if (Div == 1) { 1964 Div = 0; 1965 return true; 1966 } 1967 1968 if (Div == 2) { 1969 Div = 3; 1970 return true; 1971 } 1972 1973 return false; 1974 } 1975 1976 static const OptionalOperand VOP3OptionalOps [] = { 1977 {"clamp", AMDGPUOperand::ImmTyClamp, true, 0, nullptr}, 1978 {"mul", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodMul}, 1979 {"div", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodDiv}, 1980 }; 1981 1982 static bool isVOP3(OperandVector &Operands) { 1983 if (operandsHaveModifiers(Operands)) 1984 return true; 1985 1986 if (Operands.size() >= 2) { 1987 AMDGPUOperand &DstOp = ((AMDGPUOperand&)*Operands[1]); 1988 1989 if (DstOp.isRegClass(AMDGPU::SGPR_64RegClassID)) 1990 return true; 1991 } 1992 1993 if (Operands.size() >= 5) 1994 return true; 1995 1996 if (Operands.size() > 3) { 1997 AMDGPUOperand &Src1Op = ((AMDGPUOperand&)*Operands[3]); 1998 if (Src1Op.isRegClass(AMDGPU::SReg_32RegClassID) || 1999 Src1Op.isRegClass(AMDGPU::SReg_64RegClassID)) 2000 return true; 2001 } 2002 return false; 2003 } 2004 2005 AMDGPUAsmParser::OperandMatchResultTy 2006 AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) { 2007 2008 // The value returned by this function may change after parsing 2009 // an operand so store the original value here. 2010 bool HasModifiers = operandsHaveModifiers(Operands); 2011 2012 bool IsVOP3 = isVOP3(Operands); 2013 if (HasModifiers || IsVOP3 || 2014 getLexer().isNot(AsmToken::EndOfStatement) || 2015 getForcedEncodingSize() == 64) { 2016 2017 AMDGPUAsmParser::OperandMatchResultTy Res = 2018 parseOptionalOps(VOP3OptionalOps, Operands); 2019 2020 if (!HasModifiers && Res == MatchOperand_Success) { 2021 // We have added a modifier operation, so we need to make sure all 2022 // previous register operands have modifiers 2023 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 2024 AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 2025 if ((Op.isReg() || Op.isImm()) && !Op.hasModifiers()) 2026 Op.setModifiers(0); 2027 } 2028 } 2029 return Res; 2030 } 2031 return MatchOperand_NoMatch; 2032 } 2033 2034 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) { 2035 unsigned I = 1; 2036 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2037 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2038 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2039 } 2040 for (unsigned E = Operands.size(); I != E; ++I) 2041 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1); 2042 } 2043 2044 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) { 2045 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 2046 if (TSFlags & SIInstrFlags::VOP3) { 2047 cvtVOP3(Inst, Operands); 2048 } else { 2049 cvtId(Inst, Operands); 2050 } 2051 } 2052 2053 void AMDGPUAsmParser::cvtVOP3_2_nomod(MCInst &Inst, const OperandVector &Operands) { 2054 if (operandsHaveModifiers(Operands)) { 2055 cvtVOP3(Inst, Operands); 2056 } else { 2057 cvtId(Inst, Operands); 2058 } 2059 } 2060 2061 void AMDGPUAsmParser::cvtVOP3_only(MCInst &Inst, const OperandVector &Operands) { 2062 cvtVOP3(Inst, Operands); 2063 } 2064 2065 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 2066 OptionalImmIndexMap OptionalIdx; 2067 unsigned I = 1; 2068 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2069 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2070 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2071 } 2072 2073 for (unsigned E = Operands.size(); I != E; ++I) { 2074 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2075 if (Op.isRegOrImmWithInputMods()) { 2076 Op.addRegOrImmWithInputModsOperands(Inst, 2); 2077 } else if (Op.isImm()) { 2078 OptionalIdx[Op.getImmTy()] = I; 2079 } else { 2080 assert(false); 2081 } 2082 } 2083 2084 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClamp); 2085 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOMod); 2086 } 2087 2088 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) { 2089 unsigned I = 1; 2090 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2091 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2092 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2093 } 2094 2095 OptionalImmIndexMap OptionalIdx; 2096 2097 for (unsigned E = Operands.size(); I != E; ++I) { 2098 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2099 2100 // Add the register arguments 2101 if (Op.isRegOrImm()) { 2102 Op.addRegOrImmOperands(Inst, 1); 2103 continue; 2104 } else if (Op.isImmModifier()) { 2105 OptionalIdx[Op.getImmTy()] = I; 2106 } else { 2107 assert(false); 2108 } 2109 } 2110 2111 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 2112 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 2113 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 2114 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 2115 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 2116 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 2117 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 2118 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 2119 } 2120 2121 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) { 2122 unsigned I = 1; 2123 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2124 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2125 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2126 } 2127 2128 // Add src, same as dst 2129 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1); 2130 2131 OptionalImmIndexMap OptionalIdx; 2132 2133 for (unsigned E = Operands.size(); I != E; ++I) { 2134 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2135 2136 // Add the register arguments 2137 if (Op.isRegOrImm()) { 2138 Op.addRegOrImmOperands(Inst, 1); 2139 continue; 2140 } else if (Op.isImmModifier()) { 2141 OptionalIdx[Op.getImmTy()] = I; 2142 } else { 2143 assert(false); 2144 } 2145 } 2146 2147 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 2148 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 2149 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 2150 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 2151 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 2152 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 2153 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 2154 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 2155 } 2156 2157 //===----------------------------------------------------------------------===// 2158 // dpp 2159 //===----------------------------------------------------------------------===// 2160 2161 bool AMDGPUOperand::isDPPCtrl() const { 2162 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 2163 if (result) { 2164 int64_t Imm = getImm(); 2165 return ((Imm >= 0x000) && (Imm <= 0x0ff)) || 2166 ((Imm >= 0x101) && (Imm <= 0x10f)) || 2167 ((Imm >= 0x111) && (Imm <= 0x11f)) || 2168 ((Imm >= 0x121) && (Imm <= 0x12f)) || 2169 (Imm == 0x130) || 2170 (Imm == 0x134) || 2171 (Imm == 0x138) || 2172 (Imm == 0x13c) || 2173 (Imm == 0x140) || 2174 (Imm == 0x141) || 2175 (Imm == 0x142) || 2176 (Imm == 0x143); 2177 } 2178 return false; 2179 } 2180 2181 AMDGPUAsmParser::OperandMatchResultTy 2182 AMDGPUAsmParser::parseDPPCtrlOps(OperandVector &Operands) { 2183 SMLoc S = Parser.getTok().getLoc(); 2184 StringRef Prefix; 2185 int64_t Int; 2186 2187 if (getLexer().getKind() == AsmToken::Identifier) { 2188 Prefix = Parser.getTok().getString(); 2189 } else { 2190 return MatchOperand_NoMatch; 2191 } 2192 2193 if (Prefix == "row_mirror") { 2194 Int = 0x140; 2195 } else if (Prefix == "row_half_mirror") { 2196 Int = 0x141; 2197 } else { 2198 // Check to prevent parseDPPCtrlOps from eating invalid tokens 2199 if (Prefix != "quad_perm" 2200 && Prefix != "row_shl" 2201 && Prefix != "row_shr" 2202 && Prefix != "row_ror" 2203 && Prefix != "wave_shl" 2204 && Prefix != "wave_rol" 2205 && Prefix != "wave_shr" 2206 && Prefix != "wave_ror" 2207 && Prefix != "row_bcast") { 2208 return MatchOperand_NoMatch; 2209 } 2210 2211 Parser.Lex(); 2212 if (getLexer().isNot(AsmToken::Colon)) 2213 return MatchOperand_ParseFail; 2214 2215 if (Prefix == "quad_perm") { 2216 // quad_perm:[%d,%d,%d,%d] 2217 Parser.Lex(); 2218 if (getLexer().isNot(AsmToken::LBrac)) 2219 return MatchOperand_ParseFail; 2220 2221 Parser.Lex(); 2222 if (getLexer().isNot(AsmToken::Integer)) 2223 return MatchOperand_ParseFail; 2224 Int = getLexer().getTok().getIntVal(); 2225 2226 Parser.Lex(); 2227 if (getLexer().isNot(AsmToken::Comma)) 2228 return MatchOperand_ParseFail; 2229 Parser.Lex(); 2230 if (getLexer().isNot(AsmToken::Integer)) 2231 return MatchOperand_ParseFail; 2232 Int += (getLexer().getTok().getIntVal() << 2); 2233 2234 Parser.Lex(); 2235 if (getLexer().isNot(AsmToken::Comma)) 2236 return MatchOperand_ParseFail; 2237 Parser.Lex(); 2238 if (getLexer().isNot(AsmToken::Integer)) 2239 return MatchOperand_ParseFail; 2240 Int += (getLexer().getTok().getIntVal() << 4); 2241 2242 Parser.Lex(); 2243 if (getLexer().isNot(AsmToken::Comma)) 2244 return MatchOperand_ParseFail; 2245 Parser.Lex(); 2246 if (getLexer().isNot(AsmToken::Integer)) 2247 return MatchOperand_ParseFail; 2248 Int += (getLexer().getTok().getIntVal() << 6); 2249 2250 Parser.Lex(); 2251 if (getLexer().isNot(AsmToken::RBrac)) 2252 return MatchOperand_ParseFail; 2253 2254 } else { 2255 // sel:%d 2256 Parser.Lex(); 2257 if (getLexer().isNot(AsmToken::Integer)) 2258 return MatchOperand_ParseFail; 2259 Int = getLexer().getTok().getIntVal(); 2260 2261 if (Prefix == "row_shl") { 2262 Int |= 0x100; 2263 } else if (Prefix == "row_shr") { 2264 Int |= 0x110; 2265 } else if (Prefix == "row_ror") { 2266 Int |= 0x120; 2267 } else if (Prefix == "wave_shl") { 2268 Int = 0x130; 2269 } else if (Prefix == "wave_rol") { 2270 Int = 0x134; 2271 } else if (Prefix == "wave_shr") { 2272 Int = 0x138; 2273 } else if (Prefix == "wave_ror") { 2274 Int = 0x13C; 2275 } else if (Prefix == "row_bcast") { 2276 if (Int == 15) { 2277 Int = 0x142; 2278 } else if (Int == 31) { 2279 Int = 0x143; 2280 } 2281 } else { 2282 return MatchOperand_ParseFail; 2283 } 2284 } 2285 } 2286 Parser.Lex(); // eat last token 2287 2288 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2289 AMDGPUOperand::ImmTyDppCtrl)); 2290 return MatchOperand_Success; 2291 } 2292 2293 static const OptionalOperand DPPOptionalOps [] = { 2294 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, 0xf, nullptr}, 2295 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, 0xf, nullptr}, 2296 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, -1, nullptr} 2297 }; 2298 2299 AMDGPUAsmParser::OperandMatchResultTy 2300 AMDGPUAsmParser::parseDPPOptionalOps(OperandVector &Operands) { 2301 SMLoc S = Parser.getTok().getLoc(); 2302 OperandMatchResultTy Res = parseOptionalOps(DPPOptionalOps, Operands); 2303 // XXX - sp3 use syntax "bound_ctrl:0" to indicate that bound_ctrl bit was set 2304 if (Res == MatchOperand_Success) { 2305 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands.back()); 2306 // If last operand was parsed as bound_ctrl we should replace it with correct value (1) 2307 if (Op.isImmTy(AMDGPUOperand::ImmTyDppBoundCtrl)) { 2308 Operands.pop_back(); 2309 Operands.push_back( 2310 AMDGPUOperand::CreateImm(1, S, AMDGPUOperand::ImmTyDppBoundCtrl)); 2311 return MatchOperand_Success; 2312 } 2313 } 2314 return Res; 2315 } 2316 2317 void AMDGPUAsmParser::cvtDPP_mod(MCInst &Inst, const OperandVector &Operands) { 2318 cvtDPP(Inst, Operands, true); 2319 } 2320 2321 void AMDGPUAsmParser::cvtDPP_nomod(MCInst &Inst, const OperandVector &Operands) { 2322 cvtDPP(Inst, Operands, false); 2323 } 2324 2325 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, 2326 bool HasMods) { 2327 OptionalImmIndexMap OptionalIdx; 2328 2329 unsigned I = 1; 2330 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2331 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2332 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2333 } 2334 2335 for (unsigned E = Operands.size(); I != E; ++I) { 2336 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2337 // Add the register arguments 2338 if (!HasMods && Op.isReg()) { 2339 Op.addRegOperands(Inst, 1); 2340 } else if (HasMods && Op.isRegOrImmWithInputMods()) { 2341 Op.addRegOrImmWithInputModsOperands(Inst, 2); 2342 } else if (Op.isDPPCtrl()) { 2343 Op.addImmOperands(Inst, 1); 2344 } else if (Op.isImm()) { 2345 // Handle optional arguments 2346 OptionalIdx[Op.getImmTy()] = I; 2347 } else { 2348 llvm_unreachable("Invalid operand type"); 2349 } 2350 } 2351 2352 // ToDo: fix default values for row_mask and bank_mask 2353 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 2354 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 2355 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 2356 } 2357 2358 //===----------------------------------------------------------------------===// 2359 // sdwa 2360 //===----------------------------------------------------------------------===// 2361 2362 AMDGPUAsmParser::OperandMatchResultTy 2363 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands) { 2364 SMLoc S = Parser.getTok().getLoc(); 2365 StringRef Value; 2366 AMDGPUAsmParser::OperandMatchResultTy res; 2367 2368 res = parseStringWithPrefix("dst_sel", Value); 2369 if (res == MatchOperand_ParseFail) { 2370 return MatchOperand_ParseFail; 2371 } else if (res == MatchOperand_NoMatch) { 2372 res = parseStringWithPrefix("src0_sel", Value); 2373 if (res == MatchOperand_ParseFail) { 2374 return MatchOperand_ParseFail; 2375 } else if (res == MatchOperand_NoMatch) { 2376 res = parseStringWithPrefix("src1_sel", Value); 2377 if (res != MatchOperand_Success) { 2378 return res; 2379 } 2380 } 2381 } 2382 2383 int64_t Int; 2384 Int = StringSwitch<int64_t>(Value) 2385 .Case("BYTE_0", 0) 2386 .Case("BYTE_1", 1) 2387 .Case("BYTE_2", 2) 2388 .Case("BYTE_3", 3) 2389 .Case("WORD_0", 4) 2390 .Case("WORD_1", 5) 2391 .Case("DWORD", 6) 2392 .Default(0xffffffff); 2393 Parser.Lex(); // eat last token 2394 2395 if (Int == 0xffffffff) { 2396 return MatchOperand_ParseFail; 2397 } 2398 2399 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2400 AMDGPUOperand::ImmTySdwaSel)); 2401 return MatchOperand_Success; 2402 } 2403 2404 AMDGPUAsmParser::OperandMatchResultTy 2405 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 2406 SMLoc S = Parser.getTok().getLoc(); 2407 StringRef Value; 2408 AMDGPUAsmParser::OperandMatchResultTy res; 2409 2410 res = parseStringWithPrefix("dst_unused", Value); 2411 if (res != MatchOperand_Success) { 2412 return res; 2413 } 2414 2415 int64_t Int; 2416 Int = StringSwitch<int64_t>(Value) 2417 .Case("UNUSED_PAD", 0) 2418 .Case("UNUSED_SEXT", 1) 2419 .Case("UNUSED_PRESERVE", 2) 2420 .Default(0xffffffff); 2421 Parser.Lex(); // eat last token 2422 2423 if (Int == 0xffffffff) { 2424 return MatchOperand_ParseFail; 2425 } 2426 2427 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2428 AMDGPUOperand::ImmTySdwaDstUnused)); 2429 return MatchOperand_Success; 2430 } 2431 2432 2433 /// Force static initialization. 2434 extern "C" void LLVMInitializeAMDGPUAsmParser() { 2435 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget); 2436 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget); 2437 } 2438 2439 #define GET_REGISTER_MATCHER 2440 #define GET_MATCHER_IMPLEMENTATION 2441 #include "AMDGPUGenAsmMatcher.inc" 2442