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