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