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