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