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