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