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/APInt.h" 19 #include "llvm/ADT/SmallBitVector.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/ADT/STLExtras.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/ADT/StringSwitch.h" 24 #include "llvm/ADT/Twine.h" 25 #include "llvm/CodeGen/MachineValueType.h" 26 #include "llvm/MC/MCAsmInfo.h" 27 #include "llvm/MC/MCContext.h" 28 #include "llvm/MC/MCExpr.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/MC/MCInstrDesc.h" 31 #include "llvm/MC/MCInstrInfo.h" 32 #include "llvm/MC/MCParser/MCAsmLexer.h" 33 #include "llvm/MC/MCParser/MCAsmParser.h" 34 #include "llvm/MC/MCParser/MCAsmParserExtension.h" 35 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 36 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 37 #include "llvm/MC/MCRegisterInfo.h" 38 #include "llvm/MC/MCStreamer.h" 39 #include "llvm/MC/MCSubtargetInfo.h" 40 #include "llvm/MC/MCSymbol.h" 41 #include "llvm/Support/Casting.h" 42 #include "llvm/Support/Debug.h" 43 #include "llvm/Support/ELF.h" 44 #include "llvm/Support/ErrorHandling.h" 45 #include "llvm/Support/MathExtras.h" 46 #include "llvm/Support/raw_ostream.h" 47 #include "llvm/Support/SMLoc.h" 48 #include "llvm/Support/TargetRegistry.h" 49 #include "llvm/Support/raw_ostream.h" 50 #include "llvm/Support/MathExtras.h" 51 #include <algorithm> 52 #include <cassert> 53 #include <cstdint> 54 #include <cstring> 55 #include <iterator> 56 #include <map> 57 #include <memory> 58 #include <string> 59 #include <vector> 60 61 using namespace llvm; 62 using namespace llvm::AMDGPU; 63 64 namespace { 65 66 class AMDGPUAsmParser; 67 68 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL }; 69 70 //===----------------------------------------------------------------------===// 71 // Operand 72 //===----------------------------------------------------------------------===// 73 74 class AMDGPUOperand : public MCParsedAsmOperand { 75 enum KindTy { 76 Token, 77 Immediate, 78 Register, 79 Expression 80 } Kind; 81 82 SMLoc StartLoc, EndLoc; 83 const AMDGPUAsmParser *AsmParser; 84 85 public: 86 AMDGPUOperand(enum KindTy Kind_, const AMDGPUAsmParser *AsmParser_) 87 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {} 88 89 typedef std::unique_ptr<AMDGPUOperand> Ptr; 90 91 struct Modifiers { 92 bool Abs = false; 93 bool Neg = false; 94 bool Sext = false; 95 96 bool hasFPModifiers() const { return Abs || Neg; } 97 bool hasIntModifiers() const { return Sext; } 98 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); } 99 100 int64_t getFPModifiersOperand() const { 101 int64_t Operand = 0; 102 Operand |= Abs ? SISrcMods::ABS : 0; 103 Operand |= Neg ? SISrcMods::NEG : 0; 104 return Operand; 105 } 106 107 int64_t getIntModifiersOperand() const { 108 int64_t Operand = 0; 109 Operand |= Sext ? SISrcMods::SEXT : 0; 110 return Operand; 111 } 112 113 int64_t getModifiersOperand() const { 114 assert(!(hasFPModifiers() && hasIntModifiers()) 115 && "fp and int modifiers should not be used simultaneously"); 116 if (hasFPModifiers()) { 117 return getFPModifiersOperand(); 118 } else if (hasIntModifiers()) { 119 return getIntModifiersOperand(); 120 } else { 121 return 0; 122 } 123 } 124 125 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods); 126 }; 127 128 enum ImmTy { 129 ImmTyNone, 130 ImmTyGDS, 131 ImmTyOffen, 132 ImmTyIdxen, 133 ImmTyAddr64, 134 ImmTyOffset, 135 ImmTyOffset0, 136 ImmTyOffset1, 137 ImmTyGLC, 138 ImmTySLC, 139 ImmTyTFE, 140 ImmTyClampSI, 141 ImmTyOModSI, 142 ImmTyDppCtrl, 143 ImmTyDppRowMask, 144 ImmTyDppBankMask, 145 ImmTyDppBoundCtrl, 146 ImmTySdwaDstSel, 147 ImmTySdwaSrc0Sel, 148 ImmTySdwaSrc1Sel, 149 ImmTySdwaDstUnused, 150 ImmTyDMask, 151 ImmTyUNorm, 152 ImmTyDA, 153 ImmTyR128, 154 ImmTyLWE, 155 ImmTyExpTgt, 156 ImmTyExpCompr, 157 ImmTyExpVM, 158 ImmTyHwreg, 159 ImmTyOff, 160 ImmTySendMsg, 161 ImmTyInterpSlot, 162 ImmTyInterpAttr, 163 ImmTyAttrChan 164 }; 165 166 struct TokOp { 167 const char *Data; 168 unsigned Length; 169 }; 170 171 struct ImmOp { 172 int64_t Val; 173 ImmTy Type; 174 bool IsFPImm; 175 Modifiers Mods; 176 }; 177 178 struct RegOp { 179 unsigned RegNo; 180 bool IsForcedVOP3; 181 Modifiers Mods; 182 }; 183 184 union { 185 TokOp Tok; 186 ImmOp Imm; 187 RegOp Reg; 188 const MCExpr *Expr; 189 }; 190 191 bool isToken() const override { 192 if (Kind == Token) 193 return true; 194 195 if (Kind != Expression || !Expr) 196 return false; 197 198 // When parsing operands, we can't always tell if something was meant to be 199 // a token, like 'gds', or an expression that references a global variable. 200 // In this case, we assume the string is an expression, and if we need to 201 // interpret is a token, then we treat the symbol name as the token. 202 return isa<MCSymbolRefExpr>(Expr); 203 } 204 205 bool isImm() const override { 206 return Kind == Immediate; 207 } 208 209 bool isInlinableImm(MVT type) const; 210 bool isLiteralImm(MVT type) const; 211 212 bool isRegKind() const { 213 return Kind == Register; 214 } 215 216 bool isReg() const override { 217 return isRegKind() && !hasModifiers(); 218 } 219 220 bool isRegOrImmWithInputMods(MVT type) const { 221 return isRegKind() || isInlinableImm(type); 222 } 223 224 bool isRegOrImmWithInt16InputMods() const { 225 return isRegOrImmWithInputMods(MVT::i16); 226 } 227 228 bool isRegOrImmWithInt32InputMods() const { 229 return isRegOrImmWithInputMods(MVT::i32); 230 } 231 232 bool isRegOrImmWithInt64InputMods() const { 233 return isRegOrImmWithInputMods(MVT::i64); 234 } 235 236 bool isRegOrImmWithFP16InputMods() const { 237 return isRegOrImmWithInputMods(MVT::f16); 238 } 239 240 bool isRegOrImmWithFP32InputMods() const { 241 return isRegOrImmWithInputMods(MVT::f32); 242 } 243 244 bool isRegOrImmWithFP64InputMods() const { 245 return isRegOrImmWithInputMods(MVT::f64); 246 } 247 248 bool isVReg() const { 249 return isRegClass(AMDGPU::VGPR_32RegClassID) || 250 isRegClass(AMDGPU::VReg_64RegClassID) || 251 isRegClass(AMDGPU::VReg_96RegClassID) || 252 isRegClass(AMDGPU::VReg_128RegClassID) || 253 isRegClass(AMDGPU::VReg_256RegClassID) || 254 isRegClass(AMDGPU::VReg_512RegClassID); 255 } 256 257 bool isVReg32OrOff() const { 258 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID); 259 } 260 261 bool isImmTy(ImmTy ImmT) const { 262 return isImm() && Imm.Type == ImmT; 263 } 264 265 bool isImmModifier() const { 266 return isImm() && Imm.Type != ImmTyNone; 267 } 268 269 bool isClampSI() const { return isImmTy(ImmTyClampSI); } 270 bool isOModSI() const { return isImmTy(ImmTyOModSI); } 271 bool isDMask() const { return isImmTy(ImmTyDMask); } 272 bool isUNorm() const { return isImmTy(ImmTyUNorm); } 273 bool isDA() const { return isImmTy(ImmTyDA); } 274 bool isR128() const { return isImmTy(ImmTyUNorm); } 275 bool isLWE() const { return isImmTy(ImmTyLWE); } 276 bool isOff() const { return isImmTy(ImmTyOff); } 277 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); } 278 bool isExpVM() const { return isImmTy(ImmTyExpVM); } 279 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); } 280 bool isOffen() const { return isImmTy(ImmTyOffen); } 281 bool isIdxen() const { return isImmTy(ImmTyIdxen); } 282 bool isAddr64() const { return isImmTy(ImmTyAddr64); } 283 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); } 284 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); } 285 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } 286 bool isGDS() const { return isImmTy(ImmTyGDS); } 287 bool isGLC() const { return isImmTy(ImmTyGLC); } 288 bool isSLC() const { return isImmTy(ImmTySLC); } 289 bool isTFE() const { return isImmTy(ImmTyTFE); } 290 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); } 291 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); } 292 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); } 293 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); } 294 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); } 295 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); } 296 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); } 297 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); } 298 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); } 299 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); } 300 301 bool isMod() const { 302 return isClampSI() || isOModSI(); 303 } 304 305 bool isRegOrImm() const { 306 return isReg() || isImm(); 307 } 308 309 bool isRegClass(unsigned RCID) const; 310 311 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const { 312 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers(); 313 } 314 315 bool isSCSrcB16() const { 316 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16); 317 } 318 319 bool isSCSrcB32() const { 320 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32); 321 } 322 323 bool isSCSrcB64() const { 324 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64); 325 } 326 327 bool isSCSrcF16() const { 328 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16); 329 } 330 331 bool isSCSrcF32() const { 332 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32); 333 } 334 335 bool isSCSrcF64() const { 336 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64); 337 } 338 339 bool isSSrcB32() const { 340 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr(); 341 } 342 343 bool isSSrcB16() const { 344 return isSCSrcB16() || isLiteralImm(MVT::i16); 345 } 346 347 bool isSSrcB64() const { 348 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 349 // See isVSrc64(). 350 return isSCSrcB64() || isLiteralImm(MVT::i64); 351 } 352 353 bool isSSrcF32() const { 354 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr(); 355 } 356 357 bool isSSrcF64() const { 358 return isSCSrcB64() || isLiteralImm(MVT::f64); 359 } 360 361 bool isSSrcF16() const { 362 return isSCSrcB16() || isLiteralImm(MVT::f16); 363 } 364 365 bool isVCSrcB32() const { 366 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32); 367 } 368 369 bool isVCSrcB64() const { 370 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64); 371 } 372 373 bool isVCSrcB16() const { 374 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16); 375 } 376 377 bool isVCSrcF32() const { 378 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32); 379 } 380 381 bool isVCSrcF64() const { 382 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64); 383 } 384 385 bool isVCSrcF16() const { 386 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16); 387 } 388 389 bool isVSrcB32() const { 390 return isVCSrcF32() || isLiteralImm(MVT::i32); 391 } 392 393 bool isVSrcB64() const { 394 return isVCSrcF64() || isLiteralImm(MVT::i64); 395 } 396 397 bool isVSrcB16() const { 398 return isVCSrcF16() || isLiteralImm(MVT::i16); 399 } 400 401 bool isVSrcF32() const { 402 return isVCSrcF32() || isLiteralImm(MVT::f32); 403 } 404 405 bool isVSrcF64() const { 406 return isVCSrcF64() || isLiteralImm(MVT::f64); 407 } 408 409 bool isVSrcF16() const { 410 return isVCSrcF16() || isLiteralImm(MVT::f16); 411 } 412 413 bool isKImmFP32() const { 414 return isLiteralImm(MVT::f32); 415 } 416 417 bool isKImmFP16() const { 418 return isLiteralImm(MVT::f16); 419 } 420 421 bool isMem() const override { 422 return false; 423 } 424 425 bool isExpr() const { 426 return Kind == Expression; 427 } 428 429 bool isSoppBrTarget() const { 430 return isExpr() || isImm(); 431 } 432 433 bool isSWaitCnt() const; 434 bool isHwreg() const; 435 bool isSendMsg() const; 436 bool isSMRDOffset8() const; 437 bool isSMRDOffset20() const; 438 bool isSMRDLiteralOffset() const; 439 bool isDPPCtrl() const; 440 bool isGPRIdxMode() const; 441 442 StringRef getExpressionAsToken() const { 443 assert(isExpr()); 444 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr); 445 return S->getSymbol().getName(); 446 } 447 448 StringRef getToken() const { 449 assert(isToken()); 450 451 if (Kind == Expression) 452 return getExpressionAsToken(); 453 454 return StringRef(Tok.Data, Tok.Length); 455 } 456 457 int64_t getImm() const { 458 assert(isImm()); 459 return Imm.Val; 460 } 461 462 enum ImmTy getImmTy() const { 463 assert(isImm()); 464 return Imm.Type; 465 } 466 467 unsigned getReg() const override { 468 return Reg.RegNo; 469 } 470 471 SMLoc getStartLoc() const override { 472 return StartLoc; 473 } 474 475 SMLoc getEndLoc() const override { 476 return EndLoc; 477 } 478 479 Modifiers getModifiers() const { 480 assert(isRegKind() || isImmTy(ImmTyNone)); 481 return isRegKind() ? Reg.Mods : Imm.Mods; 482 } 483 484 void setModifiers(Modifiers Mods) { 485 assert(isRegKind() || isImmTy(ImmTyNone)); 486 if (isRegKind()) 487 Reg.Mods = Mods; 488 else 489 Imm.Mods = Mods; 490 } 491 492 bool hasModifiers() const { 493 return getModifiers().hasModifiers(); 494 } 495 496 bool hasFPModifiers() const { 497 return getModifiers().hasFPModifiers(); 498 } 499 500 bool hasIntModifiers() const { 501 return getModifiers().hasIntModifiers(); 502 } 503 504 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const; 505 506 void addLiteralImmOperand(MCInst &Inst, int64_t Val) const; 507 508 template <unsigned Bitwidth> 509 void addKImmFPOperands(MCInst &Inst, unsigned N) const; 510 511 void addKImmFP16Operands(MCInst &Inst, unsigned N) const { 512 addKImmFPOperands<16>(Inst, N); 513 } 514 515 void addKImmFP32Operands(MCInst &Inst, unsigned N) const { 516 addKImmFPOperands<32>(Inst, N); 517 } 518 519 void addRegOperands(MCInst &Inst, unsigned N) const; 520 521 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 522 if (isRegKind()) 523 addRegOperands(Inst, N); 524 else if (isExpr()) 525 Inst.addOperand(MCOperand::createExpr(Expr)); 526 else 527 addImmOperands(Inst, N); 528 } 529 530 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 531 Modifiers Mods = getModifiers(); 532 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 533 if (isRegKind()) { 534 addRegOperands(Inst, N); 535 } else { 536 addImmOperands(Inst, N, false); 537 } 538 } 539 540 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 541 assert(!hasIntModifiers()); 542 addRegOrImmWithInputModsOperands(Inst, N); 543 } 544 545 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 546 assert(!hasFPModifiers()); 547 addRegOrImmWithInputModsOperands(Inst, N); 548 } 549 550 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 551 Modifiers Mods = getModifiers(); 552 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 553 assert(isRegKind()); 554 addRegOperands(Inst, N); 555 } 556 557 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 558 assert(!hasIntModifiers()); 559 addRegWithInputModsOperands(Inst, N); 560 } 561 562 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 563 assert(!hasFPModifiers()); 564 addRegWithInputModsOperands(Inst, N); 565 } 566 567 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 568 if (isImm()) 569 addImmOperands(Inst, N); 570 else { 571 assert(isExpr()); 572 Inst.addOperand(MCOperand::createExpr(Expr)); 573 } 574 } 575 576 static void printImmTy(raw_ostream& OS, ImmTy Type) { 577 switch (Type) { 578 case ImmTyNone: OS << "None"; break; 579 case ImmTyGDS: OS << "GDS"; break; 580 case ImmTyOffen: OS << "Offen"; break; 581 case ImmTyIdxen: OS << "Idxen"; break; 582 case ImmTyAddr64: OS << "Addr64"; break; 583 case ImmTyOffset: OS << "Offset"; break; 584 case ImmTyOffset0: OS << "Offset0"; break; 585 case ImmTyOffset1: OS << "Offset1"; break; 586 case ImmTyGLC: OS << "GLC"; break; 587 case ImmTySLC: OS << "SLC"; break; 588 case ImmTyTFE: OS << "TFE"; break; 589 case ImmTyClampSI: OS << "ClampSI"; break; 590 case ImmTyOModSI: OS << "OModSI"; break; 591 case ImmTyDppCtrl: OS << "DppCtrl"; break; 592 case ImmTyDppRowMask: OS << "DppRowMask"; break; 593 case ImmTyDppBankMask: OS << "DppBankMask"; break; 594 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break; 595 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break; 596 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break; 597 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break; 598 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break; 599 case ImmTyDMask: OS << "DMask"; break; 600 case ImmTyUNorm: OS << "UNorm"; break; 601 case ImmTyDA: OS << "DA"; break; 602 case ImmTyR128: OS << "R128"; break; 603 case ImmTyLWE: OS << "LWE"; break; 604 case ImmTyOff: OS << "Off"; break; 605 case ImmTyExpTgt: OS << "ExpTgt"; break; 606 case ImmTyExpCompr: OS << "ExpCompr"; break; 607 case ImmTyExpVM: OS << "ExpVM"; break; 608 case ImmTyHwreg: OS << "Hwreg"; break; 609 case ImmTySendMsg: OS << "SendMsg"; break; 610 case ImmTyInterpSlot: OS << "InterpSlot"; break; 611 case ImmTyInterpAttr: OS << "InterpAttr"; break; 612 case ImmTyAttrChan: OS << "AttrChan"; break; 613 } 614 } 615 616 void print(raw_ostream &OS) const override { 617 switch (Kind) { 618 case Register: 619 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>'; 620 break; 621 case Immediate: 622 OS << '<' << getImm(); 623 if (getImmTy() != ImmTyNone) { 624 OS << " type: "; printImmTy(OS, getImmTy()); 625 } 626 OS << " mods: " << Imm.Mods << '>'; 627 break; 628 case Token: 629 OS << '\'' << getToken() << '\''; 630 break; 631 case Expression: 632 OS << "<expr " << *Expr << '>'; 633 break; 634 } 635 } 636 637 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser, 638 int64_t Val, SMLoc Loc, 639 enum ImmTy Type = ImmTyNone, 640 bool IsFPImm = false) { 641 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser); 642 Op->Imm.Val = Val; 643 Op->Imm.IsFPImm = IsFPImm; 644 Op->Imm.Type = Type; 645 Op->Imm.Mods = Modifiers(); 646 Op->StartLoc = Loc; 647 Op->EndLoc = Loc; 648 return Op; 649 } 650 651 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser, 652 StringRef Str, SMLoc Loc, 653 bool HasExplicitEncodingSize = true) { 654 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser); 655 Res->Tok.Data = Str.data(); 656 Res->Tok.Length = Str.size(); 657 Res->StartLoc = Loc; 658 Res->EndLoc = Loc; 659 return Res; 660 } 661 662 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser, 663 unsigned RegNo, SMLoc S, 664 SMLoc E, 665 bool ForceVOP3) { 666 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser); 667 Op->Reg.RegNo = RegNo; 668 Op->Reg.Mods = Modifiers(); 669 Op->Reg.IsForcedVOP3 = ForceVOP3; 670 Op->StartLoc = S; 671 Op->EndLoc = E; 672 return Op; 673 } 674 675 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser, 676 const class MCExpr *Expr, SMLoc S) { 677 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser); 678 Op->Expr = Expr; 679 Op->StartLoc = S; 680 Op->EndLoc = S; 681 return Op; 682 } 683 }; 684 685 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { 686 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; 687 return OS; 688 } 689 690 //===----------------------------------------------------------------------===// 691 // AsmParser 692 //===----------------------------------------------------------------------===// 693 694 // Holds info related to the current kernel, e.g. count of SGPRs used. 695 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next 696 // .amdgpu_hsa_kernel or at EOF. 697 class KernelScopeInfo { 698 int SgprIndexUnusedMin; 699 int VgprIndexUnusedMin; 700 MCContext *Ctx; 701 702 void usesSgprAt(int i) { 703 if (i >= SgprIndexUnusedMin) { 704 SgprIndexUnusedMin = ++i; 705 if (Ctx) { 706 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count")); 707 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx)); 708 } 709 } 710 } 711 void usesVgprAt(int i) { 712 if (i >= VgprIndexUnusedMin) { 713 VgprIndexUnusedMin = ++i; 714 if (Ctx) { 715 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 716 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx)); 717 } 718 } 719 } 720 public: 721 KernelScopeInfo() : SgprIndexUnusedMin(-1), VgprIndexUnusedMin(-1), Ctx(nullptr) 722 {} 723 void initialize(MCContext &Context) { 724 Ctx = &Context; 725 usesSgprAt(SgprIndexUnusedMin = -1); 726 usesVgprAt(VgprIndexUnusedMin = -1); 727 } 728 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) { 729 switch (RegKind) { 730 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break; 731 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break; 732 default: break; 733 } 734 } 735 }; 736 737 class AMDGPUAsmParser : public MCTargetAsmParser { 738 const MCInstrInfo &MII; 739 MCAsmParser &Parser; 740 741 unsigned ForcedEncodingSize; 742 bool ForcedDPP; 743 bool ForcedSDWA; 744 KernelScopeInfo KernelScope; 745 746 /// @name Auto-generated Match Functions 747 /// { 748 749 #define GET_ASSEMBLER_HEADER 750 #include "AMDGPUGenAsmMatcher.inc" 751 752 /// } 753 754 private: 755 bool ParseAsAbsoluteExpression(uint32_t &Ret); 756 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 757 bool ParseDirectiveHSACodeObjectVersion(); 758 bool ParseDirectiveHSACodeObjectISA(); 759 bool ParseDirectiveRuntimeMetadata(); 760 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 761 bool ParseDirectiveAMDKernelCodeT(); 762 bool ParseSectionDirectiveHSAText(); 763 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; 764 bool ParseDirectiveAMDGPUHsaKernel(); 765 bool ParseDirectiveAMDGPUHsaModuleGlobal(); 766 bool ParseDirectiveAMDGPUHsaProgramGlobal(); 767 bool ParseSectionDirectiveHSADataGlobalAgent(); 768 bool ParseSectionDirectiveHSADataGlobalProgram(); 769 bool ParseSectionDirectiveHSARodataReadonlyAgent(); 770 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum); 771 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex); 772 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn); 773 774 public: 775 enum AMDGPUMatchResultTy { 776 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 777 }; 778 779 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 780 const MCInstrInfo &MII, 781 const MCTargetOptions &Options) 782 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser), 783 ForcedEncodingSize(0), 784 ForcedDPP(false), 785 ForcedSDWA(false) { 786 MCAsmParserExtension::Initialize(Parser); 787 788 if (getSTI().getFeatureBits().none()) { 789 // Set default features. 790 copySTI().ToggleFeature("SOUTHERN_ISLANDS"); 791 } 792 793 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); 794 795 { 796 // TODO: make those pre-defined variables read-only. 797 // Currently there is none suitable machinery in the core llvm-mc for this. 798 // MCSymbol::isRedefinable is intended for another purpose, and 799 // AsmParser::parseDirectiveSet() cannot be specialized for specific target. 800 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits()); 801 MCContext &Ctx = getContext(); 802 MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major")); 803 Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx)); 804 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor")); 805 Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx)); 806 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping")); 807 Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx)); 808 } 809 KernelScope.initialize(getContext()); 810 } 811 812 bool isSI() const { 813 return AMDGPU::isSI(getSTI()); 814 } 815 816 bool isCI() const { 817 return AMDGPU::isCI(getSTI()); 818 } 819 820 bool isVI() const { 821 return AMDGPU::isVI(getSTI()); 822 } 823 824 bool hasInv2PiInlineImm() const { 825 return getSTI().getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; 826 } 827 828 bool hasSGPR102_SGPR103() const { 829 return !isVI(); 830 } 831 832 AMDGPUTargetStreamer &getTargetStreamer() { 833 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 834 return static_cast<AMDGPUTargetStreamer &>(TS); 835 } 836 837 const MCRegisterInfo *getMRI() const { 838 // We need this const_cast because for some reason getContext() is not const 839 // in MCAsmParser. 840 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo(); 841 } 842 843 const MCInstrInfo *getMII() const { 844 return &MII; 845 } 846 847 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; } 848 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; } 849 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; } 850 851 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; } 852 bool isForcedVOP3() const { return ForcedEncodingSize == 64; } 853 bool isForcedDPP() const { return ForcedDPP; } 854 bool isForcedSDWA() const { return ForcedSDWA; } 855 ArrayRef<unsigned> getMatchedVariants() const; 856 857 std::unique_ptr<AMDGPUOperand> parseRegister(); 858 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 859 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 860 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 861 unsigned Kind) override; 862 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 863 OperandVector &Operands, MCStreamer &Out, 864 uint64_t &ErrorInfo, 865 bool MatchingInlineAsm) override; 866 bool ParseDirective(AsmToken DirectiveID) override; 867 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); 868 StringRef parseMnemonicSuffix(StringRef Name); 869 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 870 SMLoc NameLoc, OperandVector &Operands) override; 871 //bool ProcessInstruction(MCInst &Inst); 872 873 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int); 874 OperandMatchResultTy 875 parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 876 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 877 bool (*ConvertResult)(int64_t &) = nullptr); 878 OperandMatchResultTy 879 parseNamedBit(const char *Name, OperandVector &Operands, 880 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone); 881 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, 882 StringRef &Value); 883 884 OperandMatchResultTy parseImm(OperandVector &Operands); 885 OperandMatchResultTy parseReg(OperandVector &Operands); 886 OperandMatchResultTy parseRegOrImm(OperandVector &Operands); 887 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true); 888 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true); 889 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands); 890 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands); 891 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands); 892 893 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 894 void cvtDS(MCInst &Inst, const OperandVector &Operands); 895 void cvtExp(MCInst &Inst, const OperandVector &Operands); 896 897 bool parseCnt(int64_t &IntVal); 898 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 899 OperandMatchResultTy parseHwreg(OperandVector &Operands); 900 901 private: 902 struct OperandInfoTy { 903 int64_t Id; 904 bool IsSymbolic; 905 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { } 906 }; 907 908 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId); 909 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width); 910 911 void errorExpTgt(); 912 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); 913 914 public: 915 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); 916 917 OperandMatchResultTy parseExpTgt(OperandVector &Operands); 918 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); 919 OperandMatchResultTy parseInterpSlot(OperandVector &Operands); 920 OperandMatchResultTy parseInterpAttr(OperandVector &Operands); 921 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 922 923 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); } 924 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); } 925 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); } 926 AMDGPUOperand::Ptr defaultGLC() const; 927 AMDGPUOperand::Ptr defaultSLC() const; 928 AMDGPUOperand::Ptr defaultTFE() const; 929 930 AMDGPUOperand::Ptr defaultDMask() const; 931 AMDGPUOperand::Ptr defaultUNorm() const; 932 AMDGPUOperand::Ptr defaultDA() const; 933 AMDGPUOperand::Ptr defaultR128() const; 934 AMDGPUOperand::Ptr defaultLWE() const; 935 AMDGPUOperand::Ptr defaultSMRDOffset8() const; 936 AMDGPUOperand::Ptr defaultSMRDOffset20() const; 937 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const; 938 939 OperandMatchResultTy parseOModOperand(OperandVector &Operands); 940 941 void cvtId(MCInst &Inst, const OperandVector &Operands); 942 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands); 943 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 944 945 void cvtMIMG(MCInst &Inst, const OperandVector &Operands); 946 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands); 947 948 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands); 949 AMDGPUOperand::Ptr defaultRowMask() const; 950 AMDGPUOperand::Ptr defaultBankMask() const; 951 AMDGPUOperand::Ptr defaultBoundCtrl() const; 952 void cvtDPP(MCInst &Inst, const OperandVector &Operands); 953 954 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix, 955 AMDGPUOperand::ImmTy Type); 956 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); 957 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); 958 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); 959 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); 960 void cvtSDWA(MCInst &Inst, const OperandVector &Operands, 961 uint64_t BasicInstType); 962 }; 963 964 struct OptionalOperand { 965 const char *Name; 966 AMDGPUOperand::ImmTy Type; 967 bool IsBit; 968 bool (*ConvertResult)(int64_t&); 969 }; 970 971 } // end anonymous namespace 972 973 // May be called with integer type with equivalent bitwidth. 974 static const fltSemantics *getFltSemantics(unsigned Size) { 975 switch (Size) { 976 case 4: 977 return &APFloat::IEEEsingle(); 978 case 8: 979 return &APFloat::IEEEdouble(); 980 case 2: 981 return &APFloat::IEEEhalf(); 982 default: 983 llvm_unreachable("unsupported fp type"); 984 } 985 } 986 987 static const fltSemantics *getFltSemantics(MVT VT) { 988 return getFltSemantics(VT.getSizeInBits() / 8); 989 } 990 991 //===----------------------------------------------------------------------===// 992 // Operand 993 //===----------------------------------------------------------------------===// 994 995 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) { 996 bool Lost; 997 998 // Convert literal to single precision 999 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT), 1000 APFloat::rmNearestTiesToEven, 1001 &Lost); 1002 // We allow precision lost but not overflow or underflow 1003 if (Status != APFloat::opOK && 1004 Lost && 1005 ((Status & APFloat::opOverflow) != 0 || 1006 (Status & APFloat::opUnderflow) != 0)) { 1007 return false; 1008 } 1009 1010 return true; 1011 } 1012 1013 bool AMDGPUOperand::isInlinableImm(MVT type) const { 1014 if (!isImmTy(ImmTyNone)) { 1015 // Only plain immediates are inlinable (e.g. "clamp" attribute is not) 1016 return false; 1017 } 1018 // TODO: We should avoid using host float here. It would be better to 1019 // check the float bit values which is what a few other places do. 1020 // We've had bot failures before due to weird NaN support on mips hosts. 1021 1022 APInt Literal(64, Imm.Val); 1023 1024 if (Imm.IsFPImm) { // We got fp literal token 1025 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1026 return AMDGPU::isInlinableLiteral64(Imm.Val, 1027 AsmParser->hasInv2PiInlineImm()); 1028 } 1029 1030 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1031 if (!canLosslesslyConvertToFPType(FPLiteral, type)) 1032 return false; 1033 1034 // Check if single precision literal is inlinable 1035 return AMDGPU::isInlinableLiteral32( 1036 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1037 AsmParser->hasInv2PiInlineImm()); 1038 } 1039 1040 1041 // We got int literal token. 1042 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1043 return AMDGPU::isInlinableLiteral64(Imm.Val, 1044 AsmParser->hasInv2PiInlineImm()); 1045 } 1046 1047 if (type.getScalarSizeInBits() == 16) { 1048 return AMDGPU::isInlinableLiteral16( 1049 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), 1050 AsmParser->hasInv2PiInlineImm()); 1051 } 1052 1053 return AMDGPU::isInlinableLiteral32( 1054 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()), 1055 AsmParser->hasInv2PiInlineImm()); 1056 } 1057 1058 bool AMDGPUOperand::isLiteralImm(MVT type) const { 1059 // Check that this imediate can be added as literal 1060 if (!isImmTy(ImmTyNone)) { 1061 return false; 1062 } 1063 1064 if (!Imm.IsFPImm) { 1065 // We got int literal token. 1066 1067 unsigned Size = type.getSizeInBits(); 1068 if (Size == 64) 1069 Size = 32; 1070 1071 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP 1072 // types. 1073 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val); 1074 } 1075 1076 // We got fp literal token 1077 if (type == MVT::f64) { // Expected 64-bit fp operand 1078 // We would set low 64-bits of literal to zeroes but we accept this literals 1079 return true; 1080 } 1081 1082 if (type == MVT::i64) { // Expected 64-bit int operand 1083 // We don't allow fp literals in 64-bit integer instructions. It is 1084 // unclear how we should encode them. 1085 return false; 1086 } 1087 1088 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1089 return canLosslesslyConvertToFPType(FPLiteral, type); 1090 } 1091 1092 bool AMDGPUOperand::isRegClass(unsigned RCID) const { 1093 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg()); 1094 } 1095 1096 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const { 1097 int64_t Val = Imm.Val; 1098 if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers() && Imm.Mods.Neg) { 1099 // Apply modifiers to immediate value. Only negate can get here 1100 if (Imm.IsFPImm) { 1101 APFloat F(BitsToDouble(Val)); 1102 F.changeSign(); 1103 Val = F.bitcastToAPInt().getZExtValue(); 1104 } else { 1105 Val = -Val; 1106 } 1107 } 1108 1109 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()), 1110 Inst.getNumOperands())) { 1111 addLiteralImmOperand(Inst, Val); 1112 } else { 1113 Inst.addOperand(MCOperand::createImm(Val)); 1114 } 1115 } 1116 1117 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val) const { 1118 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode()); 1119 auto OpNum = Inst.getNumOperands(); 1120 // Check that this operand accepts literals 1121 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum)); 1122 1123 auto OpSize = AMDGPU::getOperandSize(InstDesc, OpNum); // expected operand size 1124 1125 if (Imm.IsFPImm) { // We got fp literal token 1126 APInt Literal(64, Val); 1127 1128 switch (OpSize) { 1129 case 8: { 1130 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(), 1131 AsmParser->hasInv2PiInlineImm())) { 1132 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue())); 1133 return; 1134 } 1135 1136 // Non-inlineable 1137 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand 1138 // For fp operands we check if low 32 bits are zeros 1139 if (Literal.getLoBits(32) != 0) { 1140 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(), 1141 "Can't encode literal as exact 64-bit floating-point operand. " 1142 "Low 32-bits will be set to zero"); 1143 } 1144 1145 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue())); 1146 return; 1147 } 1148 1149 // We don't allow fp literals in 64-bit integer instructions. It is 1150 // unclear how we should encode them. This case should be checked earlier 1151 // in predicate methods (isLiteralImm()) 1152 llvm_unreachable("fp literal in 64-bit integer instruction."); 1153 } 1154 case 4: 1155 case 2: { 1156 bool lost; 1157 APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1158 // Convert literal to single precision 1159 FPLiteral.convert(*getFltSemantics(OpSize), 1160 APFloat::rmNearestTiesToEven, &lost); 1161 // We allow precision lost but not overflow or underflow. This should be 1162 // checked earlier in isLiteralImm() 1163 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue())); 1164 return; 1165 } 1166 default: 1167 llvm_unreachable("invalid operand size"); 1168 } 1169 1170 return; 1171 } 1172 1173 // We got int literal token. 1174 // Only sign extend inline immediates. 1175 // FIXME: No errors on truncation 1176 switch (OpSize) { 1177 case 4: { 1178 if (isInt<32>(Val) && 1179 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val), 1180 AsmParser->hasInv2PiInlineImm())) { 1181 Inst.addOperand(MCOperand::createImm(Val)); 1182 return; 1183 } 1184 1185 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff)); 1186 return; 1187 } 1188 case 8: { 1189 if (AMDGPU::isInlinableLiteral64(Val, 1190 AsmParser->hasInv2PiInlineImm())) { 1191 Inst.addOperand(MCOperand::createImm(Val)); 1192 return; 1193 } 1194 1195 Inst.addOperand(MCOperand::createImm(Lo_32(Val))); 1196 return; 1197 } 1198 case 2: { 1199 if (isInt<16>(Val) && 1200 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 1201 AsmParser->hasInv2PiInlineImm())) { 1202 Inst.addOperand(MCOperand::createImm(Val)); 1203 return; 1204 } 1205 1206 Inst.addOperand(MCOperand::createImm(Val & 0xffff)); 1207 return; 1208 } 1209 default: 1210 llvm_unreachable("invalid operand size"); 1211 } 1212 } 1213 1214 template <unsigned Bitwidth> 1215 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const { 1216 APInt Literal(64, Imm.Val); 1217 1218 if (!Imm.IsFPImm) { 1219 // We got int literal token. 1220 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue())); 1221 return; 1222 } 1223 1224 bool Lost; 1225 APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1226 FPLiteral.convert(*getFltSemantics(Bitwidth / 8), 1227 APFloat::rmNearestTiesToEven, &Lost); 1228 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue())); 1229 } 1230 1231 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const { 1232 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI()))); 1233 } 1234 1235 //===----------------------------------------------------------------------===// 1236 // AsmParser 1237 //===----------------------------------------------------------------------===// 1238 1239 static int getRegClass(RegisterKind Is, unsigned RegWidth) { 1240 if (Is == IS_VGPR) { 1241 switch (RegWidth) { 1242 default: return -1; 1243 case 1: return AMDGPU::VGPR_32RegClassID; 1244 case 2: return AMDGPU::VReg_64RegClassID; 1245 case 3: return AMDGPU::VReg_96RegClassID; 1246 case 4: return AMDGPU::VReg_128RegClassID; 1247 case 8: return AMDGPU::VReg_256RegClassID; 1248 case 16: return AMDGPU::VReg_512RegClassID; 1249 } 1250 } else if (Is == IS_TTMP) { 1251 switch (RegWidth) { 1252 default: return -1; 1253 case 1: return AMDGPU::TTMP_32RegClassID; 1254 case 2: return AMDGPU::TTMP_64RegClassID; 1255 case 4: return AMDGPU::TTMP_128RegClassID; 1256 } 1257 } else if (Is == IS_SGPR) { 1258 switch (RegWidth) { 1259 default: return -1; 1260 case 1: return AMDGPU::SGPR_32RegClassID; 1261 case 2: return AMDGPU::SGPR_64RegClassID; 1262 case 4: return AMDGPU::SGPR_128RegClassID; 1263 case 8: return AMDGPU::SReg_256RegClassID; 1264 case 16: return AMDGPU::SReg_512RegClassID; 1265 } 1266 } 1267 return -1; 1268 } 1269 1270 static unsigned getSpecialRegForName(StringRef RegName) { 1271 return StringSwitch<unsigned>(RegName) 1272 .Case("exec", AMDGPU::EXEC) 1273 .Case("vcc", AMDGPU::VCC) 1274 .Case("flat_scratch", AMDGPU::FLAT_SCR) 1275 .Case("m0", AMDGPU::M0) 1276 .Case("scc", AMDGPU::SCC) 1277 .Case("tba", AMDGPU::TBA) 1278 .Case("tma", AMDGPU::TMA) 1279 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 1280 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 1281 .Case("vcc_lo", AMDGPU::VCC_LO) 1282 .Case("vcc_hi", AMDGPU::VCC_HI) 1283 .Case("exec_lo", AMDGPU::EXEC_LO) 1284 .Case("exec_hi", AMDGPU::EXEC_HI) 1285 .Case("tma_lo", AMDGPU::TMA_LO) 1286 .Case("tma_hi", AMDGPU::TMA_HI) 1287 .Case("tba_lo", AMDGPU::TBA_LO) 1288 .Case("tba_hi", AMDGPU::TBA_HI) 1289 .Default(0); 1290 } 1291 1292 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { 1293 auto R = parseRegister(); 1294 if (!R) return true; 1295 assert(R->isReg()); 1296 RegNo = R->getReg(); 1297 StartLoc = R->getStartLoc(); 1298 EndLoc = R->getEndLoc(); 1299 return false; 1300 } 1301 1302 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum) 1303 { 1304 switch (RegKind) { 1305 case IS_SPECIAL: 1306 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; } 1307 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; } 1308 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; } 1309 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; } 1310 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; } 1311 return false; 1312 case IS_VGPR: 1313 case IS_SGPR: 1314 case IS_TTMP: 1315 if (Reg1 != Reg + RegWidth) { return false; } 1316 RegWidth++; 1317 return true; 1318 default: 1319 llvm_unreachable("unexpected register kind"); 1320 } 1321 } 1322 1323 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex) 1324 { 1325 if (DwordRegIndex) { *DwordRegIndex = 0; } 1326 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 1327 if (getLexer().is(AsmToken::Identifier)) { 1328 StringRef RegName = Parser.getTok().getString(); 1329 if ((Reg = getSpecialRegForName(RegName))) { 1330 Parser.Lex(); 1331 RegKind = IS_SPECIAL; 1332 } else { 1333 unsigned RegNumIndex = 0; 1334 if (RegName[0] == 'v') { 1335 RegNumIndex = 1; 1336 RegKind = IS_VGPR; 1337 } else if (RegName[0] == 's') { 1338 RegNumIndex = 1; 1339 RegKind = IS_SGPR; 1340 } else if (RegName.startswith("ttmp")) { 1341 RegNumIndex = strlen("ttmp"); 1342 RegKind = IS_TTMP; 1343 } else { 1344 return false; 1345 } 1346 if (RegName.size() > RegNumIndex) { 1347 // Single 32-bit register: vXX. 1348 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum)) 1349 return false; 1350 Parser.Lex(); 1351 RegWidth = 1; 1352 } else { 1353 // Range of registers: v[XX:YY]. ":YY" is optional. 1354 Parser.Lex(); 1355 int64_t RegLo, RegHi; 1356 if (getLexer().isNot(AsmToken::LBrac)) 1357 return false; 1358 Parser.Lex(); 1359 1360 if (getParser().parseAbsoluteExpression(RegLo)) 1361 return false; 1362 1363 const bool isRBrace = getLexer().is(AsmToken::RBrac); 1364 if (!isRBrace && getLexer().isNot(AsmToken::Colon)) 1365 return false; 1366 Parser.Lex(); 1367 1368 if (isRBrace) { 1369 RegHi = RegLo; 1370 } else { 1371 if (getParser().parseAbsoluteExpression(RegHi)) 1372 return false; 1373 1374 if (getLexer().isNot(AsmToken::RBrac)) 1375 return false; 1376 Parser.Lex(); 1377 } 1378 RegNum = (unsigned) RegLo; 1379 RegWidth = (RegHi - RegLo) + 1; 1380 } 1381 } 1382 } else if (getLexer().is(AsmToken::LBrac)) { 1383 // List of consecutive registers: [s0,s1,s2,s3] 1384 Parser.Lex(); 1385 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr)) 1386 return false; 1387 if (RegWidth != 1) 1388 return false; 1389 RegisterKind RegKind1; 1390 unsigned Reg1, RegNum1, RegWidth1; 1391 do { 1392 if (getLexer().is(AsmToken::Comma)) { 1393 Parser.Lex(); 1394 } else if (getLexer().is(AsmToken::RBrac)) { 1395 Parser.Lex(); 1396 break; 1397 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) { 1398 if (RegWidth1 != 1) { 1399 return false; 1400 } 1401 if (RegKind1 != RegKind) { 1402 return false; 1403 } 1404 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) { 1405 return false; 1406 } 1407 } else { 1408 return false; 1409 } 1410 } while (true); 1411 } else { 1412 return false; 1413 } 1414 switch (RegKind) { 1415 case IS_SPECIAL: 1416 RegNum = 0; 1417 RegWidth = 1; 1418 break; 1419 case IS_VGPR: 1420 case IS_SGPR: 1421 case IS_TTMP: 1422 { 1423 unsigned Size = 1; 1424 if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 1425 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords. 1426 Size = std::min(RegWidth, 4u); 1427 } 1428 if (RegNum % Size != 0) 1429 return false; 1430 if (DwordRegIndex) { *DwordRegIndex = RegNum; } 1431 RegNum = RegNum / Size; 1432 int RCID = getRegClass(RegKind, RegWidth); 1433 if (RCID == -1) 1434 return false; 1435 const MCRegisterClass RC = TRI->getRegClass(RCID); 1436 if (RegNum >= RC.getNumRegs()) 1437 return false; 1438 Reg = RC.getRegister(RegNum); 1439 break; 1440 } 1441 1442 default: 1443 llvm_unreachable("unexpected register kind"); 1444 } 1445 1446 if (!subtargetHasRegister(*TRI, Reg)) 1447 return false; 1448 return true; 1449 } 1450 1451 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() { 1452 const auto &Tok = Parser.getTok(); 1453 SMLoc StartLoc = Tok.getLoc(); 1454 SMLoc EndLoc = Tok.getEndLoc(); 1455 RegisterKind RegKind; 1456 unsigned Reg, RegNum, RegWidth, DwordRegIndex; 1457 1458 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) { 1459 return nullptr; 1460 } 1461 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth); 1462 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false); 1463 } 1464 1465 OperandMatchResultTy 1466 AMDGPUAsmParser::parseImm(OperandVector &Operands) { 1467 // TODO: add syntactic sugar for 1/(2*PI) 1468 bool Minus = false; 1469 if (getLexer().getKind() == AsmToken::Minus) { 1470 Minus = true; 1471 Parser.Lex(); 1472 } 1473 1474 SMLoc S = Parser.getTok().getLoc(); 1475 switch(getLexer().getKind()) { 1476 case AsmToken::Integer: { 1477 int64_t IntVal; 1478 if (getParser().parseAbsoluteExpression(IntVal)) 1479 return MatchOperand_ParseFail; 1480 if (Minus) 1481 IntVal *= -1; 1482 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 1483 return MatchOperand_Success; 1484 } 1485 case AsmToken::Real: { 1486 int64_t IntVal; 1487 if (getParser().parseAbsoluteExpression(IntVal)) 1488 return MatchOperand_ParseFail; 1489 1490 APFloat F(BitsToDouble(IntVal)); 1491 if (Minus) 1492 F.changeSign(); 1493 Operands.push_back( 1494 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S, 1495 AMDGPUOperand::ImmTyNone, true)); 1496 return MatchOperand_Success; 1497 } 1498 default: 1499 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch; 1500 } 1501 } 1502 1503 OperandMatchResultTy 1504 AMDGPUAsmParser::parseReg(OperandVector &Operands) { 1505 if (auto R = parseRegister()) { 1506 assert(R->isReg()); 1507 R->Reg.IsForcedVOP3 = isForcedVOP3(); 1508 Operands.push_back(std::move(R)); 1509 return MatchOperand_Success; 1510 } 1511 return MatchOperand_NoMatch; 1512 } 1513 1514 OperandMatchResultTy 1515 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) { 1516 auto res = parseImm(Operands); 1517 if (res != MatchOperand_NoMatch) { 1518 return res; 1519 } 1520 1521 return parseReg(Operands); 1522 } 1523 1524 OperandMatchResultTy 1525 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm) { 1526 // XXX: During parsing we can't determine if minus sign means 1527 // negate-modifier or negative immediate value. 1528 // By default we suppose it is modifier. 1529 bool Negate = false, Abs = false, Abs2 = false; 1530 1531 if (getLexer().getKind()== AsmToken::Minus) { 1532 Parser.Lex(); 1533 Negate = true; 1534 } 1535 1536 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") { 1537 Parser.Lex(); 1538 Abs2 = true; 1539 if (getLexer().isNot(AsmToken::LParen)) { 1540 Error(Parser.getTok().getLoc(), "expected left paren after abs"); 1541 return MatchOperand_ParseFail; 1542 } 1543 Parser.Lex(); 1544 } 1545 1546 if (getLexer().getKind() == AsmToken::Pipe) { 1547 if (Abs2) { 1548 Error(Parser.getTok().getLoc(), "expected register or immediate"); 1549 return MatchOperand_ParseFail; 1550 } 1551 Parser.Lex(); 1552 Abs = true; 1553 } 1554 1555 OperandMatchResultTy Res; 1556 if (AllowImm) { 1557 Res = parseRegOrImm(Operands); 1558 } else { 1559 Res = parseReg(Operands); 1560 } 1561 if (Res != MatchOperand_Success) { 1562 return Res; 1563 } 1564 1565 AMDGPUOperand::Modifiers Mods; 1566 if (Negate) { 1567 Mods.Neg = true; 1568 } 1569 if (Abs) { 1570 if (getLexer().getKind() != AsmToken::Pipe) { 1571 Error(Parser.getTok().getLoc(), "expected vertical bar"); 1572 return MatchOperand_ParseFail; 1573 } 1574 Parser.Lex(); 1575 Mods.Abs = true; 1576 } 1577 if (Abs2) { 1578 if (getLexer().isNot(AsmToken::RParen)) { 1579 Error(Parser.getTok().getLoc(), "expected closing parentheses"); 1580 return MatchOperand_ParseFail; 1581 } 1582 Parser.Lex(); 1583 Mods.Abs = true; 1584 } 1585 1586 if (Mods.hasFPModifiers()) { 1587 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 1588 Op.setModifiers(Mods); 1589 } 1590 return MatchOperand_Success; 1591 } 1592 1593 OperandMatchResultTy 1594 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm) { 1595 bool Sext = false; 1596 1597 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") { 1598 Parser.Lex(); 1599 Sext = true; 1600 if (getLexer().isNot(AsmToken::LParen)) { 1601 Error(Parser.getTok().getLoc(), "expected left paren after sext"); 1602 return MatchOperand_ParseFail; 1603 } 1604 Parser.Lex(); 1605 } 1606 1607 OperandMatchResultTy Res; 1608 if (AllowImm) { 1609 Res = parseRegOrImm(Operands); 1610 } else { 1611 Res = parseReg(Operands); 1612 } 1613 if (Res != MatchOperand_Success) { 1614 return Res; 1615 } 1616 1617 AMDGPUOperand::Modifiers Mods; 1618 if (Sext) { 1619 if (getLexer().isNot(AsmToken::RParen)) { 1620 Error(Parser.getTok().getLoc(), "expected closing parentheses"); 1621 return MatchOperand_ParseFail; 1622 } 1623 Parser.Lex(); 1624 Mods.Sext = true; 1625 } 1626 1627 if (Mods.hasIntModifiers()) { 1628 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 1629 Op.setModifiers(Mods); 1630 } 1631 1632 return MatchOperand_Success; 1633 } 1634 1635 OperandMatchResultTy 1636 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) { 1637 return parseRegOrImmWithFPInputMods(Operands, false); 1638 } 1639 1640 OperandMatchResultTy 1641 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) { 1642 return parseRegOrImmWithIntInputMods(Operands, false); 1643 } 1644 1645 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) { 1646 std::unique_ptr<AMDGPUOperand> Reg = parseRegister(); 1647 if (Reg) { 1648 Operands.push_back(std::move(Reg)); 1649 return MatchOperand_Success; 1650 } 1651 1652 const AsmToken &Tok = Parser.getTok(); 1653 if (Tok.getString() == "off") { 1654 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(), 1655 AMDGPUOperand::ImmTyOff, false)); 1656 Parser.Lex(); 1657 return MatchOperand_Success; 1658 } 1659 1660 return MatchOperand_NoMatch; 1661 } 1662 1663 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 1664 1665 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 1666 1667 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 1668 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) || 1669 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) || 1670 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) ) 1671 return Match_InvalidOperand; 1672 1673 if ((TSFlags & SIInstrFlags::VOP3) && 1674 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 1675 getForcedEncodingSize() != 64) 1676 return Match_PreferE32; 1677 1678 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 1679 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 1680 // v_mac_f32/16 allow only dst_sel == DWORD; 1681 auto OpNum = 1682 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel); 1683 const auto &Op = Inst.getOperand(OpNum); 1684 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) { 1685 return Match_InvalidOperand; 1686 } 1687 } 1688 1689 return Match_Success; 1690 } 1691 1692 // What asm variants we should check 1693 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const { 1694 if (getForcedEncodingSize() == 32) { 1695 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT}; 1696 return makeArrayRef(Variants); 1697 } 1698 1699 if (isForcedVOP3()) { 1700 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; 1701 return makeArrayRef(Variants); 1702 } 1703 1704 if (isForcedSDWA()) { 1705 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA}; 1706 return makeArrayRef(Variants); 1707 } 1708 1709 if (isForcedDPP()) { 1710 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; 1711 return makeArrayRef(Variants); 1712 } 1713 1714 static const unsigned Variants[] = { 1715 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, 1716 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::DPP 1717 }; 1718 1719 return makeArrayRef(Variants); 1720 } 1721 1722 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1723 OperandVector &Operands, 1724 MCStreamer &Out, 1725 uint64_t &ErrorInfo, 1726 bool MatchingInlineAsm) { 1727 MCInst Inst; 1728 unsigned Result = Match_Success; 1729 for (auto Variant : getMatchedVariants()) { 1730 uint64_t EI; 1731 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, 1732 Variant); 1733 // We order match statuses from least to most specific. We use most specific 1734 // status as resulting 1735 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 1736 if ((R == Match_Success) || 1737 (R == Match_PreferE32) || 1738 (R == Match_MissingFeature && Result != Match_PreferE32) || 1739 (R == Match_InvalidOperand && Result != Match_MissingFeature 1740 && Result != Match_PreferE32) || 1741 (R == Match_MnemonicFail && Result != Match_InvalidOperand 1742 && Result != Match_MissingFeature 1743 && Result != Match_PreferE32)) { 1744 Result = R; 1745 ErrorInfo = EI; 1746 } 1747 if (R == Match_Success) 1748 break; 1749 } 1750 1751 switch (Result) { 1752 default: break; 1753 case Match_Success: 1754 Inst.setLoc(IDLoc); 1755 Out.EmitInstruction(Inst, getSTI()); 1756 return false; 1757 1758 case Match_MissingFeature: 1759 return Error(IDLoc, "instruction not supported on this GPU"); 1760 1761 case Match_MnemonicFail: 1762 return Error(IDLoc, "unrecognized instruction mnemonic"); 1763 1764 case Match_InvalidOperand: { 1765 SMLoc ErrorLoc = IDLoc; 1766 if (ErrorInfo != ~0ULL) { 1767 if (ErrorInfo >= Operands.size()) { 1768 return Error(IDLoc, "too few operands for instruction"); 1769 } 1770 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 1771 if (ErrorLoc == SMLoc()) 1772 ErrorLoc = IDLoc; 1773 } 1774 return Error(ErrorLoc, "invalid operand for instruction"); 1775 } 1776 1777 case Match_PreferE32: 1778 return Error(IDLoc, "internal error: instruction without _e64 suffix " 1779 "should be encoded as e32"); 1780 } 1781 llvm_unreachable("Implement any new match types added!"); 1782 } 1783 1784 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) { 1785 int64_t Tmp = -1; 1786 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) { 1787 return true; 1788 } 1789 if (getParser().parseAbsoluteExpression(Tmp)) { 1790 return true; 1791 } 1792 Ret = static_cast<uint32_t>(Tmp); 1793 return false; 1794 } 1795 1796 1797 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 1798 uint32_t &Minor) { 1799 if (ParseAsAbsoluteExpression(Major)) 1800 return TokError("invalid major version"); 1801 1802 if (getLexer().isNot(AsmToken::Comma)) 1803 return TokError("minor version number required, comma expected"); 1804 Lex(); 1805 1806 if (ParseAsAbsoluteExpression(Minor)) 1807 return TokError("invalid minor version"); 1808 1809 return false; 1810 } 1811 1812 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 1813 1814 uint32_t Major; 1815 uint32_t Minor; 1816 1817 if (ParseDirectiveMajorMinor(Major, Minor)) 1818 return true; 1819 1820 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 1821 return false; 1822 } 1823 1824 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 1825 uint32_t Major; 1826 uint32_t Minor; 1827 uint32_t Stepping; 1828 StringRef VendorName; 1829 StringRef ArchName; 1830 1831 // If this directive has no arguments, then use the ISA version for the 1832 // targeted GPU. 1833 if (getLexer().is(AsmToken::EndOfStatement)) { 1834 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits()); 1835 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor, 1836 Isa.Stepping, 1837 "AMD", "AMDGPU"); 1838 return false; 1839 } 1840 1841 if (ParseDirectiveMajorMinor(Major, Minor)) 1842 return true; 1843 1844 if (getLexer().isNot(AsmToken::Comma)) 1845 return TokError("stepping version number required, comma expected"); 1846 Lex(); 1847 1848 if (ParseAsAbsoluteExpression(Stepping)) 1849 return TokError("invalid stepping version"); 1850 1851 if (getLexer().isNot(AsmToken::Comma)) 1852 return TokError("vendor name required, comma expected"); 1853 Lex(); 1854 1855 if (getLexer().isNot(AsmToken::String)) 1856 return TokError("invalid vendor name"); 1857 1858 VendorName = getLexer().getTok().getStringContents(); 1859 Lex(); 1860 1861 if (getLexer().isNot(AsmToken::Comma)) 1862 return TokError("arch name required, comma expected"); 1863 Lex(); 1864 1865 if (getLexer().isNot(AsmToken::String)) 1866 return TokError("invalid arch name"); 1867 1868 ArchName = getLexer().getTok().getStringContents(); 1869 Lex(); 1870 1871 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 1872 VendorName, ArchName); 1873 return false; 1874 } 1875 1876 bool AMDGPUAsmParser::ParseDirectiveRuntimeMetadata() { 1877 std::string Metadata; 1878 raw_string_ostream MS(Metadata); 1879 1880 getLexer().setSkipSpace(false); 1881 1882 bool FoundEnd = false; 1883 while (!getLexer().is(AsmToken::Eof)) { 1884 while (getLexer().is(AsmToken::Space)) { 1885 MS << ' '; 1886 Lex(); 1887 } 1888 1889 if (getLexer().is(AsmToken::Identifier)) { 1890 StringRef ID = getLexer().getTok().getIdentifier(); 1891 if (ID == ".end_amdgpu_runtime_metadata") { 1892 Lex(); 1893 FoundEnd = true; 1894 break; 1895 } 1896 } 1897 1898 MS << Parser.parseStringToEndOfStatement() 1899 << getContext().getAsmInfo()->getSeparatorString(); 1900 1901 Parser.eatToEndOfStatement(); 1902 } 1903 1904 getLexer().setSkipSpace(true); 1905 1906 if (getLexer().is(AsmToken::Eof) && !FoundEnd) 1907 return TokError("expected directive .end_amdgpu_runtime_metadata not found"); 1908 1909 MS.flush(); 1910 1911 getTargetStreamer().EmitRuntimeMetadata(Metadata); 1912 1913 return false; 1914 } 1915 1916 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 1917 amd_kernel_code_t &Header) { 1918 SmallString<40> ErrStr; 1919 raw_svector_ostream Err(ErrStr); 1920 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) { 1921 return TokError(Err.str()); 1922 } 1923 Lex(); 1924 return false; 1925 } 1926 1927 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 1928 amd_kernel_code_t Header; 1929 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits()); 1930 1931 while (true) { 1932 // Lex EndOfStatement. This is in a while loop, because lexing a comment 1933 // will set the current token to EndOfStatement. 1934 while(getLexer().is(AsmToken::EndOfStatement)) 1935 Lex(); 1936 1937 if (getLexer().isNot(AsmToken::Identifier)) 1938 return TokError("expected value identifier or .end_amd_kernel_code_t"); 1939 1940 StringRef ID = getLexer().getTok().getIdentifier(); 1941 Lex(); 1942 1943 if (ID == ".end_amd_kernel_code_t") 1944 break; 1945 1946 if (ParseAMDKernelCodeTValue(ID, Header)) 1947 return true; 1948 } 1949 1950 getTargetStreamer().EmitAMDKernelCodeT(Header); 1951 1952 return false; 1953 } 1954 1955 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() { 1956 getParser().getStreamer().SwitchSection( 1957 AMDGPU::getHSATextSection(getContext())); 1958 return false; 1959 } 1960 1961 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 1962 if (getLexer().isNot(AsmToken::Identifier)) 1963 return TokError("expected symbol name"); 1964 1965 StringRef KernelName = Parser.getTok().getString(); 1966 1967 getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 1968 ELF::STT_AMDGPU_HSA_KERNEL); 1969 Lex(); 1970 KernelScope.initialize(getContext()); 1971 return false; 1972 } 1973 1974 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() { 1975 if (getLexer().isNot(AsmToken::Identifier)) 1976 return TokError("expected symbol name"); 1977 1978 StringRef GlobalName = Parser.getTok().getIdentifier(); 1979 1980 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName); 1981 Lex(); 1982 return false; 1983 } 1984 1985 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() { 1986 if (getLexer().isNot(AsmToken::Identifier)) 1987 return TokError("expected symbol name"); 1988 1989 StringRef GlobalName = Parser.getTok().getIdentifier(); 1990 1991 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName); 1992 Lex(); 1993 return false; 1994 } 1995 1996 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() { 1997 getParser().getStreamer().SwitchSection( 1998 AMDGPU::getHSADataGlobalAgentSection(getContext())); 1999 return false; 2000 } 2001 2002 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() { 2003 getParser().getStreamer().SwitchSection( 2004 AMDGPU::getHSADataGlobalProgramSection(getContext())); 2005 return false; 2006 } 2007 2008 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() { 2009 getParser().getStreamer().SwitchSection( 2010 AMDGPU::getHSARodataReadonlyAgentSection(getContext())); 2011 return false; 2012 } 2013 2014 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 2015 StringRef IDVal = DirectiveID.getString(); 2016 2017 if (IDVal == ".hsa_code_object_version") 2018 return ParseDirectiveHSACodeObjectVersion(); 2019 2020 if (IDVal == ".hsa_code_object_isa") 2021 return ParseDirectiveHSACodeObjectISA(); 2022 2023 if (IDVal == ".amdgpu_runtime_metadata") 2024 return ParseDirectiveRuntimeMetadata(); 2025 2026 if (IDVal == ".amd_kernel_code_t") 2027 return ParseDirectiveAMDKernelCodeT(); 2028 2029 if (IDVal == ".hsatext") 2030 return ParseSectionDirectiveHSAText(); 2031 2032 if (IDVal == ".amdgpu_hsa_kernel") 2033 return ParseDirectiveAMDGPUHsaKernel(); 2034 2035 if (IDVal == ".amdgpu_hsa_module_global") 2036 return ParseDirectiveAMDGPUHsaModuleGlobal(); 2037 2038 if (IDVal == ".amdgpu_hsa_program_global") 2039 return ParseDirectiveAMDGPUHsaProgramGlobal(); 2040 2041 if (IDVal == ".hsadata_global_agent") 2042 return ParseSectionDirectiveHSADataGlobalAgent(); 2043 2044 if (IDVal == ".hsadata_global_program") 2045 return ParseSectionDirectiveHSADataGlobalProgram(); 2046 2047 if (IDVal == ".hsarodata_readonly_agent") 2048 return ParseSectionDirectiveHSARodataReadonlyAgent(); 2049 2050 return true; 2051 } 2052 2053 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 2054 unsigned RegNo) const { 2055 if (isCI()) 2056 return true; 2057 2058 if (isSI()) { 2059 // No flat_scr 2060 switch (RegNo) { 2061 case AMDGPU::FLAT_SCR: 2062 case AMDGPU::FLAT_SCR_LO: 2063 case AMDGPU::FLAT_SCR_HI: 2064 return false; 2065 default: 2066 return true; 2067 } 2068 } 2069 2070 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 2071 // SI/CI have. 2072 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true); 2073 R.isValid(); ++R) { 2074 if (*R == RegNo) 2075 return false; 2076 } 2077 2078 return true; 2079 } 2080 2081 OperandMatchResultTy 2082 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 2083 2084 // Try to parse with a custom parser 2085 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 2086 2087 // If we successfully parsed the operand or if there as an error parsing, 2088 // we are done. 2089 // 2090 // If we are parsing after we reach EndOfStatement then this means we 2091 // are appending default values to the Operands list. This is only done 2092 // by custom parser, so we shouldn't continue on to the generic parsing. 2093 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail || 2094 getLexer().is(AsmToken::EndOfStatement)) 2095 return ResTy; 2096 2097 ResTy = parseRegOrImm(Operands); 2098 2099 if (ResTy == MatchOperand_Success) 2100 return ResTy; 2101 2102 if (getLexer().getKind() == AsmToken::Identifier) { 2103 // If this identifier is a symbol, we want to create an expression for it. 2104 // It is a little difficult to distinguish between a symbol name, and 2105 // an instruction flag like 'gds'. In order to do this, we parse 2106 // all tokens as expressions and then treate the symbol name as the token 2107 // string when we want to interpret the operand as a token. 2108 const auto &Tok = Parser.getTok(); 2109 SMLoc S = Tok.getLoc(); 2110 const MCExpr *Expr = nullptr; 2111 if (!Parser.parseExpression(Expr)) { 2112 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 2113 return MatchOperand_Success; 2114 } 2115 2116 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc())); 2117 Parser.Lex(); 2118 return MatchOperand_Success; 2119 } 2120 return MatchOperand_NoMatch; 2121 } 2122 2123 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) { 2124 // Clear any forced encodings from the previous instruction. 2125 setForcedEncodingSize(0); 2126 setForcedDPP(false); 2127 setForcedSDWA(false); 2128 2129 if (Name.endswith("_e64")) { 2130 setForcedEncodingSize(64); 2131 return Name.substr(0, Name.size() - 4); 2132 } else if (Name.endswith("_e32")) { 2133 setForcedEncodingSize(32); 2134 return Name.substr(0, Name.size() - 4); 2135 } else if (Name.endswith("_dpp")) { 2136 setForcedDPP(true); 2137 return Name.substr(0, Name.size() - 4); 2138 } else if (Name.endswith("_sdwa")) { 2139 setForcedSDWA(true); 2140 return Name.substr(0, Name.size() - 5); 2141 } 2142 return Name; 2143 } 2144 2145 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 2146 StringRef Name, 2147 SMLoc NameLoc, OperandVector &Operands) { 2148 // Add the instruction mnemonic 2149 Name = parseMnemonicSuffix(Name); 2150 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc)); 2151 2152 while (!getLexer().is(AsmToken::EndOfStatement)) { 2153 OperandMatchResultTy Res = parseOperand(Operands, Name); 2154 2155 // Eat the comma or space if there is one. 2156 if (getLexer().is(AsmToken::Comma)) 2157 Parser.Lex(); 2158 2159 switch (Res) { 2160 case MatchOperand_Success: break; 2161 case MatchOperand_ParseFail: 2162 Error(getLexer().getLoc(), "failed parsing operand."); 2163 while (!getLexer().is(AsmToken::EndOfStatement)) { 2164 Parser.Lex(); 2165 } 2166 return true; 2167 case MatchOperand_NoMatch: 2168 Error(getLexer().getLoc(), "not a valid operand."); 2169 while (!getLexer().is(AsmToken::EndOfStatement)) { 2170 Parser.Lex(); 2171 } 2172 return true; 2173 } 2174 } 2175 2176 return false; 2177 } 2178 2179 //===----------------------------------------------------------------------===// 2180 // Utility functions 2181 //===----------------------------------------------------------------------===// 2182 2183 OperandMatchResultTy 2184 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) { 2185 switch(getLexer().getKind()) { 2186 default: return MatchOperand_NoMatch; 2187 case AsmToken::Identifier: { 2188 StringRef Name = Parser.getTok().getString(); 2189 if (!Name.equals(Prefix)) { 2190 return MatchOperand_NoMatch; 2191 } 2192 2193 Parser.Lex(); 2194 if (getLexer().isNot(AsmToken::Colon)) 2195 return MatchOperand_ParseFail; 2196 2197 Parser.Lex(); 2198 if (getLexer().isNot(AsmToken::Integer)) 2199 return MatchOperand_ParseFail; 2200 2201 if (getParser().parseAbsoluteExpression(Int)) 2202 return MatchOperand_ParseFail; 2203 break; 2204 } 2205 } 2206 return MatchOperand_Success; 2207 } 2208 2209 OperandMatchResultTy 2210 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 2211 enum AMDGPUOperand::ImmTy ImmTy, 2212 bool (*ConvertResult)(int64_t&)) { 2213 SMLoc S = Parser.getTok().getLoc(); 2214 int64_t Value = 0; 2215 2216 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value); 2217 if (Res != MatchOperand_Success) 2218 return Res; 2219 2220 if (ConvertResult && !ConvertResult(Value)) { 2221 return MatchOperand_ParseFail; 2222 } 2223 2224 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy)); 2225 return MatchOperand_Success; 2226 } 2227 2228 OperandMatchResultTy 2229 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 2230 enum AMDGPUOperand::ImmTy ImmTy) { 2231 int64_t Bit = 0; 2232 SMLoc S = Parser.getTok().getLoc(); 2233 2234 // We are at the end of the statement, and this is a default argument, so 2235 // use a default value. 2236 if (getLexer().isNot(AsmToken::EndOfStatement)) { 2237 switch(getLexer().getKind()) { 2238 case AsmToken::Identifier: { 2239 StringRef Tok = Parser.getTok().getString(); 2240 if (Tok == Name) { 2241 Bit = 1; 2242 Parser.Lex(); 2243 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 2244 Bit = 0; 2245 Parser.Lex(); 2246 } else { 2247 return MatchOperand_NoMatch; 2248 } 2249 break; 2250 } 2251 default: 2252 return MatchOperand_NoMatch; 2253 } 2254 } 2255 2256 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy)); 2257 return MatchOperand_Success; 2258 } 2259 2260 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap; 2261 2262 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands, 2263 OptionalImmIndexMap& OptionalIdx, 2264 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) { 2265 auto i = OptionalIdx.find(ImmT); 2266 if (i != OptionalIdx.end()) { 2267 unsigned Idx = i->second; 2268 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 2269 } else { 2270 Inst.addOperand(MCOperand::createImm(Default)); 2271 } 2272 } 2273 2274 OperandMatchResultTy 2275 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) { 2276 if (getLexer().isNot(AsmToken::Identifier)) { 2277 return MatchOperand_NoMatch; 2278 } 2279 StringRef Tok = Parser.getTok().getString(); 2280 if (Tok != Prefix) { 2281 return MatchOperand_NoMatch; 2282 } 2283 2284 Parser.Lex(); 2285 if (getLexer().isNot(AsmToken::Colon)) { 2286 return MatchOperand_ParseFail; 2287 } 2288 2289 Parser.Lex(); 2290 if (getLexer().isNot(AsmToken::Identifier)) { 2291 return MatchOperand_ParseFail; 2292 } 2293 2294 Value = Parser.getTok().getString(); 2295 return MatchOperand_Success; 2296 } 2297 2298 //===----------------------------------------------------------------------===// 2299 // ds 2300 //===----------------------------------------------------------------------===// 2301 2302 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 2303 const OperandVector &Operands) { 2304 OptionalImmIndexMap OptionalIdx; 2305 2306 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 2307 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 2308 2309 // Add the register arguments 2310 if (Op.isReg()) { 2311 Op.addRegOperands(Inst, 1); 2312 continue; 2313 } 2314 2315 // Handle optional arguments 2316 OptionalIdx[Op.getImmTy()] = i; 2317 } 2318 2319 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0); 2320 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1); 2321 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 2322 2323 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 2324 } 2325 2326 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 2327 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 2328 bool GDSOnly = false; 2329 2330 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 2331 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 2332 2333 // Add the register arguments 2334 if (Op.isReg()) { 2335 Op.addRegOperands(Inst, 1); 2336 continue; 2337 } 2338 2339 if (Op.isToken() && Op.getToken() == "gds") { 2340 GDSOnly = true; 2341 continue; 2342 } 2343 2344 // Handle optional arguments 2345 OptionalIdx[Op.getImmTy()] = i; 2346 } 2347 2348 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 2349 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 2350 2351 if (!GDSOnly) { 2352 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 2353 } 2354 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 2355 } 2356 2357 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) { 2358 OptionalImmIndexMap OptionalIdx; 2359 2360 unsigned EnMask = 0; 2361 int SrcIdx = 0; 2362 2363 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 2364 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 2365 2366 // Add the register arguments 2367 if (Op.isReg()) { 2368 EnMask |= (1 << SrcIdx); 2369 Op.addRegOperands(Inst, 1); 2370 ++SrcIdx; 2371 continue; 2372 } 2373 2374 if (Op.isOff()) { 2375 ++SrcIdx; 2376 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister)); 2377 continue; 2378 } 2379 2380 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) { 2381 Op.addImmOperands(Inst, 1); 2382 continue; 2383 } 2384 2385 if (Op.isToken() && Op.getToken() == "done") 2386 continue; 2387 2388 // Handle optional arguments 2389 OptionalIdx[Op.getImmTy()] = i; 2390 } 2391 2392 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM); 2393 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr); 2394 2395 Inst.addOperand(MCOperand::createImm(EnMask)); 2396 } 2397 2398 //===----------------------------------------------------------------------===// 2399 // s_waitcnt 2400 //===----------------------------------------------------------------------===// 2401 2402 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 2403 StringRef CntName = Parser.getTok().getString(); 2404 int64_t CntVal; 2405 2406 Parser.Lex(); 2407 if (getLexer().isNot(AsmToken::LParen)) 2408 return true; 2409 2410 Parser.Lex(); 2411 if (getLexer().isNot(AsmToken::Integer)) 2412 return true; 2413 2414 if (getParser().parseAbsoluteExpression(CntVal)) 2415 return true; 2416 2417 if (getLexer().isNot(AsmToken::RParen)) 2418 return true; 2419 2420 Parser.Lex(); 2421 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 2422 Parser.Lex(); 2423 2424 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits()); 2425 if (CntName == "vmcnt") 2426 IntVal = encodeVmcnt(IV, IntVal, CntVal); 2427 else if (CntName == "expcnt") 2428 IntVal = encodeExpcnt(IV, IntVal, CntVal); 2429 else if (CntName == "lgkmcnt") 2430 IntVal = encodeLgkmcnt(IV, IntVal, CntVal); 2431 else 2432 return true; 2433 2434 return false; 2435 } 2436 2437 OperandMatchResultTy 2438 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 2439 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits()); 2440 int64_t Waitcnt = getWaitcntBitMask(IV); 2441 SMLoc S = Parser.getTok().getLoc(); 2442 2443 switch(getLexer().getKind()) { 2444 default: return MatchOperand_ParseFail; 2445 case AsmToken::Integer: 2446 // The operand can be an integer value. 2447 if (getParser().parseAbsoluteExpression(Waitcnt)) 2448 return MatchOperand_ParseFail; 2449 break; 2450 2451 case AsmToken::Identifier: 2452 do { 2453 if (parseCnt(Waitcnt)) 2454 return MatchOperand_ParseFail; 2455 } while(getLexer().isNot(AsmToken::EndOfStatement)); 2456 break; 2457 } 2458 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S)); 2459 return MatchOperand_Success; 2460 } 2461 2462 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) { 2463 using namespace llvm::AMDGPU::Hwreg; 2464 2465 if (Parser.getTok().getString() != "hwreg") 2466 return true; 2467 Parser.Lex(); 2468 2469 if (getLexer().isNot(AsmToken::LParen)) 2470 return true; 2471 Parser.Lex(); 2472 2473 if (getLexer().is(AsmToken::Identifier)) { 2474 HwReg.IsSymbolic = true; 2475 HwReg.Id = ID_UNKNOWN_; 2476 const StringRef tok = Parser.getTok().getString(); 2477 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) { 2478 if (tok == IdSymbolic[i]) { 2479 HwReg.Id = i; 2480 break; 2481 } 2482 } 2483 Parser.Lex(); 2484 } else { 2485 HwReg.IsSymbolic = false; 2486 if (getLexer().isNot(AsmToken::Integer)) 2487 return true; 2488 if (getParser().parseAbsoluteExpression(HwReg.Id)) 2489 return true; 2490 } 2491 2492 if (getLexer().is(AsmToken::RParen)) { 2493 Parser.Lex(); 2494 return false; 2495 } 2496 2497 // optional params 2498 if (getLexer().isNot(AsmToken::Comma)) 2499 return true; 2500 Parser.Lex(); 2501 2502 if (getLexer().isNot(AsmToken::Integer)) 2503 return true; 2504 if (getParser().parseAbsoluteExpression(Offset)) 2505 return true; 2506 2507 if (getLexer().isNot(AsmToken::Comma)) 2508 return true; 2509 Parser.Lex(); 2510 2511 if (getLexer().isNot(AsmToken::Integer)) 2512 return true; 2513 if (getParser().parseAbsoluteExpression(Width)) 2514 return true; 2515 2516 if (getLexer().isNot(AsmToken::RParen)) 2517 return true; 2518 Parser.Lex(); 2519 2520 return false; 2521 } 2522 2523 OperandMatchResultTy 2524 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) { 2525 using namespace llvm::AMDGPU::Hwreg; 2526 2527 int64_t Imm16Val = 0; 2528 SMLoc S = Parser.getTok().getLoc(); 2529 2530 switch(getLexer().getKind()) { 2531 default: return MatchOperand_NoMatch; 2532 case AsmToken::Integer: 2533 // The operand can be an integer value. 2534 if (getParser().parseAbsoluteExpression(Imm16Val)) 2535 return MatchOperand_NoMatch; 2536 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) { 2537 Error(S, "invalid immediate: only 16-bit values are legal"); 2538 // Do not return error code, but create an imm operand anyway and proceed 2539 // to the next operand, if any. That avoids unneccessary error messages. 2540 } 2541 break; 2542 2543 case AsmToken::Identifier: { 2544 OperandInfoTy HwReg(ID_UNKNOWN_); 2545 int64_t Offset = OFFSET_DEFAULT_; 2546 int64_t Width = WIDTH_M1_DEFAULT_ + 1; 2547 if (parseHwregConstruct(HwReg, Offset, Width)) 2548 return MatchOperand_ParseFail; 2549 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) { 2550 if (HwReg.IsSymbolic) 2551 Error(S, "invalid symbolic name of hardware register"); 2552 else 2553 Error(S, "invalid code of hardware register: only 6-bit values are legal"); 2554 } 2555 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset)) 2556 Error(S, "invalid bit offset: only 5-bit values are legal"); 2557 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1)) 2558 Error(S, "invalid bitfield width: only values from 1 to 32 are legal"); 2559 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_); 2560 } 2561 break; 2562 } 2563 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg)); 2564 return MatchOperand_Success; 2565 } 2566 2567 bool AMDGPUOperand::isSWaitCnt() const { 2568 return isImm(); 2569 } 2570 2571 bool AMDGPUOperand::isHwreg() const { 2572 return isImmTy(ImmTyHwreg); 2573 } 2574 2575 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) { 2576 using namespace llvm::AMDGPU::SendMsg; 2577 2578 if (Parser.getTok().getString() != "sendmsg") 2579 return true; 2580 Parser.Lex(); 2581 2582 if (getLexer().isNot(AsmToken::LParen)) 2583 return true; 2584 Parser.Lex(); 2585 2586 if (getLexer().is(AsmToken::Identifier)) { 2587 Msg.IsSymbolic = true; 2588 Msg.Id = ID_UNKNOWN_; 2589 const std::string tok = Parser.getTok().getString(); 2590 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) { 2591 switch(i) { 2592 default: continue; // Omit gaps. 2593 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break; 2594 } 2595 if (tok == IdSymbolic[i]) { 2596 Msg.Id = i; 2597 break; 2598 } 2599 } 2600 Parser.Lex(); 2601 } else { 2602 Msg.IsSymbolic = false; 2603 if (getLexer().isNot(AsmToken::Integer)) 2604 return true; 2605 if (getParser().parseAbsoluteExpression(Msg.Id)) 2606 return true; 2607 if (getLexer().is(AsmToken::Integer)) 2608 if (getParser().parseAbsoluteExpression(Msg.Id)) 2609 Msg.Id = ID_UNKNOWN_; 2610 } 2611 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest. 2612 return false; 2613 2614 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) { 2615 if (getLexer().isNot(AsmToken::RParen)) 2616 return true; 2617 Parser.Lex(); 2618 return false; 2619 } 2620 2621 if (getLexer().isNot(AsmToken::Comma)) 2622 return true; 2623 Parser.Lex(); 2624 2625 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG); 2626 Operation.Id = ID_UNKNOWN_; 2627 if (getLexer().is(AsmToken::Identifier)) { 2628 Operation.IsSymbolic = true; 2629 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic; 2630 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_; 2631 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_; 2632 const StringRef Tok = Parser.getTok().getString(); 2633 for (int i = F; i < L; ++i) { 2634 if (Tok == S[i]) { 2635 Operation.Id = i; 2636 break; 2637 } 2638 } 2639 Parser.Lex(); 2640 } else { 2641 Operation.IsSymbolic = false; 2642 if (getLexer().isNot(AsmToken::Integer)) 2643 return true; 2644 if (getParser().parseAbsoluteExpression(Operation.Id)) 2645 return true; 2646 } 2647 2648 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) { 2649 // Stream id is optional. 2650 if (getLexer().is(AsmToken::RParen)) { 2651 Parser.Lex(); 2652 return false; 2653 } 2654 2655 if (getLexer().isNot(AsmToken::Comma)) 2656 return true; 2657 Parser.Lex(); 2658 2659 if (getLexer().isNot(AsmToken::Integer)) 2660 return true; 2661 if (getParser().parseAbsoluteExpression(StreamId)) 2662 return true; 2663 } 2664 2665 if (getLexer().isNot(AsmToken::RParen)) 2666 return true; 2667 Parser.Lex(); 2668 return false; 2669 } 2670 2671 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) { 2672 if (getLexer().getKind() != AsmToken::Identifier) 2673 return MatchOperand_NoMatch; 2674 2675 StringRef Str = Parser.getTok().getString(); 2676 int Slot = StringSwitch<int>(Str) 2677 .Case("p10", 0) 2678 .Case("p20", 1) 2679 .Case("p0", 2) 2680 .Default(-1); 2681 2682 SMLoc S = Parser.getTok().getLoc(); 2683 if (Slot == -1) 2684 return MatchOperand_ParseFail; 2685 2686 Parser.Lex(); 2687 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S, 2688 AMDGPUOperand::ImmTyInterpSlot)); 2689 return MatchOperand_Success; 2690 } 2691 2692 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) { 2693 if (getLexer().getKind() != AsmToken::Identifier) 2694 return MatchOperand_NoMatch; 2695 2696 StringRef Str = Parser.getTok().getString(); 2697 if (!Str.startswith("attr")) 2698 return MatchOperand_NoMatch; 2699 2700 StringRef Chan = Str.take_back(2); 2701 int AttrChan = StringSwitch<int>(Chan) 2702 .Case(".x", 0) 2703 .Case(".y", 1) 2704 .Case(".z", 2) 2705 .Case(".w", 3) 2706 .Default(-1); 2707 if (AttrChan == -1) 2708 return MatchOperand_ParseFail; 2709 2710 Str = Str.drop_back(2).drop_front(4); 2711 2712 uint8_t Attr; 2713 if (Str.getAsInteger(10, Attr)) 2714 return MatchOperand_ParseFail; 2715 2716 SMLoc S = Parser.getTok().getLoc(); 2717 Parser.Lex(); 2718 if (Attr > 63) { 2719 Error(S, "out of bounds attr"); 2720 return MatchOperand_Success; 2721 } 2722 2723 SMLoc SChan = SMLoc::getFromPointer(Chan.data()); 2724 2725 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S, 2726 AMDGPUOperand::ImmTyInterpAttr)); 2727 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan, 2728 AMDGPUOperand::ImmTyAttrChan)); 2729 return MatchOperand_Success; 2730 } 2731 2732 void AMDGPUAsmParser::errorExpTgt() { 2733 Error(Parser.getTok().getLoc(), "invalid exp target"); 2734 } 2735 2736 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str, 2737 uint8_t &Val) { 2738 if (Str == "null") { 2739 Val = 9; 2740 return MatchOperand_Success; 2741 } 2742 2743 if (Str.startswith("mrt")) { 2744 Str = Str.drop_front(3); 2745 if (Str == "z") { // == mrtz 2746 Val = 8; 2747 return MatchOperand_Success; 2748 } 2749 2750 if (Str.getAsInteger(10, Val)) 2751 return MatchOperand_ParseFail; 2752 2753 if (Val > 7) 2754 errorExpTgt(); 2755 2756 return MatchOperand_Success; 2757 } 2758 2759 if (Str.startswith("pos")) { 2760 Str = Str.drop_front(3); 2761 if (Str.getAsInteger(10, Val)) 2762 return MatchOperand_ParseFail; 2763 2764 if (Val > 3) 2765 errorExpTgt(); 2766 2767 Val += 12; 2768 return MatchOperand_Success; 2769 } 2770 2771 if (Str.startswith("param")) { 2772 Str = Str.drop_front(5); 2773 if (Str.getAsInteger(10, Val)) 2774 return MatchOperand_ParseFail; 2775 2776 if (Val >= 32) 2777 errorExpTgt(); 2778 2779 Val += 32; 2780 return MatchOperand_Success; 2781 } 2782 2783 if (Str.startswith("invalid_target_")) { 2784 Str = Str.drop_front(15); 2785 if (Str.getAsInteger(10, Val)) 2786 return MatchOperand_ParseFail; 2787 2788 errorExpTgt(); 2789 return MatchOperand_Success; 2790 } 2791 2792 return MatchOperand_NoMatch; 2793 } 2794 2795 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) { 2796 uint8_t Val; 2797 StringRef Str = Parser.getTok().getString(); 2798 2799 auto Res = parseExpTgtImpl(Str, Val); 2800 if (Res != MatchOperand_Success) 2801 return Res; 2802 2803 SMLoc S = Parser.getTok().getLoc(); 2804 Parser.Lex(); 2805 2806 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, 2807 AMDGPUOperand::ImmTyExpTgt)); 2808 return MatchOperand_Success; 2809 } 2810 2811 OperandMatchResultTy 2812 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) { 2813 using namespace llvm::AMDGPU::SendMsg; 2814 2815 int64_t Imm16Val = 0; 2816 SMLoc S = Parser.getTok().getLoc(); 2817 2818 switch(getLexer().getKind()) { 2819 default: 2820 return MatchOperand_NoMatch; 2821 case AsmToken::Integer: 2822 // The operand can be an integer value. 2823 if (getParser().parseAbsoluteExpression(Imm16Val)) 2824 return MatchOperand_NoMatch; 2825 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) { 2826 Error(S, "invalid immediate: only 16-bit values are legal"); 2827 // Do not return error code, but create an imm operand anyway and proceed 2828 // to the next operand, if any. That avoids unneccessary error messages. 2829 } 2830 break; 2831 case AsmToken::Identifier: { 2832 OperandInfoTy Msg(ID_UNKNOWN_); 2833 OperandInfoTy Operation(OP_UNKNOWN_); 2834 int64_t StreamId = STREAM_ID_DEFAULT_; 2835 if (parseSendMsgConstruct(Msg, Operation, StreamId)) 2836 return MatchOperand_ParseFail; 2837 do { 2838 // Validate and encode message ID. 2839 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE) 2840 || Msg.Id == ID_SYSMSG)) { 2841 if (Msg.IsSymbolic) 2842 Error(S, "invalid/unsupported symbolic name of message"); 2843 else 2844 Error(S, "invalid/unsupported code of message"); 2845 break; 2846 } 2847 Imm16Val = (Msg.Id << ID_SHIFT_); 2848 // Validate and encode operation ID. 2849 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) { 2850 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) { 2851 if (Operation.IsSymbolic) 2852 Error(S, "invalid symbolic name of GS_OP"); 2853 else 2854 Error(S, "invalid code of GS_OP: only 2-bit values are legal"); 2855 break; 2856 } 2857 if (Operation.Id == OP_GS_NOP 2858 && Msg.Id != ID_GS_DONE) { 2859 Error(S, "invalid GS_OP: NOP is for GS_DONE only"); 2860 break; 2861 } 2862 Imm16Val |= (Operation.Id << OP_SHIFT_); 2863 } 2864 if (Msg.Id == ID_SYSMSG) { 2865 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) { 2866 if (Operation.IsSymbolic) 2867 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP"); 2868 else 2869 Error(S, "invalid/unsupported code of SYSMSG_OP"); 2870 break; 2871 } 2872 Imm16Val |= (Operation.Id << OP_SHIFT_); 2873 } 2874 // Validate and encode stream ID. 2875 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) { 2876 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) { 2877 Error(S, "invalid stream id: only 2-bit values are legal"); 2878 break; 2879 } 2880 Imm16Val |= (StreamId << STREAM_ID_SHIFT_); 2881 } 2882 } while (false); 2883 } 2884 break; 2885 } 2886 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg)); 2887 return MatchOperand_Success; 2888 } 2889 2890 bool AMDGPUOperand::isSendMsg() const { 2891 return isImmTy(ImmTySendMsg); 2892 } 2893 2894 //===----------------------------------------------------------------------===// 2895 // sopp branch targets 2896 //===----------------------------------------------------------------------===// 2897 2898 OperandMatchResultTy 2899 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 2900 SMLoc S = Parser.getTok().getLoc(); 2901 2902 switch (getLexer().getKind()) { 2903 default: return MatchOperand_ParseFail; 2904 case AsmToken::Integer: { 2905 int64_t Imm; 2906 if (getParser().parseAbsoluteExpression(Imm)) 2907 return MatchOperand_ParseFail; 2908 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S)); 2909 return MatchOperand_Success; 2910 } 2911 2912 case AsmToken::Identifier: 2913 Operands.push_back(AMDGPUOperand::CreateExpr(this, 2914 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 2915 Parser.getTok().getString()), getContext()), S)); 2916 Parser.Lex(); 2917 return MatchOperand_Success; 2918 } 2919 } 2920 2921 //===----------------------------------------------------------------------===// 2922 // mubuf 2923 //===----------------------------------------------------------------------===// 2924 2925 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const { 2926 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC); 2927 } 2928 2929 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const { 2930 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC); 2931 } 2932 2933 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const { 2934 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE); 2935 } 2936 2937 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, 2938 const OperandVector &Operands, 2939 bool IsAtomic, bool IsAtomicReturn) { 2940 OptionalImmIndexMap OptionalIdx; 2941 assert(IsAtomicReturn ? IsAtomic : true); 2942 2943 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 2944 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 2945 2946 // Add the register arguments 2947 if (Op.isReg()) { 2948 Op.addRegOperands(Inst, 1); 2949 continue; 2950 } 2951 2952 // Handle the case where soffset is an immediate 2953 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 2954 Op.addImmOperands(Inst, 1); 2955 continue; 2956 } 2957 2958 // Handle tokens like 'offen' which are sometimes hard-coded into the 2959 // asm string. There are no MCInst operands for these. 2960 if (Op.isToken()) { 2961 continue; 2962 } 2963 assert(Op.isImm()); 2964 2965 // Handle optional arguments 2966 OptionalIdx[Op.getImmTy()] = i; 2967 } 2968 2969 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns. 2970 if (IsAtomicReturn) { 2971 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning. 2972 Inst.insert(I, *I); 2973 } 2974 2975 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 2976 if (!IsAtomic) { // glc is hard-coded. 2977 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 2978 } 2979 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 2980 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 2981 } 2982 2983 //===----------------------------------------------------------------------===// 2984 // mimg 2985 //===----------------------------------------------------------------------===// 2986 2987 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) { 2988 unsigned I = 1; 2989 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2990 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2991 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2992 } 2993 2994 OptionalImmIndexMap OptionalIdx; 2995 2996 for (unsigned E = Operands.size(); I != E; ++I) { 2997 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2998 2999 // Add the register arguments 3000 if (Op.isRegOrImm()) { 3001 Op.addRegOrImmOperands(Inst, 1); 3002 continue; 3003 } else if (Op.isImmModifier()) { 3004 OptionalIdx[Op.getImmTy()] = I; 3005 } else { 3006 llvm_unreachable("unexpected operand type"); 3007 } 3008 } 3009 3010 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 3011 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 3012 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 3013 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 3014 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 3015 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 3016 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 3017 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 3018 } 3019 3020 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) { 3021 unsigned I = 1; 3022 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3023 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 3024 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 3025 } 3026 3027 // Add src, same as dst 3028 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1); 3029 3030 OptionalImmIndexMap OptionalIdx; 3031 3032 for (unsigned E = Operands.size(); I != E; ++I) { 3033 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 3034 3035 // Add the register arguments 3036 if (Op.isRegOrImm()) { 3037 Op.addRegOrImmOperands(Inst, 1); 3038 continue; 3039 } else if (Op.isImmModifier()) { 3040 OptionalIdx[Op.getImmTy()] = I; 3041 } else { 3042 llvm_unreachable("unexpected operand type"); 3043 } 3044 } 3045 3046 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 3047 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 3048 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 3049 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 3050 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 3051 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 3052 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 3053 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 3054 } 3055 3056 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const { 3057 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask); 3058 } 3059 3060 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const { 3061 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm); 3062 } 3063 3064 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const { 3065 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA); 3066 } 3067 3068 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const { 3069 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128); 3070 } 3071 3072 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const { 3073 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE); 3074 } 3075 3076 //===----------------------------------------------------------------------===// 3077 // smrd 3078 //===----------------------------------------------------------------------===// 3079 3080 bool AMDGPUOperand::isSMRDOffset8() const { 3081 return isImm() && isUInt<8>(getImm()); 3082 } 3083 3084 bool AMDGPUOperand::isSMRDOffset20() const { 3085 return isImm() && isUInt<20>(getImm()); 3086 } 3087 3088 bool AMDGPUOperand::isSMRDLiteralOffset() const { 3089 // 32-bit literals are only supported on CI and we only want to use them 3090 // when the offset is > 8-bits. 3091 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 3092 } 3093 3094 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const { 3095 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 3096 } 3097 3098 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const { 3099 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 3100 } 3101 3102 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const { 3103 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 3104 } 3105 3106 //===----------------------------------------------------------------------===// 3107 // vop3 3108 //===----------------------------------------------------------------------===// 3109 3110 static bool ConvertOmodMul(int64_t &Mul) { 3111 if (Mul != 1 && Mul != 2 && Mul != 4) 3112 return false; 3113 3114 Mul >>= 1; 3115 return true; 3116 } 3117 3118 static bool ConvertOmodDiv(int64_t &Div) { 3119 if (Div == 1) { 3120 Div = 0; 3121 return true; 3122 } 3123 3124 if (Div == 2) { 3125 Div = 3; 3126 return true; 3127 } 3128 3129 return false; 3130 } 3131 3132 static bool ConvertBoundCtrl(int64_t &BoundCtrl) { 3133 if (BoundCtrl == 0) { 3134 BoundCtrl = 1; 3135 return true; 3136 } 3137 3138 if (BoundCtrl == -1) { 3139 BoundCtrl = 0; 3140 return true; 3141 } 3142 3143 return false; 3144 } 3145 3146 // Note: the order in this table matches the order of operands in AsmString. 3147 static const OptionalOperand AMDGPUOptionalOperandTable[] = { 3148 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr}, 3149 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr}, 3150 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr}, 3151 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr}, 3152 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr}, 3153 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr}, 3154 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr}, 3155 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr}, 3156 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr}, 3157 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr}, 3158 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr}, 3159 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul}, 3160 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr}, 3161 {"da", AMDGPUOperand::ImmTyDA, true, nullptr}, 3162 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr}, 3163 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr}, 3164 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr}, 3165 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr}, 3166 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr}, 3167 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl}, 3168 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr}, 3169 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr}, 3170 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr}, 3171 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr}, 3172 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr}, 3173 }; 3174 3175 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) { 3176 OperandMatchResultTy res; 3177 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) { 3178 // try to parse any optional operand here 3179 if (Op.IsBit) { 3180 res = parseNamedBit(Op.Name, Operands, Op.Type); 3181 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) { 3182 res = parseOModOperand(Operands); 3183 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel || 3184 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel || 3185 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) { 3186 res = parseSDWASel(Operands, Op.Name, Op.Type); 3187 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) { 3188 res = parseSDWADstUnused(Operands); 3189 } else { 3190 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult); 3191 } 3192 if (res != MatchOperand_NoMatch) { 3193 return res; 3194 } 3195 } 3196 return MatchOperand_NoMatch; 3197 } 3198 3199 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) { 3200 StringRef Name = Parser.getTok().getString(); 3201 if (Name == "mul") { 3202 return parseIntWithPrefix("mul", Operands, 3203 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul); 3204 } 3205 3206 if (Name == "div") { 3207 return parseIntWithPrefix("div", Operands, 3208 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv); 3209 } 3210 3211 return MatchOperand_NoMatch; 3212 } 3213 3214 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) { 3215 unsigned I = 1; 3216 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3217 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 3218 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 3219 } 3220 for (unsigned E = Operands.size(); I != E; ++I) 3221 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1); 3222 } 3223 3224 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) { 3225 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 3226 if (TSFlags & SIInstrFlags::VOP3) { 3227 cvtVOP3(Inst, Operands); 3228 } else { 3229 cvtId(Inst, Operands); 3230 } 3231 } 3232 3233 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) { 3234 // 1. This operand is input modifiers 3235 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS 3236 // 2. This is not last operand 3237 && Desc.NumOperands > (OpNum + 1) 3238 // 3. Next operand is register class 3239 && Desc.OpInfo[OpNum + 1].RegClass != -1 3240 // 4. Next register is not tied to any other operand 3241 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1; 3242 } 3243 3244 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 3245 OptionalImmIndexMap OptionalIdx; 3246 unsigned I = 1; 3247 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3248 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 3249 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 3250 } 3251 3252 for (unsigned E = Operands.size(); I != E; ++I) { 3253 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 3254 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 3255 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 3256 } else if (Op.isImm()) { 3257 OptionalIdx[Op.getImmTy()] = I; 3258 } else { 3259 llvm_unreachable("unhandled operand type"); 3260 } 3261 } 3262 3263 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 3264 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 3265 3266 // special case v_mac_{f16, f32}: 3267 // it has src2 register operand that is tied to dst operand 3268 // we don't allow modifiers for this operand in assembler so src2_modifiers 3269 // should be 0 3270 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si || 3271 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi || 3272 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) { 3273 auto it = Inst.begin(); 3274 std::advance( 3275 it, 3276 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ? 3277 AMDGPU::V_MAC_F16_e64 : 3278 AMDGPU::V_MAC_F32_e64, 3279 AMDGPU::OpName::src2_modifiers)); 3280 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2 3281 ++it; 3282 Inst.insert(it, Inst.getOperand(0)); // src2 = dst 3283 } 3284 } 3285 3286 //===----------------------------------------------------------------------===// 3287 // dpp 3288 //===----------------------------------------------------------------------===// 3289 3290 bool AMDGPUOperand::isDPPCtrl() const { 3291 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 3292 if (result) { 3293 int64_t Imm = getImm(); 3294 return ((Imm >= 0x000) && (Imm <= 0x0ff)) || 3295 ((Imm >= 0x101) && (Imm <= 0x10f)) || 3296 ((Imm >= 0x111) && (Imm <= 0x11f)) || 3297 ((Imm >= 0x121) && (Imm <= 0x12f)) || 3298 (Imm == 0x130) || 3299 (Imm == 0x134) || 3300 (Imm == 0x138) || 3301 (Imm == 0x13c) || 3302 (Imm == 0x140) || 3303 (Imm == 0x141) || 3304 (Imm == 0x142) || 3305 (Imm == 0x143); 3306 } 3307 return false; 3308 } 3309 3310 bool AMDGPUOperand::isGPRIdxMode() const { 3311 return isImm() && isUInt<4>(getImm()); 3312 } 3313 3314 OperandMatchResultTy 3315 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { 3316 SMLoc S = Parser.getTok().getLoc(); 3317 StringRef Prefix; 3318 int64_t Int; 3319 3320 if (getLexer().getKind() == AsmToken::Identifier) { 3321 Prefix = Parser.getTok().getString(); 3322 } else { 3323 return MatchOperand_NoMatch; 3324 } 3325 3326 if (Prefix == "row_mirror") { 3327 Int = 0x140; 3328 Parser.Lex(); 3329 } else if (Prefix == "row_half_mirror") { 3330 Int = 0x141; 3331 Parser.Lex(); 3332 } else { 3333 // Check to prevent parseDPPCtrlOps from eating invalid tokens 3334 if (Prefix != "quad_perm" 3335 && Prefix != "row_shl" 3336 && Prefix != "row_shr" 3337 && Prefix != "row_ror" 3338 && Prefix != "wave_shl" 3339 && Prefix != "wave_rol" 3340 && Prefix != "wave_shr" 3341 && Prefix != "wave_ror" 3342 && Prefix != "row_bcast") { 3343 return MatchOperand_NoMatch; 3344 } 3345 3346 Parser.Lex(); 3347 if (getLexer().isNot(AsmToken::Colon)) 3348 return MatchOperand_ParseFail; 3349 3350 if (Prefix == "quad_perm") { 3351 // quad_perm:[%d,%d,%d,%d] 3352 Parser.Lex(); 3353 if (getLexer().isNot(AsmToken::LBrac)) 3354 return MatchOperand_ParseFail; 3355 Parser.Lex(); 3356 3357 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3)) 3358 return MatchOperand_ParseFail; 3359 3360 for (int i = 0; i < 3; ++i) { 3361 if (getLexer().isNot(AsmToken::Comma)) 3362 return MatchOperand_ParseFail; 3363 Parser.Lex(); 3364 3365 int64_t Temp; 3366 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3)) 3367 return MatchOperand_ParseFail; 3368 const int shift = i*2 + 2; 3369 Int += (Temp << shift); 3370 } 3371 3372 if (getLexer().isNot(AsmToken::RBrac)) 3373 return MatchOperand_ParseFail; 3374 Parser.Lex(); 3375 3376 } else { 3377 // sel:%d 3378 Parser.Lex(); 3379 if (getParser().parseAbsoluteExpression(Int)) 3380 return MatchOperand_ParseFail; 3381 3382 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) { 3383 Int |= 0x100; 3384 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) { 3385 Int |= 0x110; 3386 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) { 3387 Int |= 0x120; 3388 } else if (Prefix == "wave_shl" && 1 == Int) { 3389 Int = 0x130; 3390 } else if (Prefix == "wave_rol" && 1 == Int) { 3391 Int = 0x134; 3392 } else if (Prefix == "wave_shr" && 1 == Int) { 3393 Int = 0x138; 3394 } else if (Prefix == "wave_ror" && 1 == Int) { 3395 Int = 0x13C; 3396 } else if (Prefix == "row_bcast") { 3397 if (Int == 15) { 3398 Int = 0x142; 3399 } else if (Int == 31) { 3400 Int = 0x143; 3401 } else { 3402 return MatchOperand_ParseFail; 3403 } 3404 } else { 3405 return MatchOperand_ParseFail; 3406 } 3407 } 3408 } 3409 3410 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl)); 3411 return MatchOperand_Success; 3412 } 3413 3414 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const { 3415 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask); 3416 } 3417 3418 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const { 3419 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask); 3420 } 3421 3422 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const { 3423 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl); 3424 } 3425 3426 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) { 3427 OptionalImmIndexMap OptionalIdx; 3428 3429 unsigned I = 1; 3430 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3431 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 3432 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 3433 } 3434 3435 for (unsigned E = Operands.size(); I != E; ++I) { 3436 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 3437 // Add the register arguments 3438 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) { 3439 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token. 3440 // Skip it. 3441 continue; 3442 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 3443 Op.addRegWithFPInputModsOperands(Inst, 2); 3444 } else if (Op.isDPPCtrl()) { 3445 Op.addImmOperands(Inst, 1); 3446 } else if (Op.isImm()) { 3447 // Handle optional arguments 3448 OptionalIdx[Op.getImmTy()] = I; 3449 } else { 3450 llvm_unreachable("Invalid operand type"); 3451 } 3452 } 3453 3454 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 3455 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 3456 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 3457 3458 // special case v_mac_{f16, f32}: 3459 // it has src2 register operand that is tied to dst operand 3460 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp || 3461 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) { 3462 auto it = Inst.begin(); 3463 std::advance( 3464 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); 3465 Inst.insert(it, Inst.getOperand(0)); // src2 = dst 3466 } 3467 } 3468 3469 //===----------------------------------------------------------------------===// 3470 // sdwa 3471 //===----------------------------------------------------------------------===// 3472 3473 OperandMatchResultTy 3474 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix, 3475 AMDGPUOperand::ImmTy Type) { 3476 using namespace llvm::AMDGPU::SDWA; 3477 3478 SMLoc S = Parser.getTok().getLoc(); 3479 StringRef Value; 3480 OperandMatchResultTy res; 3481 3482 res = parseStringWithPrefix(Prefix, Value); 3483 if (res != MatchOperand_Success) { 3484 return res; 3485 } 3486 3487 int64_t Int; 3488 Int = StringSwitch<int64_t>(Value) 3489 .Case("BYTE_0", SdwaSel::BYTE_0) 3490 .Case("BYTE_1", SdwaSel::BYTE_1) 3491 .Case("BYTE_2", SdwaSel::BYTE_2) 3492 .Case("BYTE_3", SdwaSel::BYTE_3) 3493 .Case("WORD_0", SdwaSel::WORD_0) 3494 .Case("WORD_1", SdwaSel::WORD_1) 3495 .Case("DWORD", SdwaSel::DWORD) 3496 .Default(0xffffffff); 3497 Parser.Lex(); // eat last token 3498 3499 if (Int == 0xffffffff) { 3500 return MatchOperand_ParseFail; 3501 } 3502 3503 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type)); 3504 return MatchOperand_Success; 3505 } 3506 3507 OperandMatchResultTy 3508 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 3509 using namespace llvm::AMDGPU::SDWA; 3510 3511 SMLoc S = Parser.getTok().getLoc(); 3512 StringRef Value; 3513 OperandMatchResultTy res; 3514 3515 res = parseStringWithPrefix("dst_unused", Value); 3516 if (res != MatchOperand_Success) { 3517 return res; 3518 } 3519 3520 int64_t Int; 3521 Int = StringSwitch<int64_t>(Value) 3522 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD) 3523 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT) 3524 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE) 3525 .Default(0xffffffff); 3526 Parser.Lex(); // eat last token 3527 3528 if (Int == 0xffffffff) { 3529 return MatchOperand_ParseFail; 3530 } 3531 3532 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused)); 3533 return MatchOperand_Success; 3534 } 3535 3536 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { 3537 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); 3538 } 3539 3540 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { 3541 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); 3542 } 3543 3544 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { 3545 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC); 3546 } 3547 3548 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, 3549 uint64_t BasicInstType) { 3550 OptionalImmIndexMap OptionalIdx; 3551 3552 unsigned I = 1; 3553 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 3554 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 3555 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 3556 } 3557 3558 for (unsigned E = Operands.size(); I != E; ++I) { 3559 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 3560 // Add the register arguments 3561 if ((BasicInstType == SIInstrFlags::VOPC || 3562 BasicInstType == SIInstrFlags::VOP2)&& 3563 Op.isReg() && 3564 Op.Reg.RegNo == AMDGPU::VCC) { 3565 // VOPC and VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. 3566 // Skip it. 3567 continue; 3568 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 3569 Op.addRegWithInputModsOperands(Inst, 2); 3570 } else if (Op.isImm()) { 3571 // Handle optional arguments 3572 OptionalIdx[Op.getImmTy()] = I; 3573 } else { 3574 llvm_unreachable("Invalid operand type"); 3575 } 3576 } 3577 3578 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 3579 3580 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) { 3581 // V_NOP_sdwa_vi has no optional sdwa arguments 3582 switch (BasicInstType) { 3583 case SIInstrFlags::VOP1: 3584 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6); 3585 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2); 3586 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6); 3587 break; 3588 3589 case SIInstrFlags::VOP2: 3590 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6); 3591 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2); 3592 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6); 3593 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6); 3594 break; 3595 3596 case SIInstrFlags::VOPC: 3597 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6); 3598 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6); 3599 break; 3600 3601 default: 3602 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); 3603 } 3604 } 3605 3606 // special case v_mac_{f16, f32}: 3607 // it has src2 register operand that is tied to dst operand 3608 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 3609 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 3610 auto it = Inst.begin(); 3611 std::advance( 3612 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); 3613 Inst.insert(it, Inst.getOperand(0)); // src2 = dst 3614 } 3615 3616 } 3617 3618 /// Force static initialization. 3619 extern "C" void LLVMInitializeAMDGPUAsmParser() { 3620 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget()); 3621 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); 3622 } 3623 3624 #define GET_REGISTER_MATCHER 3625 #define GET_MATCHER_IMPLEMENTATION 3626 #include "AMDGPUGenAsmMatcher.inc" 3627 3628 // This fuction should be defined after auto-generated include so that we have 3629 // MatchClassKind enum defined 3630 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 3631 unsigned Kind) { 3632 // Tokens like "glc" would be parsed as immediate operands in ParseOperand(). 3633 // But MatchInstructionImpl() expects to meet token and fails to validate 3634 // operand. This method checks if we are given immediate operand but expect to 3635 // get corresponding token. 3636 AMDGPUOperand &Operand = (AMDGPUOperand&)Op; 3637 switch (Kind) { 3638 case MCK_addr64: 3639 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand; 3640 case MCK_gds: 3641 return Operand.isGDS() ? Match_Success : Match_InvalidOperand; 3642 case MCK_glc: 3643 return Operand.isGLC() ? Match_Success : Match_InvalidOperand; 3644 case MCK_idxen: 3645 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand; 3646 case MCK_offen: 3647 return Operand.isOffen() ? Match_Success : Match_InvalidOperand; 3648 case MCK_SSrcB32: 3649 // When operands have expression values, they will return true for isToken, 3650 // because it is not possible to distinguish between a token and an 3651 // expression at parse time. MatchInstructionImpl() will always try to 3652 // match an operand as a token, when isToken returns true, and when the 3653 // name of the expression is not a valid token, the match will fail, 3654 // so we need to handle it here. 3655 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand; 3656 case MCK_SSrcF32: 3657 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand; 3658 case MCK_SoppBrTarget: 3659 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand; 3660 case MCK_VReg32OrOff: 3661 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand; 3662 case MCK_InterpSlot: 3663 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand; 3664 case MCK_Attr: 3665 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand; 3666 case MCK_AttrChan: 3667 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand; 3668 default: 3669 return Match_InvalidOperand; 3670 } 3671 } 3672