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