1 //===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "AMDKernelCodeT.h" 10 #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 11 #include "MCTargetDesc/AMDGPUTargetStreamer.h" 12 #include "SIDefines.h" 13 #include "SIInstrInfo.h" 14 #include "TargetInfo/AMDGPUTargetInfo.h" 15 #include "Utils/AMDGPUAsmUtils.h" 16 #include "Utils/AMDGPUBaseInfo.h" 17 #include "Utils/AMDKernelCodeTUtils.h" 18 #include "llvm/ADT/APFloat.h" 19 #include "llvm/ADT/SmallBitVector.h" 20 #include "llvm/ADT/StringSet.h" 21 #include "llvm/ADT/Twine.h" 22 #include "llvm/MC/MCAsmInfo.h" 23 #include "llvm/MC/MCContext.h" 24 #include "llvm/MC/MCExpr.h" 25 #include "llvm/MC/MCInst.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 28 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 29 #include "llvm/MC/MCSymbol.h" 30 #include "llvm/Support/AMDGPUMetadata.h" 31 #include "llvm/Support/AMDHSAKernelDescriptor.h" 32 #include "llvm/Support/Casting.h" 33 #include "llvm/Support/MachineValueType.h" 34 #include "llvm/Support/TargetParser.h" 35 #include "llvm/Support/TargetRegistry.h" 36 37 using namespace llvm; 38 using namespace llvm::AMDGPU; 39 using namespace llvm::amdhsa; 40 41 namespace { 42 43 class AMDGPUAsmParser; 44 45 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_AGPR, IS_TTMP, IS_SPECIAL }; 46 47 //===----------------------------------------------------------------------===// 48 // Operand 49 //===----------------------------------------------------------------------===// 50 51 class AMDGPUOperand : public MCParsedAsmOperand { 52 enum KindTy { 53 Token, 54 Immediate, 55 Register, 56 Expression 57 } Kind; 58 59 SMLoc StartLoc, EndLoc; 60 const AMDGPUAsmParser *AsmParser; 61 62 public: 63 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_) 64 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {} 65 66 using Ptr = std::unique_ptr<AMDGPUOperand>; 67 68 struct Modifiers { 69 bool Abs = false; 70 bool Neg = false; 71 bool Sext = false; 72 73 bool hasFPModifiers() const { return Abs || Neg; } 74 bool hasIntModifiers() const { return Sext; } 75 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); } 76 77 int64_t getFPModifiersOperand() const { 78 int64_t Operand = 0; 79 Operand |= Abs ? SISrcMods::ABS : 0u; 80 Operand |= Neg ? SISrcMods::NEG : 0u; 81 return Operand; 82 } 83 84 int64_t getIntModifiersOperand() const { 85 int64_t Operand = 0; 86 Operand |= Sext ? SISrcMods::SEXT : 0u; 87 return Operand; 88 } 89 90 int64_t getModifiersOperand() const { 91 assert(!(hasFPModifiers() && hasIntModifiers()) 92 && "fp and int modifiers should not be used simultaneously"); 93 if (hasFPModifiers()) { 94 return getFPModifiersOperand(); 95 } else if (hasIntModifiers()) { 96 return getIntModifiersOperand(); 97 } else { 98 return 0; 99 } 100 } 101 102 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods); 103 }; 104 105 enum ImmTy { 106 ImmTyNone, 107 ImmTyGDS, 108 ImmTyLDS, 109 ImmTyOffen, 110 ImmTyIdxen, 111 ImmTyAddr64, 112 ImmTyOffset, 113 ImmTyInstOffset, 114 ImmTyOffset0, 115 ImmTyOffset1, 116 ImmTyDLC, 117 ImmTyGLC, 118 ImmTySLC, 119 ImmTySWZ, 120 ImmTyTFE, 121 ImmTyD16, 122 ImmTyClampSI, 123 ImmTyOModSI, 124 ImmTyDPP8, 125 ImmTyDppCtrl, 126 ImmTyDppRowMask, 127 ImmTyDppBankMask, 128 ImmTyDppBoundCtrl, 129 ImmTyDppFi, 130 ImmTySdwaDstSel, 131 ImmTySdwaSrc0Sel, 132 ImmTySdwaSrc1Sel, 133 ImmTySdwaDstUnused, 134 ImmTyDMask, 135 ImmTyDim, 136 ImmTyUNorm, 137 ImmTyDA, 138 ImmTyR128A16, 139 ImmTyA16, 140 ImmTyLWE, 141 ImmTyExpTgt, 142 ImmTyExpCompr, 143 ImmTyExpVM, 144 ImmTyFORMAT, 145 ImmTyHwreg, 146 ImmTyOff, 147 ImmTySendMsg, 148 ImmTyInterpSlot, 149 ImmTyInterpAttr, 150 ImmTyAttrChan, 151 ImmTyOpSel, 152 ImmTyOpSelHi, 153 ImmTyNegLo, 154 ImmTyNegHi, 155 ImmTySwizzle, 156 ImmTyGprIdxMode, 157 ImmTyHigh, 158 ImmTyBLGP, 159 ImmTyCBSZ, 160 ImmTyABID, 161 ImmTyEndpgm, 162 }; 163 164 enum ImmKindTy { 165 ImmKindTyNone, 166 ImmKindTyLiteral, 167 ImmKindTyConst, 168 }; 169 170 private: 171 struct TokOp { 172 const char *Data; 173 unsigned Length; 174 }; 175 176 struct ImmOp { 177 int64_t Val; 178 ImmTy Type; 179 bool IsFPImm; 180 mutable ImmKindTy Kind; 181 Modifiers Mods; 182 }; 183 184 struct RegOp { 185 unsigned RegNo; 186 Modifiers Mods; 187 }; 188 189 union { 190 TokOp Tok; 191 ImmOp Imm; 192 RegOp Reg; 193 const MCExpr *Expr; 194 }; 195 196 public: 197 bool isToken() const override { 198 if (Kind == Token) 199 return true; 200 201 // When parsing operands, we can't always tell if something was meant to be 202 // a token, like 'gds', or an expression that references a global variable. 203 // In this case, we assume the string is an expression, and if we need to 204 // interpret is a token, then we treat the symbol name as the token. 205 return isSymbolRefExpr(); 206 } 207 208 bool isSymbolRefExpr() const { 209 return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr); 210 } 211 212 bool isImm() const override { 213 return Kind == Immediate; 214 } 215 216 void setImmKindNone() const { 217 assert(isImm()); 218 Imm.Kind = ImmKindTyNone; 219 } 220 221 void setImmKindLiteral() const { 222 assert(isImm()); 223 Imm.Kind = ImmKindTyLiteral; 224 } 225 226 void setImmKindConst() const { 227 assert(isImm()); 228 Imm.Kind = ImmKindTyConst; 229 } 230 231 bool IsImmKindLiteral() const { 232 return isImm() && Imm.Kind == ImmKindTyLiteral; 233 } 234 235 bool isImmKindConst() const { 236 return isImm() && Imm.Kind == ImmKindTyConst; 237 } 238 239 bool isInlinableImm(MVT type) const; 240 bool isLiteralImm(MVT type) const; 241 242 bool isRegKind() const { 243 return Kind == Register; 244 } 245 246 bool isReg() const override { 247 return isRegKind() && !hasModifiers(); 248 } 249 250 bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const { 251 return isRegClass(RCID) || isInlinableImm(type) || isLiteralImm(type); 252 } 253 254 bool isRegOrImmWithInt16InputMods() const { 255 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16); 256 } 257 258 bool isRegOrImmWithInt32InputMods() const { 259 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32); 260 } 261 262 bool isRegOrImmWithInt64InputMods() const { 263 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64); 264 } 265 266 bool isRegOrImmWithFP16InputMods() const { 267 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16); 268 } 269 270 bool isRegOrImmWithFP32InputMods() const { 271 return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32); 272 } 273 274 bool isRegOrImmWithFP64InputMods() const { 275 return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64); 276 } 277 278 bool isVReg() const { 279 return isRegClass(AMDGPU::VGPR_32RegClassID) || 280 isRegClass(AMDGPU::VReg_64RegClassID) || 281 isRegClass(AMDGPU::VReg_96RegClassID) || 282 isRegClass(AMDGPU::VReg_128RegClassID) || 283 isRegClass(AMDGPU::VReg_160RegClassID) || 284 isRegClass(AMDGPU::VReg_192RegClassID) || 285 isRegClass(AMDGPU::VReg_256RegClassID) || 286 isRegClass(AMDGPU::VReg_512RegClassID) || 287 isRegClass(AMDGPU::VReg_1024RegClassID); 288 } 289 290 bool isVReg32() const { 291 return isRegClass(AMDGPU::VGPR_32RegClassID); 292 } 293 294 bool isVReg32OrOff() const { 295 return isOff() || isVReg32(); 296 } 297 298 bool isNull() const { 299 return isRegKind() && getReg() == AMDGPU::SGPR_NULL; 300 } 301 302 bool isSDWAOperand(MVT type) const; 303 bool isSDWAFP16Operand() const; 304 bool isSDWAFP32Operand() const; 305 bool isSDWAInt16Operand() const; 306 bool isSDWAInt32Operand() const; 307 308 bool isImmTy(ImmTy ImmT) const { 309 return isImm() && Imm.Type == ImmT; 310 } 311 312 bool isImmModifier() const { 313 return isImm() && Imm.Type != ImmTyNone; 314 } 315 316 bool isClampSI() const { return isImmTy(ImmTyClampSI); } 317 bool isOModSI() const { return isImmTy(ImmTyOModSI); } 318 bool isDMask() const { return isImmTy(ImmTyDMask); } 319 bool isDim() const { return isImmTy(ImmTyDim); } 320 bool isUNorm() const { return isImmTy(ImmTyUNorm); } 321 bool isDA() const { return isImmTy(ImmTyDA); } 322 bool isR128A16() const { return isImmTy(ImmTyR128A16); } 323 bool isGFX10A16() const { return isImmTy(ImmTyA16); } 324 bool isLWE() const { return isImmTy(ImmTyLWE); } 325 bool isOff() const { return isImmTy(ImmTyOff); } 326 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); } 327 bool isExpVM() const { return isImmTy(ImmTyExpVM); } 328 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); } 329 bool isOffen() const { return isImmTy(ImmTyOffen); } 330 bool isIdxen() const { return isImmTy(ImmTyIdxen); } 331 bool isAddr64() const { return isImmTy(ImmTyAddr64); } 332 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); } 333 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); } 334 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } 335 336 bool isFlatOffset() const { return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset); } 337 bool isGDS() const { return isImmTy(ImmTyGDS); } 338 bool isLDS() const { return isImmTy(ImmTyLDS); } 339 bool isDLC() const { return isImmTy(ImmTyDLC); } 340 bool isGLC() const { return isImmTy(ImmTyGLC); } 341 // "GLC_1" is a MatchClass of the GLC_1 operand with the default and forced 342 // value of the GLC operand. 343 bool isGLC_1() const { return isImmTy(ImmTyGLC); } 344 bool isSLC() const { return isImmTy(ImmTySLC); } 345 bool isSWZ() const { return isImmTy(ImmTySWZ); } 346 bool isTFE() const { return isImmTy(ImmTyTFE); } 347 bool isD16() const { return isImmTy(ImmTyD16); } 348 bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<7>(getImm()); } 349 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); } 350 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); } 351 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); } 352 bool isFI() const { return isImmTy(ImmTyDppFi); } 353 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); } 354 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); } 355 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); } 356 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); } 357 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); } 358 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); } 359 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); } 360 bool isOpSel() const { return isImmTy(ImmTyOpSel); } 361 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); } 362 bool isNegLo() const { return isImmTy(ImmTyNegLo); } 363 bool isNegHi() const { return isImmTy(ImmTyNegHi); } 364 bool isHigh() const { return isImmTy(ImmTyHigh); } 365 366 bool isMod() const { 367 return isClampSI() || isOModSI(); 368 } 369 370 bool isRegOrImm() const { 371 return isReg() || isImm(); 372 } 373 374 bool isRegClass(unsigned RCID) const; 375 376 bool isInlineValue() const; 377 378 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const { 379 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers(); 380 } 381 382 bool isSCSrcB16() const { 383 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16); 384 } 385 386 bool isSCSrcV2B16() const { 387 return isSCSrcB16(); 388 } 389 390 bool isSCSrcB32() const { 391 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32); 392 } 393 394 bool isSCSrcB64() const { 395 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64); 396 } 397 398 bool isBoolReg() const; 399 400 bool isSCSrcF16() const { 401 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16); 402 } 403 404 bool isSCSrcV2F16() const { 405 return isSCSrcF16(); 406 } 407 408 bool isSCSrcF32() const { 409 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32); 410 } 411 412 bool isSCSrcF64() const { 413 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64); 414 } 415 416 bool isSSrcB32() const { 417 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr(); 418 } 419 420 bool isSSrcB16() const { 421 return isSCSrcB16() || isLiteralImm(MVT::i16); 422 } 423 424 bool isSSrcV2B16() const { 425 llvm_unreachable("cannot happen"); 426 return isSSrcB16(); 427 } 428 429 bool isSSrcB64() const { 430 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 431 // See isVSrc64(). 432 return isSCSrcB64() || isLiteralImm(MVT::i64); 433 } 434 435 bool isSSrcF32() const { 436 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr(); 437 } 438 439 bool isSSrcF64() const { 440 return isSCSrcB64() || isLiteralImm(MVT::f64); 441 } 442 443 bool isSSrcF16() const { 444 return isSCSrcB16() || isLiteralImm(MVT::f16); 445 } 446 447 bool isSSrcV2F16() const { 448 llvm_unreachable("cannot happen"); 449 return isSSrcF16(); 450 } 451 452 bool isSSrcOrLdsB32() const { 453 return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) || 454 isLiteralImm(MVT::i32) || isExpr(); 455 } 456 457 bool isVCSrcB32() const { 458 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32); 459 } 460 461 bool isVCSrcB64() const { 462 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64); 463 } 464 465 bool isVCSrcB16() const { 466 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16); 467 } 468 469 bool isVCSrcV2B16() const { 470 return isVCSrcB16(); 471 } 472 473 bool isVCSrcF32() const { 474 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32); 475 } 476 477 bool isVCSrcF64() const { 478 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64); 479 } 480 481 bool isVCSrcF16() const { 482 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16); 483 } 484 485 bool isVCSrcV2F16() const { 486 return isVCSrcF16(); 487 } 488 489 bool isVSrcB32() const { 490 return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr(); 491 } 492 493 bool isVSrcB64() const { 494 return isVCSrcF64() || isLiteralImm(MVT::i64); 495 } 496 497 bool isVSrcB16() const { 498 return isVCSrcB16() || isLiteralImm(MVT::i16); 499 } 500 501 bool isVSrcV2B16() const { 502 return isVSrcB16() || isLiteralImm(MVT::v2i16); 503 } 504 505 bool isVSrcF32() const { 506 return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr(); 507 } 508 509 bool isVSrcF64() const { 510 return isVCSrcF64() || isLiteralImm(MVT::f64); 511 } 512 513 bool isVSrcF16() const { 514 return isVCSrcF16() || isLiteralImm(MVT::f16); 515 } 516 517 bool isVSrcV2F16() const { 518 return isVSrcF16() || isLiteralImm(MVT::v2f16); 519 } 520 521 bool isVISrcB32() const { 522 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32); 523 } 524 525 bool isVISrcB16() const { 526 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16); 527 } 528 529 bool isVISrcV2B16() const { 530 return isVISrcB16(); 531 } 532 533 bool isVISrcF32() const { 534 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32); 535 } 536 537 bool isVISrcF16() const { 538 return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16); 539 } 540 541 bool isVISrcV2F16() const { 542 return isVISrcF16() || isVISrcB32(); 543 } 544 545 bool isAISrcB32() const { 546 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32); 547 } 548 549 bool isAISrcB16() const { 550 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16); 551 } 552 553 bool isAISrcV2B16() const { 554 return isAISrcB16(); 555 } 556 557 bool isAISrcF32() const { 558 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32); 559 } 560 561 bool isAISrcF16() const { 562 return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16); 563 } 564 565 bool isAISrcV2F16() const { 566 return isAISrcF16() || isAISrcB32(); 567 } 568 569 bool isAISrc_128B32() const { 570 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32); 571 } 572 573 bool isAISrc_128B16() const { 574 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16); 575 } 576 577 bool isAISrc_128V2B16() const { 578 return isAISrc_128B16(); 579 } 580 581 bool isAISrc_128F32() const { 582 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32); 583 } 584 585 bool isAISrc_128F16() const { 586 return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16); 587 } 588 589 bool isAISrc_128V2F16() const { 590 return isAISrc_128F16() || isAISrc_128B32(); 591 } 592 593 bool isAISrc_512B32() const { 594 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32); 595 } 596 597 bool isAISrc_512B16() const { 598 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16); 599 } 600 601 bool isAISrc_512V2B16() const { 602 return isAISrc_512B16(); 603 } 604 605 bool isAISrc_512F32() const { 606 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32); 607 } 608 609 bool isAISrc_512F16() const { 610 return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16); 611 } 612 613 bool isAISrc_512V2F16() const { 614 return isAISrc_512F16() || isAISrc_512B32(); 615 } 616 617 bool isAISrc_1024B32() const { 618 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32); 619 } 620 621 bool isAISrc_1024B16() const { 622 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16); 623 } 624 625 bool isAISrc_1024V2B16() const { 626 return isAISrc_1024B16(); 627 } 628 629 bool isAISrc_1024F32() const { 630 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32); 631 } 632 633 bool isAISrc_1024F16() const { 634 return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16); 635 } 636 637 bool isAISrc_1024V2F16() const { 638 return isAISrc_1024F16() || isAISrc_1024B32(); 639 } 640 641 bool isKImmFP32() const { 642 return isLiteralImm(MVT::f32); 643 } 644 645 bool isKImmFP16() const { 646 return isLiteralImm(MVT::f16); 647 } 648 649 bool isMem() const override { 650 return false; 651 } 652 653 bool isExpr() const { 654 return Kind == Expression; 655 } 656 657 bool isSoppBrTarget() const { 658 return isExpr() || isImm(); 659 } 660 661 bool isSWaitCnt() const; 662 bool isHwreg() const; 663 bool isSendMsg() const; 664 bool isSwizzle() const; 665 bool isSMRDOffset8() const; 666 bool isSMEMOffset() const; 667 bool isSMRDLiteralOffset() const; 668 bool isDPP8() const; 669 bool isDPPCtrl() const; 670 bool isBLGP() const; 671 bool isCBSZ() const; 672 bool isABID() const; 673 bool isGPRIdxMode() const; 674 bool isS16Imm() const; 675 bool isU16Imm() const; 676 bool isEndpgm() const; 677 678 StringRef getExpressionAsToken() const { 679 assert(isExpr()); 680 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr); 681 return S->getSymbol().getName(); 682 } 683 684 StringRef getToken() const { 685 assert(isToken()); 686 687 if (Kind == Expression) 688 return getExpressionAsToken(); 689 690 return StringRef(Tok.Data, Tok.Length); 691 } 692 693 int64_t getImm() const { 694 assert(isImm()); 695 return Imm.Val; 696 } 697 698 void setImm(int64_t Val) { 699 assert(isImm()); 700 Imm.Val = Val; 701 } 702 703 ImmTy getImmTy() const { 704 assert(isImm()); 705 return Imm.Type; 706 } 707 708 unsigned getReg() const override { 709 assert(isRegKind()); 710 return Reg.RegNo; 711 } 712 713 SMLoc getStartLoc() const override { 714 return StartLoc; 715 } 716 717 SMLoc getEndLoc() const override { 718 return EndLoc; 719 } 720 721 SMRange getLocRange() const { 722 return SMRange(StartLoc, EndLoc); 723 } 724 725 Modifiers getModifiers() const { 726 assert(isRegKind() || isImmTy(ImmTyNone)); 727 return isRegKind() ? Reg.Mods : Imm.Mods; 728 } 729 730 void setModifiers(Modifiers Mods) { 731 assert(isRegKind() || isImmTy(ImmTyNone)); 732 if (isRegKind()) 733 Reg.Mods = Mods; 734 else 735 Imm.Mods = Mods; 736 } 737 738 bool hasModifiers() const { 739 return getModifiers().hasModifiers(); 740 } 741 742 bool hasFPModifiers() const { 743 return getModifiers().hasFPModifiers(); 744 } 745 746 bool hasIntModifiers() const { 747 return getModifiers().hasIntModifiers(); 748 } 749 750 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const; 751 752 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const; 753 754 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const; 755 756 template <unsigned Bitwidth> 757 void addKImmFPOperands(MCInst &Inst, unsigned N) const; 758 759 void addKImmFP16Operands(MCInst &Inst, unsigned N) const { 760 addKImmFPOperands<16>(Inst, N); 761 } 762 763 void addKImmFP32Operands(MCInst &Inst, unsigned N) const { 764 addKImmFPOperands<32>(Inst, N); 765 } 766 767 void addRegOperands(MCInst &Inst, unsigned N) const; 768 769 void addBoolRegOperands(MCInst &Inst, unsigned N) const { 770 addRegOperands(Inst, N); 771 } 772 773 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 774 if (isRegKind()) 775 addRegOperands(Inst, N); 776 else if (isExpr()) 777 Inst.addOperand(MCOperand::createExpr(Expr)); 778 else 779 addImmOperands(Inst, N); 780 } 781 782 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 783 Modifiers Mods = getModifiers(); 784 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 785 if (isRegKind()) { 786 addRegOperands(Inst, N); 787 } else { 788 addImmOperands(Inst, N, false); 789 } 790 } 791 792 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 793 assert(!hasIntModifiers()); 794 addRegOrImmWithInputModsOperands(Inst, N); 795 } 796 797 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 798 assert(!hasFPModifiers()); 799 addRegOrImmWithInputModsOperands(Inst, N); 800 } 801 802 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 803 Modifiers Mods = getModifiers(); 804 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand())); 805 assert(isRegKind()); 806 addRegOperands(Inst, N); 807 } 808 809 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const { 810 assert(!hasIntModifiers()); 811 addRegWithInputModsOperands(Inst, N); 812 } 813 814 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const { 815 assert(!hasFPModifiers()); 816 addRegWithInputModsOperands(Inst, N); 817 } 818 819 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 820 if (isImm()) 821 addImmOperands(Inst, N); 822 else { 823 assert(isExpr()); 824 Inst.addOperand(MCOperand::createExpr(Expr)); 825 } 826 } 827 828 static void printImmTy(raw_ostream& OS, ImmTy Type) { 829 switch (Type) { 830 case ImmTyNone: OS << "None"; break; 831 case ImmTyGDS: OS << "GDS"; break; 832 case ImmTyLDS: OS << "LDS"; break; 833 case ImmTyOffen: OS << "Offen"; break; 834 case ImmTyIdxen: OS << "Idxen"; break; 835 case ImmTyAddr64: OS << "Addr64"; break; 836 case ImmTyOffset: OS << "Offset"; break; 837 case ImmTyInstOffset: OS << "InstOffset"; break; 838 case ImmTyOffset0: OS << "Offset0"; break; 839 case ImmTyOffset1: OS << "Offset1"; break; 840 case ImmTyDLC: OS << "DLC"; break; 841 case ImmTyGLC: OS << "GLC"; break; 842 case ImmTySLC: OS << "SLC"; break; 843 case ImmTySWZ: OS << "SWZ"; break; 844 case ImmTyTFE: OS << "TFE"; break; 845 case ImmTyD16: OS << "D16"; break; 846 case ImmTyFORMAT: OS << "FORMAT"; break; 847 case ImmTyClampSI: OS << "ClampSI"; break; 848 case ImmTyOModSI: OS << "OModSI"; break; 849 case ImmTyDPP8: OS << "DPP8"; break; 850 case ImmTyDppCtrl: OS << "DppCtrl"; break; 851 case ImmTyDppRowMask: OS << "DppRowMask"; break; 852 case ImmTyDppBankMask: OS << "DppBankMask"; break; 853 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break; 854 case ImmTyDppFi: OS << "FI"; break; 855 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break; 856 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break; 857 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break; 858 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break; 859 case ImmTyDMask: OS << "DMask"; break; 860 case ImmTyDim: OS << "Dim"; break; 861 case ImmTyUNorm: OS << "UNorm"; break; 862 case ImmTyDA: OS << "DA"; break; 863 case ImmTyR128A16: OS << "R128A16"; break; 864 case ImmTyA16: OS << "A16"; break; 865 case ImmTyLWE: OS << "LWE"; break; 866 case ImmTyOff: OS << "Off"; break; 867 case ImmTyExpTgt: OS << "ExpTgt"; break; 868 case ImmTyExpCompr: OS << "ExpCompr"; break; 869 case ImmTyExpVM: OS << "ExpVM"; break; 870 case ImmTyHwreg: OS << "Hwreg"; break; 871 case ImmTySendMsg: OS << "SendMsg"; break; 872 case ImmTyInterpSlot: OS << "InterpSlot"; break; 873 case ImmTyInterpAttr: OS << "InterpAttr"; break; 874 case ImmTyAttrChan: OS << "AttrChan"; break; 875 case ImmTyOpSel: OS << "OpSel"; break; 876 case ImmTyOpSelHi: OS << "OpSelHi"; break; 877 case ImmTyNegLo: OS << "NegLo"; break; 878 case ImmTyNegHi: OS << "NegHi"; break; 879 case ImmTySwizzle: OS << "Swizzle"; break; 880 case ImmTyGprIdxMode: OS << "GprIdxMode"; break; 881 case ImmTyHigh: OS << "High"; break; 882 case ImmTyBLGP: OS << "BLGP"; break; 883 case ImmTyCBSZ: OS << "CBSZ"; break; 884 case ImmTyABID: OS << "ABID"; break; 885 case ImmTyEndpgm: OS << "Endpgm"; break; 886 } 887 } 888 889 void print(raw_ostream &OS) const override { 890 switch (Kind) { 891 case Register: 892 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>'; 893 break; 894 case Immediate: 895 OS << '<' << getImm(); 896 if (getImmTy() != ImmTyNone) { 897 OS << " type: "; printImmTy(OS, getImmTy()); 898 } 899 OS << " mods: " << Imm.Mods << '>'; 900 break; 901 case Token: 902 OS << '\'' << getToken() << '\''; 903 break; 904 case Expression: 905 OS << "<expr " << *Expr << '>'; 906 break; 907 } 908 } 909 910 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser, 911 int64_t Val, SMLoc Loc, 912 ImmTy Type = ImmTyNone, 913 bool IsFPImm = false) { 914 auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser); 915 Op->Imm.Val = Val; 916 Op->Imm.IsFPImm = IsFPImm; 917 Op->Imm.Kind = ImmKindTyNone; 918 Op->Imm.Type = Type; 919 Op->Imm.Mods = Modifiers(); 920 Op->StartLoc = Loc; 921 Op->EndLoc = Loc; 922 return Op; 923 } 924 925 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser, 926 StringRef Str, SMLoc Loc, 927 bool HasExplicitEncodingSize = true) { 928 auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser); 929 Res->Tok.Data = Str.data(); 930 Res->Tok.Length = Str.size(); 931 Res->StartLoc = Loc; 932 Res->EndLoc = Loc; 933 return Res; 934 } 935 936 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser, 937 unsigned RegNo, SMLoc S, 938 SMLoc E) { 939 auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser); 940 Op->Reg.RegNo = RegNo; 941 Op->Reg.Mods = Modifiers(); 942 Op->StartLoc = S; 943 Op->EndLoc = E; 944 return Op; 945 } 946 947 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser, 948 const class MCExpr *Expr, SMLoc S) { 949 auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser); 950 Op->Expr = Expr; 951 Op->StartLoc = S; 952 Op->EndLoc = S; 953 return Op; 954 } 955 }; 956 957 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) { 958 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext; 959 return OS; 960 } 961 962 //===----------------------------------------------------------------------===// 963 // AsmParser 964 //===----------------------------------------------------------------------===// 965 966 // Holds info related to the current kernel, e.g. count of SGPRs used. 967 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next 968 // .amdgpu_hsa_kernel or at EOF. 969 class KernelScopeInfo { 970 int SgprIndexUnusedMin = -1; 971 int VgprIndexUnusedMin = -1; 972 MCContext *Ctx = nullptr; 973 974 void usesSgprAt(int i) { 975 if (i >= SgprIndexUnusedMin) { 976 SgprIndexUnusedMin = ++i; 977 if (Ctx) { 978 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count")); 979 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx)); 980 } 981 } 982 } 983 984 void usesVgprAt(int i) { 985 if (i >= VgprIndexUnusedMin) { 986 VgprIndexUnusedMin = ++i; 987 if (Ctx) { 988 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count")); 989 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx)); 990 } 991 } 992 } 993 994 public: 995 KernelScopeInfo() = default; 996 997 void initialize(MCContext &Context) { 998 Ctx = &Context; 999 usesSgprAt(SgprIndexUnusedMin = -1); 1000 usesVgprAt(VgprIndexUnusedMin = -1); 1001 } 1002 1003 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) { 1004 switch (RegKind) { 1005 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break; 1006 case IS_AGPR: // fall through 1007 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break; 1008 default: break; 1009 } 1010 } 1011 }; 1012 1013 class AMDGPUAsmParser : public MCTargetAsmParser { 1014 MCAsmParser &Parser; 1015 1016 // Number of extra operands parsed after the first optional operand. 1017 // This may be necessary to skip hardcoded mandatory operands. 1018 static const unsigned MAX_OPR_LOOKAHEAD = 8; 1019 1020 unsigned ForcedEncodingSize = 0; 1021 bool ForcedDPP = false; 1022 bool ForcedSDWA = false; 1023 KernelScopeInfo KernelScope; 1024 1025 /// @name Auto-generated Match Functions 1026 /// { 1027 1028 #define GET_ASSEMBLER_HEADER 1029 #include "AMDGPUGenAsmMatcher.inc" 1030 1031 /// } 1032 1033 private: 1034 bool ParseAsAbsoluteExpression(uint32_t &Ret); 1035 bool OutOfRangeError(SMRange Range); 1036 /// Calculate VGPR/SGPR blocks required for given target, reserved 1037 /// registers, and user-specified NextFreeXGPR values. 1038 /// 1039 /// \param Features [in] Target features, used for bug corrections. 1040 /// \param VCCUsed [in] Whether VCC special SGPR is reserved. 1041 /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved. 1042 /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved. 1043 /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel 1044 /// descriptor field, if valid. 1045 /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one. 1046 /// \param VGPRRange [in] Token range, used for VGPR diagnostics. 1047 /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one. 1048 /// \param SGPRRange [in] Token range, used for SGPR diagnostics. 1049 /// \param VGPRBlocks [out] Result VGPR block count. 1050 /// \param SGPRBlocks [out] Result SGPR block count. 1051 bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed, 1052 bool FlatScrUsed, bool XNACKUsed, 1053 Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR, 1054 SMRange VGPRRange, unsigned NextFreeSGPR, 1055 SMRange SGPRRange, unsigned &VGPRBlocks, 1056 unsigned &SGPRBlocks); 1057 bool ParseDirectiveAMDGCNTarget(); 1058 bool ParseDirectiveAMDHSAKernel(); 1059 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 1060 bool ParseDirectiveHSACodeObjectVersion(); 1061 bool ParseDirectiveHSACodeObjectISA(); 1062 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 1063 bool ParseDirectiveAMDKernelCodeT(); 1064 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; 1065 bool ParseDirectiveAMDGPUHsaKernel(); 1066 1067 bool ParseDirectiveISAVersion(); 1068 bool ParseDirectiveHSAMetadata(); 1069 bool ParseDirectivePALMetadataBegin(); 1070 bool ParseDirectivePALMetadata(); 1071 bool ParseDirectiveAMDGPULDS(); 1072 1073 /// Common code to parse out a block of text (typically YAML) between start and 1074 /// end directives. 1075 bool ParseToEndDirective(const char *AssemblerDirectiveBegin, 1076 const char *AssemblerDirectiveEnd, 1077 std::string &CollectString); 1078 1079 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, 1080 RegisterKind RegKind, unsigned Reg1, SMLoc Loc); 1081 bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 1082 unsigned &RegNum, unsigned &RegWidth, 1083 bool RestoreOnFailure = false); 1084 bool ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 1085 unsigned &RegNum, unsigned &RegWidth, 1086 SmallVectorImpl<AsmToken> &Tokens); 1087 unsigned ParseRegularReg(RegisterKind &RegKind, unsigned &RegNum, 1088 unsigned &RegWidth, 1089 SmallVectorImpl<AsmToken> &Tokens); 1090 unsigned ParseSpecialReg(RegisterKind &RegKind, unsigned &RegNum, 1091 unsigned &RegWidth, 1092 SmallVectorImpl<AsmToken> &Tokens); 1093 unsigned ParseRegList(RegisterKind &RegKind, unsigned &RegNum, 1094 unsigned &RegWidth, SmallVectorImpl<AsmToken> &Tokens); 1095 bool ParseRegRange(unsigned& Num, unsigned& Width); 1096 unsigned getRegularReg(RegisterKind RegKind, 1097 unsigned RegNum, 1098 unsigned RegWidth, 1099 SMLoc Loc); 1100 1101 bool isRegister(); 1102 bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const; 1103 Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind); 1104 void initializeGprCountSymbol(RegisterKind RegKind); 1105 bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex, 1106 unsigned RegWidth); 1107 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, 1108 bool IsAtomic, bool IsAtomicReturn, bool IsLds = false); 1109 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands, 1110 bool IsGdsHardcoded); 1111 1112 public: 1113 enum AMDGPUMatchResultTy { 1114 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 1115 }; 1116 enum OperandMode { 1117 OperandMode_Default, 1118 OperandMode_NSA, 1119 }; 1120 1121 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>; 1122 1123 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 1124 const MCInstrInfo &MII, 1125 const MCTargetOptions &Options) 1126 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) { 1127 MCAsmParserExtension::Initialize(Parser); 1128 1129 if (getFeatureBits().none()) { 1130 // Set default features. 1131 copySTI().ToggleFeature("southern-islands"); 1132 } 1133 1134 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits())); 1135 1136 { 1137 // TODO: make those pre-defined variables read-only. 1138 // Currently there is none suitable machinery in the core llvm-mc for this. 1139 // MCSymbol::isRedefinable is intended for another purpose, and 1140 // AsmParser::parseDirectiveSet() cannot be specialized for specific target. 1141 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 1142 MCContext &Ctx = getContext(); 1143 if (ISA.Major >= 6 && isHsaAbiVersion3(&getSTI())) { 1144 MCSymbol *Sym = 1145 Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number")); 1146 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1147 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor")); 1148 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1149 Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping")); 1150 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1151 } else { 1152 MCSymbol *Sym = 1153 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major")); 1154 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx)); 1155 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor")); 1156 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx)); 1157 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping")); 1158 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx)); 1159 } 1160 if (ISA.Major >= 6 && isHsaAbiVersion3(&getSTI())) { 1161 initializeGprCountSymbol(IS_VGPR); 1162 initializeGprCountSymbol(IS_SGPR); 1163 } else 1164 KernelScope.initialize(getContext()); 1165 } 1166 } 1167 1168 bool hasXNACK() const { 1169 return AMDGPU::hasXNACK(getSTI()); 1170 } 1171 1172 bool hasMIMG_R128() const { 1173 return AMDGPU::hasMIMG_R128(getSTI()); 1174 } 1175 1176 bool hasPackedD16() const { 1177 return AMDGPU::hasPackedD16(getSTI()); 1178 } 1179 1180 bool hasGFX10A16() const { 1181 return AMDGPU::hasGFX10A16(getSTI()); 1182 } 1183 1184 bool isSI() const { 1185 return AMDGPU::isSI(getSTI()); 1186 } 1187 1188 bool isCI() const { 1189 return AMDGPU::isCI(getSTI()); 1190 } 1191 1192 bool isVI() const { 1193 return AMDGPU::isVI(getSTI()); 1194 } 1195 1196 bool isGFX9() const { 1197 return AMDGPU::isGFX9(getSTI()); 1198 } 1199 1200 bool isGFX9Plus() const { 1201 return AMDGPU::isGFX9Plus(getSTI()); 1202 } 1203 1204 bool isGFX10() const { 1205 return AMDGPU::isGFX10(getSTI()); 1206 } 1207 1208 bool isGFX10Plus() const { return AMDGPU::isGFX10Plus(getSTI()); } 1209 1210 bool isGFX10_BEncoding() const { 1211 return AMDGPU::isGFX10_BEncoding(getSTI()); 1212 } 1213 1214 bool hasInv2PiInlineImm() const { 1215 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm]; 1216 } 1217 1218 bool hasFlatOffsets() const { 1219 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets]; 1220 } 1221 1222 bool hasSGPR102_SGPR103() const { 1223 return !isVI() && !isGFX9(); 1224 } 1225 1226 bool hasSGPR104_SGPR105() const { return isGFX10Plus(); } 1227 1228 bool hasIntClamp() const { 1229 return getFeatureBits()[AMDGPU::FeatureIntClamp]; 1230 } 1231 1232 AMDGPUTargetStreamer &getTargetStreamer() { 1233 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 1234 return static_cast<AMDGPUTargetStreamer &>(TS); 1235 } 1236 1237 const MCRegisterInfo *getMRI() const { 1238 // We need this const_cast because for some reason getContext() is not const 1239 // in MCAsmParser. 1240 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo(); 1241 } 1242 1243 const MCInstrInfo *getMII() const { 1244 return &MII; 1245 } 1246 1247 const FeatureBitset &getFeatureBits() const { 1248 return getSTI().getFeatureBits(); 1249 } 1250 1251 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; } 1252 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; } 1253 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; } 1254 1255 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; } 1256 bool isForcedVOP3() const { return ForcedEncodingSize == 64; } 1257 bool isForcedDPP() const { return ForcedDPP; } 1258 bool isForcedSDWA() const { return ForcedSDWA; } 1259 ArrayRef<unsigned> getMatchedVariants() const; 1260 StringRef getMatchedVariantName() const; 1261 1262 std::unique_ptr<AMDGPUOperand> parseRegister(bool RestoreOnFailure = false); 1263 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc, 1264 bool RestoreOnFailure); 1265 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 1266 OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, 1267 SMLoc &EndLoc) override; 1268 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 1269 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op, 1270 unsigned Kind) override; 1271 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 1272 OperandVector &Operands, MCStreamer &Out, 1273 uint64_t &ErrorInfo, 1274 bool MatchingInlineAsm) override; 1275 bool ParseDirective(AsmToken DirectiveID) override; 1276 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic, 1277 OperandMode Mode = OperandMode_Default); 1278 StringRef parseMnemonicSuffix(StringRef Name); 1279 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 1280 SMLoc NameLoc, OperandVector &Operands) override; 1281 //bool ProcessInstruction(MCInst &Inst); 1282 1283 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int); 1284 1285 OperandMatchResultTy 1286 parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1287 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1288 bool (*ConvertResult)(int64_t &) = nullptr); 1289 1290 OperandMatchResultTy 1291 parseOperandArrayWithPrefix(const char *Prefix, 1292 OperandVector &Operands, 1293 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 1294 bool (*ConvertResult)(int64_t&) = nullptr); 1295 1296 OperandMatchResultTy 1297 parseNamedBit(const char *Name, OperandVector &Operands, 1298 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone); 1299 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, 1300 StringRef &Value); 1301 1302 bool isModifier(); 1303 bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1304 bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1305 bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const; 1306 bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const; 1307 bool parseSP3NegModifier(); 1308 OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false); 1309 OperandMatchResultTy parseReg(OperandVector &Operands); 1310 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false); 1311 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true); 1312 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true); 1313 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands); 1314 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands); 1315 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands); 1316 OperandMatchResultTy parseDfmtNfmt(int64_t &Format); 1317 OperandMatchResultTy parseUfmt(int64_t &Format); 1318 OperandMatchResultTy parseSymbolicSplitFormat(StringRef FormatStr, SMLoc Loc, int64_t &Format); 1319 OperandMatchResultTy parseSymbolicUnifiedFormat(StringRef FormatStr, SMLoc Loc, int64_t &Format); 1320 OperandMatchResultTy parseFORMAT(OperandVector &Operands); 1321 OperandMatchResultTy parseSymbolicOrNumericFormat(int64_t &Format); 1322 OperandMatchResultTy parseNumericFormat(int64_t &Format); 1323 bool tryParseFmt(const char *Pref, int64_t MaxVal, int64_t &Val); 1324 bool matchDfmtNfmt(int64_t &Dfmt, int64_t &Nfmt, StringRef FormatStr, SMLoc Loc); 1325 1326 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 1327 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); } 1328 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); } 1329 void cvtExp(MCInst &Inst, const OperandVector &Operands); 1330 1331 bool parseCnt(int64_t &IntVal); 1332 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 1333 OperandMatchResultTy parseHwreg(OperandVector &Operands); 1334 1335 private: 1336 struct OperandInfoTy { 1337 SMLoc Loc; 1338 int64_t Id; 1339 bool IsSymbolic = false; 1340 bool IsDefined = false; 1341 1342 OperandInfoTy(int64_t Id_) : Id(Id_) {} 1343 }; 1344 1345 bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream); 1346 bool validateSendMsg(const OperandInfoTy &Msg, 1347 const OperandInfoTy &Op, 1348 const OperandInfoTy &Stream); 1349 1350 bool parseHwregBody(OperandInfoTy &HwReg, 1351 OperandInfoTy &Offset, 1352 OperandInfoTy &Width); 1353 bool validateHwreg(const OperandInfoTy &HwReg, 1354 const OperandInfoTy &Offset, 1355 const OperandInfoTy &Width); 1356 1357 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val); 1358 SMLoc getFlatOffsetLoc(const OperandVector &Operands) const; 1359 SMLoc getSMEMOffsetLoc(const OperandVector &Operands) const; 1360 1361 SMLoc getOperandLoc(std::function<bool(const AMDGPUOperand&)> Test, 1362 const OperandVector &Operands) const; 1363 SMLoc getImmLoc(AMDGPUOperand::ImmTy Type, const OperandVector &Operands) const; 1364 SMLoc getRegLoc(unsigned Reg, const OperandVector &Operands) const; 1365 SMLoc getLitLoc(const OperandVector &Operands) const; 1366 SMLoc getConstLoc(const OperandVector &Operands) const; 1367 1368 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands); 1369 bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands); 1370 bool validateSMEMOffset(const MCInst &Inst, const OperandVector &Operands); 1371 bool validateSOPLiteral(const MCInst &Inst) const; 1372 bool validateConstantBusLimitations(const MCInst &Inst, const OperandVector &Operands); 1373 bool validateEarlyClobberLimitations(const MCInst &Inst, const OperandVector &Operands); 1374 bool validateIntClampSupported(const MCInst &Inst); 1375 bool validateMIMGAtomicDMask(const MCInst &Inst); 1376 bool validateMIMGGatherDMask(const MCInst &Inst); 1377 bool validateMovrels(const MCInst &Inst, const OperandVector &Operands); 1378 bool validateMIMGDataSize(const MCInst &Inst); 1379 bool validateMIMGAddrSize(const MCInst &Inst); 1380 bool validateMIMGD16(const MCInst &Inst); 1381 bool validateMIMGDim(const MCInst &Inst); 1382 bool validateLdsDirect(const MCInst &Inst); 1383 bool validateOpSel(const MCInst &Inst); 1384 bool validateVccOperand(unsigned Reg) const; 1385 bool validateVOP3Literal(const MCInst &Inst, const OperandVector &Operands); 1386 bool validateMAIAccWrite(const MCInst &Inst, const OperandVector &Operands); 1387 bool validateDivScale(const MCInst &Inst); 1388 bool validateCoherencyBits(const MCInst &Inst, const OperandVector &Operands, 1389 const SMLoc &IDLoc); 1390 unsigned getConstantBusLimit(unsigned Opcode) const; 1391 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx); 1392 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const; 1393 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const; 1394 1395 bool isSupportedMnemo(StringRef Mnemo, 1396 const FeatureBitset &FBS); 1397 bool isSupportedMnemo(StringRef Mnemo, 1398 const FeatureBitset &FBS, 1399 ArrayRef<unsigned> Variants); 1400 bool checkUnsupportedInstruction(StringRef Name, const SMLoc &IDLoc); 1401 1402 bool isId(const StringRef Id) const; 1403 bool isId(const AsmToken &Token, const StringRef Id) const; 1404 bool isToken(const AsmToken::TokenKind Kind) const; 1405 bool trySkipId(const StringRef Id); 1406 bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind); 1407 bool trySkipToken(const AsmToken::TokenKind Kind); 1408 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg); 1409 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string"); 1410 bool parseId(StringRef &Val, const StringRef ErrMsg = ""); 1411 1412 void peekTokens(MutableArrayRef<AsmToken> Tokens); 1413 AsmToken::TokenKind getTokenKind() const; 1414 bool parseExpr(int64_t &Imm, StringRef Expected = ""); 1415 bool parseExpr(OperandVector &Operands); 1416 StringRef getTokenStr() const; 1417 AsmToken peekToken(); 1418 AsmToken getToken() const; 1419 SMLoc getLoc() const; 1420 void lex(); 1421 1422 public: 1423 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands); 1424 OperandMatchResultTy parseOptionalOpr(OperandVector &Operands); 1425 1426 OperandMatchResultTy parseExpTgt(OperandVector &Operands); 1427 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands); 1428 OperandMatchResultTy parseInterpSlot(OperandVector &Operands); 1429 OperandMatchResultTy parseInterpAttr(OperandVector &Operands); 1430 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 1431 OperandMatchResultTy parseBoolReg(OperandVector &Operands); 1432 1433 bool parseSwizzleOperand(int64_t &Op, 1434 const unsigned MinVal, 1435 const unsigned MaxVal, 1436 const StringRef ErrMsg, 1437 SMLoc &Loc); 1438 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 1439 const unsigned MinVal, 1440 const unsigned MaxVal, 1441 const StringRef ErrMsg); 1442 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands); 1443 bool parseSwizzleOffset(int64_t &Imm); 1444 bool parseSwizzleMacro(int64_t &Imm); 1445 bool parseSwizzleQuadPerm(int64_t &Imm); 1446 bool parseSwizzleBitmaskPerm(int64_t &Imm); 1447 bool parseSwizzleBroadcast(int64_t &Imm); 1448 bool parseSwizzleSwap(int64_t &Imm); 1449 bool parseSwizzleReverse(int64_t &Imm); 1450 1451 OperandMatchResultTy parseGPRIdxMode(OperandVector &Operands); 1452 int64_t parseGPRIdxMacro(); 1453 1454 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); } 1455 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); } 1456 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); } 1457 void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); } 1458 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands); 1459 1460 AMDGPUOperand::Ptr defaultDLC() const; 1461 AMDGPUOperand::Ptr defaultGLC() const; 1462 AMDGPUOperand::Ptr defaultGLC_1() const; 1463 AMDGPUOperand::Ptr defaultSLC() const; 1464 1465 AMDGPUOperand::Ptr defaultSMRDOffset8() const; 1466 AMDGPUOperand::Ptr defaultSMEMOffset() const; 1467 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const; 1468 AMDGPUOperand::Ptr defaultFlatOffset() const; 1469 1470 OperandMatchResultTy parseOModOperand(OperandVector &Operands); 1471 1472 void cvtVOP3(MCInst &Inst, const OperandVector &Operands, 1473 OptionalImmIndexMap &OptionalIdx); 1474 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands); 1475 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 1476 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands); 1477 1478 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands); 1479 1480 void cvtMIMG(MCInst &Inst, const OperandVector &Operands, 1481 bool IsAtomic = false); 1482 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands); 1483 void cvtIntersectRay(MCInst &Inst, const OperandVector &Operands); 1484 1485 OperandMatchResultTy parseDim(OperandVector &Operands); 1486 OperandMatchResultTy parseDPP8(OperandVector &Operands); 1487 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands); 1488 AMDGPUOperand::Ptr defaultRowMask() const; 1489 AMDGPUOperand::Ptr defaultBankMask() const; 1490 AMDGPUOperand::Ptr defaultBoundCtrl() const; 1491 AMDGPUOperand::Ptr defaultFI() const; 1492 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false); 1493 void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { cvtDPP(Inst, Operands, true); } 1494 1495 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix, 1496 AMDGPUOperand::ImmTy Type); 1497 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); 1498 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands); 1499 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands); 1500 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands); 1501 void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands); 1502 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands); 1503 void cvtSDWA(MCInst &Inst, const OperandVector &Operands, 1504 uint64_t BasicInstType, 1505 bool SkipDstVcc = false, 1506 bool SkipSrcVcc = false); 1507 1508 AMDGPUOperand::Ptr defaultBLGP() const; 1509 AMDGPUOperand::Ptr defaultCBSZ() const; 1510 AMDGPUOperand::Ptr defaultABID() const; 1511 1512 OperandMatchResultTy parseEndpgmOp(OperandVector &Operands); 1513 AMDGPUOperand::Ptr defaultEndpgmImmOperands() const; 1514 }; 1515 1516 struct OptionalOperand { 1517 const char *Name; 1518 AMDGPUOperand::ImmTy Type; 1519 bool IsBit; 1520 bool (*ConvertResult)(int64_t&); 1521 }; 1522 1523 } // end anonymous namespace 1524 1525 // May be called with integer type with equivalent bitwidth. 1526 static const fltSemantics *getFltSemantics(unsigned Size) { 1527 switch (Size) { 1528 case 4: 1529 return &APFloat::IEEEsingle(); 1530 case 8: 1531 return &APFloat::IEEEdouble(); 1532 case 2: 1533 return &APFloat::IEEEhalf(); 1534 default: 1535 llvm_unreachable("unsupported fp type"); 1536 } 1537 } 1538 1539 static const fltSemantics *getFltSemantics(MVT VT) { 1540 return getFltSemantics(VT.getSizeInBits() / 8); 1541 } 1542 1543 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) { 1544 switch (OperandType) { 1545 case AMDGPU::OPERAND_REG_IMM_INT32: 1546 case AMDGPU::OPERAND_REG_IMM_FP32: 1547 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1548 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1549 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1550 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1551 return &APFloat::IEEEsingle(); 1552 case AMDGPU::OPERAND_REG_IMM_INT64: 1553 case AMDGPU::OPERAND_REG_IMM_FP64: 1554 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1555 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1556 return &APFloat::IEEEdouble(); 1557 case AMDGPU::OPERAND_REG_IMM_INT16: 1558 case AMDGPU::OPERAND_REG_IMM_FP16: 1559 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1560 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1561 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1562 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1563 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1564 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1565 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1566 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 1567 case AMDGPU::OPERAND_REG_IMM_V2INT16: 1568 case AMDGPU::OPERAND_REG_IMM_V2FP16: 1569 return &APFloat::IEEEhalf(); 1570 default: 1571 llvm_unreachable("unsupported fp type"); 1572 } 1573 } 1574 1575 //===----------------------------------------------------------------------===// 1576 // Operand 1577 //===----------------------------------------------------------------------===// 1578 1579 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) { 1580 bool Lost; 1581 1582 // Convert literal to single precision 1583 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT), 1584 APFloat::rmNearestTiesToEven, 1585 &Lost); 1586 // We allow precision lost but not overflow or underflow 1587 if (Status != APFloat::opOK && 1588 Lost && 1589 ((Status & APFloat::opOverflow) != 0 || 1590 (Status & APFloat::opUnderflow) != 0)) { 1591 return false; 1592 } 1593 1594 return true; 1595 } 1596 1597 static bool isSafeTruncation(int64_t Val, unsigned Size) { 1598 return isUIntN(Size, Val) || isIntN(Size, Val); 1599 } 1600 1601 static bool isInlineableLiteralOp16(int64_t Val, MVT VT, bool HasInv2Pi) { 1602 if (VT.getScalarType() == MVT::i16) { 1603 // FP immediate values are broken. 1604 return isInlinableIntLiteral(Val); 1605 } 1606 1607 // f16/v2f16 operands work correctly for all values. 1608 return AMDGPU::isInlinableLiteral16(Val, HasInv2Pi); 1609 } 1610 1611 bool AMDGPUOperand::isInlinableImm(MVT type) const { 1612 1613 // This is a hack to enable named inline values like 1614 // shared_base with both 32-bit and 64-bit operands. 1615 // Note that these values are defined as 1616 // 32-bit operands only. 1617 if (isInlineValue()) { 1618 return true; 1619 } 1620 1621 if (!isImmTy(ImmTyNone)) { 1622 // Only plain immediates are inlinable (e.g. "clamp" attribute is not) 1623 return false; 1624 } 1625 // TODO: We should avoid using host float here. It would be better to 1626 // check the float bit values which is what a few other places do. 1627 // We've had bot failures before due to weird NaN support on mips hosts. 1628 1629 APInt Literal(64, Imm.Val); 1630 1631 if (Imm.IsFPImm) { // We got fp literal token 1632 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1633 return AMDGPU::isInlinableLiteral64(Imm.Val, 1634 AsmParser->hasInv2PiInlineImm()); 1635 } 1636 1637 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1638 if (!canLosslesslyConvertToFPType(FPLiteral, type)) 1639 return false; 1640 1641 if (type.getScalarSizeInBits() == 16) { 1642 return isInlineableLiteralOp16( 1643 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1644 type, AsmParser->hasInv2PiInlineImm()); 1645 } 1646 1647 // Check if single precision literal is inlinable 1648 return AMDGPU::isInlinableLiteral32( 1649 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()), 1650 AsmParser->hasInv2PiInlineImm()); 1651 } 1652 1653 // We got int literal token. 1654 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand 1655 return AMDGPU::isInlinableLiteral64(Imm.Val, 1656 AsmParser->hasInv2PiInlineImm()); 1657 } 1658 1659 if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) { 1660 return false; 1661 } 1662 1663 if (type.getScalarSizeInBits() == 16) { 1664 return isInlineableLiteralOp16( 1665 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()), 1666 type, AsmParser->hasInv2PiInlineImm()); 1667 } 1668 1669 return AMDGPU::isInlinableLiteral32( 1670 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()), 1671 AsmParser->hasInv2PiInlineImm()); 1672 } 1673 1674 bool AMDGPUOperand::isLiteralImm(MVT type) const { 1675 // Check that this immediate can be added as literal 1676 if (!isImmTy(ImmTyNone)) { 1677 return false; 1678 } 1679 1680 if (!Imm.IsFPImm) { 1681 // We got int literal token. 1682 1683 if (type == MVT::f64 && hasFPModifiers()) { 1684 // Cannot apply fp modifiers to int literals preserving the same semantics 1685 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity, 1686 // disable these cases. 1687 return false; 1688 } 1689 1690 unsigned Size = type.getSizeInBits(); 1691 if (Size == 64) 1692 Size = 32; 1693 1694 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP 1695 // types. 1696 return isSafeTruncation(Imm.Val, Size); 1697 } 1698 1699 // We got fp literal token 1700 if (type == MVT::f64) { // Expected 64-bit fp operand 1701 // We would set low 64-bits of literal to zeroes but we accept this literals 1702 return true; 1703 } 1704 1705 if (type == MVT::i64) { // Expected 64-bit int operand 1706 // We don't allow fp literals in 64-bit integer instructions. It is 1707 // unclear how we should encode them. 1708 return false; 1709 } 1710 1711 // We allow fp literals with f16x2 operands assuming that the specified 1712 // literal goes into the lower half and the upper half is zero. We also 1713 // require that the literal may be losslesly converted to f16. 1714 MVT ExpectedType = (type == MVT::v2f16)? MVT::f16 : 1715 (type == MVT::v2i16)? MVT::i16 : type; 1716 1717 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val)); 1718 return canLosslesslyConvertToFPType(FPLiteral, ExpectedType); 1719 } 1720 1721 bool AMDGPUOperand::isRegClass(unsigned RCID) const { 1722 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg()); 1723 } 1724 1725 bool AMDGPUOperand::isSDWAOperand(MVT type) const { 1726 if (AsmParser->isVI()) 1727 return isVReg32(); 1728 else if (AsmParser->isGFX9Plus()) 1729 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type); 1730 else 1731 return false; 1732 } 1733 1734 bool AMDGPUOperand::isSDWAFP16Operand() const { 1735 return isSDWAOperand(MVT::f16); 1736 } 1737 1738 bool AMDGPUOperand::isSDWAFP32Operand() const { 1739 return isSDWAOperand(MVT::f32); 1740 } 1741 1742 bool AMDGPUOperand::isSDWAInt16Operand() const { 1743 return isSDWAOperand(MVT::i16); 1744 } 1745 1746 bool AMDGPUOperand::isSDWAInt32Operand() const { 1747 return isSDWAOperand(MVT::i32); 1748 } 1749 1750 bool AMDGPUOperand::isBoolReg() const { 1751 return (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize64] && isSCSrcB64()) || 1752 (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize32] && isSCSrcB32()); 1753 } 1754 1755 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const 1756 { 1757 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 1758 assert(Size == 2 || Size == 4 || Size == 8); 1759 1760 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1)); 1761 1762 if (Imm.Mods.Abs) { 1763 Val &= ~FpSignMask; 1764 } 1765 if (Imm.Mods.Neg) { 1766 Val ^= FpSignMask; 1767 } 1768 1769 return Val; 1770 } 1771 1772 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const { 1773 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()), 1774 Inst.getNumOperands())) { 1775 addLiteralImmOperand(Inst, Imm.Val, 1776 ApplyModifiers & 1777 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers()); 1778 } else { 1779 assert(!isImmTy(ImmTyNone) || !hasModifiers()); 1780 Inst.addOperand(MCOperand::createImm(Imm.Val)); 1781 setImmKindNone(); 1782 } 1783 } 1784 1785 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const { 1786 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode()); 1787 auto OpNum = Inst.getNumOperands(); 1788 // Check that this operand accepts literals 1789 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum)); 1790 1791 if (ApplyModifiers) { 1792 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum)); 1793 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum); 1794 Val = applyInputFPModifiers(Val, Size); 1795 } 1796 1797 APInt Literal(64, Val); 1798 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType; 1799 1800 if (Imm.IsFPImm) { // We got fp literal token 1801 switch (OpTy) { 1802 case AMDGPU::OPERAND_REG_IMM_INT64: 1803 case AMDGPU::OPERAND_REG_IMM_FP64: 1804 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1805 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1806 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(), 1807 AsmParser->hasInv2PiInlineImm())) { 1808 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue())); 1809 setImmKindConst(); 1810 return; 1811 } 1812 1813 // Non-inlineable 1814 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand 1815 // For fp operands we check if low 32 bits are zeros 1816 if (Literal.getLoBits(32) != 0) { 1817 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(), 1818 "Can't encode literal as exact 64-bit floating-point operand. " 1819 "Low 32-bits will be set to zero"); 1820 } 1821 1822 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue())); 1823 setImmKindLiteral(); 1824 return; 1825 } 1826 1827 // We don't allow fp literals in 64-bit integer instructions. It is 1828 // unclear how we should encode them. This case should be checked earlier 1829 // in predicate methods (isLiteralImm()) 1830 llvm_unreachable("fp literal in 64-bit integer instruction."); 1831 1832 case AMDGPU::OPERAND_REG_IMM_INT32: 1833 case AMDGPU::OPERAND_REG_IMM_FP32: 1834 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1835 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1836 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1837 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1838 case AMDGPU::OPERAND_REG_IMM_INT16: 1839 case AMDGPU::OPERAND_REG_IMM_FP16: 1840 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1841 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1842 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1843 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1844 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1845 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1846 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1847 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: 1848 case AMDGPU::OPERAND_REG_IMM_V2INT16: 1849 case AMDGPU::OPERAND_REG_IMM_V2FP16: { 1850 bool lost; 1851 APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1852 // Convert literal to single precision 1853 FPLiteral.convert(*getOpFltSemantics(OpTy), 1854 APFloat::rmNearestTiesToEven, &lost); 1855 // We allow precision lost but not overflow or underflow. This should be 1856 // checked earlier in isLiteralImm() 1857 1858 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue(); 1859 Inst.addOperand(MCOperand::createImm(ImmVal)); 1860 setImmKindLiteral(); 1861 return; 1862 } 1863 default: 1864 llvm_unreachable("invalid operand size"); 1865 } 1866 1867 return; 1868 } 1869 1870 // We got int literal token. 1871 // Only sign extend inline immediates. 1872 switch (OpTy) { 1873 case AMDGPU::OPERAND_REG_IMM_INT32: 1874 case AMDGPU::OPERAND_REG_IMM_FP32: 1875 case AMDGPU::OPERAND_REG_INLINE_C_INT32: 1876 case AMDGPU::OPERAND_REG_INLINE_C_FP32: 1877 case AMDGPU::OPERAND_REG_INLINE_AC_INT32: 1878 case AMDGPU::OPERAND_REG_INLINE_AC_FP32: 1879 case AMDGPU::OPERAND_REG_IMM_V2INT16: 1880 case AMDGPU::OPERAND_REG_IMM_V2FP16: 1881 if (isSafeTruncation(Val, 32) && 1882 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val), 1883 AsmParser->hasInv2PiInlineImm())) { 1884 Inst.addOperand(MCOperand::createImm(Val)); 1885 setImmKindConst(); 1886 return; 1887 } 1888 1889 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff)); 1890 setImmKindLiteral(); 1891 return; 1892 1893 case AMDGPU::OPERAND_REG_IMM_INT64: 1894 case AMDGPU::OPERAND_REG_IMM_FP64: 1895 case AMDGPU::OPERAND_REG_INLINE_C_INT64: 1896 case AMDGPU::OPERAND_REG_INLINE_C_FP64: 1897 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) { 1898 Inst.addOperand(MCOperand::createImm(Val)); 1899 setImmKindConst(); 1900 return; 1901 } 1902 1903 Inst.addOperand(MCOperand::createImm(Lo_32(Val))); 1904 setImmKindLiteral(); 1905 return; 1906 1907 case AMDGPU::OPERAND_REG_IMM_INT16: 1908 case AMDGPU::OPERAND_REG_IMM_FP16: 1909 case AMDGPU::OPERAND_REG_INLINE_C_INT16: 1910 case AMDGPU::OPERAND_REG_INLINE_C_FP16: 1911 case AMDGPU::OPERAND_REG_INLINE_AC_INT16: 1912 case AMDGPU::OPERAND_REG_INLINE_AC_FP16: 1913 if (isSafeTruncation(Val, 16) && 1914 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 1915 AsmParser->hasInv2PiInlineImm())) { 1916 Inst.addOperand(MCOperand::createImm(Val)); 1917 setImmKindConst(); 1918 return; 1919 } 1920 1921 Inst.addOperand(MCOperand::createImm(Val & 0xffff)); 1922 setImmKindLiteral(); 1923 return; 1924 1925 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16: 1926 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: 1927 case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16: 1928 case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: { 1929 assert(isSafeTruncation(Val, 16)); 1930 assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val), 1931 AsmParser->hasInv2PiInlineImm())); 1932 1933 Inst.addOperand(MCOperand::createImm(Val)); 1934 return; 1935 } 1936 default: 1937 llvm_unreachable("invalid operand size"); 1938 } 1939 } 1940 1941 template <unsigned Bitwidth> 1942 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const { 1943 APInt Literal(64, Imm.Val); 1944 setImmKindNone(); 1945 1946 if (!Imm.IsFPImm) { 1947 // We got int literal token. 1948 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue())); 1949 return; 1950 } 1951 1952 bool Lost; 1953 APFloat FPLiteral(APFloat::IEEEdouble(), Literal); 1954 FPLiteral.convert(*getFltSemantics(Bitwidth / 8), 1955 APFloat::rmNearestTiesToEven, &Lost); 1956 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue())); 1957 } 1958 1959 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const { 1960 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI()))); 1961 } 1962 1963 static bool isInlineValue(unsigned Reg) { 1964 switch (Reg) { 1965 case AMDGPU::SRC_SHARED_BASE: 1966 case AMDGPU::SRC_SHARED_LIMIT: 1967 case AMDGPU::SRC_PRIVATE_BASE: 1968 case AMDGPU::SRC_PRIVATE_LIMIT: 1969 case AMDGPU::SRC_POPS_EXITING_WAVE_ID: 1970 return true; 1971 case AMDGPU::SRC_VCCZ: 1972 case AMDGPU::SRC_EXECZ: 1973 case AMDGPU::SRC_SCC: 1974 return true; 1975 case AMDGPU::SGPR_NULL: 1976 return true; 1977 default: 1978 return false; 1979 } 1980 } 1981 1982 bool AMDGPUOperand::isInlineValue() const { 1983 return isRegKind() && ::isInlineValue(getReg()); 1984 } 1985 1986 //===----------------------------------------------------------------------===// 1987 // AsmParser 1988 //===----------------------------------------------------------------------===// 1989 1990 static int getRegClass(RegisterKind Is, unsigned RegWidth) { 1991 if (Is == IS_VGPR) { 1992 switch (RegWidth) { 1993 default: return -1; 1994 case 1: return AMDGPU::VGPR_32RegClassID; 1995 case 2: return AMDGPU::VReg_64RegClassID; 1996 case 3: return AMDGPU::VReg_96RegClassID; 1997 case 4: return AMDGPU::VReg_128RegClassID; 1998 case 5: return AMDGPU::VReg_160RegClassID; 1999 case 6: return AMDGPU::VReg_192RegClassID; 2000 case 8: return AMDGPU::VReg_256RegClassID; 2001 case 16: return AMDGPU::VReg_512RegClassID; 2002 case 32: return AMDGPU::VReg_1024RegClassID; 2003 } 2004 } else if (Is == IS_TTMP) { 2005 switch (RegWidth) { 2006 default: return -1; 2007 case 1: return AMDGPU::TTMP_32RegClassID; 2008 case 2: return AMDGPU::TTMP_64RegClassID; 2009 case 4: return AMDGPU::TTMP_128RegClassID; 2010 case 8: return AMDGPU::TTMP_256RegClassID; 2011 case 16: return AMDGPU::TTMP_512RegClassID; 2012 } 2013 } else if (Is == IS_SGPR) { 2014 switch (RegWidth) { 2015 default: return -1; 2016 case 1: return AMDGPU::SGPR_32RegClassID; 2017 case 2: return AMDGPU::SGPR_64RegClassID; 2018 case 3: return AMDGPU::SGPR_96RegClassID; 2019 case 4: return AMDGPU::SGPR_128RegClassID; 2020 case 5: return AMDGPU::SGPR_160RegClassID; 2021 case 6: return AMDGPU::SGPR_192RegClassID; 2022 case 8: return AMDGPU::SGPR_256RegClassID; 2023 case 16: return AMDGPU::SGPR_512RegClassID; 2024 } 2025 } else if (Is == IS_AGPR) { 2026 switch (RegWidth) { 2027 default: return -1; 2028 case 1: return AMDGPU::AGPR_32RegClassID; 2029 case 2: return AMDGPU::AReg_64RegClassID; 2030 case 3: return AMDGPU::AReg_96RegClassID; 2031 case 4: return AMDGPU::AReg_128RegClassID; 2032 case 5: return AMDGPU::AReg_160RegClassID; 2033 case 6: return AMDGPU::AReg_192RegClassID; 2034 case 8: return AMDGPU::AReg_256RegClassID; 2035 case 16: return AMDGPU::AReg_512RegClassID; 2036 case 32: return AMDGPU::AReg_1024RegClassID; 2037 } 2038 } 2039 return -1; 2040 } 2041 2042 static unsigned getSpecialRegForName(StringRef RegName) { 2043 return StringSwitch<unsigned>(RegName) 2044 .Case("exec", AMDGPU::EXEC) 2045 .Case("vcc", AMDGPU::VCC) 2046 .Case("flat_scratch", AMDGPU::FLAT_SCR) 2047 .Case("xnack_mask", AMDGPU::XNACK_MASK) 2048 .Case("shared_base", AMDGPU::SRC_SHARED_BASE) 2049 .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE) 2050 .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT) 2051 .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT) 2052 .Case("private_base", AMDGPU::SRC_PRIVATE_BASE) 2053 .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE) 2054 .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 2055 .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT) 2056 .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 2057 .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID) 2058 .Case("lds_direct", AMDGPU::LDS_DIRECT) 2059 .Case("src_lds_direct", AMDGPU::LDS_DIRECT) 2060 .Case("m0", AMDGPU::M0) 2061 .Case("vccz", AMDGPU::SRC_VCCZ) 2062 .Case("src_vccz", AMDGPU::SRC_VCCZ) 2063 .Case("execz", AMDGPU::SRC_EXECZ) 2064 .Case("src_execz", AMDGPU::SRC_EXECZ) 2065 .Case("scc", AMDGPU::SRC_SCC) 2066 .Case("src_scc", AMDGPU::SRC_SCC) 2067 .Case("tba", AMDGPU::TBA) 2068 .Case("tma", AMDGPU::TMA) 2069 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 2070 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 2071 .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO) 2072 .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI) 2073 .Case("vcc_lo", AMDGPU::VCC_LO) 2074 .Case("vcc_hi", AMDGPU::VCC_HI) 2075 .Case("exec_lo", AMDGPU::EXEC_LO) 2076 .Case("exec_hi", AMDGPU::EXEC_HI) 2077 .Case("tma_lo", AMDGPU::TMA_LO) 2078 .Case("tma_hi", AMDGPU::TMA_HI) 2079 .Case("tba_lo", AMDGPU::TBA_LO) 2080 .Case("tba_hi", AMDGPU::TBA_HI) 2081 .Case("pc", AMDGPU::PC_REG) 2082 .Case("null", AMDGPU::SGPR_NULL) 2083 .Default(AMDGPU::NoRegister); 2084 } 2085 2086 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 2087 SMLoc &EndLoc, bool RestoreOnFailure) { 2088 auto R = parseRegister(); 2089 if (!R) return true; 2090 assert(R->isReg()); 2091 RegNo = R->getReg(); 2092 StartLoc = R->getStartLoc(); 2093 EndLoc = R->getEndLoc(); 2094 return false; 2095 } 2096 2097 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, 2098 SMLoc &EndLoc) { 2099 return ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/false); 2100 } 2101 2102 OperandMatchResultTy AMDGPUAsmParser::tryParseRegister(unsigned &RegNo, 2103 SMLoc &StartLoc, 2104 SMLoc &EndLoc) { 2105 bool Result = 2106 ParseRegister(RegNo, StartLoc, EndLoc, /*RestoreOnFailure=*/true); 2107 bool PendingErrors = getParser().hasPendingError(); 2108 getParser().clearPendingErrors(); 2109 if (PendingErrors) 2110 return MatchOperand_ParseFail; 2111 if (Result) 2112 return MatchOperand_NoMatch; 2113 return MatchOperand_Success; 2114 } 2115 2116 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth, 2117 RegisterKind RegKind, unsigned Reg1, 2118 SMLoc Loc) { 2119 switch (RegKind) { 2120 case IS_SPECIAL: 2121 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { 2122 Reg = AMDGPU::EXEC; 2123 RegWidth = 2; 2124 return true; 2125 } 2126 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { 2127 Reg = AMDGPU::FLAT_SCR; 2128 RegWidth = 2; 2129 return true; 2130 } 2131 if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) { 2132 Reg = AMDGPU::XNACK_MASK; 2133 RegWidth = 2; 2134 return true; 2135 } 2136 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { 2137 Reg = AMDGPU::VCC; 2138 RegWidth = 2; 2139 return true; 2140 } 2141 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { 2142 Reg = AMDGPU::TBA; 2143 RegWidth = 2; 2144 return true; 2145 } 2146 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { 2147 Reg = AMDGPU::TMA; 2148 RegWidth = 2; 2149 return true; 2150 } 2151 Error(Loc, "register does not fit in the list"); 2152 return false; 2153 case IS_VGPR: 2154 case IS_SGPR: 2155 case IS_AGPR: 2156 case IS_TTMP: 2157 if (Reg1 != Reg + RegWidth) { 2158 Error(Loc, "registers in a list must have consecutive indices"); 2159 return false; 2160 } 2161 RegWidth++; 2162 return true; 2163 default: 2164 llvm_unreachable("unexpected register kind"); 2165 } 2166 } 2167 2168 struct RegInfo { 2169 StringLiteral Name; 2170 RegisterKind Kind; 2171 }; 2172 2173 static constexpr RegInfo RegularRegisters[] = { 2174 {{"v"}, IS_VGPR}, 2175 {{"s"}, IS_SGPR}, 2176 {{"ttmp"}, IS_TTMP}, 2177 {{"acc"}, IS_AGPR}, 2178 {{"a"}, IS_AGPR}, 2179 }; 2180 2181 static bool isRegularReg(RegisterKind Kind) { 2182 return Kind == IS_VGPR || 2183 Kind == IS_SGPR || 2184 Kind == IS_TTMP || 2185 Kind == IS_AGPR; 2186 } 2187 2188 static const RegInfo* getRegularRegInfo(StringRef Str) { 2189 for (const RegInfo &Reg : RegularRegisters) 2190 if (Str.startswith(Reg.Name)) 2191 return &Reg; 2192 return nullptr; 2193 } 2194 2195 static bool getRegNum(StringRef Str, unsigned& Num) { 2196 return !Str.getAsInteger(10, Num); 2197 } 2198 2199 bool 2200 AMDGPUAsmParser::isRegister(const AsmToken &Token, 2201 const AsmToken &NextToken) const { 2202 2203 // A list of consecutive registers: [s0,s1,s2,s3] 2204 if (Token.is(AsmToken::LBrac)) 2205 return true; 2206 2207 if (!Token.is(AsmToken::Identifier)) 2208 return false; 2209 2210 // A single register like s0 or a range of registers like s[0:1] 2211 2212 StringRef Str = Token.getString(); 2213 const RegInfo *Reg = getRegularRegInfo(Str); 2214 if (Reg) { 2215 StringRef RegName = Reg->Name; 2216 StringRef RegSuffix = Str.substr(RegName.size()); 2217 if (!RegSuffix.empty()) { 2218 unsigned Num; 2219 // A single register with an index: rXX 2220 if (getRegNum(RegSuffix, Num)) 2221 return true; 2222 } else { 2223 // A range of registers: r[XX:YY]. 2224 if (NextToken.is(AsmToken::LBrac)) 2225 return true; 2226 } 2227 } 2228 2229 return getSpecialRegForName(Str) != AMDGPU::NoRegister; 2230 } 2231 2232 bool 2233 AMDGPUAsmParser::isRegister() 2234 { 2235 return isRegister(getToken(), peekToken()); 2236 } 2237 2238 unsigned 2239 AMDGPUAsmParser::getRegularReg(RegisterKind RegKind, 2240 unsigned RegNum, 2241 unsigned RegWidth, 2242 SMLoc Loc) { 2243 2244 assert(isRegularReg(RegKind)); 2245 2246 unsigned AlignSize = 1; 2247 if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 2248 // SGPR and TTMP registers must be aligned. 2249 // Max required alignment is 4 dwords. 2250 AlignSize = std::min(RegWidth, 4u); 2251 } 2252 2253 if (RegNum % AlignSize != 0) { 2254 Error(Loc, "invalid register alignment"); 2255 return AMDGPU::NoRegister; 2256 } 2257 2258 unsigned RegIdx = RegNum / AlignSize; 2259 int RCID = getRegClass(RegKind, RegWidth); 2260 if (RCID == -1) { 2261 Error(Loc, "invalid or unsupported register size"); 2262 return AMDGPU::NoRegister; 2263 } 2264 2265 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2266 const MCRegisterClass RC = TRI->getRegClass(RCID); 2267 if (RegIdx >= RC.getNumRegs()) { 2268 Error(Loc, "register index is out of range"); 2269 return AMDGPU::NoRegister; 2270 } 2271 2272 return RC.getRegister(RegIdx); 2273 } 2274 2275 bool 2276 AMDGPUAsmParser::ParseRegRange(unsigned& Num, unsigned& Width) { 2277 int64_t RegLo, RegHi; 2278 if (!skipToken(AsmToken::LBrac, "missing register index")) 2279 return false; 2280 2281 SMLoc FirstIdxLoc = getLoc(); 2282 SMLoc SecondIdxLoc; 2283 2284 if (!parseExpr(RegLo)) 2285 return false; 2286 2287 if (trySkipToken(AsmToken::Colon)) { 2288 SecondIdxLoc = getLoc(); 2289 if (!parseExpr(RegHi)) 2290 return false; 2291 } else { 2292 RegHi = RegLo; 2293 } 2294 2295 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 2296 return false; 2297 2298 if (!isUInt<32>(RegLo)) { 2299 Error(FirstIdxLoc, "invalid register index"); 2300 return false; 2301 } 2302 2303 if (!isUInt<32>(RegHi)) { 2304 Error(SecondIdxLoc, "invalid register index"); 2305 return false; 2306 } 2307 2308 if (RegLo > RegHi) { 2309 Error(FirstIdxLoc, "first register index should not exceed second index"); 2310 return false; 2311 } 2312 2313 Num = static_cast<unsigned>(RegLo); 2314 Width = (RegHi - RegLo) + 1; 2315 return true; 2316 } 2317 2318 unsigned AMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind, 2319 unsigned &RegNum, unsigned &RegWidth, 2320 SmallVectorImpl<AsmToken> &Tokens) { 2321 assert(isToken(AsmToken::Identifier)); 2322 unsigned Reg = getSpecialRegForName(getTokenStr()); 2323 if (Reg) { 2324 RegNum = 0; 2325 RegWidth = 1; 2326 RegKind = IS_SPECIAL; 2327 Tokens.push_back(getToken()); 2328 lex(); // skip register name 2329 } 2330 return Reg; 2331 } 2332 2333 unsigned AMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind, 2334 unsigned &RegNum, unsigned &RegWidth, 2335 SmallVectorImpl<AsmToken> &Tokens) { 2336 assert(isToken(AsmToken::Identifier)); 2337 StringRef RegName = getTokenStr(); 2338 auto Loc = getLoc(); 2339 2340 const RegInfo *RI = getRegularRegInfo(RegName); 2341 if (!RI) { 2342 Error(Loc, "invalid register name"); 2343 return AMDGPU::NoRegister; 2344 } 2345 2346 Tokens.push_back(getToken()); 2347 lex(); // skip register name 2348 2349 RegKind = RI->Kind; 2350 StringRef RegSuffix = RegName.substr(RI->Name.size()); 2351 if (!RegSuffix.empty()) { 2352 // Single 32-bit register: vXX. 2353 if (!getRegNum(RegSuffix, RegNum)) { 2354 Error(Loc, "invalid register index"); 2355 return AMDGPU::NoRegister; 2356 } 2357 RegWidth = 1; 2358 } else { 2359 // Range of registers: v[XX:YY]. ":YY" is optional. 2360 if (!ParseRegRange(RegNum, RegWidth)) 2361 return AMDGPU::NoRegister; 2362 } 2363 2364 return getRegularReg(RegKind, RegNum, RegWidth, Loc); 2365 } 2366 2367 unsigned AMDGPUAsmParser::ParseRegList(RegisterKind &RegKind, unsigned &RegNum, 2368 unsigned &RegWidth, 2369 SmallVectorImpl<AsmToken> &Tokens) { 2370 unsigned Reg = AMDGPU::NoRegister; 2371 auto ListLoc = getLoc(); 2372 2373 if (!skipToken(AsmToken::LBrac, 2374 "expected a register or a list of registers")) { 2375 return AMDGPU::NoRegister; 2376 } 2377 2378 // List of consecutive registers, e.g.: [s0,s1,s2,s3] 2379 2380 auto Loc = getLoc(); 2381 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) 2382 return AMDGPU::NoRegister; 2383 if (RegWidth != 1) { 2384 Error(Loc, "expected a single 32-bit register"); 2385 return AMDGPU::NoRegister; 2386 } 2387 2388 for (; trySkipToken(AsmToken::Comma); ) { 2389 RegisterKind NextRegKind; 2390 unsigned NextReg, NextRegNum, NextRegWidth; 2391 Loc = getLoc(); 2392 2393 if (!ParseAMDGPURegister(NextRegKind, NextReg, 2394 NextRegNum, NextRegWidth, 2395 Tokens)) { 2396 return AMDGPU::NoRegister; 2397 } 2398 if (NextRegWidth != 1) { 2399 Error(Loc, "expected a single 32-bit register"); 2400 return AMDGPU::NoRegister; 2401 } 2402 if (NextRegKind != RegKind) { 2403 Error(Loc, "registers in a list must be of the same kind"); 2404 return AMDGPU::NoRegister; 2405 } 2406 if (!AddNextRegisterToList(Reg, RegWidth, RegKind, NextReg, Loc)) 2407 return AMDGPU::NoRegister; 2408 } 2409 2410 if (!skipToken(AsmToken::RBrac, 2411 "expected a comma or a closing square bracket")) { 2412 return AMDGPU::NoRegister; 2413 } 2414 2415 if (isRegularReg(RegKind)) 2416 Reg = getRegularReg(RegKind, RegNum, RegWidth, ListLoc); 2417 2418 return Reg; 2419 } 2420 2421 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 2422 unsigned &RegNum, unsigned &RegWidth, 2423 SmallVectorImpl<AsmToken> &Tokens) { 2424 auto Loc = getLoc(); 2425 Reg = AMDGPU::NoRegister; 2426 2427 if (isToken(AsmToken::Identifier)) { 2428 Reg = ParseSpecialReg(RegKind, RegNum, RegWidth, Tokens); 2429 if (Reg == AMDGPU::NoRegister) 2430 Reg = ParseRegularReg(RegKind, RegNum, RegWidth, Tokens); 2431 } else { 2432 Reg = ParseRegList(RegKind, RegNum, RegWidth, Tokens); 2433 } 2434 2435 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 2436 if (Reg == AMDGPU::NoRegister) { 2437 assert(Parser.hasPendingError()); 2438 return false; 2439 } 2440 2441 if (!subtargetHasRegister(*TRI, Reg)) { 2442 if (Reg == AMDGPU::SGPR_NULL) { 2443 Error(Loc, "'null' operand is not supported on this GPU"); 2444 } else { 2445 Error(Loc, "register not available on this GPU"); 2446 } 2447 return false; 2448 } 2449 2450 return true; 2451 } 2452 2453 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg, 2454 unsigned &RegNum, unsigned &RegWidth, 2455 bool RestoreOnFailure /*=false*/) { 2456 Reg = AMDGPU::NoRegister; 2457 2458 SmallVector<AsmToken, 1> Tokens; 2459 if (ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, Tokens)) { 2460 if (RestoreOnFailure) { 2461 while (!Tokens.empty()) { 2462 getLexer().UnLex(Tokens.pop_back_val()); 2463 } 2464 } 2465 return true; 2466 } 2467 return false; 2468 } 2469 2470 Optional<StringRef> 2471 AMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) { 2472 switch (RegKind) { 2473 case IS_VGPR: 2474 return StringRef(".amdgcn.next_free_vgpr"); 2475 case IS_SGPR: 2476 return StringRef(".amdgcn.next_free_sgpr"); 2477 default: 2478 return None; 2479 } 2480 } 2481 2482 void AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) { 2483 auto SymbolName = getGprCountSymbolName(RegKind); 2484 assert(SymbolName && "initializing invalid register kind"); 2485 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2486 Sym->setVariableValue(MCConstantExpr::create(0, getContext())); 2487 } 2488 2489 bool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind, 2490 unsigned DwordRegIndex, 2491 unsigned RegWidth) { 2492 // Symbols are only defined for GCN targets 2493 if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6) 2494 return true; 2495 2496 auto SymbolName = getGprCountSymbolName(RegKind); 2497 if (!SymbolName) 2498 return true; 2499 MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName); 2500 2501 int64_t NewMax = DwordRegIndex + RegWidth - 1; 2502 int64_t OldCount; 2503 2504 if (!Sym->isVariable()) 2505 return !Error(getLoc(), 2506 ".amdgcn.next_free_{v,s}gpr symbols must be variable"); 2507 if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount)) 2508 return !Error( 2509 getLoc(), 2510 ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions"); 2511 2512 if (OldCount <= NewMax) 2513 Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext())); 2514 2515 return true; 2516 } 2517 2518 std::unique_ptr<AMDGPUOperand> 2519 AMDGPUAsmParser::parseRegister(bool RestoreOnFailure) { 2520 const auto &Tok = getToken(); 2521 SMLoc StartLoc = Tok.getLoc(); 2522 SMLoc EndLoc = Tok.getEndLoc(); 2523 RegisterKind RegKind; 2524 unsigned Reg, RegNum, RegWidth; 2525 2526 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { 2527 return nullptr; 2528 } 2529 if (isHsaAbiVersion3(&getSTI())) { 2530 if (!updateGprCountSymbols(RegKind, RegNum, RegWidth)) 2531 return nullptr; 2532 } else 2533 KernelScope.usesRegister(RegKind, RegNum, RegWidth); 2534 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc); 2535 } 2536 2537 OperandMatchResultTy 2538 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) { 2539 // TODO: add syntactic sugar for 1/(2*PI) 2540 2541 assert(!isRegister()); 2542 assert(!isModifier()); 2543 2544 const auto& Tok = getToken(); 2545 const auto& NextTok = peekToken(); 2546 bool IsReal = Tok.is(AsmToken::Real); 2547 SMLoc S = getLoc(); 2548 bool Negate = false; 2549 2550 if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) { 2551 lex(); 2552 IsReal = true; 2553 Negate = true; 2554 } 2555 2556 if (IsReal) { 2557 // Floating-point expressions are not supported. 2558 // Can only allow floating-point literals with an 2559 // optional sign. 2560 2561 StringRef Num = getTokenStr(); 2562 lex(); 2563 2564 APFloat RealVal(APFloat::IEEEdouble()); 2565 auto roundMode = APFloat::rmNearestTiesToEven; 2566 if (errorToBool(RealVal.convertFromString(Num, roundMode).takeError())) { 2567 return MatchOperand_ParseFail; 2568 } 2569 if (Negate) 2570 RealVal.changeSign(); 2571 2572 Operands.push_back( 2573 AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S, 2574 AMDGPUOperand::ImmTyNone, true)); 2575 2576 return MatchOperand_Success; 2577 2578 } else { 2579 int64_t IntVal; 2580 const MCExpr *Expr; 2581 SMLoc S = getLoc(); 2582 2583 if (HasSP3AbsModifier) { 2584 // This is a workaround for handling expressions 2585 // as arguments of SP3 'abs' modifier, for example: 2586 // |1.0| 2587 // |-1| 2588 // |1+x| 2589 // This syntax is not compatible with syntax of standard 2590 // MC expressions (due to the trailing '|'). 2591 SMLoc EndLoc; 2592 if (getParser().parsePrimaryExpr(Expr, EndLoc, nullptr)) 2593 return MatchOperand_ParseFail; 2594 } else { 2595 if (Parser.parseExpression(Expr)) 2596 return MatchOperand_ParseFail; 2597 } 2598 2599 if (Expr->evaluateAsAbsolute(IntVal)) { 2600 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 2601 } else { 2602 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 2603 } 2604 2605 return MatchOperand_Success; 2606 } 2607 2608 return MatchOperand_NoMatch; 2609 } 2610 2611 OperandMatchResultTy 2612 AMDGPUAsmParser::parseReg(OperandVector &Operands) { 2613 if (!isRegister()) 2614 return MatchOperand_NoMatch; 2615 2616 if (auto R = parseRegister()) { 2617 assert(R->isReg()); 2618 Operands.push_back(std::move(R)); 2619 return MatchOperand_Success; 2620 } 2621 return MatchOperand_ParseFail; 2622 } 2623 2624 OperandMatchResultTy 2625 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod) { 2626 auto res = parseReg(Operands); 2627 if (res != MatchOperand_NoMatch) { 2628 return res; 2629 } else if (isModifier()) { 2630 return MatchOperand_NoMatch; 2631 } else { 2632 return parseImm(Operands, HasSP3AbsMod); 2633 } 2634 } 2635 2636 bool 2637 AMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2638 if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) { 2639 const auto &str = Token.getString(); 2640 return str == "abs" || str == "neg" || str == "sext"; 2641 } 2642 return false; 2643 } 2644 2645 bool 2646 AMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const { 2647 return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon); 2648 } 2649 2650 bool 2651 AMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2652 return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe); 2653 } 2654 2655 bool 2656 AMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const { 2657 return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken); 2658 } 2659 2660 // Check if this is an operand modifier or an opcode modifier 2661 // which may look like an expression but it is not. We should 2662 // avoid parsing these modifiers as expressions. Currently 2663 // recognized sequences are: 2664 // |...| 2665 // abs(...) 2666 // neg(...) 2667 // sext(...) 2668 // -reg 2669 // -|...| 2670 // -abs(...) 2671 // name:... 2672 // Note that simple opcode modifiers like 'gds' may be parsed as 2673 // expressions; this is a special case. See getExpressionAsToken. 2674 // 2675 bool 2676 AMDGPUAsmParser::isModifier() { 2677 2678 AsmToken Tok = getToken(); 2679 AsmToken NextToken[2]; 2680 peekTokens(NextToken); 2681 2682 return isOperandModifier(Tok, NextToken[0]) || 2683 (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) || 2684 isOpcodeModifierWithVal(Tok, NextToken[0]); 2685 } 2686 2687 // Check if the current token is an SP3 'neg' modifier. 2688 // Currently this modifier is allowed in the following context: 2689 // 2690 // 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]". 2691 // 2. Before an 'abs' modifier: -abs(...) 2692 // 3. Before an SP3 'abs' modifier: -|...| 2693 // 2694 // In all other cases "-" is handled as a part 2695 // of an expression that follows the sign. 2696 // 2697 // Note: When "-" is followed by an integer literal, 2698 // this is interpreted as integer negation rather 2699 // than a floating-point NEG modifier applied to N. 2700 // Beside being contr-intuitive, such use of floating-point 2701 // NEG modifier would have resulted in different meaning 2702 // of integer literals used with VOP1/2/C and VOP3, 2703 // for example: 2704 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF 2705 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001 2706 // Negative fp literals with preceding "-" are 2707 // handled likewise for unifomtity 2708 // 2709 bool 2710 AMDGPUAsmParser::parseSP3NegModifier() { 2711 2712 AsmToken NextToken[2]; 2713 peekTokens(NextToken); 2714 2715 if (isToken(AsmToken::Minus) && 2716 (isRegister(NextToken[0], NextToken[1]) || 2717 NextToken[0].is(AsmToken::Pipe) || 2718 isId(NextToken[0], "abs"))) { 2719 lex(); 2720 return true; 2721 } 2722 2723 return false; 2724 } 2725 2726 OperandMatchResultTy 2727 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, 2728 bool AllowImm) { 2729 bool Neg, SP3Neg; 2730 bool Abs, SP3Abs; 2731 SMLoc Loc; 2732 2733 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead. 2734 if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) { 2735 Error(getLoc(), "invalid syntax, expected 'neg' modifier"); 2736 return MatchOperand_ParseFail; 2737 } 2738 2739 SP3Neg = parseSP3NegModifier(); 2740 2741 Loc = getLoc(); 2742 Neg = trySkipId("neg"); 2743 if (Neg && SP3Neg) { 2744 Error(Loc, "expected register or immediate"); 2745 return MatchOperand_ParseFail; 2746 } 2747 if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg")) 2748 return MatchOperand_ParseFail; 2749 2750 Abs = trySkipId("abs"); 2751 if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs")) 2752 return MatchOperand_ParseFail; 2753 2754 Loc = getLoc(); 2755 SP3Abs = trySkipToken(AsmToken::Pipe); 2756 if (Abs && SP3Abs) { 2757 Error(Loc, "expected register or immediate"); 2758 return MatchOperand_ParseFail; 2759 } 2760 2761 OperandMatchResultTy Res; 2762 if (AllowImm) { 2763 Res = parseRegOrImm(Operands, SP3Abs); 2764 } else { 2765 Res = parseReg(Operands); 2766 } 2767 if (Res != MatchOperand_Success) { 2768 return (SP3Neg || Neg || SP3Abs || Abs)? MatchOperand_ParseFail : Res; 2769 } 2770 2771 if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar")) 2772 return MatchOperand_ParseFail; 2773 if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2774 return MatchOperand_ParseFail; 2775 if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2776 return MatchOperand_ParseFail; 2777 2778 AMDGPUOperand::Modifiers Mods; 2779 Mods.Abs = Abs || SP3Abs; 2780 Mods.Neg = Neg || SP3Neg; 2781 2782 if (Mods.hasFPModifiers()) { 2783 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 2784 if (Op.isExpr()) { 2785 Error(Op.getStartLoc(), "expected an absolute expression"); 2786 return MatchOperand_ParseFail; 2787 } 2788 Op.setModifiers(Mods); 2789 } 2790 return MatchOperand_Success; 2791 } 2792 2793 OperandMatchResultTy 2794 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, 2795 bool AllowImm) { 2796 bool Sext = trySkipId("sext"); 2797 if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext")) 2798 return MatchOperand_ParseFail; 2799 2800 OperandMatchResultTy Res; 2801 if (AllowImm) { 2802 Res = parseRegOrImm(Operands); 2803 } else { 2804 Res = parseReg(Operands); 2805 } 2806 if (Res != MatchOperand_Success) { 2807 return Sext? MatchOperand_ParseFail : Res; 2808 } 2809 2810 if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses")) 2811 return MatchOperand_ParseFail; 2812 2813 AMDGPUOperand::Modifiers Mods; 2814 Mods.Sext = Sext; 2815 2816 if (Mods.hasIntModifiers()) { 2817 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back()); 2818 if (Op.isExpr()) { 2819 Error(Op.getStartLoc(), "expected an absolute expression"); 2820 return MatchOperand_ParseFail; 2821 } 2822 Op.setModifiers(Mods); 2823 } 2824 2825 return MatchOperand_Success; 2826 } 2827 2828 OperandMatchResultTy 2829 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) { 2830 return parseRegOrImmWithFPInputMods(Operands, false); 2831 } 2832 2833 OperandMatchResultTy 2834 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) { 2835 return parseRegOrImmWithIntInputMods(Operands, false); 2836 } 2837 2838 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) { 2839 auto Loc = getLoc(); 2840 if (trySkipId("off")) { 2841 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc, 2842 AMDGPUOperand::ImmTyOff, false)); 2843 return MatchOperand_Success; 2844 } 2845 2846 if (!isRegister()) 2847 return MatchOperand_NoMatch; 2848 2849 std::unique_ptr<AMDGPUOperand> Reg = parseRegister(); 2850 if (Reg) { 2851 Operands.push_back(std::move(Reg)); 2852 return MatchOperand_Success; 2853 } 2854 2855 return MatchOperand_ParseFail; 2856 2857 } 2858 2859 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 2860 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 2861 2862 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 2863 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) || 2864 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) || 2865 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) ) 2866 return Match_InvalidOperand; 2867 2868 if ((TSFlags & SIInstrFlags::VOP3) && 2869 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 2870 getForcedEncodingSize() != 64) 2871 return Match_PreferE32; 2872 2873 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 2874 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 2875 // v_mac_f32/16 allow only dst_sel == DWORD; 2876 auto OpNum = 2877 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel); 2878 const auto &Op = Inst.getOperand(OpNum); 2879 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) { 2880 return Match_InvalidOperand; 2881 } 2882 } 2883 2884 return Match_Success; 2885 } 2886 2887 static ArrayRef<unsigned> getAllVariants() { 2888 static const unsigned Variants[] = { 2889 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3, 2890 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP 2891 }; 2892 2893 return makeArrayRef(Variants); 2894 } 2895 2896 // What asm variants we should check 2897 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const { 2898 if (getForcedEncodingSize() == 32) { 2899 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT}; 2900 return makeArrayRef(Variants); 2901 } 2902 2903 if (isForcedVOP3()) { 2904 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3}; 2905 return makeArrayRef(Variants); 2906 } 2907 2908 if (isForcedSDWA()) { 2909 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA, 2910 AMDGPUAsmVariants::SDWA9}; 2911 return makeArrayRef(Variants); 2912 } 2913 2914 if (isForcedDPP()) { 2915 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP}; 2916 return makeArrayRef(Variants); 2917 } 2918 2919 return getAllVariants(); 2920 } 2921 2922 StringRef AMDGPUAsmParser::getMatchedVariantName() const { 2923 if (getForcedEncodingSize() == 32) 2924 return "e32"; 2925 2926 if (isForcedVOP3()) 2927 return "e64"; 2928 2929 if (isForcedSDWA()) 2930 return "sdwa"; 2931 2932 if (isForcedDPP()) 2933 return "dpp"; 2934 2935 return ""; 2936 } 2937 2938 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const { 2939 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2940 const unsigned Num = Desc.getNumImplicitUses(); 2941 for (unsigned i = 0; i < Num; ++i) { 2942 unsigned Reg = Desc.ImplicitUses[i]; 2943 switch (Reg) { 2944 case AMDGPU::FLAT_SCR: 2945 case AMDGPU::VCC: 2946 case AMDGPU::VCC_LO: 2947 case AMDGPU::VCC_HI: 2948 case AMDGPU::M0: 2949 return Reg; 2950 default: 2951 break; 2952 } 2953 } 2954 return AMDGPU::NoRegister; 2955 } 2956 2957 // NB: This code is correct only when used to check constant 2958 // bus limitations because GFX7 support no f16 inline constants. 2959 // Note that there are no cases when a GFX7 opcode violates 2960 // constant bus limitations due to the use of an f16 constant. 2961 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst, 2962 unsigned OpIdx) const { 2963 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2964 2965 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) { 2966 return false; 2967 } 2968 2969 const MCOperand &MO = Inst.getOperand(OpIdx); 2970 2971 int64_t Val = MO.getImm(); 2972 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx); 2973 2974 switch (OpSize) { // expected operand size 2975 case 8: 2976 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm()); 2977 case 4: 2978 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm()); 2979 case 2: { 2980 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType; 2981 if (OperandType == AMDGPU::OPERAND_REG_IMM_INT16 || 2982 OperandType == AMDGPU::OPERAND_REG_INLINE_C_INT16 || 2983 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_INT16) 2984 return AMDGPU::isInlinableIntLiteral(Val); 2985 2986 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 || 2987 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 || 2988 OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16) 2989 return AMDGPU::isInlinableIntLiteralV216(Val); 2990 2991 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 || 2992 OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 || 2993 OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) 2994 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm()); 2995 2996 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm()); 2997 } 2998 default: 2999 llvm_unreachable("invalid operand size"); 3000 } 3001 } 3002 3003 unsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const { 3004 if (!isGFX10Plus()) 3005 return 1; 3006 3007 switch (Opcode) { 3008 // 64-bit shift instructions can use only one scalar value input 3009 case AMDGPU::V_LSHLREV_B64: 3010 case AMDGPU::V_LSHLREV_B64_gfx10: 3011 case AMDGPU::V_LSHL_B64: 3012 case AMDGPU::V_LSHRREV_B64: 3013 case AMDGPU::V_LSHRREV_B64_gfx10: 3014 case AMDGPU::V_LSHR_B64: 3015 case AMDGPU::V_ASHRREV_I64: 3016 case AMDGPU::V_ASHRREV_I64_gfx10: 3017 case AMDGPU::V_ASHR_I64: 3018 return 1; 3019 default: 3020 return 2; 3021 } 3022 } 3023 3024 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) { 3025 const MCOperand &MO = Inst.getOperand(OpIdx); 3026 if (MO.isImm()) { 3027 return !isInlineConstant(Inst, OpIdx); 3028 } else if (MO.isReg()) { 3029 auto Reg = MO.getReg(); 3030 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3031 auto PReg = mc2PseudoReg(Reg); 3032 return isSGPR(PReg, TRI) && PReg != SGPR_NULL; 3033 } else { 3034 return true; 3035 } 3036 } 3037 3038 bool 3039 AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst, 3040 const OperandVector &Operands) { 3041 const unsigned Opcode = Inst.getOpcode(); 3042 const MCInstrDesc &Desc = MII.get(Opcode); 3043 unsigned LastSGPR = AMDGPU::NoRegister; 3044 unsigned ConstantBusUseCount = 0; 3045 unsigned NumLiterals = 0; 3046 unsigned LiteralSize; 3047 3048 if (Desc.TSFlags & 3049 (SIInstrFlags::VOPC | 3050 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 | 3051 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P | 3052 SIInstrFlags::SDWA)) { 3053 // Check special imm operands (used by madmk, etc) 3054 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) { 3055 ++ConstantBusUseCount; 3056 } 3057 3058 SmallDenseSet<unsigned> SGPRsUsed; 3059 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst); 3060 if (SGPRUsed != AMDGPU::NoRegister) { 3061 SGPRsUsed.insert(SGPRUsed); 3062 ++ConstantBusUseCount; 3063 } 3064 3065 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3066 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3067 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3068 3069 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 3070 3071 for (int OpIdx : OpIndices) { 3072 if (OpIdx == -1) break; 3073 3074 const MCOperand &MO = Inst.getOperand(OpIdx); 3075 if (usesConstantBus(Inst, OpIdx)) { 3076 if (MO.isReg()) { 3077 LastSGPR = mc2PseudoReg(MO.getReg()); 3078 // Pairs of registers with a partial intersections like these 3079 // s0, s[0:1] 3080 // flat_scratch_lo, flat_scratch 3081 // flat_scratch_lo, flat_scratch_hi 3082 // are theoretically valid but they are disabled anyway. 3083 // Note that this code mimics SIInstrInfo::verifyInstruction 3084 if (!SGPRsUsed.count(LastSGPR)) { 3085 SGPRsUsed.insert(LastSGPR); 3086 ++ConstantBusUseCount; 3087 } 3088 } else { // Expression or a literal 3089 3090 if (Desc.OpInfo[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE) 3091 continue; // special operand like VINTERP attr_chan 3092 3093 // An instruction may use only one literal. 3094 // This has been validated on the previous step. 3095 // See validateVOP3Literal. 3096 // This literal may be used as more than one operand. 3097 // If all these operands are of the same size, 3098 // this literal counts as one scalar value. 3099 // Otherwise it counts as 2 scalar values. 3100 // See "GFX10 Shader Programming", section 3.6.2.3. 3101 3102 unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx); 3103 if (Size < 4) Size = 4; 3104 3105 if (NumLiterals == 0) { 3106 NumLiterals = 1; 3107 LiteralSize = Size; 3108 } else if (LiteralSize != Size) { 3109 NumLiterals = 2; 3110 } 3111 } 3112 } 3113 } 3114 } 3115 ConstantBusUseCount += NumLiterals; 3116 3117 if (ConstantBusUseCount <= getConstantBusLimit(Opcode)) 3118 return true; 3119 3120 SMLoc LitLoc = getLitLoc(Operands); 3121 SMLoc RegLoc = getRegLoc(LastSGPR, Operands); 3122 SMLoc Loc = (LitLoc.getPointer() < RegLoc.getPointer()) ? RegLoc : LitLoc; 3123 Error(Loc, "invalid operand (violates constant bus restrictions)"); 3124 return false; 3125 } 3126 3127 bool 3128 AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst, 3129 const OperandVector &Operands) { 3130 const unsigned Opcode = Inst.getOpcode(); 3131 const MCInstrDesc &Desc = MII.get(Opcode); 3132 3133 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst); 3134 if (DstIdx == -1 || 3135 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) { 3136 return true; 3137 } 3138 3139 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3140 3141 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3142 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3143 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3144 3145 assert(DstIdx != -1); 3146 const MCOperand &Dst = Inst.getOperand(DstIdx); 3147 assert(Dst.isReg()); 3148 const unsigned DstReg = mc2PseudoReg(Dst.getReg()); 3149 3150 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 3151 3152 for (int SrcIdx : SrcIndices) { 3153 if (SrcIdx == -1) break; 3154 const MCOperand &Src = Inst.getOperand(SrcIdx); 3155 if (Src.isReg()) { 3156 const unsigned SrcReg = mc2PseudoReg(Src.getReg()); 3157 if (isRegIntersect(DstReg, SrcReg, TRI)) { 3158 Error(getRegLoc(SrcReg, Operands), 3159 "destination must be different than all sources"); 3160 return false; 3161 } 3162 } 3163 } 3164 3165 return true; 3166 } 3167 3168 bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) { 3169 3170 const unsigned Opc = Inst.getOpcode(); 3171 const MCInstrDesc &Desc = MII.get(Opc); 3172 3173 if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) { 3174 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp); 3175 assert(ClampIdx != -1); 3176 return Inst.getOperand(ClampIdx).getImm() == 0; 3177 } 3178 3179 return true; 3180 } 3181 3182 bool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) { 3183 3184 const unsigned Opc = Inst.getOpcode(); 3185 const MCInstrDesc &Desc = MII.get(Opc); 3186 3187 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3188 return true; 3189 3190 int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata); 3191 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3192 int TFEIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe); 3193 3194 assert(VDataIdx != -1); 3195 3196 if (DMaskIdx == -1 || TFEIdx == -1) // intersect_ray 3197 return true; 3198 3199 unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx); 3200 unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0; 3201 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3202 if (DMask == 0) 3203 DMask = 1; 3204 3205 unsigned DataSize = 3206 (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : countPopulation(DMask); 3207 if (hasPackedD16()) { 3208 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 3209 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) 3210 DataSize = (DataSize + 1) / 2; 3211 } 3212 3213 return (VDataSize / 4) == DataSize + TFESize; 3214 } 3215 3216 bool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst) { 3217 const unsigned Opc = Inst.getOpcode(); 3218 const MCInstrDesc &Desc = MII.get(Opc); 3219 3220 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0 || !isGFX10Plus()) 3221 return true; 3222 3223 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc); 3224 3225 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode = 3226 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode); 3227 int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0); 3228 int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc); 3229 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 3230 3231 assert(VAddr0Idx != -1); 3232 assert(SrsrcIdx != -1); 3233 assert(SrsrcIdx > VAddr0Idx); 3234 3235 if (DimIdx == -1) 3236 return true; // intersect_ray 3237 3238 unsigned Dim = Inst.getOperand(DimIdx).getImm(); 3239 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim); 3240 bool IsNSA = SrsrcIdx - VAddr0Idx > 1; 3241 unsigned VAddrSize = 3242 IsNSA ? SrsrcIdx - VAddr0Idx 3243 : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4; 3244 3245 unsigned AddrSize = BaseOpcode->NumExtraArgs + 3246 (BaseOpcode->Gradients ? DimInfo->NumGradients : 0) + 3247 (BaseOpcode->Coordinates ? DimInfo->NumCoords : 0) + 3248 (BaseOpcode->LodOrClampOrMip ? 1 : 0); 3249 if (!IsNSA) { 3250 if (AddrSize > 8) 3251 AddrSize = 16; 3252 else if (AddrSize > 4) 3253 AddrSize = 8; 3254 } 3255 3256 return VAddrSize == AddrSize; 3257 } 3258 3259 bool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) { 3260 3261 const unsigned Opc = Inst.getOpcode(); 3262 const MCInstrDesc &Desc = MII.get(Opc); 3263 3264 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3265 return true; 3266 if (!Desc.mayLoad() || !Desc.mayStore()) 3267 return true; // Not atomic 3268 3269 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3270 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3271 3272 // This is an incomplete check because image_atomic_cmpswap 3273 // may only use 0x3 and 0xf while other atomic operations 3274 // may use 0x1 and 0x3. However these limitations are 3275 // verified when we check that dmask matches dst size. 3276 return DMask == 0x1 || DMask == 0x3 || DMask == 0xf; 3277 } 3278 3279 bool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) { 3280 3281 const unsigned Opc = Inst.getOpcode(); 3282 const MCInstrDesc &Desc = MII.get(Opc); 3283 3284 if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0) 3285 return true; 3286 3287 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask); 3288 unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf; 3289 3290 // GATHER4 instructions use dmask in a different fashion compared to 3291 // other MIMG instructions. The only useful DMASK values are 3292 // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns 3293 // (red,red,red,red) etc.) The ISA document doesn't mention 3294 // this. 3295 return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8; 3296 } 3297 3298 static bool IsMovrelsSDWAOpcode(const unsigned Opcode) 3299 { 3300 switch (Opcode) { 3301 case AMDGPU::V_MOVRELS_B32_sdwa_gfx10: 3302 case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10: 3303 case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10: 3304 return true; 3305 default: 3306 return false; 3307 } 3308 } 3309 3310 // movrels* opcodes should only allow VGPRS as src0. 3311 // This is specified in .td description for vop1/vop3, 3312 // but sdwa is handled differently. See isSDWAOperand. 3313 bool AMDGPUAsmParser::validateMovrels(const MCInst &Inst, 3314 const OperandVector &Operands) { 3315 3316 const unsigned Opc = Inst.getOpcode(); 3317 const MCInstrDesc &Desc = MII.get(Opc); 3318 3319 if ((Desc.TSFlags & SIInstrFlags::SDWA) == 0 || !IsMovrelsSDWAOpcode(Opc)) 3320 return true; 3321 3322 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3323 assert(Src0Idx != -1); 3324 3325 SMLoc ErrLoc; 3326 const MCOperand &Src0 = Inst.getOperand(Src0Idx); 3327 if (Src0.isReg()) { 3328 auto Reg = mc2PseudoReg(Src0.getReg()); 3329 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3330 if (!isSGPR(Reg, TRI)) 3331 return true; 3332 ErrLoc = getRegLoc(Reg, Operands); 3333 } else { 3334 ErrLoc = getConstLoc(Operands); 3335 } 3336 3337 Error(ErrLoc, "source operand must be a VGPR"); 3338 return false; 3339 } 3340 3341 bool AMDGPUAsmParser::validateMAIAccWrite(const MCInst &Inst, 3342 const OperandVector &Operands) { 3343 3344 const unsigned Opc = Inst.getOpcode(); 3345 3346 if (Opc != AMDGPU::V_ACCVGPR_WRITE_B32_vi) 3347 return true; 3348 3349 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0); 3350 assert(Src0Idx != -1); 3351 3352 const MCOperand &Src0 = Inst.getOperand(Src0Idx); 3353 if (!Src0.isReg()) 3354 return true; 3355 3356 auto Reg = mc2PseudoReg(Src0.getReg()); 3357 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 3358 if (isSGPR(Reg, TRI)) { 3359 Error(getRegLoc(Reg, Operands), 3360 "source operand must be either a VGPR or an inline constant"); 3361 return false; 3362 } 3363 3364 return true; 3365 } 3366 3367 bool AMDGPUAsmParser::validateDivScale(const MCInst &Inst) { 3368 switch (Inst.getOpcode()) { 3369 default: 3370 return true; 3371 case V_DIV_SCALE_F32_gfx6_gfx7: 3372 case V_DIV_SCALE_F32_vi: 3373 case V_DIV_SCALE_F32_gfx10: 3374 case V_DIV_SCALE_F64_gfx6_gfx7: 3375 case V_DIV_SCALE_F64_vi: 3376 case V_DIV_SCALE_F64_gfx10: 3377 break; 3378 } 3379 3380 // TODO: Check that src0 = src1 or src2. 3381 3382 for (auto Name : {AMDGPU::OpName::src0_modifiers, 3383 AMDGPU::OpName::src2_modifiers, 3384 AMDGPU::OpName::src2_modifiers}) { 3385 if (Inst.getOperand(AMDGPU::getNamedOperandIdx(Inst.getOpcode(), Name)) 3386 .getImm() & 3387 SISrcMods::ABS) { 3388 return false; 3389 } 3390 } 3391 3392 return true; 3393 } 3394 3395 bool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) { 3396 3397 const unsigned Opc = Inst.getOpcode(); 3398 const MCInstrDesc &Desc = MII.get(Opc); 3399 3400 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3401 return true; 3402 3403 int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16); 3404 if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) { 3405 if (isCI() || isSI()) 3406 return false; 3407 } 3408 3409 return true; 3410 } 3411 3412 bool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst) { 3413 const unsigned Opc = Inst.getOpcode(); 3414 const MCInstrDesc &Desc = MII.get(Opc); 3415 3416 if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0) 3417 return true; 3418 3419 int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim); 3420 if (DimIdx < 0) 3421 return true; 3422 3423 long Imm = Inst.getOperand(DimIdx).getImm(); 3424 if (Imm < 0 || Imm >= 8) 3425 return false; 3426 3427 return true; 3428 } 3429 3430 static bool IsRevOpcode(const unsigned Opcode) 3431 { 3432 switch (Opcode) { 3433 case AMDGPU::V_SUBREV_F32_e32: 3434 case AMDGPU::V_SUBREV_F32_e64: 3435 case AMDGPU::V_SUBREV_F32_e32_gfx10: 3436 case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7: 3437 case AMDGPU::V_SUBREV_F32_e32_vi: 3438 case AMDGPU::V_SUBREV_F32_e64_gfx10: 3439 case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7: 3440 case AMDGPU::V_SUBREV_F32_e64_vi: 3441 3442 case AMDGPU::V_SUBREV_CO_U32_e32: 3443 case AMDGPU::V_SUBREV_CO_U32_e64: 3444 case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7: 3445 case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7: 3446 3447 case AMDGPU::V_SUBBREV_U32_e32: 3448 case AMDGPU::V_SUBBREV_U32_e64: 3449 case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7: 3450 case AMDGPU::V_SUBBREV_U32_e32_vi: 3451 case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7: 3452 case AMDGPU::V_SUBBREV_U32_e64_vi: 3453 3454 case AMDGPU::V_SUBREV_U32_e32: 3455 case AMDGPU::V_SUBREV_U32_e64: 3456 case AMDGPU::V_SUBREV_U32_e32_gfx9: 3457 case AMDGPU::V_SUBREV_U32_e32_vi: 3458 case AMDGPU::V_SUBREV_U32_e64_gfx9: 3459 case AMDGPU::V_SUBREV_U32_e64_vi: 3460 3461 case AMDGPU::V_SUBREV_F16_e32: 3462 case AMDGPU::V_SUBREV_F16_e64: 3463 case AMDGPU::V_SUBREV_F16_e32_gfx10: 3464 case AMDGPU::V_SUBREV_F16_e32_vi: 3465 case AMDGPU::V_SUBREV_F16_e64_gfx10: 3466 case AMDGPU::V_SUBREV_F16_e64_vi: 3467 3468 case AMDGPU::V_SUBREV_U16_e32: 3469 case AMDGPU::V_SUBREV_U16_e64: 3470 case AMDGPU::V_SUBREV_U16_e32_vi: 3471 case AMDGPU::V_SUBREV_U16_e64_vi: 3472 3473 case AMDGPU::V_SUBREV_CO_U32_e32_gfx9: 3474 case AMDGPU::V_SUBREV_CO_U32_e64_gfx10: 3475 case AMDGPU::V_SUBREV_CO_U32_e64_gfx9: 3476 3477 case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9: 3478 case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9: 3479 3480 case AMDGPU::V_SUBREV_NC_U32_e32_gfx10: 3481 case AMDGPU::V_SUBREV_NC_U32_e64_gfx10: 3482 3483 case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10: 3484 case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10: 3485 3486 case AMDGPU::V_LSHRREV_B32_e32: 3487 case AMDGPU::V_LSHRREV_B32_e64: 3488 case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7: 3489 case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7: 3490 case AMDGPU::V_LSHRREV_B32_e32_vi: 3491 case AMDGPU::V_LSHRREV_B32_e64_vi: 3492 case AMDGPU::V_LSHRREV_B32_e32_gfx10: 3493 case AMDGPU::V_LSHRREV_B32_e64_gfx10: 3494 3495 case AMDGPU::V_ASHRREV_I32_e32: 3496 case AMDGPU::V_ASHRREV_I32_e64: 3497 case AMDGPU::V_ASHRREV_I32_e32_gfx10: 3498 case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7: 3499 case AMDGPU::V_ASHRREV_I32_e32_vi: 3500 case AMDGPU::V_ASHRREV_I32_e64_gfx10: 3501 case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7: 3502 case AMDGPU::V_ASHRREV_I32_e64_vi: 3503 3504 case AMDGPU::V_LSHLREV_B32_e32: 3505 case AMDGPU::V_LSHLREV_B32_e64: 3506 case AMDGPU::V_LSHLREV_B32_e32_gfx10: 3507 case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7: 3508 case AMDGPU::V_LSHLREV_B32_e32_vi: 3509 case AMDGPU::V_LSHLREV_B32_e64_gfx10: 3510 case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7: 3511 case AMDGPU::V_LSHLREV_B32_e64_vi: 3512 3513 case AMDGPU::V_LSHLREV_B16_e32: 3514 case AMDGPU::V_LSHLREV_B16_e64: 3515 case AMDGPU::V_LSHLREV_B16_e32_vi: 3516 case AMDGPU::V_LSHLREV_B16_e64_vi: 3517 case AMDGPU::V_LSHLREV_B16_gfx10: 3518 3519 case AMDGPU::V_LSHRREV_B16_e32: 3520 case AMDGPU::V_LSHRREV_B16_e64: 3521 case AMDGPU::V_LSHRREV_B16_e32_vi: 3522 case AMDGPU::V_LSHRREV_B16_e64_vi: 3523 case AMDGPU::V_LSHRREV_B16_gfx10: 3524 3525 case AMDGPU::V_ASHRREV_I16_e32: 3526 case AMDGPU::V_ASHRREV_I16_e64: 3527 case AMDGPU::V_ASHRREV_I16_e32_vi: 3528 case AMDGPU::V_ASHRREV_I16_e64_vi: 3529 case AMDGPU::V_ASHRREV_I16_gfx10: 3530 3531 case AMDGPU::V_LSHLREV_B64: 3532 case AMDGPU::V_LSHLREV_B64_gfx10: 3533 case AMDGPU::V_LSHLREV_B64_vi: 3534 3535 case AMDGPU::V_LSHRREV_B64: 3536 case AMDGPU::V_LSHRREV_B64_gfx10: 3537 case AMDGPU::V_LSHRREV_B64_vi: 3538 3539 case AMDGPU::V_ASHRREV_I64: 3540 case AMDGPU::V_ASHRREV_I64_gfx10: 3541 case AMDGPU::V_ASHRREV_I64_vi: 3542 3543 case AMDGPU::V_PK_LSHLREV_B16: 3544 case AMDGPU::V_PK_LSHLREV_B16_gfx10: 3545 case AMDGPU::V_PK_LSHLREV_B16_vi: 3546 3547 case AMDGPU::V_PK_LSHRREV_B16: 3548 case AMDGPU::V_PK_LSHRREV_B16_gfx10: 3549 case AMDGPU::V_PK_LSHRREV_B16_vi: 3550 case AMDGPU::V_PK_ASHRREV_I16: 3551 case AMDGPU::V_PK_ASHRREV_I16_gfx10: 3552 case AMDGPU::V_PK_ASHRREV_I16_vi: 3553 return true; 3554 default: 3555 return false; 3556 } 3557 } 3558 3559 bool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) { 3560 3561 using namespace SIInstrFlags; 3562 const unsigned Opcode = Inst.getOpcode(); 3563 const MCInstrDesc &Desc = MII.get(Opcode); 3564 3565 // lds_direct register is defined so that it can be used 3566 // with 9-bit operands only. Ignore encodings which do not accept these. 3567 if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0) 3568 return true; 3569 3570 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3571 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3572 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3573 3574 const int SrcIndices[] = { Src1Idx, Src2Idx }; 3575 3576 // lds_direct cannot be specified as either src1 or src2. 3577 for (int SrcIdx : SrcIndices) { 3578 if (SrcIdx == -1) break; 3579 const MCOperand &Src = Inst.getOperand(SrcIdx); 3580 if (Src.isReg() && Src.getReg() == LDS_DIRECT) { 3581 return false; 3582 } 3583 } 3584 3585 if (Src0Idx == -1) 3586 return true; 3587 3588 const MCOperand &Src = Inst.getOperand(Src0Idx); 3589 if (!Src.isReg() || Src.getReg() != LDS_DIRECT) 3590 return true; 3591 3592 // lds_direct is specified as src0. Check additional limitations. 3593 return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode); 3594 } 3595 3596 SMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const { 3597 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 3598 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 3599 if (Op.isFlatOffset()) 3600 return Op.getStartLoc(); 3601 } 3602 return getLoc(); 3603 } 3604 3605 bool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst, 3606 const OperandVector &Operands) { 3607 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 3608 if ((TSFlags & SIInstrFlags::FLAT) == 0) 3609 return true; 3610 3611 auto Opcode = Inst.getOpcode(); 3612 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 3613 assert(OpNum != -1); 3614 3615 const auto &Op = Inst.getOperand(OpNum); 3616 if (!hasFlatOffsets() && Op.getImm() != 0) { 3617 Error(getFlatOffsetLoc(Operands), 3618 "flat offset modifier is not supported on this GPU"); 3619 return false; 3620 } 3621 3622 // For FLAT segment the offset must be positive; 3623 // MSB is ignored and forced to zero. 3624 if (TSFlags & (SIInstrFlags::IsFlatGlobal | SIInstrFlags::IsFlatScratch)) { 3625 unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI(), true); 3626 if (!isIntN(OffsetSize, Op.getImm())) { 3627 Error(getFlatOffsetLoc(Operands), 3628 Twine("expected a ") + Twine(OffsetSize) + "-bit signed offset"); 3629 return false; 3630 } 3631 } else { 3632 unsigned OffsetSize = AMDGPU::getNumFlatOffsetBits(getSTI(), false); 3633 if (!isUIntN(OffsetSize, Op.getImm())) { 3634 Error(getFlatOffsetLoc(Operands), 3635 Twine("expected a ") + Twine(OffsetSize) + "-bit unsigned offset"); 3636 return false; 3637 } 3638 } 3639 3640 return true; 3641 } 3642 3643 SMLoc AMDGPUAsmParser::getSMEMOffsetLoc(const OperandVector &Operands) const { 3644 // Start with second operand because SMEM Offset cannot be dst or src0. 3645 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 3646 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 3647 if (Op.isSMEMOffset()) 3648 return Op.getStartLoc(); 3649 } 3650 return getLoc(); 3651 } 3652 3653 bool AMDGPUAsmParser::validateSMEMOffset(const MCInst &Inst, 3654 const OperandVector &Operands) { 3655 if (isCI() || isSI()) 3656 return true; 3657 3658 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 3659 if ((TSFlags & SIInstrFlags::SMRD) == 0) 3660 return true; 3661 3662 auto Opcode = Inst.getOpcode(); 3663 auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset); 3664 if (OpNum == -1) 3665 return true; 3666 3667 const auto &Op = Inst.getOperand(OpNum); 3668 if (!Op.isImm()) 3669 return true; 3670 3671 uint64_t Offset = Op.getImm(); 3672 bool IsBuffer = AMDGPU::getSMEMIsBuffer(Opcode); 3673 if (AMDGPU::isLegalSMRDEncodedUnsignedOffset(getSTI(), Offset) || 3674 AMDGPU::isLegalSMRDEncodedSignedOffset(getSTI(), Offset, IsBuffer)) 3675 return true; 3676 3677 Error(getSMEMOffsetLoc(Operands), 3678 (isVI() || IsBuffer) ? "expected a 20-bit unsigned offset" : 3679 "expected a 21-bit signed offset"); 3680 3681 return false; 3682 } 3683 3684 bool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const { 3685 unsigned Opcode = Inst.getOpcode(); 3686 const MCInstrDesc &Desc = MII.get(Opcode); 3687 if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC))) 3688 return true; 3689 3690 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3691 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3692 3693 const int OpIndices[] = { Src0Idx, Src1Idx }; 3694 3695 unsigned NumExprs = 0; 3696 unsigned NumLiterals = 0; 3697 uint32_t LiteralValue; 3698 3699 for (int OpIdx : OpIndices) { 3700 if (OpIdx == -1) break; 3701 3702 const MCOperand &MO = Inst.getOperand(OpIdx); 3703 // Exclude special imm operands (like that used by s_set_gpr_idx_on) 3704 if (AMDGPU::isSISrcOperand(Desc, OpIdx)) { 3705 if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 3706 uint32_t Value = static_cast<uint32_t>(MO.getImm()); 3707 if (NumLiterals == 0 || LiteralValue != Value) { 3708 LiteralValue = Value; 3709 ++NumLiterals; 3710 } 3711 } else if (MO.isExpr()) { 3712 ++NumExprs; 3713 } 3714 } 3715 } 3716 3717 return NumLiterals + NumExprs <= 1; 3718 } 3719 3720 bool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) { 3721 const unsigned Opc = Inst.getOpcode(); 3722 if (Opc == AMDGPU::V_PERMLANE16_B32_gfx10 || 3723 Opc == AMDGPU::V_PERMLANEX16_B32_gfx10) { 3724 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 3725 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 3726 3727 if (OpSel & ~3) 3728 return false; 3729 } 3730 return true; 3731 } 3732 3733 // Check if VCC register matches wavefront size 3734 bool AMDGPUAsmParser::validateVccOperand(unsigned Reg) const { 3735 auto FB = getFeatureBits(); 3736 return (FB[AMDGPU::FeatureWavefrontSize64] && Reg == AMDGPU::VCC) || 3737 (FB[AMDGPU::FeatureWavefrontSize32] && Reg == AMDGPU::VCC_LO); 3738 } 3739 3740 // VOP3 literal is only allowed in GFX10+ and only one can be used 3741 bool AMDGPUAsmParser::validateVOP3Literal(const MCInst &Inst, 3742 const OperandVector &Operands) { 3743 unsigned Opcode = Inst.getOpcode(); 3744 const MCInstrDesc &Desc = MII.get(Opcode); 3745 if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P))) 3746 return true; 3747 3748 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); 3749 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); 3750 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); 3751 3752 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx }; 3753 3754 unsigned NumExprs = 0; 3755 unsigned NumLiterals = 0; 3756 uint32_t LiteralValue; 3757 3758 for (int OpIdx : OpIndices) { 3759 if (OpIdx == -1) break; 3760 3761 const MCOperand &MO = Inst.getOperand(OpIdx); 3762 if (!MO.isImm() && !MO.isExpr()) 3763 continue; 3764 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) 3765 continue; 3766 3767 if (OpIdx == Src2Idx && (Desc.TSFlags & SIInstrFlags::IsMAI) && 3768 getFeatureBits()[AMDGPU::FeatureMFMAInlineLiteralBug]) { 3769 Error(getConstLoc(Operands), 3770 "inline constants are not allowed for this operand"); 3771 return false; 3772 } 3773 3774 if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) { 3775 uint32_t Value = static_cast<uint32_t>(MO.getImm()); 3776 if (NumLiterals == 0 || LiteralValue != Value) { 3777 LiteralValue = Value; 3778 ++NumLiterals; 3779 } 3780 } else if (MO.isExpr()) { 3781 ++NumExprs; 3782 } 3783 } 3784 NumLiterals += NumExprs; 3785 3786 if (!NumLiterals) 3787 return true; 3788 3789 if (!getFeatureBits()[AMDGPU::FeatureVOP3Literal]) { 3790 Error(getLitLoc(Operands), "literal operands are not supported"); 3791 return false; 3792 } 3793 3794 if (NumLiterals > 1) { 3795 Error(getLitLoc(Operands), "only one literal operand is allowed"); 3796 return false; 3797 } 3798 3799 return true; 3800 } 3801 3802 bool AMDGPUAsmParser::validateCoherencyBits(const MCInst &Inst, 3803 const OperandVector &Operands, 3804 const SMLoc &IDLoc) { 3805 int GLCPos = AMDGPU::getNamedOperandIdx(Inst.getOpcode(), 3806 AMDGPU::OpName::glc1); 3807 if (GLCPos != -1) { 3808 // -1 is set by GLC_1 default operand. In all cases "glc" must be present 3809 // in the asm string, and the default value means it is not present. 3810 if (Inst.getOperand(GLCPos).getImm() == -1) { 3811 Error(IDLoc, "instruction must use glc"); 3812 return false; 3813 } 3814 } 3815 3816 return true; 3817 } 3818 3819 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst, 3820 const SMLoc &IDLoc, 3821 const OperandVector &Operands) { 3822 if (!validateLdsDirect(Inst)) { 3823 Error(getRegLoc(AMDGPU::LDS_DIRECT, Operands), 3824 "invalid use of lds_direct"); 3825 return false; 3826 } 3827 if (!validateSOPLiteral(Inst)) { 3828 Error(getLitLoc(Operands), 3829 "only one literal operand is allowed"); 3830 return false; 3831 } 3832 if (!validateVOP3Literal(Inst, Operands)) { 3833 return false; 3834 } 3835 if (!validateConstantBusLimitations(Inst, Operands)) { 3836 return false; 3837 } 3838 if (!validateEarlyClobberLimitations(Inst, Operands)) { 3839 return false; 3840 } 3841 if (!validateIntClampSupported(Inst)) { 3842 Error(getImmLoc(AMDGPUOperand::ImmTyClampSI, Operands), 3843 "integer clamping is not supported on this GPU"); 3844 return false; 3845 } 3846 if (!validateOpSel(Inst)) { 3847 Error(getImmLoc(AMDGPUOperand::ImmTyOpSel, Operands), 3848 "invalid op_sel operand"); 3849 return false; 3850 } 3851 // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate. 3852 if (!validateMIMGD16(Inst)) { 3853 Error(getImmLoc(AMDGPUOperand::ImmTyD16, Operands), 3854 "d16 modifier is not supported on this GPU"); 3855 return false; 3856 } 3857 if (!validateMIMGDim(Inst)) { 3858 Error(IDLoc, "dim modifier is required on this GPU"); 3859 return false; 3860 } 3861 if (!validateMIMGDataSize(Inst)) { 3862 Error(IDLoc, 3863 "image data size does not match dmask and tfe"); 3864 return false; 3865 } 3866 if (!validateMIMGAddrSize(Inst)) { 3867 Error(IDLoc, 3868 "image address size does not match dim and a16"); 3869 return false; 3870 } 3871 if (!validateMIMGAtomicDMask(Inst)) { 3872 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands), 3873 "invalid atomic image dmask"); 3874 return false; 3875 } 3876 if (!validateMIMGGatherDMask(Inst)) { 3877 Error(getImmLoc(AMDGPUOperand::ImmTyDMask, Operands), 3878 "invalid image_gather dmask: only one bit must be set"); 3879 return false; 3880 } 3881 if (!validateMovrels(Inst, Operands)) { 3882 return false; 3883 } 3884 if (!validateFlatOffset(Inst, Operands)) { 3885 return false; 3886 } 3887 if (!validateSMEMOffset(Inst, Operands)) { 3888 return false; 3889 } 3890 if (!validateMAIAccWrite(Inst, Operands)) { 3891 return false; 3892 } 3893 if (!validateDivScale(Inst)) { 3894 Error(IDLoc, "ABS not allowed in VOP3B instructions"); 3895 return false; 3896 } 3897 if (!validateCoherencyBits(Inst, Operands, IDLoc)) { 3898 return false; 3899 } 3900 3901 return true; 3902 } 3903 3904 static std::string AMDGPUMnemonicSpellCheck(StringRef S, 3905 const FeatureBitset &FBS, 3906 unsigned VariantID = 0); 3907 3908 static bool AMDGPUCheckMnemonic(StringRef Mnemonic, 3909 const FeatureBitset &AvailableFeatures, 3910 unsigned VariantID); 3911 3912 bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo, 3913 const FeatureBitset &FBS) { 3914 return isSupportedMnemo(Mnemo, FBS, getAllVariants()); 3915 } 3916 3917 bool AMDGPUAsmParser::isSupportedMnemo(StringRef Mnemo, 3918 const FeatureBitset &FBS, 3919 ArrayRef<unsigned> Variants) { 3920 for (auto Variant : Variants) { 3921 if (AMDGPUCheckMnemonic(Mnemo, FBS, Variant)) 3922 return true; 3923 } 3924 3925 return false; 3926 } 3927 3928 bool AMDGPUAsmParser::checkUnsupportedInstruction(StringRef Mnemo, 3929 const SMLoc &IDLoc) { 3930 FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits()); 3931 3932 // Check if requested instruction variant is supported. 3933 if (isSupportedMnemo(Mnemo, FBS, getMatchedVariants())) 3934 return false; 3935 3936 // This instruction is not supported. 3937 // Clear any other pending errors because they are no longer relevant. 3938 getParser().clearPendingErrors(); 3939 3940 // Requested instruction variant is not supported. 3941 // Check if any other variants are supported. 3942 StringRef VariantName = getMatchedVariantName(); 3943 if (!VariantName.empty() && isSupportedMnemo(Mnemo, FBS)) { 3944 return Error(IDLoc, 3945 Twine(VariantName, 3946 " variant of this instruction is not supported")); 3947 } 3948 3949 // Finally check if this instruction is supported on any other GPU. 3950 if (isSupportedMnemo(Mnemo, FeatureBitset().set())) { 3951 return Error(IDLoc, "instruction not supported on this GPU"); 3952 } 3953 3954 // Instruction not supported on any GPU. Probably a typo. 3955 std::string Suggestion = AMDGPUMnemonicSpellCheck(Mnemo, FBS); 3956 return Error(IDLoc, "invalid instruction" + Suggestion); 3957 } 3958 3959 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 3960 OperandVector &Operands, 3961 MCStreamer &Out, 3962 uint64_t &ErrorInfo, 3963 bool MatchingInlineAsm) { 3964 MCInst Inst; 3965 unsigned Result = Match_Success; 3966 for (auto Variant : getMatchedVariants()) { 3967 uint64_t EI; 3968 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm, 3969 Variant); 3970 // We order match statuses from least to most specific. We use most specific 3971 // status as resulting 3972 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32 3973 if ((R == Match_Success) || 3974 (R == Match_PreferE32) || 3975 (R == Match_MissingFeature && Result != Match_PreferE32) || 3976 (R == Match_InvalidOperand && Result != Match_MissingFeature 3977 && Result != Match_PreferE32) || 3978 (R == Match_MnemonicFail && Result != Match_InvalidOperand 3979 && Result != Match_MissingFeature 3980 && Result != Match_PreferE32)) { 3981 Result = R; 3982 ErrorInfo = EI; 3983 } 3984 if (R == Match_Success) 3985 break; 3986 } 3987 3988 if (Result == Match_Success) { 3989 if (!validateInstruction(Inst, IDLoc, Operands)) { 3990 return true; 3991 } 3992 Inst.setLoc(IDLoc); 3993 Out.emitInstruction(Inst, getSTI()); 3994 return false; 3995 } 3996 3997 StringRef Mnemo = ((AMDGPUOperand &)*Operands[0]).getToken(); 3998 if (checkUnsupportedInstruction(Mnemo, IDLoc)) { 3999 return true; 4000 } 4001 4002 switch (Result) { 4003 default: break; 4004 case Match_MissingFeature: 4005 // It has been verified that the specified instruction 4006 // mnemonic is valid. A match was found but it requires 4007 // features which are not supported on this GPU. 4008 return Error(IDLoc, "operands are not valid for this GPU or mode"); 4009 4010 case Match_InvalidOperand: { 4011 SMLoc ErrorLoc = IDLoc; 4012 if (ErrorInfo != ~0ULL) { 4013 if (ErrorInfo >= Operands.size()) { 4014 return Error(IDLoc, "too few operands for instruction"); 4015 } 4016 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 4017 if (ErrorLoc == SMLoc()) 4018 ErrorLoc = IDLoc; 4019 } 4020 return Error(ErrorLoc, "invalid operand for instruction"); 4021 } 4022 4023 case Match_PreferE32: 4024 return Error(IDLoc, "internal error: instruction without _e64 suffix " 4025 "should be encoded as e32"); 4026 case Match_MnemonicFail: 4027 llvm_unreachable("Invalid instructions should have been handled already"); 4028 } 4029 llvm_unreachable("Implement any new match types added!"); 4030 } 4031 4032 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) { 4033 int64_t Tmp = -1; 4034 if (!isToken(AsmToken::Integer) && !isToken(AsmToken::Identifier)) { 4035 return true; 4036 } 4037 if (getParser().parseAbsoluteExpression(Tmp)) { 4038 return true; 4039 } 4040 Ret = static_cast<uint32_t>(Tmp); 4041 return false; 4042 } 4043 4044 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 4045 uint32_t &Minor) { 4046 if (ParseAsAbsoluteExpression(Major)) 4047 return TokError("invalid major version"); 4048 4049 if (!trySkipToken(AsmToken::Comma)) 4050 return TokError("minor version number required, comma expected"); 4051 4052 if (ParseAsAbsoluteExpression(Minor)) 4053 return TokError("invalid minor version"); 4054 4055 return false; 4056 } 4057 4058 bool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() { 4059 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 4060 return TokError("directive only supported for amdgcn architecture"); 4061 4062 std::string Target; 4063 4064 SMLoc TargetStart = getLoc(); 4065 if (getParser().parseEscapedString(Target)) 4066 return true; 4067 SMRange TargetRange = SMRange(TargetStart, getLoc()); 4068 4069 std::string ExpectedTarget; 4070 raw_string_ostream ExpectedTargetOS(ExpectedTarget); 4071 IsaInfo::streamIsaVersion(&getSTI(), ExpectedTargetOS); 4072 4073 if (Target != ExpectedTargetOS.str()) 4074 return Error(TargetRange.Start, "target must match options", TargetRange); 4075 4076 getTargetStreamer().EmitDirectiveAMDGCNTarget(Target); 4077 return false; 4078 } 4079 4080 bool AMDGPUAsmParser::OutOfRangeError(SMRange Range) { 4081 return Error(Range.Start, "value out of range", Range); 4082 } 4083 4084 bool AMDGPUAsmParser::calculateGPRBlocks( 4085 const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed, 4086 bool XNACKUsed, Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR, 4087 SMRange VGPRRange, unsigned NextFreeSGPR, SMRange SGPRRange, 4088 unsigned &VGPRBlocks, unsigned &SGPRBlocks) { 4089 // TODO(scott.linder): These calculations are duplicated from 4090 // AMDGPUAsmPrinter::getSIProgramInfo and could be unified. 4091 IsaVersion Version = getIsaVersion(getSTI().getCPU()); 4092 4093 unsigned NumVGPRs = NextFreeVGPR; 4094 unsigned NumSGPRs = NextFreeSGPR; 4095 4096 if (Version.Major >= 10) 4097 NumSGPRs = 0; 4098 else { 4099 unsigned MaxAddressableNumSGPRs = 4100 IsaInfo::getAddressableNumSGPRs(&getSTI()); 4101 4102 if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) && 4103 NumSGPRs > MaxAddressableNumSGPRs) 4104 return OutOfRangeError(SGPRRange); 4105 4106 NumSGPRs += 4107 IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed); 4108 4109 if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) && 4110 NumSGPRs > MaxAddressableNumSGPRs) 4111 return OutOfRangeError(SGPRRange); 4112 4113 if (Features.test(FeatureSGPRInitBug)) 4114 NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG; 4115 } 4116 4117 VGPRBlocks = 4118 IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs, EnableWavefrontSize32); 4119 SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs); 4120 4121 return false; 4122 } 4123 4124 bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { 4125 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) 4126 return TokError("directive only supported for amdgcn architecture"); 4127 4128 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) 4129 return TokError("directive only supported for amdhsa OS"); 4130 4131 StringRef KernelName; 4132 if (getParser().parseIdentifier(KernelName)) 4133 return true; 4134 4135 kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI()); 4136 4137 StringSet<> Seen; 4138 4139 IsaVersion IVersion = getIsaVersion(getSTI().getCPU()); 4140 4141 SMRange VGPRRange; 4142 uint64_t NextFreeVGPR = 0; 4143 SMRange SGPRRange; 4144 uint64_t NextFreeSGPR = 0; 4145 unsigned UserSGPRCount = 0; 4146 bool ReserveVCC = true; 4147 bool ReserveFlatScr = true; 4148 bool ReserveXNACK = hasXNACK(); 4149 Optional<bool> EnableWavefrontSize32; 4150 4151 while (true) { 4152 while (trySkipToken(AsmToken::EndOfStatement)); 4153 4154 StringRef ID; 4155 SMRange IDRange = getTok().getLocRange(); 4156 if (!parseId(ID, "expected .amdhsa_ directive or .end_amdhsa_kernel")) 4157 return true; 4158 4159 if (ID == ".end_amdhsa_kernel") 4160 break; 4161 4162 if (Seen.find(ID) != Seen.end()) 4163 return TokError(".amdhsa_ directives cannot be repeated"); 4164 Seen.insert(ID); 4165 4166 SMLoc ValStart = getLoc(); 4167 int64_t IVal; 4168 if (getParser().parseAbsoluteExpression(IVal)) 4169 return true; 4170 SMLoc ValEnd = getLoc(); 4171 SMRange ValRange = SMRange(ValStart, ValEnd); 4172 4173 if (IVal < 0) 4174 return OutOfRangeError(ValRange); 4175 4176 uint64_t Val = IVal; 4177 4178 #define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE) \ 4179 if (!isUInt<ENTRY##_WIDTH>(VALUE)) \ 4180 return OutOfRangeError(RANGE); \ 4181 AMDHSA_BITS_SET(FIELD, ENTRY, VALUE); 4182 4183 if (ID == ".amdhsa_group_segment_fixed_size") { 4184 if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val)) 4185 return OutOfRangeError(ValRange); 4186 KD.group_segment_fixed_size = Val; 4187 } else if (ID == ".amdhsa_private_segment_fixed_size") { 4188 if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val)) 4189 return OutOfRangeError(ValRange); 4190 KD.private_segment_fixed_size = Val; 4191 } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") { 4192 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4193 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER, 4194 Val, ValRange); 4195 if (Val) 4196 UserSGPRCount += 4; 4197 } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") { 4198 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4199 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val, 4200 ValRange); 4201 if (Val) 4202 UserSGPRCount += 2; 4203 } else if (ID == ".amdhsa_user_sgpr_queue_ptr") { 4204 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4205 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val, 4206 ValRange); 4207 if (Val) 4208 UserSGPRCount += 2; 4209 } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") { 4210 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4211 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR, 4212 Val, ValRange); 4213 if (Val) 4214 UserSGPRCount += 2; 4215 } else if (ID == ".amdhsa_user_sgpr_dispatch_id") { 4216 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4217 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val, 4218 ValRange); 4219 if (Val) 4220 UserSGPRCount += 2; 4221 } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") { 4222 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4223 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val, 4224 ValRange); 4225 if (Val) 4226 UserSGPRCount += 2; 4227 } else if (ID == ".amdhsa_user_sgpr_private_segment_size") { 4228 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4229 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE, 4230 Val, ValRange); 4231 if (Val) 4232 UserSGPRCount += 1; 4233 } else if (ID == ".amdhsa_wavefront_size32") { 4234 if (IVersion.Major < 10) 4235 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 4236 EnableWavefrontSize32 = Val; 4237 PARSE_BITS_ENTRY(KD.kernel_code_properties, 4238 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32, 4239 Val, ValRange); 4240 } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") { 4241 PARSE_BITS_ENTRY( 4242 KD.compute_pgm_rsrc2, 4243 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT, Val, 4244 ValRange); 4245 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") { 4246 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4247 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val, 4248 ValRange); 4249 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") { 4250 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4251 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val, 4252 ValRange); 4253 } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") { 4254 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4255 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val, 4256 ValRange); 4257 } else if (ID == ".amdhsa_system_sgpr_workgroup_info") { 4258 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4259 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val, 4260 ValRange); 4261 } else if (ID == ".amdhsa_system_vgpr_workitem_id") { 4262 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4263 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val, 4264 ValRange); 4265 } else if (ID == ".amdhsa_next_free_vgpr") { 4266 VGPRRange = ValRange; 4267 NextFreeVGPR = Val; 4268 } else if (ID == ".amdhsa_next_free_sgpr") { 4269 SGPRRange = ValRange; 4270 NextFreeSGPR = Val; 4271 } else if (ID == ".amdhsa_reserve_vcc") { 4272 if (!isUInt<1>(Val)) 4273 return OutOfRangeError(ValRange); 4274 ReserveVCC = Val; 4275 } else if (ID == ".amdhsa_reserve_flat_scratch") { 4276 if (IVersion.Major < 7) 4277 return Error(IDRange.Start, "directive requires gfx7+", IDRange); 4278 if (!isUInt<1>(Val)) 4279 return OutOfRangeError(ValRange); 4280 ReserveFlatScr = Val; 4281 } else if (ID == ".amdhsa_reserve_xnack_mask") { 4282 if (IVersion.Major < 8) 4283 return Error(IDRange.Start, "directive requires gfx8+", IDRange); 4284 if (!isUInt<1>(Val)) 4285 return OutOfRangeError(ValRange); 4286 ReserveXNACK = Val; 4287 } else if (ID == ".amdhsa_float_round_mode_32") { 4288 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 4289 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange); 4290 } else if (ID == ".amdhsa_float_round_mode_16_64") { 4291 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 4292 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange); 4293 } else if (ID == ".amdhsa_float_denorm_mode_32") { 4294 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 4295 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange); 4296 } else if (ID == ".amdhsa_float_denorm_mode_16_64") { 4297 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 4298 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val, 4299 ValRange); 4300 } else if (ID == ".amdhsa_dx10_clamp") { 4301 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, 4302 COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange); 4303 } else if (ID == ".amdhsa_ieee_mode") { 4304 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_ENABLE_IEEE_MODE, 4305 Val, ValRange); 4306 } else if (ID == ".amdhsa_fp16_overflow") { 4307 if (IVersion.Major < 9) 4308 return Error(IDRange.Start, "directive requires gfx9+", IDRange); 4309 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FP16_OVFL, Val, 4310 ValRange); 4311 } else if (ID == ".amdhsa_workgroup_processor_mode") { 4312 if (IVersion.Major < 10) 4313 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 4314 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_WGP_MODE, Val, 4315 ValRange); 4316 } else if (ID == ".amdhsa_memory_ordered") { 4317 if (IVersion.Major < 10) 4318 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 4319 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_MEM_ORDERED, Val, 4320 ValRange); 4321 } else if (ID == ".amdhsa_forward_progress") { 4322 if (IVersion.Major < 10) 4323 return Error(IDRange.Start, "directive requires gfx10+", IDRange); 4324 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FWD_PROGRESS, Val, 4325 ValRange); 4326 } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { 4327 PARSE_BITS_ENTRY( 4328 KD.compute_pgm_rsrc2, 4329 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val, 4330 ValRange); 4331 } else if (ID == ".amdhsa_exception_fp_denorm_src") { 4332 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4333 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE, 4334 Val, ValRange); 4335 } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") { 4336 PARSE_BITS_ENTRY( 4337 KD.compute_pgm_rsrc2, 4338 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val, 4339 ValRange); 4340 } else if (ID == ".amdhsa_exception_fp_ieee_overflow") { 4341 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4342 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW, 4343 Val, ValRange); 4344 } else if (ID == ".amdhsa_exception_fp_ieee_underflow") { 4345 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4346 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW, 4347 Val, ValRange); 4348 } else if (ID == ".amdhsa_exception_fp_ieee_inexact") { 4349 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4350 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT, 4351 Val, ValRange); 4352 } else if (ID == ".amdhsa_exception_int_div_zero") { 4353 PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2, 4354 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO, 4355 Val, ValRange); 4356 } else { 4357 return Error(IDRange.Start, "unknown .amdhsa_kernel directive", IDRange); 4358 } 4359 4360 #undef PARSE_BITS_ENTRY 4361 } 4362 4363 if (Seen.find(".amdhsa_next_free_vgpr") == Seen.end()) 4364 return TokError(".amdhsa_next_free_vgpr directive is required"); 4365 4366 if (Seen.find(".amdhsa_next_free_sgpr") == Seen.end()) 4367 return TokError(".amdhsa_next_free_sgpr directive is required"); 4368 4369 unsigned VGPRBlocks; 4370 unsigned SGPRBlocks; 4371 if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr, 4372 ReserveXNACK, EnableWavefrontSize32, NextFreeVGPR, 4373 VGPRRange, NextFreeSGPR, SGPRRange, VGPRBlocks, 4374 SGPRBlocks)) 4375 return true; 4376 4377 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>( 4378 VGPRBlocks)) 4379 return OutOfRangeError(VGPRRange); 4380 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 4381 COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks); 4382 4383 if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>( 4384 SGPRBlocks)) 4385 return OutOfRangeError(SGPRRange); 4386 AMDHSA_BITS_SET(KD.compute_pgm_rsrc1, 4387 COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT, 4388 SGPRBlocks); 4389 4390 if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount)) 4391 return TokError("too many user SGPRs enabled"); 4392 AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT, 4393 UserSGPRCount); 4394 4395 getTargetStreamer().EmitAmdhsaKernelDescriptor( 4396 getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC, 4397 ReserveFlatScr, ReserveXNACK); 4398 return false; 4399 } 4400 4401 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 4402 uint32_t Major; 4403 uint32_t Minor; 4404 4405 if (ParseDirectiveMajorMinor(Major, Minor)) 4406 return true; 4407 4408 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 4409 return false; 4410 } 4411 4412 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 4413 uint32_t Major; 4414 uint32_t Minor; 4415 uint32_t Stepping; 4416 StringRef VendorName; 4417 StringRef ArchName; 4418 4419 // If this directive has no arguments, then use the ISA version for the 4420 // targeted GPU. 4421 if (isToken(AsmToken::EndOfStatement)) { 4422 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 4423 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor, 4424 ISA.Stepping, 4425 "AMD", "AMDGPU"); 4426 return false; 4427 } 4428 4429 if (ParseDirectiveMajorMinor(Major, Minor)) 4430 return true; 4431 4432 if (!trySkipToken(AsmToken::Comma)) 4433 return TokError("stepping version number required, comma expected"); 4434 4435 if (ParseAsAbsoluteExpression(Stepping)) 4436 return TokError("invalid stepping version"); 4437 4438 if (!trySkipToken(AsmToken::Comma)) 4439 return TokError("vendor name required, comma expected"); 4440 4441 if (!parseString(VendorName, "invalid vendor name")) 4442 return true; 4443 4444 if (!trySkipToken(AsmToken::Comma)) 4445 return TokError("arch name required, comma expected"); 4446 4447 if (!parseString(ArchName, "invalid arch name")) 4448 return true; 4449 4450 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 4451 VendorName, ArchName); 4452 return false; 4453 } 4454 4455 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 4456 amd_kernel_code_t &Header) { 4457 // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing 4458 // assembly for backwards compatibility. 4459 if (ID == "max_scratch_backing_memory_byte_size") { 4460 Parser.eatToEndOfStatement(); 4461 return false; 4462 } 4463 4464 SmallString<40> ErrStr; 4465 raw_svector_ostream Err(ErrStr); 4466 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) { 4467 return TokError(Err.str()); 4468 } 4469 Lex(); 4470 4471 if (ID == "enable_wavefront_size32") { 4472 if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) { 4473 if (!isGFX10Plus()) 4474 return TokError("enable_wavefront_size32=1 is only allowed on GFX10+"); 4475 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 4476 return TokError("enable_wavefront_size32=1 requires +WavefrontSize32"); 4477 } else { 4478 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 4479 return TokError("enable_wavefront_size32=0 requires +WavefrontSize64"); 4480 } 4481 } 4482 4483 if (ID == "wavefront_size") { 4484 if (Header.wavefront_size == 5) { 4485 if (!isGFX10Plus()) 4486 return TokError("wavefront_size=5 is only allowed on GFX10+"); 4487 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32]) 4488 return TokError("wavefront_size=5 requires +WavefrontSize32"); 4489 } else if (Header.wavefront_size == 6) { 4490 if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64]) 4491 return TokError("wavefront_size=6 requires +WavefrontSize64"); 4492 } 4493 } 4494 4495 if (ID == "enable_wgp_mode") { 4496 if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && 4497 !isGFX10Plus()) 4498 return TokError("enable_wgp_mode=1 is only allowed on GFX10+"); 4499 } 4500 4501 if (ID == "enable_mem_ordered") { 4502 if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && 4503 !isGFX10Plus()) 4504 return TokError("enable_mem_ordered=1 is only allowed on GFX10+"); 4505 } 4506 4507 if (ID == "enable_fwd_progress") { 4508 if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && 4509 !isGFX10Plus()) 4510 return TokError("enable_fwd_progress=1 is only allowed on GFX10+"); 4511 } 4512 4513 return false; 4514 } 4515 4516 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 4517 amd_kernel_code_t Header; 4518 AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI()); 4519 4520 while (true) { 4521 // Lex EndOfStatement. This is in a while loop, because lexing a comment 4522 // will set the current token to EndOfStatement. 4523 while(trySkipToken(AsmToken::EndOfStatement)); 4524 4525 StringRef ID; 4526 if (!parseId(ID, "expected value identifier or .end_amd_kernel_code_t")) 4527 return true; 4528 4529 if (ID == ".end_amd_kernel_code_t") 4530 break; 4531 4532 if (ParseAMDKernelCodeTValue(ID, Header)) 4533 return true; 4534 } 4535 4536 getTargetStreamer().EmitAMDKernelCodeT(Header); 4537 4538 return false; 4539 } 4540 4541 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 4542 StringRef KernelName; 4543 if (!parseId(KernelName, "expected symbol name")) 4544 return true; 4545 4546 getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 4547 ELF::STT_AMDGPU_HSA_KERNEL); 4548 4549 KernelScope.initialize(getContext()); 4550 return false; 4551 } 4552 4553 bool AMDGPUAsmParser::ParseDirectiveISAVersion() { 4554 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) { 4555 return Error(getLoc(), 4556 ".amd_amdgpu_isa directive is not available on non-amdgcn " 4557 "architectures"); 4558 } 4559 4560 auto ISAVersionStringFromASM = getToken().getStringContents(); 4561 4562 std::string ISAVersionStringFromSTI; 4563 raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI); 4564 IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI); 4565 4566 if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) { 4567 return Error(getLoc(), 4568 ".amd_amdgpu_isa directive does not match triple and/or mcpu " 4569 "arguments specified through the command line"); 4570 } 4571 4572 getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str()); 4573 Lex(); 4574 4575 return false; 4576 } 4577 4578 bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() { 4579 const char *AssemblerDirectiveBegin; 4580 const char *AssemblerDirectiveEnd; 4581 std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) = 4582 isHsaAbiVersion3(&getSTI()) 4583 ? std::make_tuple(HSAMD::V3::AssemblerDirectiveBegin, 4584 HSAMD::V3::AssemblerDirectiveEnd) 4585 : std::make_tuple(HSAMD::AssemblerDirectiveBegin, 4586 HSAMD::AssemblerDirectiveEnd); 4587 4588 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) { 4589 return Error(getLoc(), 4590 (Twine(AssemblerDirectiveBegin) + Twine(" directive is " 4591 "not available on non-amdhsa OSes")).str()); 4592 } 4593 4594 std::string HSAMetadataString; 4595 if (ParseToEndDirective(AssemblerDirectiveBegin, AssemblerDirectiveEnd, 4596 HSAMetadataString)) 4597 return true; 4598 4599 if (isHsaAbiVersion3(&getSTI())) { 4600 if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString)) 4601 return Error(getLoc(), "invalid HSA metadata"); 4602 } else { 4603 if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString)) 4604 return Error(getLoc(), "invalid HSA metadata"); 4605 } 4606 4607 return false; 4608 } 4609 4610 /// Common code to parse out a block of text (typically YAML) between start and 4611 /// end directives. 4612 bool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin, 4613 const char *AssemblerDirectiveEnd, 4614 std::string &CollectString) { 4615 4616 raw_string_ostream CollectStream(CollectString); 4617 4618 getLexer().setSkipSpace(false); 4619 4620 bool FoundEnd = false; 4621 while (!isToken(AsmToken::Eof)) { 4622 while (isToken(AsmToken::Space)) { 4623 CollectStream << getTokenStr(); 4624 Lex(); 4625 } 4626 4627 if (trySkipId(AssemblerDirectiveEnd)) { 4628 FoundEnd = true; 4629 break; 4630 } 4631 4632 CollectStream << Parser.parseStringToEndOfStatement() 4633 << getContext().getAsmInfo()->getSeparatorString(); 4634 4635 Parser.eatToEndOfStatement(); 4636 } 4637 4638 getLexer().setSkipSpace(true); 4639 4640 if (isToken(AsmToken::Eof) && !FoundEnd) { 4641 return TokError(Twine("expected directive ") + 4642 Twine(AssemblerDirectiveEnd) + Twine(" not found")); 4643 } 4644 4645 CollectStream.flush(); 4646 return false; 4647 } 4648 4649 /// Parse the assembler directive for new MsgPack-format PAL metadata. 4650 bool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() { 4651 std::string String; 4652 if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin, 4653 AMDGPU::PALMD::AssemblerDirectiveEnd, String)) 4654 return true; 4655 4656 auto PALMetadata = getTargetStreamer().getPALMetadata(); 4657 if (!PALMetadata->setFromString(String)) 4658 return Error(getLoc(), "invalid PAL metadata"); 4659 return false; 4660 } 4661 4662 /// Parse the assembler directive for old linear-format PAL metadata. 4663 bool AMDGPUAsmParser::ParseDirectivePALMetadata() { 4664 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) { 4665 return Error(getLoc(), 4666 (Twine(PALMD::AssemblerDirective) + Twine(" directive is " 4667 "not available on non-amdpal OSes")).str()); 4668 } 4669 4670 auto PALMetadata = getTargetStreamer().getPALMetadata(); 4671 PALMetadata->setLegacy(); 4672 for (;;) { 4673 uint32_t Key, Value; 4674 if (ParseAsAbsoluteExpression(Key)) { 4675 return TokError(Twine("invalid value in ") + 4676 Twine(PALMD::AssemblerDirective)); 4677 } 4678 if (!trySkipToken(AsmToken::Comma)) { 4679 return TokError(Twine("expected an even number of values in ") + 4680 Twine(PALMD::AssemblerDirective)); 4681 } 4682 if (ParseAsAbsoluteExpression(Value)) { 4683 return TokError(Twine("invalid value in ") + 4684 Twine(PALMD::AssemblerDirective)); 4685 } 4686 PALMetadata->setRegister(Key, Value); 4687 if (!trySkipToken(AsmToken::Comma)) 4688 break; 4689 } 4690 return false; 4691 } 4692 4693 /// ParseDirectiveAMDGPULDS 4694 /// ::= .amdgpu_lds identifier ',' size_expression [',' align_expression] 4695 bool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() { 4696 if (getParser().checkForValidSection()) 4697 return true; 4698 4699 StringRef Name; 4700 SMLoc NameLoc = getLoc(); 4701 if (getParser().parseIdentifier(Name)) 4702 return TokError("expected identifier in directive"); 4703 4704 MCSymbol *Symbol = getContext().getOrCreateSymbol(Name); 4705 if (parseToken(AsmToken::Comma, "expected ','")) 4706 return true; 4707 4708 unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(&getSTI()); 4709 4710 int64_t Size; 4711 SMLoc SizeLoc = getLoc(); 4712 if (getParser().parseAbsoluteExpression(Size)) 4713 return true; 4714 if (Size < 0) 4715 return Error(SizeLoc, "size must be non-negative"); 4716 if (Size > LocalMemorySize) 4717 return Error(SizeLoc, "size is too large"); 4718 4719 int64_t Alignment = 4; 4720 if (trySkipToken(AsmToken::Comma)) { 4721 SMLoc AlignLoc = getLoc(); 4722 if (getParser().parseAbsoluteExpression(Alignment)) 4723 return true; 4724 if (Alignment < 0 || !isPowerOf2_64(Alignment)) 4725 return Error(AlignLoc, "alignment must be a power of two"); 4726 4727 // Alignment larger than the size of LDS is possible in theory, as long 4728 // as the linker manages to place to symbol at address 0, but we do want 4729 // to make sure the alignment fits nicely into a 32-bit integer. 4730 if (Alignment >= 1u << 31) 4731 return Error(AlignLoc, "alignment is too large"); 4732 } 4733 4734 if (parseToken(AsmToken::EndOfStatement, 4735 "unexpected token in '.amdgpu_lds' directive")) 4736 return true; 4737 4738 Symbol->redefineIfPossible(); 4739 if (!Symbol->isUndefined()) 4740 return Error(NameLoc, "invalid symbol redefinition"); 4741 4742 getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align(Alignment)); 4743 return false; 4744 } 4745 4746 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 4747 StringRef IDVal = DirectiveID.getString(); 4748 4749 if (isHsaAbiVersion3(&getSTI())) { 4750 if (IDVal == ".amdgcn_target") 4751 return ParseDirectiveAMDGCNTarget(); 4752 4753 if (IDVal == ".amdhsa_kernel") 4754 return ParseDirectiveAMDHSAKernel(); 4755 4756 // TODO: Restructure/combine with PAL metadata directive. 4757 if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin) 4758 return ParseDirectiveHSAMetadata(); 4759 } else { 4760 if (IDVal == ".hsa_code_object_version") 4761 return ParseDirectiveHSACodeObjectVersion(); 4762 4763 if (IDVal == ".hsa_code_object_isa") 4764 return ParseDirectiveHSACodeObjectISA(); 4765 4766 if (IDVal == ".amd_kernel_code_t") 4767 return ParseDirectiveAMDKernelCodeT(); 4768 4769 if (IDVal == ".amdgpu_hsa_kernel") 4770 return ParseDirectiveAMDGPUHsaKernel(); 4771 4772 if (IDVal == ".amd_amdgpu_isa") 4773 return ParseDirectiveISAVersion(); 4774 4775 if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin) 4776 return ParseDirectiveHSAMetadata(); 4777 } 4778 4779 if (IDVal == ".amdgpu_lds") 4780 return ParseDirectiveAMDGPULDS(); 4781 4782 if (IDVal == PALMD::AssemblerDirectiveBegin) 4783 return ParseDirectivePALMetadataBegin(); 4784 4785 if (IDVal == PALMD::AssemblerDirective) 4786 return ParseDirectivePALMetadata(); 4787 4788 return true; 4789 } 4790 4791 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 4792 unsigned RegNo) const { 4793 4794 for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true); 4795 R.isValid(); ++R) { 4796 if (*R == RegNo) 4797 return isGFX9Plus(); 4798 } 4799 4800 // GFX10 has 2 more SGPRs 104 and 105. 4801 for (MCRegAliasIterator R(AMDGPU::SGPR104_SGPR105, &MRI, true); 4802 R.isValid(); ++R) { 4803 if (*R == RegNo) 4804 return hasSGPR104_SGPR105(); 4805 } 4806 4807 switch (RegNo) { 4808 case AMDGPU::SRC_SHARED_BASE: 4809 case AMDGPU::SRC_SHARED_LIMIT: 4810 case AMDGPU::SRC_PRIVATE_BASE: 4811 case AMDGPU::SRC_PRIVATE_LIMIT: 4812 case AMDGPU::SRC_POPS_EXITING_WAVE_ID: 4813 return isGFX9Plus(); 4814 case AMDGPU::TBA: 4815 case AMDGPU::TBA_LO: 4816 case AMDGPU::TBA_HI: 4817 case AMDGPU::TMA: 4818 case AMDGPU::TMA_LO: 4819 case AMDGPU::TMA_HI: 4820 return !isGFX9Plus(); 4821 case AMDGPU::XNACK_MASK: 4822 case AMDGPU::XNACK_MASK_LO: 4823 case AMDGPU::XNACK_MASK_HI: 4824 return (isVI() || isGFX9()) && hasXNACK(); 4825 case AMDGPU::SGPR_NULL: 4826 return isGFX10Plus(); 4827 default: 4828 break; 4829 } 4830 4831 if (isCI()) 4832 return true; 4833 4834 if (isSI() || isGFX10Plus()) { 4835 // No flat_scr on SI. 4836 // On GFX10 flat scratch is not a valid register operand and can only be 4837 // accessed with s_setreg/s_getreg. 4838 switch (RegNo) { 4839 case AMDGPU::FLAT_SCR: 4840 case AMDGPU::FLAT_SCR_LO: 4841 case AMDGPU::FLAT_SCR_HI: 4842 return false; 4843 default: 4844 return true; 4845 } 4846 } 4847 4848 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 4849 // SI/CI have. 4850 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true); 4851 R.isValid(); ++R) { 4852 if (*R == RegNo) 4853 return hasSGPR102_SGPR103(); 4854 } 4855 4856 return true; 4857 } 4858 4859 OperandMatchResultTy 4860 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic, 4861 OperandMode Mode) { 4862 // Try to parse with a custom parser 4863 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 4864 4865 // If we successfully parsed the operand or if there as an error parsing, 4866 // we are done. 4867 // 4868 // If we are parsing after we reach EndOfStatement then this means we 4869 // are appending default values to the Operands list. This is only done 4870 // by custom parser, so we shouldn't continue on to the generic parsing. 4871 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail || 4872 isToken(AsmToken::EndOfStatement)) 4873 return ResTy; 4874 4875 SMLoc RBraceLoc; 4876 SMLoc LBraceLoc = getLoc(); 4877 if (Mode == OperandMode_NSA && trySkipToken(AsmToken::LBrac)) { 4878 unsigned Prefix = Operands.size(); 4879 4880 for (;;) { 4881 ResTy = parseReg(Operands); 4882 if (ResTy != MatchOperand_Success) 4883 return ResTy; 4884 4885 RBraceLoc = getLoc(); 4886 if (trySkipToken(AsmToken::RBrac)) 4887 break; 4888 4889 if (!trySkipToken(AsmToken::Comma)) 4890 return MatchOperand_ParseFail; 4891 } 4892 4893 if (Operands.size() - Prefix > 1) { 4894 Operands.insert(Operands.begin() + Prefix, 4895 AMDGPUOperand::CreateToken(this, "[", LBraceLoc)); 4896 Operands.push_back(AMDGPUOperand::CreateToken(this, "]", RBraceLoc)); 4897 } 4898 4899 return MatchOperand_Success; 4900 } 4901 4902 return parseRegOrImm(Operands); 4903 } 4904 4905 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) { 4906 // Clear any forced encodings from the previous instruction. 4907 setForcedEncodingSize(0); 4908 setForcedDPP(false); 4909 setForcedSDWA(false); 4910 4911 if (Name.endswith("_e64")) { 4912 setForcedEncodingSize(64); 4913 return Name.substr(0, Name.size() - 4); 4914 } else if (Name.endswith("_e32")) { 4915 setForcedEncodingSize(32); 4916 return Name.substr(0, Name.size() - 4); 4917 } else if (Name.endswith("_dpp")) { 4918 setForcedDPP(true); 4919 return Name.substr(0, Name.size() - 4); 4920 } else if (Name.endswith("_sdwa")) { 4921 setForcedSDWA(true); 4922 return Name.substr(0, Name.size() - 5); 4923 } 4924 return Name; 4925 } 4926 4927 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 4928 StringRef Name, 4929 SMLoc NameLoc, OperandVector &Operands) { 4930 // Add the instruction mnemonic 4931 Name = parseMnemonicSuffix(Name); 4932 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc)); 4933 4934 bool IsMIMG = Name.startswith("image_"); 4935 4936 while (!trySkipToken(AsmToken::EndOfStatement)) { 4937 OperandMode Mode = OperandMode_Default; 4938 if (IsMIMG && isGFX10Plus() && Operands.size() == 2) 4939 Mode = OperandMode_NSA; 4940 OperandMatchResultTy Res = parseOperand(Operands, Name, Mode); 4941 4942 // Eat the comma or space if there is one. 4943 trySkipToken(AsmToken::Comma); 4944 4945 if (Res != MatchOperand_Success) { 4946 checkUnsupportedInstruction(Name, NameLoc); 4947 if (!Parser.hasPendingError()) { 4948 // FIXME: use real operand location rather than the current location. 4949 StringRef Msg = 4950 (Res == MatchOperand_ParseFail) ? "failed parsing operand." : 4951 "not a valid operand."; 4952 Error(getLoc(), Msg); 4953 } 4954 while (!trySkipToken(AsmToken::EndOfStatement)) { 4955 Parser.Lex(); 4956 } 4957 return true; 4958 } 4959 } 4960 4961 return false; 4962 } 4963 4964 //===----------------------------------------------------------------------===// 4965 // Utility functions 4966 //===----------------------------------------------------------------------===// 4967 4968 OperandMatchResultTy 4969 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &IntVal) { 4970 4971 if (!trySkipId(Prefix, AsmToken::Colon)) 4972 return MatchOperand_NoMatch; 4973 4974 return parseExpr(IntVal) ? MatchOperand_Success : MatchOperand_ParseFail; 4975 } 4976 4977 OperandMatchResultTy 4978 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 4979 AMDGPUOperand::ImmTy ImmTy, 4980 bool (*ConvertResult)(int64_t&)) { 4981 SMLoc S = getLoc(); 4982 int64_t Value = 0; 4983 4984 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value); 4985 if (Res != MatchOperand_Success) 4986 return Res; 4987 4988 if (ConvertResult && !ConvertResult(Value)) { 4989 Error(S, "invalid " + StringRef(Prefix) + " value."); 4990 } 4991 4992 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy)); 4993 return MatchOperand_Success; 4994 } 4995 4996 OperandMatchResultTy 4997 AMDGPUAsmParser::parseOperandArrayWithPrefix(const char *Prefix, 4998 OperandVector &Operands, 4999 AMDGPUOperand::ImmTy ImmTy, 5000 bool (*ConvertResult)(int64_t&)) { 5001 SMLoc S = getLoc(); 5002 if (!trySkipId(Prefix, AsmToken::Colon)) 5003 return MatchOperand_NoMatch; 5004 5005 if (!skipToken(AsmToken::LBrac, "expected a left square bracket")) 5006 return MatchOperand_ParseFail; 5007 5008 unsigned Val = 0; 5009 const unsigned MaxSize = 4; 5010 5011 // FIXME: How to verify the number of elements matches the number of src 5012 // operands? 5013 for (int I = 0; ; ++I) { 5014 int64_t Op; 5015 SMLoc Loc = getLoc(); 5016 if (!parseExpr(Op)) 5017 return MatchOperand_ParseFail; 5018 5019 if (Op != 0 && Op != 1) { 5020 Error(Loc, "invalid " + StringRef(Prefix) + " value."); 5021 return MatchOperand_ParseFail; 5022 } 5023 5024 Val |= (Op << I); 5025 5026 if (trySkipToken(AsmToken::RBrac)) 5027 break; 5028 5029 if (I + 1 == MaxSize) { 5030 Error(getLoc(), "expected a closing square bracket"); 5031 return MatchOperand_ParseFail; 5032 } 5033 5034 if (!skipToken(AsmToken::Comma, "expected a comma")) 5035 return MatchOperand_ParseFail; 5036 } 5037 5038 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy)); 5039 return MatchOperand_Success; 5040 } 5041 5042 OperandMatchResultTy 5043 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 5044 AMDGPUOperand::ImmTy ImmTy) { 5045 int64_t Bit = 0; 5046 SMLoc S = getLoc(); 5047 5048 // We are at the end of the statement, and this is a default argument, so 5049 // use a default value. 5050 if (!isToken(AsmToken::EndOfStatement)) { 5051 switch(getTokenKind()) { 5052 case AsmToken::Identifier: { 5053 StringRef Tok = getTokenStr(); 5054 if (Tok == Name) { 5055 if (Tok == "r128" && !hasMIMG_R128()) 5056 Error(S, "r128 modifier is not supported on this GPU"); 5057 if (Tok == "a16" && !isGFX9() && !hasGFX10A16()) 5058 Error(S, "a16 modifier is not supported on this GPU"); 5059 Bit = 1; 5060 Parser.Lex(); 5061 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 5062 Bit = 0; 5063 Parser.Lex(); 5064 } else { 5065 return MatchOperand_NoMatch; 5066 } 5067 break; 5068 } 5069 default: 5070 return MatchOperand_NoMatch; 5071 } 5072 } 5073 5074 if (!isGFX10Plus() && ImmTy == AMDGPUOperand::ImmTyDLC) 5075 return MatchOperand_ParseFail; 5076 5077 if (isGFX9() && ImmTy == AMDGPUOperand::ImmTyA16) 5078 ImmTy = AMDGPUOperand::ImmTyR128A16; 5079 5080 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy)); 5081 return MatchOperand_Success; 5082 } 5083 5084 static void addOptionalImmOperand( 5085 MCInst& Inst, const OperandVector& Operands, 5086 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx, 5087 AMDGPUOperand::ImmTy ImmT, 5088 int64_t Default = 0) { 5089 auto i = OptionalIdx.find(ImmT); 5090 if (i != OptionalIdx.end()) { 5091 unsigned Idx = i->second; 5092 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 5093 } else { 5094 Inst.addOperand(MCOperand::createImm(Default)); 5095 } 5096 } 5097 5098 OperandMatchResultTy 5099 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) { 5100 if (!trySkipId(Prefix, AsmToken::Colon)) 5101 return MatchOperand_NoMatch; 5102 5103 return parseId(Value) ? MatchOperand_Success : MatchOperand_ParseFail; 5104 } 5105 5106 //===----------------------------------------------------------------------===// 5107 // MTBUF format 5108 //===----------------------------------------------------------------------===// 5109 5110 bool AMDGPUAsmParser::tryParseFmt(const char *Pref, 5111 int64_t MaxVal, 5112 int64_t &Fmt) { 5113 int64_t Val; 5114 SMLoc Loc = getLoc(); 5115 5116 auto Res = parseIntWithPrefix(Pref, Val); 5117 if (Res == MatchOperand_ParseFail) 5118 return false; 5119 if (Res == MatchOperand_NoMatch) 5120 return true; 5121 5122 if (Val < 0 || Val > MaxVal) { 5123 Error(Loc, Twine("out of range ", StringRef(Pref))); 5124 return false; 5125 } 5126 5127 Fmt = Val; 5128 return true; 5129 } 5130 5131 // dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their 5132 // values to live in a joint format operand in the MCInst encoding. 5133 OperandMatchResultTy 5134 AMDGPUAsmParser::parseDfmtNfmt(int64_t &Format) { 5135 using namespace llvm::AMDGPU::MTBUFFormat; 5136 5137 int64_t Dfmt = DFMT_UNDEF; 5138 int64_t Nfmt = NFMT_UNDEF; 5139 5140 // dfmt and nfmt can appear in either order, and each is optional. 5141 for (int I = 0; I < 2; ++I) { 5142 if (Dfmt == DFMT_UNDEF && !tryParseFmt("dfmt", DFMT_MAX, Dfmt)) 5143 return MatchOperand_ParseFail; 5144 5145 if (Nfmt == NFMT_UNDEF && !tryParseFmt("nfmt", NFMT_MAX, Nfmt)) { 5146 return MatchOperand_ParseFail; 5147 } 5148 // Skip optional comma between dfmt/nfmt 5149 // but guard against 2 commas following each other. 5150 if ((Dfmt == DFMT_UNDEF) != (Nfmt == NFMT_UNDEF) && 5151 !peekToken().is(AsmToken::Comma)) { 5152 trySkipToken(AsmToken::Comma); 5153 } 5154 } 5155 5156 if (Dfmt == DFMT_UNDEF && Nfmt == NFMT_UNDEF) 5157 return MatchOperand_NoMatch; 5158 5159 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt; 5160 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt; 5161 5162 Format = encodeDfmtNfmt(Dfmt, Nfmt); 5163 return MatchOperand_Success; 5164 } 5165 5166 OperandMatchResultTy 5167 AMDGPUAsmParser::parseUfmt(int64_t &Format) { 5168 using namespace llvm::AMDGPU::MTBUFFormat; 5169 5170 int64_t Fmt = UFMT_UNDEF; 5171 5172 if (!tryParseFmt("format", UFMT_MAX, Fmt)) 5173 return MatchOperand_ParseFail; 5174 5175 if (Fmt == UFMT_UNDEF) 5176 return MatchOperand_NoMatch; 5177 5178 Format = Fmt; 5179 return MatchOperand_Success; 5180 } 5181 5182 bool AMDGPUAsmParser::matchDfmtNfmt(int64_t &Dfmt, 5183 int64_t &Nfmt, 5184 StringRef FormatStr, 5185 SMLoc Loc) { 5186 using namespace llvm::AMDGPU::MTBUFFormat; 5187 int64_t Format; 5188 5189 Format = getDfmt(FormatStr); 5190 if (Format != DFMT_UNDEF) { 5191 Dfmt = Format; 5192 return true; 5193 } 5194 5195 Format = getNfmt(FormatStr, getSTI()); 5196 if (Format != NFMT_UNDEF) { 5197 Nfmt = Format; 5198 return true; 5199 } 5200 5201 Error(Loc, "unsupported format"); 5202 return false; 5203 } 5204 5205 OperandMatchResultTy 5206 AMDGPUAsmParser::parseSymbolicSplitFormat(StringRef FormatStr, 5207 SMLoc FormatLoc, 5208 int64_t &Format) { 5209 using namespace llvm::AMDGPU::MTBUFFormat; 5210 5211 int64_t Dfmt = DFMT_UNDEF; 5212 int64_t Nfmt = NFMT_UNDEF; 5213 if (!matchDfmtNfmt(Dfmt, Nfmt, FormatStr, FormatLoc)) 5214 return MatchOperand_ParseFail; 5215 5216 if (trySkipToken(AsmToken::Comma)) { 5217 StringRef Str; 5218 SMLoc Loc = getLoc(); 5219 if (!parseId(Str, "expected a format string") || 5220 !matchDfmtNfmt(Dfmt, Nfmt, Str, Loc)) { 5221 return MatchOperand_ParseFail; 5222 } 5223 if (Dfmt == DFMT_UNDEF) { 5224 Error(Loc, "duplicate numeric format"); 5225 return MatchOperand_ParseFail; 5226 } else if (Nfmt == NFMT_UNDEF) { 5227 Error(Loc, "duplicate data format"); 5228 return MatchOperand_ParseFail; 5229 } 5230 } 5231 5232 Dfmt = (Dfmt == DFMT_UNDEF) ? DFMT_DEFAULT : Dfmt; 5233 Nfmt = (Nfmt == NFMT_UNDEF) ? NFMT_DEFAULT : Nfmt; 5234 5235 if (isGFX10Plus()) { 5236 auto Ufmt = convertDfmtNfmt2Ufmt(Dfmt, Nfmt); 5237 if (Ufmt == UFMT_UNDEF) { 5238 Error(FormatLoc, "unsupported format"); 5239 return MatchOperand_ParseFail; 5240 } 5241 Format = Ufmt; 5242 } else { 5243 Format = encodeDfmtNfmt(Dfmt, Nfmt); 5244 } 5245 5246 return MatchOperand_Success; 5247 } 5248 5249 OperandMatchResultTy 5250 AMDGPUAsmParser::parseSymbolicUnifiedFormat(StringRef FormatStr, 5251 SMLoc Loc, 5252 int64_t &Format) { 5253 using namespace llvm::AMDGPU::MTBUFFormat; 5254 5255 auto Id = getUnifiedFormat(FormatStr); 5256 if (Id == UFMT_UNDEF) 5257 return MatchOperand_NoMatch; 5258 5259 if (!isGFX10Plus()) { 5260 Error(Loc, "unified format is not supported on this GPU"); 5261 return MatchOperand_ParseFail; 5262 } 5263 5264 Format = Id; 5265 return MatchOperand_Success; 5266 } 5267 5268 OperandMatchResultTy 5269 AMDGPUAsmParser::parseNumericFormat(int64_t &Format) { 5270 using namespace llvm::AMDGPU::MTBUFFormat; 5271 SMLoc Loc = getLoc(); 5272 5273 if (!parseExpr(Format)) 5274 return MatchOperand_ParseFail; 5275 if (!isValidFormatEncoding(Format, getSTI())) { 5276 Error(Loc, "out of range format"); 5277 return MatchOperand_ParseFail; 5278 } 5279 5280 return MatchOperand_Success; 5281 } 5282 5283 OperandMatchResultTy 5284 AMDGPUAsmParser::parseSymbolicOrNumericFormat(int64_t &Format) { 5285 using namespace llvm::AMDGPU::MTBUFFormat; 5286 5287 if (!trySkipId("format", AsmToken::Colon)) 5288 return MatchOperand_NoMatch; 5289 5290 if (trySkipToken(AsmToken::LBrac)) { 5291 StringRef FormatStr; 5292 SMLoc Loc = getLoc(); 5293 if (!parseId(FormatStr, "expected a format string")) 5294 return MatchOperand_ParseFail; 5295 5296 auto Res = parseSymbolicUnifiedFormat(FormatStr, Loc, Format); 5297 if (Res == MatchOperand_NoMatch) 5298 Res = parseSymbolicSplitFormat(FormatStr, Loc, Format); 5299 if (Res != MatchOperand_Success) 5300 return Res; 5301 5302 if (!skipToken(AsmToken::RBrac, "expected a closing square bracket")) 5303 return MatchOperand_ParseFail; 5304 5305 return MatchOperand_Success; 5306 } 5307 5308 return parseNumericFormat(Format); 5309 } 5310 5311 OperandMatchResultTy 5312 AMDGPUAsmParser::parseFORMAT(OperandVector &Operands) { 5313 using namespace llvm::AMDGPU::MTBUFFormat; 5314 5315 int64_t Format = getDefaultFormatEncoding(getSTI()); 5316 OperandMatchResultTy Res; 5317 SMLoc Loc = getLoc(); 5318 5319 // Parse legacy format syntax. 5320 Res = isGFX10Plus() ? parseUfmt(Format) : parseDfmtNfmt(Format); 5321 if (Res == MatchOperand_ParseFail) 5322 return Res; 5323 5324 bool FormatFound = (Res == MatchOperand_Success); 5325 5326 Operands.push_back( 5327 AMDGPUOperand::CreateImm(this, Format, Loc, AMDGPUOperand::ImmTyFORMAT)); 5328 5329 if (FormatFound) 5330 trySkipToken(AsmToken::Comma); 5331 5332 if (isToken(AsmToken::EndOfStatement)) { 5333 // We are expecting an soffset operand, 5334 // but let matcher handle the error. 5335 return MatchOperand_Success; 5336 } 5337 5338 // Parse soffset. 5339 Res = parseRegOrImm(Operands); 5340 if (Res != MatchOperand_Success) 5341 return Res; 5342 5343 trySkipToken(AsmToken::Comma); 5344 5345 if (!FormatFound) { 5346 Res = parseSymbolicOrNumericFormat(Format); 5347 if (Res == MatchOperand_ParseFail) 5348 return Res; 5349 if (Res == MatchOperand_Success) { 5350 auto Size = Operands.size(); 5351 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands[Size - 2]); 5352 assert(Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyFORMAT); 5353 Op.setImm(Format); 5354 } 5355 return MatchOperand_Success; 5356 } 5357 5358 if (isId("format") && peekToken().is(AsmToken::Colon)) { 5359 Error(getLoc(), "duplicate format"); 5360 return MatchOperand_ParseFail; 5361 } 5362 return MatchOperand_Success; 5363 } 5364 5365 //===----------------------------------------------------------------------===// 5366 // ds 5367 //===----------------------------------------------------------------------===// 5368 5369 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 5370 const OperandVector &Operands) { 5371 OptionalImmIndexMap OptionalIdx; 5372 5373 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 5374 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 5375 5376 // Add the register arguments 5377 if (Op.isReg()) { 5378 Op.addRegOperands(Inst, 1); 5379 continue; 5380 } 5381 5382 // Handle optional arguments 5383 OptionalIdx[Op.getImmTy()] = i; 5384 } 5385 5386 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0); 5387 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1); 5388 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 5389 5390 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 5391 } 5392 5393 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands, 5394 bool IsGdsHardcoded) { 5395 OptionalImmIndexMap OptionalIdx; 5396 5397 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 5398 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 5399 5400 // Add the register arguments 5401 if (Op.isReg()) { 5402 Op.addRegOperands(Inst, 1); 5403 continue; 5404 } 5405 5406 if (Op.isToken() && Op.getToken() == "gds") { 5407 IsGdsHardcoded = true; 5408 continue; 5409 } 5410 5411 // Handle optional arguments 5412 OptionalIdx[Op.getImmTy()] = i; 5413 } 5414 5415 AMDGPUOperand::ImmTy OffsetType = 5416 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx10 || 5417 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx6_gfx7 || 5418 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle : 5419 AMDGPUOperand::ImmTyOffset; 5420 5421 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType); 5422 5423 if (!IsGdsHardcoded) { 5424 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 5425 } 5426 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 5427 } 5428 5429 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) { 5430 OptionalImmIndexMap OptionalIdx; 5431 5432 unsigned OperandIdx[4]; 5433 unsigned EnMask = 0; 5434 int SrcIdx = 0; 5435 5436 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 5437 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 5438 5439 // Add the register arguments 5440 if (Op.isReg()) { 5441 assert(SrcIdx < 4); 5442 OperandIdx[SrcIdx] = Inst.size(); 5443 Op.addRegOperands(Inst, 1); 5444 ++SrcIdx; 5445 continue; 5446 } 5447 5448 if (Op.isOff()) { 5449 assert(SrcIdx < 4); 5450 OperandIdx[SrcIdx] = Inst.size(); 5451 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister)); 5452 ++SrcIdx; 5453 continue; 5454 } 5455 5456 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) { 5457 Op.addImmOperands(Inst, 1); 5458 continue; 5459 } 5460 5461 if (Op.isToken() && Op.getToken() == "done") 5462 continue; 5463 5464 // Handle optional arguments 5465 OptionalIdx[Op.getImmTy()] = i; 5466 } 5467 5468 assert(SrcIdx == 4); 5469 5470 bool Compr = false; 5471 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) { 5472 Compr = true; 5473 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]); 5474 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister); 5475 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister); 5476 } 5477 5478 for (auto i = 0; i < SrcIdx; ++i) { 5479 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) { 5480 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i); 5481 } 5482 } 5483 5484 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM); 5485 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr); 5486 5487 Inst.addOperand(MCOperand::createImm(EnMask)); 5488 } 5489 5490 //===----------------------------------------------------------------------===// 5491 // s_waitcnt 5492 //===----------------------------------------------------------------------===// 5493 5494 static bool 5495 encodeCnt( 5496 const AMDGPU::IsaVersion ISA, 5497 int64_t &IntVal, 5498 int64_t CntVal, 5499 bool Saturate, 5500 unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned), 5501 unsigned (*decode)(const IsaVersion &Version, unsigned)) 5502 { 5503 bool Failed = false; 5504 5505 IntVal = encode(ISA, IntVal, CntVal); 5506 if (CntVal != decode(ISA, IntVal)) { 5507 if (Saturate) { 5508 IntVal = encode(ISA, IntVal, -1); 5509 } else { 5510 Failed = true; 5511 } 5512 } 5513 return Failed; 5514 } 5515 5516 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 5517 5518 SMLoc CntLoc = getLoc(); 5519 StringRef CntName = getTokenStr(); 5520 5521 if (!skipToken(AsmToken::Identifier, "expected a counter name") || 5522 !skipToken(AsmToken::LParen, "expected a left parenthesis")) 5523 return false; 5524 5525 int64_t CntVal; 5526 SMLoc ValLoc = getLoc(); 5527 if (!parseExpr(CntVal)) 5528 return false; 5529 5530 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 5531 5532 bool Failed = true; 5533 bool Sat = CntName.endswith("_sat"); 5534 5535 if (CntName == "vmcnt" || CntName == "vmcnt_sat") { 5536 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt); 5537 } else if (CntName == "expcnt" || CntName == "expcnt_sat") { 5538 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt); 5539 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") { 5540 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt); 5541 } else { 5542 Error(CntLoc, "invalid counter name " + CntName); 5543 return false; 5544 } 5545 5546 if (Failed) { 5547 Error(ValLoc, "too large value for " + CntName); 5548 return false; 5549 } 5550 5551 if (!skipToken(AsmToken::RParen, "expected a closing parenthesis")) 5552 return false; 5553 5554 if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) { 5555 if (isToken(AsmToken::EndOfStatement)) { 5556 Error(getLoc(), "expected a counter name"); 5557 return false; 5558 } 5559 } 5560 5561 return true; 5562 } 5563 5564 OperandMatchResultTy 5565 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 5566 AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU()); 5567 int64_t Waitcnt = getWaitcntBitMask(ISA); 5568 SMLoc S = getLoc(); 5569 5570 if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) { 5571 while (!isToken(AsmToken::EndOfStatement)) { 5572 if (!parseCnt(Waitcnt)) 5573 return MatchOperand_ParseFail; 5574 } 5575 } else { 5576 if (!parseExpr(Waitcnt)) 5577 return MatchOperand_ParseFail; 5578 } 5579 5580 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S)); 5581 return MatchOperand_Success; 5582 } 5583 5584 bool 5585 AMDGPUOperand::isSWaitCnt() const { 5586 return isImm(); 5587 } 5588 5589 //===----------------------------------------------------------------------===// 5590 // hwreg 5591 //===----------------------------------------------------------------------===// 5592 5593 bool 5594 AMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg, 5595 OperandInfoTy &Offset, 5596 OperandInfoTy &Width) { 5597 using namespace llvm::AMDGPU::Hwreg; 5598 5599 // The register may be specified by name or using a numeric code 5600 HwReg.Loc = getLoc(); 5601 if (isToken(AsmToken::Identifier) && 5602 (HwReg.Id = getHwregId(getTokenStr())) >= 0) { 5603 HwReg.IsSymbolic = true; 5604 lex(); // skip register name 5605 } else if (!parseExpr(HwReg.Id, "a register name")) { 5606 return false; 5607 } 5608 5609 if (trySkipToken(AsmToken::RParen)) 5610 return true; 5611 5612 // parse optional params 5613 if (!skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis")) 5614 return false; 5615 5616 Offset.Loc = getLoc(); 5617 if (!parseExpr(Offset.Id)) 5618 return false; 5619 5620 if (!skipToken(AsmToken::Comma, "expected a comma")) 5621 return false; 5622 5623 Width.Loc = getLoc(); 5624 return parseExpr(Width.Id) && 5625 skipToken(AsmToken::RParen, "expected a closing parenthesis"); 5626 } 5627 5628 bool 5629 AMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg, 5630 const OperandInfoTy &Offset, 5631 const OperandInfoTy &Width) { 5632 5633 using namespace llvm::AMDGPU::Hwreg; 5634 5635 if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) { 5636 Error(HwReg.Loc, 5637 "specified hardware register is not supported on this GPU"); 5638 return false; 5639 } 5640 if (!isValidHwreg(HwReg.Id)) { 5641 Error(HwReg.Loc, 5642 "invalid code of hardware register: only 6-bit values are legal"); 5643 return false; 5644 } 5645 if (!isValidHwregOffset(Offset.Id)) { 5646 Error(Offset.Loc, "invalid bit offset: only 5-bit values are legal"); 5647 return false; 5648 } 5649 if (!isValidHwregWidth(Width.Id)) { 5650 Error(Width.Loc, 5651 "invalid bitfield width: only values from 1 to 32 are legal"); 5652 return false; 5653 } 5654 return true; 5655 } 5656 5657 OperandMatchResultTy 5658 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) { 5659 using namespace llvm::AMDGPU::Hwreg; 5660 5661 int64_t ImmVal = 0; 5662 SMLoc Loc = getLoc(); 5663 5664 if (trySkipId("hwreg", AsmToken::LParen)) { 5665 OperandInfoTy HwReg(ID_UNKNOWN_); 5666 OperandInfoTy Offset(OFFSET_DEFAULT_); 5667 OperandInfoTy Width(WIDTH_DEFAULT_); 5668 if (parseHwregBody(HwReg, Offset, Width) && 5669 validateHwreg(HwReg, Offset, Width)) { 5670 ImmVal = encodeHwreg(HwReg.Id, Offset.Id, Width.Id); 5671 } else { 5672 return MatchOperand_ParseFail; 5673 } 5674 } else if (parseExpr(ImmVal, "a hwreg macro")) { 5675 if (ImmVal < 0 || !isUInt<16>(ImmVal)) { 5676 Error(Loc, "invalid immediate: only 16-bit values are legal"); 5677 return MatchOperand_ParseFail; 5678 } 5679 } else { 5680 return MatchOperand_ParseFail; 5681 } 5682 5683 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg)); 5684 return MatchOperand_Success; 5685 } 5686 5687 bool AMDGPUOperand::isHwreg() const { 5688 return isImmTy(ImmTyHwreg); 5689 } 5690 5691 //===----------------------------------------------------------------------===// 5692 // sendmsg 5693 //===----------------------------------------------------------------------===// 5694 5695 bool 5696 AMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg, 5697 OperandInfoTy &Op, 5698 OperandInfoTy &Stream) { 5699 using namespace llvm::AMDGPU::SendMsg; 5700 5701 Msg.Loc = getLoc(); 5702 if (isToken(AsmToken::Identifier) && (Msg.Id = getMsgId(getTokenStr())) >= 0) { 5703 Msg.IsSymbolic = true; 5704 lex(); // skip message name 5705 } else if (!parseExpr(Msg.Id, "a message name")) { 5706 return false; 5707 } 5708 5709 if (trySkipToken(AsmToken::Comma)) { 5710 Op.IsDefined = true; 5711 Op.Loc = getLoc(); 5712 if (isToken(AsmToken::Identifier) && 5713 (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) { 5714 lex(); // skip operation name 5715 } else if (!parseExpr(Op.Id, "an operation name")) { 5716 return false; 5717 } 5718 5719 if (trySkipToken(AsmToken::Comma)) { 5720 Stream.IsDefined = true; 5721 Stream.Loc = getLoc(); 5722 if (!parseExpr(Stream.Id)) 5723 return false; 5724 } 5725 } 5726 5727 return skipToken(AsmToken::RParen, "expected a closing parenthesis"); 5728 } 5729 5730 bool 5731 AMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg, 5732 const OperandInfoTy &Op, 5733 const OperandInfoTy &Stream) { 5734 using namespace llvm::AMDGPU::SendMsg; 5735 5736 // Validation strictness depends on whether message is specified 5737 // in a symbolc or in a numeric form. In the latter case 5738 // only encoding possibility is checked. 5739 bool Strict = Msg.IsSymbolic; 5740 5741 if (!isValidMsgId(Msg.Id, getSTI(), Strict)) { 5742 Error(Msg.Loc, "invalid message id"); 5743 return false; 5744 } 5745 if (Strict && (msgRequiresOp(Msg.Id) != Op.IsDefined)) { 5746 if (Op.IsDefined) { 5747 Error(Op.Loc, "message does not support operations"); 5748 } else { 5749 Error(Msg.Loc, "missing message operation"); 5750 } 5751 return false; 5752 } 5753 if (!isValidMsgOp(Msg.Id, Op.Id, Strict)) { 5754 Error(Op.Loc, "invalid operation id"); 5755 return false; 5756 } 5757 if (Strict && !msgSupportsStream(Msg.Id, Op.Id) && Stream.IsDefined) { 5758 Error(Stream.Loc, "message operation does not support streams"); 5759 return false; 5760 } 5761 if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, Strict)) { 5762 Error(Stream.Loc, "invalid message stream id"); 5763 return false; 5764 } 5765 return true; 5766 } 5767 5768 OperandMatchResultTy 5769 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) { 5770 using namespace llvm::AMDGPU::SendMsg; 5771 5772 int64_t ImmVal = 0; 5773 SMLoc Loc = getLoc(); 5774 5775 if (trySkipId("sendmsg", AsmToken::LParen)) { 5776 OperandInfoTy Msg(ID_UNKNOWN_); 5777 OperandInfoTy Op(OP_NONE_); 5778 OperandInfoTy Stream(STREAM_ID_NONE_); 5779 if (parseSendMsgBody(Msg, Op, Stream) && 5780 validateSendMsg(Msg, Op, Stream)) { 5781 ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id); 5782 } else { 5783 return MatchOperand_ParseFail; 5784 } 5785 } else if (parseExpr(ImmVal, "a sendmsg macro")) { 5786 if (ImmVal < 0 || !isUInt<16>(ImmVal)) { 5787 Error(Loc, "invalid immediate: only 16-bit values are legal"); 5788 return MatchOperand_ParseFail; 5789 } 5790 } else { 5791 return MatchOperand_ParseFail; 5792 } 5793 5794 Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg)); 5795 return MatchOperand_Success; 5796 } 5797 5798 bool AMDGPUOperand::isSendMsg() const { 5799 return isImmTy(ImmTySendMsg); 5800 } 5801 5802 //===----------------------------------------------------------------------===// 5803 // v_interp 5804 //===----------------------------------------------------------------------===// 5805 5806 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) { 5807 StringRef Str; 5808 SMLoc S = getLoc(); 5809 5810 if (!parseId(Str)) 5811 return MatchOperand_NoMatch; 5812 5813 int Slot = StringSwitch<int>(Str) 5814 .Case("p10", 0) 5815 .Case("p20", 1) 5816 .Case("p0", 2) 5817 .Default(-1); 5818 5819 if (Slot == -1) { 5820 Error(S, "invalid interpolation slot"); 5821 return MatchOperand_ParseFail; 5822 } 5823 5824 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S, 5825 AMDGPUOperand::ImmTyInterpSlot)); 5826 return MatchOperand_Success; 5827 } 5828 5829 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) { 5830 StringRef Str; 5831 SMLoc S = getLoc(); 5832 5833 if (!parseId(Str)) 5834 return MatchOperand_NoMatch; 5835 5836 if (!Str.startswith("attr")) { 5837 Error(S, "invalid interpolation attribute"); 5838 return MatchOperand_ParseFail; 5839 } 5840 5841 StringRef Chan = Str.take_back(2); 5842 int AttrChan = StringSwitch<int>(Chan) 5843 .Case(".x", 0) 5844 .Case(".y", 1) 5845 .Case(".z", 2) 5846 .Case(".w", 3) 5847 .Default(-1); 5848 if (AttrChan == -1) { 5849 Error(S, "invalid or missing interpolation attribute channel"); 5850 return MatchOperand_ParseFail; 5851 } 5852 5853 Str = Str.drop_back(2).drop_front(4); 5854 5855 uint8_t Attr; 5856 if (Str.getAsInteger(10, Attr)) { 5857 Error(S, "invalid or missing interpolation attribute number"); 5858 return MatchOperand_ParseFail; 5859 } 5860 5861 if (Attr > 63) { 5862 Error(S, "out of bounds interpolation attribute number"); 5863 return MatchOperand_ParseFail; 5864 } 5865 5866 SMLoc SChan = SMLoc::getFromPointer(Chan.data()); 5867 5868 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S, 5869 AMDGPUOperand::ImmTyInterpAttr)); 5870 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan, 5871 AMDGPUOperand::ImmTyAttrChan)); 5872 return MatchOperand_Success; 5873 } 5874 5875 //===----------------------------------------------------------------------===// 5876 // exp 5877 //===----------------------------------------------------------------------===// 5878 5879 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str, 5880 uint8_t &Val) { 5881 if (Str == "null") { 5882 Val = Exp::ET_NULL; 5883 return MatchOperand_Success; 5884 } 5885 5886 if (Str.startswith("mrt")) { 5887 Str = Str.drop_front(3); 5888 if (Str == "z") { // == mrtz 5889 Val = Exp::ET_MRTZ; 5890 return MatchOperand_Success; 5891 } 5892 5893 if (Str.getAsInteger(10, Val)) 5894 return MatchOperand_ParseFail; 5895 5896 if (Val > Exp::ET_MRT7) 5897 return MatchOperand_ParseFail; 5898 5899 return MatchOperand_Success; 5900 } 5901 5902 if (Str.startswith("pos")) { 5903 Str = Str.drop_front(3); 5904 if (Str.getAsInteger(10, Val)) 5905 return MatchOperand_ParseFail; 5906 5907 if (Val > (isGFX10Plus() ? 4 : 3)) 5908 return MatchOperand_ParseFail; 5909 5910 Val += Exp::ET_POS0; 5911 return MatchOperand_Success; 5912 } 5913 5914 if (isGFX10Plus() && Str == "prim") { 5915 Val = Exp::ET_PRIM; 5916 return MatchOperand_Success; 5917 } 5918 5919 if (Str.startswith("param")) { 5920 Str = Str.drop_front(5); 5921 if (Str.getAsInteger(10, Val)) 5922 return MatchOperand_ParseFail; 5923 5924 if (Val >= 32) 5925 return MatchOperand_ParseFail; 5926 5927 Val += Exp::ET_PARAM0; 5928 return MatchOperand_Success; 5929 } 5930 5931 return MatchOperand_ParseFail; 5932 } 5933 5934 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) { 5935 StringRef Str; 5936 SMLoc S = getLoc(); 5937 5938 if (!parseId(Str)) 5939 return MatchOperand_NoMatch; 5940 5941 uint8_t Val; 5942 auto Res = parseExpTgtImpl(Str, Val); 5943 if (Res != MatchOperand_Success) { 5944 Error(S, "invalid exp target"); 5945 return Res; 5946 } 5947 5948 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, 5949 AMDGPUOperand::ImmTyExpTgt)); 5950 return MatchOperand_Success; 5951 } 5952 5953 //===----------------------------------------------------------------------===// 5954 // parser helpers 5955 //===----------------------------------------------------------------------===// 5956 5957 bool 5958 AMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const { 5959 return Token.is(AsmToken::Identifier) && Token.getString() == Id; 5960 } 5961 5962 bool 5963 AMDGPUAsmParser::isId(const StringRef Id) const { 5964 return isId(getToken(), Id); 5965 } 5966 5967 bool 5968 AMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const { 5969 return getTokenKind() == Kind; 5970 } 5971 5972 bool 5973 AMDGPUAsmParser::trySkipId(const StringRef Id) { 5974 if (isId(Id)) { 5975 lex(); 5976 return true; 5977 } 5978 return false; 5979 } 5980 5981 bool 5982 AMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) { 5983 if (isId(Id) && peekToken().is(Kind)) { 5984 lex(); 5985 lex(); 5986 return true; 5987 } 5988 return false; 5989 } 5990 5991 bool 5992 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) { 5993 if (isToken(Kind)) { 5994 lex(); 5995 return true; 5996 } 5997 return false; 5998 } 5999 6000 bool 6001 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind, 6002 const StringRef ErrMsg) { 6003 if (!trySkipToken(Kind)) { 6004 Error(getLoc(), ErrMsg); 6005 return false; 6006 } 6007 return true; 6008 } 6009 6010 bool 6011 AMDGPUAsmParser::parseExpr(int64_t &Imm, StringRef Expected) { 6012 SMLoc S = getLoc(); 6013 6014 const MCExpr *Expr; 6015 if (Parser.parseExpression(Expr)) 6016 return false; 6017 6018 if (Expr->evaluateAsAbsolute(Imm)) 6019 return true; 6020 6021 if (Expected.empty()) { 6022 Error(S, "expected absolute expression"); 6023 } else { 6024 Error(S, Twine("expected ", Expected) + 6025 Twine(" or an absolute expression")); 6026 } 6027 return false; 6028 } 6029 6030 bool 6031 AMDGPUAsmParser::parseExpr(OperandVector &Operands) { 6032 SMLoc S = getLoc(); 6033 6034 const MCExpr *Expr; 6035 if (Parser.parseExpression(Expr)) 6036 return false; 6037 6038 int64_t IntVal; 6039 if (Expr->evaluateAsAbsolute(IntVal)) { 6040 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S)); 6041 } else { 6042 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S)); 6043 } 6044 return true; 6045 } 6046 6047 bool 6048 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) { 6049 if (isToken(AsmToken::String)) { 6050 Val = getToken().getStringContents(); 6051 lex(); 6052 return true; 6053 } else { 6054 Error(getLoc(), ErrMsg); 6055 return false; 6056 } 6057 } 6058 6059 bool 6060 AMDGPUAsmParser::parseId(StringRef &Val, const StringRef ErrMsg) { 6061 if (isToken(AsmToken::Identifier)) { 6062 Val = getTokenStr(); 6063 lex(); 6064 return true; 6065 } else { 6066 if (!ErrMsg.empty()) 6067 Error(getLoc(), ErrMsg); 6068 return false; 6069 } 6070 } 6071 6072 AsmToken 6073 AMDGPUAsmParser::getToken() const { 6074 return Parser.getTok(); 6075 } 6076 6077 AsmToken 6078 AMDGPUAsmParser::peekToken() { 6079 return isToken(AsmToken::EndOfStatement) ? getToken() : getLexer().peekTok(); 6080 } 6081 6082 void 6083 AMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) { 6084 auto TokCount = getLexer().peekTokens(Tokens); 6085 6086 for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx) 6087 Tokens[Idx] = AsmToken(AsmToken::Error, ""); 6088 } 6089 6090 AsmToken::TokenKind 6091 AMDGPUAsmParser::getTokenKind() const { 6092 return getLexer().getKind(); 6093 } 6094 6095 SMLoc 6096 AMDGPUAsmParser::getLoc() const { 6097 return getToken().getLoc(); 6098 } 6099 6100 StringRef 6101 AMDGPUAsmParser::getTokenStr() const { 6102 return getToken().getString(); 6103 } 6104 6105 void 6106 AMDGPUAsmParser::lex() { 6107 Parser.Lex(); 6108 } 6109 6110 SMLoc 6111 AMDGPUAsmParser::getOperandLoc(std::function<bool(const AMDGPUOperand&)> Test, 6112 const OperandVector &Operands) const { 6113 for (unsigned i = Operands.size() - 1; i > 0; --i) { 6114 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 6115 if (Test(Op)) 6116 return Op.getStartLoc(); 6117 } 6118 return ((AMDGPUOperand &)*Operands[0]).getStartLoc(); 6119 } 6120 6121 SMLoc 6122 AMDGPUAsmParser::getImmLoc(AMDGPUOperand::ImmTy Type, 6123 const OperandVector &Operands) const { 6124 auto Test = [=](const AMDGPUOperand& Op) { return Op.isImmTy(Type); }; 6125 return getOperandLoc(Test, Operands); 6126 } 6127 6128 SMLoc 6129 AMDGPUAsmParser::getRegLoc(unsigned Reg, 6130 const OperandVector &Operands) const { 6131 auto Test = [=](const AMDGPUOperand& Op) { 6132 return Op.isRegKind() && Op.getReg() == Reg; 6133 }; 6134 return getOperandLoc(Test, Operands); 6135 } 6136 6137 SMLoc 6138 AMDGPUAsmParser::getLitLoc(const OperandVector &Operands) const { 6139 auto Test = [](const AMDGPUOperand& Op) { 6140 return Op.IsImmKindLiteral() || Op.isExpr(); 6141 }; 6142 return getOperandLoc(Test, Operands); 6143 } 6144 6145 SMLoc 6146 AMDGPUAsmParser::getConstLoc(const OperandVector &Operands) const { 6147 auto Test = [](const AMDGPUOperand& Op) { 6148 return Op.isImmKindConst(); 6149 }; 6150 return getOperandLoc(Test, Operands); 6151 } 6152 6153 //===----------------------------------------------------------------------===// 6154 // swizzle 6155 //===----------------------------------------------------------------------===// 6156 6157 LLVM_READNONE 6158 static unsigned 6159 encodeBitmaskPerm(const unsigned AndMask, 6160 const unsigned OrMask, 6161 const unsigned XorMask) { 6162 using namespace llvm::AMDGPU::Swizzle; 6163 6164 return BITMASK_PERM_ENC | 6165 (AndMask << BITMASK_AND_SHIFT) | 6166 (OrMask << BITMASK_OR_SHIFT) | 6167 (XorMask << BITMASK_XOR_SHIFT); 6168 } 6169 6170 bool 6171 AMDGPUAsmParser::parseSwizzleOperand(int64_t &Op, 6172 const unsigned MinVal, 6173 const unsigned MaxVal, 6174 const StringRef ErrMsg, 6175 SMLoc &Loc) { 6176 if (!skipToken(AsmToken::Comma, "expected a comma")) { 6177 return false; 6178 } 6179 Loc = getLoc(); 6180 if (!parseExpr(Op)) { 6181 return false; 6182 } 6183 if (Op < MinVal || Op > MaxVal) { 6184 Error(Loc, ErrMsg); 6185 return false; 6186 } 6187 6188 return true; 6189 } 6190 6191 bool 6192 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op, 6193 const unsigned MinVal, 6194 const unsigned MaxVal, 6195 const StringRef ErrMsg) { 6196 SMLoc Loc; 6197 for (unsigned i = 0; i < OpNum; ++i) { 6198 if (!parseSwizzleOperand(Op[i], MinVal, MaxVal, ErrMsg, Loc)) 6199 return false; 6200 } 6201 6202 return true; 6203 } 6204 6205 bool 6206 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) { 6207 using namespace llvm::AMDGPU::Swizzle; 6208 6209 int64_t Lane[LANE_NUM]; 6210 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX, 6211 "expected a 2-bit lane id")) { 6212 Imm = QUAD_PERM_ENC; 6213 for (unsigned I = 0; I < LANE_NUM; ++I) { 6214 Imm |= Lane[I] << (LANE_SHIFT * I); 6215 } 6216 return true; 6217 } 6218 return false; 6219 } 6220 6221 bool 6222 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) { 6223 using namespace llvm::AMDGPU::Swizzle; 6224 6225 SMLoc Loc; 6226 int64_t GroupSize; 6227 int64_t LaneIdx; 6228 6229 if (!parseSwizzleOperand(GroupSize, 6230 2, 32, 6231 "group size must be in the interval [2,32]", 6232 Loc)) { 6233 return false; 6234 } 6235 if (!isPowerOf2_64(GroupSize)) { 6236 Error(Loc, "group size must be a power of two"); 6237 return false; 6238 } 6239 if (parseSwizzleOperand(LaneIdx, 6240 0, GroupSize - 1, 6241 "lane id must be in the interval [0,group size - 1]", 6242 Loc)) { 6243 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0); 6244 return true; 6245 } 6246 return false; 6247 } 6248 6249 bool 6250 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) { 6251 using namespace llvm::AMDGPU::Swizzle; 6252 6253 SMLoc Loc; 6254 int64_t GroupSize; 6255 6256 if (!parseSwizzleOperand(GroupSize, 6257 2, 32, 6258 "group size must be in the interval [2,32]", 6259 Loc)) { 6260 return false; 6261 } 6262 if (!isPowerOf2_64(GroupSize)) { 6263 Error(Loc, "group size must be a power of two"); 6264 return false; 6265 } 6266 6267 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1); 6268 return true; 6269 } 6270 6271 bool 6272 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) { 6273 using namespace llvm::AMDGPU::Swizzle; 6274 6275 SMLoc Loc; 6276 int64_t GroupSize; 6277 6278 if (!parseSwizzleOperand(GroupSize, 6279 1, 16, 6280 "group size must be in the interval [1,16]", 6281 Loc)) { 6282 return false; 6283 } 6284 if (!isPowerOf2_64(GroupSize)) { 6285 Error(Loc, "group size must be a power of two"); 6286 return false; 6287 } 6288 6289 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize); 6290 return true; 6291 } 6292 6293 bool 6294 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) { 6295 using namespace llvm::AMDGPU::Swizzle; 6296 6297 if (!skipToken(AsmToken::Comma, "expected a comma")) { 6298 return false; 6299 } 6300 6301 StringRef Ctl; 6302 SMLoc StrLoc = getLoc(); 6303 if (!parseString(Ctl)) { 6304 return false; 6305 } 6306 if (Ctl.size() != BITMASK_WIDTH) { 6307 Error(StrLoc, "expected a 5-character mask"); 6308 return false; 6309 } 6310 6311 unsigned AndMask = 0; 6312 unsigned OrMask = 0; 6313 unsigned XorMask = 0; 6314 6315 for (size_t i = 0; i < Ctl.size(); ++i) { 6316 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i); 6317 switch(Ctl[i]) { 6318 default: 6319 Error(StrLoc, "invalid mask"); 6320 return false; 6321 case '0': 6322 break; 6323 case '1': 6324 OrMask |= Mask; 6325 break; 6326 case 'p': 6327 AndMask |= Mask; 6328 break; 6329 case 'i': 6330 AndMask |= Mask; 6331 XorMask |= Mask; 6332 break; 6333 } 6334 } 6335 6336 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask); 6337 return true; 6338 } 6339 6340 bool 6341 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) { 6342 6343 SMLoc OffsetLoc = getLoc(); 6344 6345 if (!parseExpr(Imm, "a swizzle macro")) { 6346 return false; 6347 } 6348 if (!isUInt<16>(Imm)) { 6349 Error(OffsetLoc, "expected a 16-bit offset"); 6350 return false; 6351 } 6352 return true; 6353 } 6354 6355 bool 6356 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) { 6357 using namespace llvm::AMDGPU::Swizzle; 6358 6359 if (skipToken(AsmToken::LParen, "expected a left parentheses")) { 6360 6361 SMLoc ModeLoc = getLoc(); 6362 bool Ok = false; 6363 6364 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) { 6365 Ok = parseSwizzleQuadPerm(Imm); 6366 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) { 6367 Ok = parseSwizzleBitmaskPerm(Imm); 6368 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) { 6369 Ok = parseSwizzleBroadcast(Imm); 6370 } else if (trySkipId(IdSymbolic[ID_SWAP])) { 6371 Ok = parseSwizzleSwap(Imm); 6372 } else if (trySkipId(IdSymbolic[ID_REVERSE])) { 6373 Ok = parseSwizzleReverse(Imm); 6374 } else { 6375 Error(ModeLoc, "expected a swizzle mode"); 6376 } 6377 6378 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses"); 6379 } 6380 6381 return false; 6382 } 6383 6384 OperandMatchResultTy 6385 AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) { 6386 SMLoc S = getLoc(); 6387 int64_t Imm = 0; 6388 6389 if (trySkipId("offset")) { 6390 6391 bool Ok = false; 6392 if (skipToken(AsmToken::Colon, "expected a colon")) { 6393 if (trySkipId("swizzle")) { 6394 Ok = parseSwizzleMacro(Imm); 6395 } else { 6396 Ok = parseSwizzleOffset(Imm); 6397 } 6398 } 6399 6400 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle)); 6401 6402 return Ok? MatchOperand_Success : MatchOperand_ParseFail; 6403 } else { 6404 // Swizzle "offset" operand is optional. 6405 // If it is omitted, try parsing other optional operands. 6406 return parseOptionalOpr(Operands); 6407 } 6408 } 6409 6410 bool 6411 AMDGPUOperand::isSwizzle() const { 6412 return isImmTy(ImmTySwizzle); 6413 } 6414 6415 //===----------------------------------------------------------------------===// 6416 // VGPR Index Mode 6417 //===----------------------------------------------------------------------===// 6418 6419 int64_t AMDGPUAsmParser::parseGPRIdxMacro() { 6420 6421 using namespace llvm::AMDGPU::VGPRIndexMode; 6422 6423 if (trySkipToken(AsmToken::RParen)) { 6424 return OFF; 6425 } 6426 6427 int64_t Imm = 0; 6428 6429 while (true) { 6430 unsigned Mode = 0; 6431 SMLoc S = getLoc(); 6432 6433 for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) { 6434 if (trySkipId(IdSymbolic[ModeId])) { 6435 Mode = 1 << ModeId; 6436 break; 6437 } 6438 } 6439 6440 if (Mode == 0) { 6441 Error(S, (Imm == 0)? 6442 "expected a VGPR index mode or a closing parenthesis" : 6443 "expected a VGPR index mode"); 6444 return UNDEF; 6445 } 6446 6447 if (Imm & Mode) { 6448 Error(S, "duplicate VGPR index mode"); 6449 return UNDEF; 6450 } 6451 Imm |= Mode; 6452 6453 if (trySkipToken(AsmToken::RParen)) 6454 break; 6455 if (!skipToken(AsmToken::Comma, 6456 "expected a comma or a closing parenthesis")) 6457 return UNDEF; 6458 } 6459 6460 return Imm; 6461 } 6462 6463 OperandMatchResultTy 6464 AMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) { 6465 6466 using namespace llvm::AMDGPU::VGPRIndexMode; 6467 6468 int64_t Imm = 0; 6469 SMLoc S = getLoc(); 6470 6471 if (trySkipId("gpr_idx", AsmToken::LParen)) { 6472 Imm = parseGPRIdxMacro(); 6473 if (Imm == UNDEF) 6474 return MatchOperand_ParseFail; 6475 } else { 6476 if (getParser().parseAbsoluteExpression(Imm)) 6477 return MatchOperand_ParseFail; 6478 if (Imm < 0 || !isUInt<4>(Imm)) { 6479 Error(S, "invalid immediate: only 4-bit values are legal"); 6480 return MatchOperand_ParseFail; 6481 } 6482 } 6483 6484 Operands.push_back( 6485 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode)); 6486 return MatchOperand_Success; 6487 } 6488 6489 bool AMDGPUOperand::isGPRIdxMode() const { 6490 return isImmTy(ImmTyGprIdxMode); 6491 } 6492 6493 //===----------------------------------------------------------------------===// 6494 // sopp branch targets 6495 //===----------------------------------------------------------------------===// 6496 6497 OperandMatchResultTy 6498 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 6499 6500 // Make sure we are not parsing something 6501 // that looks like a label or an expression but is not. 6502 // This will improve error messages. 6503 if (isRegister() || isModifier()) 6504 return MatchOperand_NoMatch; 6505 6506 if (!parseExpr(Operands)) 6507 return MatchOperand_ParseFail; 6508 6509 AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]); 6510 assert(Opr.isImm() || Opr.isExpr()); 6511 SMLoc Loc = Opr.getStartLoc(); 6512 6513 // Currently we do not support arbitrary expressions as branch targets. 6514 // Only labels and absolute expressions are accepted. 6515 if (Opr.isExpr() && !Opr.isSymbolRefExpr()) { 6516 Error(Loc, "expected an absolute expression or a label"); 6517 } else if (Opr.isImm() && !Opr.isS16Imm()) { 6518 Error(Loc, "expected a 16-bit signed jump offset"); 6519 } 6520 6521 return MatchOperand_Success; 6522 } 6523 6524 //===----------------------------------------------------------------------===// 6525 // Boolean holding registers 6526 //===----------------------------------------------------------------------===// 6527 6528 OperandMatchResultTy 6529 AMDGPUAsmParser::parseBoolReg(OperandVector &Operands) { 6530 return parseReg(Operands); 6531 } 6532 6533 //===----------------------------------------------------------------------===// 6534 // mubuf 6535 //===----------------------------------------------------------------------===// 6536 6537 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDLC() const { 6538 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDLC); 6539 } 6540 6541 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const { 6542 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC); 6543 } 6544 6545 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC_1() const { 6546 return AMDGPUOperand::CreateImm(this, -1, SMLoc(), AMDGPUOperand::ImmTyGLC); 6547 } 6548 6549 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const { 6550 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC); 6551 } 6552 6553 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst, 6554 const OperandVector &Operands, 6555 bool IsAtomic, 6556 bool IsAtomicReturn, 6557 bool IsLds) { 6558 bool IsLdsOpcode = IsLds; 6559 bool HasLdsModifier = false; 6560 OptionalImmIndexMap OptionalIdx; 6561 assert(IsAtomicReturn ? IsAtomic : true); 6562 unsigned FirstOperandIdx = 1; 6563 6564 for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) { 6565 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 6566 6567 // Add the register arguments 6568 if (Op.isReg()) { 6569 Op.addRegOperands(Inst, 1); 6570 // Insert a tied src for atomic return dst. 6571 // This cannot be postponed as subsequent calls to 6572 // addImmOperands rely on correct number of MC operands. 6573 if (IsAtomicReturn && i == FirstOperandIdx) 6574 Op.addRegOperands(Inst, 1); 6575 continue; 6576 } 6577 6578 // Handle the case where soffset is an immediate 6579 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 6580 Op.addImmOperands(Inst, 1); 6581 continue; 6582 } 6583 6584 HasLdsModifier |= Op.isLDS(); 6585 6586 // Handle tokens like 'offen' which are sometimes hard-coded into the 6587 // asm string. There are no MCInst operands for these. 6588 if (Op.isToken()) { 6589 continue; 6590 } 6591 assert(Op.isImm()); 6592 6593 // Handle optional arguments 6594 OptionalIdx[Op.getImmTy()] = i; 6595 } 6596 6597 // This is a workaround for an llvm quirk which may result in an 6598 // incorrect instruction selection. Lds and non-lds versions of 6599 // MUBUF instructions are identical except that lds versions 6600 // have mandatory 'lds' modifier. However this modifier follows 6601 // optional modifiers and llvm asm matcher regards this 'lds' 6602 // modifier as an optional one. As a result, an lds version 6603 // of opcode may be selected even if it has no 'lds' modifier. 6604 if (IsLdsOpcode && !HasLdsModifier) { 6605 int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode()); 6606 if (NoLdsOpcode != -1) { // Got lds version - correct it. 6607 Inst.setOpcode(NoLdsOpcode); 6608 IsLdsOpcode = false; 6609 } 6610 } 6611 6612 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 6613 if (!IsAtomic || IsAtomicReturn) { 6614 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC, 6615 IsAtomicReturn ? -1 : 0); 6616 } 6617 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 6618 6619 if (!IsLdsOpcode) { // tfe is not legal with lds opcodes 6620 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 6621 } 6622 6623 if (isGFX10Plus()) 6624 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 6625 } 6626 6627 void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) { 6628 OptionalImmIndexMap OptionalIdx; 6629 6630 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 6631 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 6632 6633 // Add the register arguments 6634 if (Op.isReg()) { 6635 Op.addRegOperands(Inst, 1); 6636 continue; 6637 } 6638 6639 // Handle the case where soffset is an immediate 6640 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 6641 Op.addImmOperands(Inst, 1); 6642 continue; 6643 } 6644 6645 // Handle tokens like 'offen' which are sometimes hard-coded into the 6646 // asm string. There are no MCInst operands for these. 6647 if (Op.isToken()) { 6648 continue; 6649 } 6650 assert(Op.isImm()); 6651 6652 // Handle optional arguments 6653 OptionalIdx[Op.getImmTy()] = i; 6654 } 6655 6656 addOptionalImmOperand(Inst, Operands, OptionalIdx, 6657 AMDGPUOperand::ImmTyOffset); 6658 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyFORMAT); 6659 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 6660 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 6661 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 6662 6663 if (isGFX10Plus()) 6664 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 6665 } 6666 6667 //===----------------------------------------------------------------------===// 6668 // mimg 6669 //===----------------------------------------------------------------------===// 6670 6671 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands, 6672 bool IsAtomic) { 6673 unsigned I = 1; 6674 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6675 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6676 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6677 } 6678 6679 if (IsAtomic) { 6680 // Add src, same as dst 6681 assert(Desc.getNumDefs() == 1); 6682 ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1); 6683 } 6684 6685 OptionalImmIndexMap OptionalIdx; 6686 6687 for (unsigned E = Operands.size(); I != E; ++I) { 6688 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6689 6690 // Add the register arguments 6691 if (Op.isReg()) { 6692 Op.addRegOperands(Inst, 1); 6693 } else if (Op.isImmModifier()) { 6694 OptionalIdx[Op.getImmTy()] = I; 6695 } else if (!Op.isToken()) { 6696 llvm_unreachable("unexpected operand type"); 6697 } 6698 } 6699 6700 bool IsGFX10Plus = isGFX10Plus(); 6701 6702 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 6703 if (IsGFX10Plus) 6704 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDim, -1); 6705 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 6706 if (IsGFX10Plus) 6707 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC); 6708 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 6709 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 6710 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16); 6711 if (IsGFX10Plus) 6712 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyA16); 6713 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 6714 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 6715 if (!IsGFX10Plus) 6716 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 6717 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyD16); 6718 } 6719 6720 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) { 6721 cvtMIMG(Inst, Operands, true); 6722 } 6723 6724 void AMDGPUAsmParser::cvtIntersectRay(MCInst &Inst, 6725 const OperandVector &Operands) { 6726 for (unsigned I = 1; I < Operands.size(); ++I) { 6727 auto &Operand = (AMDGPUOperand &)*Operands[I]; 6728 if (Operand.isReg()) 6729 Operand.addRegOperands(Inst, 1); 6730 } 6731 6732 Inst.addOperand(MCOperand::createImm(1)); // a16 6733 } 6734 6735 //===----------------------------------------------------------------------===// 6736 // smrd 6737 //===----------------------------------------------------------------------===// 6738 6739 bool AMDGPUOperand::isSMRDOffset8() const { 6740 return isImm() && isUInt<8>(getImm()); 6741 } 6742 6743 bool AMDGPUOperand::isSMEMOffset() const { 6744 return isImm(); // Offset range is checked later by validator. 6745 } 6746 6747 bool AMDGPUOperand::isSMRDLiteralOffset() const { 6748 // 32-bit literals are only supported on CI and we only want to use them 6749 // when the offset is > 8-bits. 6750 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 6751 } 6752 6753 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const { 6754 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6755 } 6756 6757 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMEMOffset() const { 6758 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6759 } 6760 6761 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const { 6762 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6763 } 6764 6765 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultFlatOffset() const { 6766 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset); 6767 } 6768 6769 //===----------------------------------------------------------------------===// 6770 // vop3 6771 //===----------------------------------------------------------------------===// 6772 6773 static bool ConvertOmodMul(int64_t &Mul) { 6774 if (Mul != 1 && Mul != 2 && Mul != 4) 6775 return false; 6776 6777 Mul >>= 1; 6778 return true; 6779 } 6780 6781 static bool ConvertOmodDiv(int64_t &Div) { 6782 if (Div == 1) { 6783 Div = 0; 6784 return true; 6785 } 6786 6787 if (Div == 2) { 6788 Div = 3; 6789 return true; 6790 } 6791 6792 return false; 6793 } 6794 6795 static bool ConvertBoundCtrl(int64_t &BoundCtrl) { 6796 if (BoundCtrl == 0) { 6797 BoundCtrl = 1; 6798 return true; 6799 } 6800 6801 if (BoundCtrl == -1) { 6802 BoundCtrl = 0; 6803 return true; 6804 } 6805 6806 return false; 6807 } 6808 6809 // Note: the order in this table matches the order of operands in AsmString. 6810 static const OptionalOperand AMDGPUOptionalOperandTable[] = { 6811 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr}, 6812 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr}, 6813 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr}, 6814 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr}, 6815 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr}, 6816 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr}, 6817 {"lds", AMDGPUOperand::ImmTyLDS, true, nullptr}, 6818 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr}, 6819 {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr}, 6820 {"dlc", AMDGPUOperand::ImmTyDLC, true, nullptr}, 6821 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr}, 6822 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr}, 6823 {"swz", AMDGPUOperand::ImmTySWZ, true, nullptr}, 6824 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr}, 6825 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr}, 6826 {"high", AMDGPUOperand::ImmTyHigh, true, nullptr}, 6827 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr}, 6828 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul}, 6829 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr}, 6830 {"da", AMDGPUOperand::ImmTyDA, true, nullptr}, 6831 {"r128", AMDGPUOperand::ImmTyR128A16, true, nullptr}, 6832 {"a16", AMDGPUOperand::ImmTyA16, true, nullptr}, 6833 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr}, 6834 {"d16", AMDGPUOperand::ImmTyD16, true, nullptr}, 6835 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr}, 6836 {"dim", AMDGPUOperand::ImmTyDim, false, nullptr}, 6837 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr}, 6838 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr}, 6839 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl}, 6840 {"fi", AMDGPUOperand::ImmTyDppFi, false, nullptr}, 6841 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr}, 6842 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr}, 6843 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr}, 6844 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr}, 6845 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr }, 6846 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr}, 6847 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr}, 6848 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr}, 6849 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr}, 6850 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}, 6851 {"blgp", AMDGPUOperand::ImmTyBLGP, false, nullptr}, 6852 {"cbsz", AMDGPUOperand::ImmTyCBSZ, false, nullptr}, 6853 {"abid", AMDGPUOperand::ImmTyABID, false, nullptr} 6854 }; 6855 6856 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) { 6857 6858 OperandMatchResultTy res = parseOptionalOpr(Operands); 6859 6860 // This is a hack to enable hardcoded mandatory operands which follow 6861 // optional operands. 6862 // 6863 // Current design assumes that all operands after the first optional operand 6864 // are also optional. However implementation of some instructions violates 6865 // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands). 6866 // 6867 // To alleviate this problem, we have to (implicitly) parse extra operands 6868 // to make sure autogenerated parser of custom operands never hit hardcoded 6869 // mandatory operands. 6870 6871 for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) { 6872 if (res != MatchOperand_Success || 6873 isToken(AsmToken::EndOfStatement)) 6874 break; 6875 6876 trySkipToken(AsmToken::Comma); 6877 res = parseOptionalOpr(Operands); 6878 } 6879 6880 return res; 6881 } 6882 6883 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) { 6884 OperandMatchResultTy res; 6885 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) { 6886 // try to parse any optional operand here 6887 if (Op.IsBit) { 6888 res = parseNamedBit(Op.Name, Operands, Op.Type); 6889 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) { 6890 res = parseOModOperand(Operands); 6891 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel || 6892 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel || 6893 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) { 6894 res = parseSDWASel(Operands, Op.Name, Op.Type); 6895 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) { 6896 res = parseSDWADstUnused(Operands); 6897 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel || 6898 Op.Type == AMDGPUOperand::ImmTyOpSelHi || 6899 Op.Type == AMDGPUOperand::ImmTyNegLo || 6900 Op.Type == AMDGPUOperand::ImmTyNegHi) { 6901 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type, 6902 Op.ConvertResult); 6903 } else if (Op.Type == AMDGPUOperand::ImmTyDim) { 6904 res = parseDim(Operands); 6905 } else { 6906 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult); 6907 } 6908 if (res != MatchOperand_NoMatch) { 6909 return res; 6910 } 6911 } 6912 return MatchOperand_NoMatch; 6913 } 6914 6915 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) { 6916 StringRef Name = getTokenStr(); 6917 if (Name == "mul") { 6918 return parseIntWithPrefix("mul", Operands, 6919 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul); 6920 } 6921 6922 if (Name == "div") { 6923 return parseIntWithPrefix("div", Operands, 6924 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv); 6925 } 6926 6927 return MatchOperand_NoMatch; 6928 } 6929 6930 void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) { 6931 cvtVOP3P(Inst, Operands); 6932 6933 int Opc = Inst.getOpcode(); 6934 6935 int SrcNum; 6936 const int Ops[] = { AMDGPU::OpName::src0, 6937 AMDGPU::OpName::src1, 6938 AMDGPU::OpName::src2 }; 6939 for (SrcNum = 0; 6940 SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1; 6941 ++SrcNum); 6942 assert(SrcNum > 0); 6943 6944 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 6945 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 6946 6947 if ((OpSel & (1 << SrcNum)) != 0) { 6948 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers); 6949 uint32_t ModVal = Inst.getOperand(ModIdx).getImm(); 6950 Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL); 6951 } 6952 } 6953 6954 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) { 6955 // 1. This operand is input modifiers 6956 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS 6957 // 2. This is not last operand 6958 && Desc.NumOperands > (OpNum + 1) 6959 // 3. Next operand is register class 6960 && Desc.OpInfo[OpNum + 1].RegClass != -1 6961 // 4. Next register is not tied to any other operand 6962 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1; 6963 } 6964 6965 void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands) 6966 { 6967 OptionalImmIndexMap OptionalIdx; 6968 unsigned Opc = Inst.getOpcode(); 6969 6970 unsigned I = 1; 6971 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 6972 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 6973 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 6974 } 6975 6976 for (unsigned E = Operands.size(); I != E; ++I) { 6977 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 6978 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 6979 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 6980 } else if (Op.isInterpSlot() || 6981 Op.isInterpAttr() || 6982 Op.isAttrChan()) { 6983 Inst.addOperand(MCOperand::createImm(Op.getImm())); 6984 } else if (Op.isImmModifier()) { 6985 OptionalIdx[Op.getImmTy()] = I; 6986 } else { 6987 llvm_unreachable("unhandled operand type"); 6988 } 6989 } 6990 6991 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) { 6992 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh); 6993 } 6994 6995 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) { 6996 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 6997 } 6998 6999 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) { 7000 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 7001 } 7002 } 7003 7004 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands, 7005 OptionalImmIndexMap &OptionalIdx) { 7006 unsigned Opc = Inst.getOpcode(); 7007 7008 unsigned I = 1; 7009 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 7010 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 7011 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 7012 } 7013 7014 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) { 7015 // This instruction has src modifiers 7016 for (unsigned E = Operands.size(); I != E; ++I) { 7017 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 7018 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 7019 Op.addRegOrImmWithFPInputModsOperands(Inst, 2); 7020 } else if (Op.isImmModifier()) { 7021 OptionalIdx[Op.getImmTy()] = I; 7022 } else if (Op.isRegOrImm()) { 7023 Op.addRegOrImmOperands(Inst, 1); 7024 } else { 7025 llvm_unreachable("unhandled operand type"); 7026 } 7027 } 7028 } else { 7029 // No src modifiers 7030 for (unsigned E = Operands.size(); I != E; ++I) { 7031 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 7032 if (Op.isMod()) { 7033 OptionalIdx[Op.getImmTy()] = I; 7034 } else { 7035 Op.addRegOrImmOperands(Inst, 1); 7036 } 7037 } 7038 } 7039 7040 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) { 7041 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 7042 } 7043 7044 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) { 7045 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 7046 } 7047 7048 // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+): 7049 // it has src2 register operand that is tied to dst operand 7050 // we don't allow modifiers for this operand in assembler so src2_modifiers 7051 // should be 0. 7052 if (Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 || 7053 Opc == AMDGPU::V_MAC_F32_e64_gfx10 || 7054 Opc == AMDGPU::V_MAC_F32_e64_vi || 7055 Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx6_gfx7 || 7056 Opc == AMDGPU::V_MAC_LEGACY_F32_e64_gfx10 || 7057 Opc == AMDGPU::V_MAC_F16_e64_vi || 7058 Opc == AMDGPU::V_FMAC_F32_e64_gfx10 || 7059 Opc == AMDGPU::V_FMAC_F32_e64_vi || 7060 Opc == AMDGPU::V_FMAC_LEGACY_F32_e64_gfx10 || 7061 Opc == AMDGPU::V_FMAC_F16_e64_gfx10) { 7062 auto it = Inst.begin(); 7063 std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers)); 7064 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2 7065 ++it; 7066 // Copy the operand to ensure it's not invalidated when Inst grows. 7067 Inst.insert(it, MCOperand(Inst.getOperand(0))); // src2 = dst 7068 } 7069 } 7070 7071 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 7072 OptionalImmIndexMap OptionalIdx; 7073 cvtVOP3(Inst, Operands, OptionalIdx); 7074 } 7075 7076 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, 7077 const OperandVector &Operands) { 7078 OptionalImmIndexMap OptIdx; 7079 const int Opc = Inst.getOpcode(); 7080 const MCInstrDesc &Desc = MII.get(Opc); 7081 7082 const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0; 7083 7084 cvtVOP3(Inst, Operands, OptIdx); 7085 7086 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) { 7087 assert(!IsPacked); 7088 Inst.addOperand(Inst.getOperand(0)); 7089 } 7090 7091 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3 7092 // instruction, and then figure out where to actually put the modifiers 7093 7094 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel); 7095 7096 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi); 7097 if (OpSelHiIdx != -1) { 7098 int DefaultVal = IsPacked ? -1 : 0; 7099 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, 7100 DefaultVal); 7101 } 7102 7103 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo); 7104 if (NegLoIdx != -1) { 7105 assert(IsPacked); 7106 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo); 7107 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi); 7108 } 7109 7110 const int Ops[] = { AMDGPU::OpName::src0, 7111 AMDGPU::OpName::src1, 7112 AMDGPU::OpName::src2 }; 7113 const int ModOps[] = { AMDGPU::OpName::src0_modifiers, 7114 AMDGPU::OpName::src1_modifiers, 7115 AMDGPU::OpName::src2_modifiers }; 7116 7117 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel); 7118 7119 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm(); 7120 unsigned OpSelHi = 0; 7121 unsigned NegLo = 0; 7122 unsigned NegHi = 0; 7123 7124 if (OpSelHiIdx != -1) { 7125 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm(); 7126 } 7127 7128 if (NegLoIdx != -1) { 7129 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi); 7130 NegLo = Inst.getOperand(NegLoIdx).getImm(); 7131 NegHi = Inst.getOperand(NegHiIdx).getImm(); 7132 } 7133 7134 for (int J = 0; J < 3; ++J) { 7135 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]); 7136 if (OpIdx == -1) 7137 break; 7138 7139 uint32_t ModVal = 0; 7140 7141 if ((OpSel & (1 << J)) != 0) 7142 ModVal |= SISrcMods::OP_SEL_0; 7143 7144 if ((OpSelHi & (1 << J)) != 0) 7145 ModVal |= SISrcMods::OP_SEL_1; 7146 7147 if ((NegLo & (1 << J)) != 0) 7148 ModVal |= SISrcMods::NEG; 7149 7150 if ((NegHi & (1 << J)) != 0) 7151 ModVal |= SISrcMods::NEG_HI; 7152 7153 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); 7154 7155 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal); 7156 } 7157 } 7158 7159 //===----------------------------------------------------------------------===// 7160 // dpp 7161 //===----------------------------------------------------------------------===// 7162 7163 bool AMDGPUOperand::isDPP8() const { 7164 return isImmTy(ImmTyDPP8); 7165 } 7166 7167 bool AMDGPUOperand::isDPPCtrl() const { 7168 using namespace AMDGPU::DPP; 7169 7170 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 7171 if (result) { 7172 int64_t Imm = getImm(); 7173 return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) || 7174 (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) || 7175 (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) || 7176 (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) || 7177 (Imm == DppCtrl::WAVE_SHL1) || 7178 (Imm == DppCtrl::WAVE_ROL1) || 7179 (Imm == DppCtrl::WAVE_SHR1) || 7180 (Imm == DppCtrl::WAVE_ROR1) || 7181 (Imm == DppCtrl::ROW_MIRROR) || 7182 (Imm == DppCtrl::ROW_HALF_MIRROR) || 7183 (Imm == DppCtrl::BCAST15) || 7184 (Imm == DppCtrl::BCAST31) || 7185 (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) || 7186 (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST); 7187 } 7188 return false; 7189 } 7190 7191 //===----------------------------------------------------------------------===// 7192 // mAI 7193 //===----------------------------------------------------------------------===// 7194 7195 bool AMDGPUOperand::isBLGP() const { 7196 return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm()); 7197 } 7198 7199 bool AMDGPUOperand::isCBSZ() const { 7200 return isImm() && getImmTy() == ImmTyCBSZ && isUInt<3>(getImm()); 7201 } 7202 7203 bool AMDGPUOperand::isABID() const { 7204 return isImm() && getImmTy() == ImmTyABID && isUInt<4>(getImm()); 7205 } 7206 7207 bool AMDGPUOperand::isS16Imm() const { 7208 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm())); 7209 } 7210 7211 bool AMDGPUOperand::isU16Imm() const { 7212 return isImm() && isUInt<16>(getImm()); 7213 } 7214 7215 OperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) { 7216 if (!isGFX10Plus()) 7217 return MatchOperand_NoMatch; 7218 7219 SMLoc S = getLoc(); 7220 7221 if (!trySkipId("dim", AsmToken::Colon)) 7222 return MatchOperand_NoMatch; 7223 7224 // We want to allow "dim:1D" etc., but the initial 1 is tokenized as an 7225 // integer. 7226 std::string Token; 7227 if (isToken(AsmToken::Integer)) { 7228 SMLoc Loc = getToken().getEndLoc(); 7229 Token = std::string(getTokenStr()); 7230 Parser.Lex(); 7231 if (getLoc() != Loc) 7232 return MatchOperand_ParseFail; 7233 } 7234 if (!isToken(AsmToken::Identifier)) 7235 return MatchOperand_ParseFail; 7236 Token += getTokenStr(); 7237 7238 StringRef DimId = Token; 7239 if (DimId.startswith("SQ_RSRC_IMG_")) 7240 DimId = DimId.substr(12); 7241 7242 const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId); 7243 if (!DimInfo) 7244 return MatchOperand_ParseFail; 7245 7246 Parser.Lex(); 7247 7248 Operands.push_back(AMDGPUOperand::CreateImm(this, DimInfo->Encoding, S, 7249 AMDGPUOperand::ImmTyDim)); 7250 return MatchOperand_Success; 7251 } 7252 7253 OperandMatchResultTy AMDGPUAsmParser::parseDPP8(OperandVector &Operands) { 7254 SMLoc S = getLoc(); 7255 7256 if (!isGFX10Plus() || !trySkipId("dpp8", AsmToken::Colon)) 7257 return MatchOperand_NoMatch; 7258 7259 // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d] 7260 7261 int64_t Sels[8]; 7262 7263 if (!trySkipToken(AsmToken::LBrac)) 7264 return MatchOperand_ParseFail; 7265 7266 if (getParser().parseAbsoluteExpression(Sels[0])) 7267 return MatchOperand_ParseFail; 7268 if (0 > Sels[0] || 7 < Sels[0]) 7269 return MatchOperand_ParseFail; 7270 7271 for (size_t i = 1; i < 8; ++i) { 7272 if (!trySkipToken(AsmToken::Comma)) 7273 return MatchOperand_ParseFail; 7274 7275 if (getParser().parseAbsoluteExpression(Sels[i])) 7276 return MatchOperand_ParseFail; 7277 if (0 > Sels[i] || 7 < Sels[i]) 7278 return MatchOperand_ParseFail; 7279 } 7280 7281 if (!trySkipToken(AsmToken::RBrac)) 7282 return MatchOperand_ParseFail; 7283 7284 unsigned DPP8 = 0; 7285 for (size_t i = 0; i < 8; ++i) 7286 DPP8 |= (Sels[i] << (i * 3)); 7287 7288 Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8)); 7289 return MatchOperand_Success; 7290 } 7291 7292 OperandMatchResultTy 7293 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) { 7294 using namespace AMDGPU::DPP; 7295 7296 SMLoc S = getLoc(); 7297 StringRef Prefix; 7298 int64_t Int; 7299 7300 if (isToken(AsmToken::Identifier)) { 7301 Prefix = getTokenStr(); 7302 } else { 7303 return MatchOperand_NoMatch; 7304 } 7305 7306 if (Prefix == "row_mirror") { 7307 Int = DppCtrl::ROW_MIRROR; 7308 Parser.Lex(); 7309 } else if (Prefix == "row_half_mirror") { 7310 Int = DppCtrl::ROW_HALF_MIRROR; 7311 Parser.Lex(); 7312 } else { 7313 // Check to prevent parseDPPCtrlOps from eating invalid tokens 7314 if (Prefix != "quad_perm" 7315 && Prefix != "row_shl" 7316 && Prefix != "row_shr" 7317 && Prefix != "row_ror" 7318 && Prefix != "wave_shl" 7319 && Prefix != "wave_rol" 7320 && Prefix != "wave_shr" 7321 && Prefix != "wave_ror" 7322 && Prefix != "row_bcast" 7323 && Prefix != "row_share" 7324 && Prefix != "row_xmask") { 7325 return MatchOperand_NoMatch; 7326 } 7327 7328 if (!isGFX10Plus() && (Prefix == "row_share" || Prefix == "row_xmask")) 7329 return MatchOperand_NoMatch; 7330 7331 if (!isVI() && !isGFX9() && 7332 (Prefix == "wave_shl" || Prefix == "wave_shr" || 7333 Prefix == "wave_rol" || Prefix == "wave_ror" || 7334 Prefix == "row_bcast")) 7335 return MatchOperand_NoMatch; 7336 7337 Parser.Lex(); 7338 if (!isToken(AsmToken::Colon)) 7339 return MatchOperand_ParseFail; 7340 7341 if (Prefix == "quad_perm") { 7342 // quad_perm:[%d,%d,%d,%d] 7343 Parser.Lex(); 7344 if (!trySkipToken(AsmToken::LBrac)) 7345 return MatchOperand_ParseFail; 7346 7347 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3)) 7348 return MatchOperand_ParseFail; 7349 7350 for (int i = 0; i < 3; ++i) { 7351 if (!trySkipToken(AsmToken::Comma)) 7352 return MatchOperand_ParseFail; 7353 7354 int64_t Temp; 7355 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3)) 7356 return MatchOperand_ParseFail; 7357 const int shift = i*2 + 2; 7358 Int += (Temp << shift); 7359 } 7360 7361 if (!trySkipToken(AsmToken::RBrac)) 7362 return MatchOperand_ParseFail; 7363 } else { 7364 // sel:%d 7365 Parser.Lex(); 7366 if (getParser().parseAbsoluteExpression(Int)) 7367 return MatchOperand_ParseFail; 7368 7369 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) { 7370 Int |= DppCtrl::ROW_SHL0; 7371 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) { 7372 Int |= DppCtrl::ROW_SHR0; 7373 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) { 7374 Int |= DppCtrl::ROW_ROR0; 7375 } else if (Prefix == "wave_shl" && 1 == Int) { 7376 Int = DppCtrl::WAVE_SHL1; 7377 } else if (Prefix == "wave_rol" && 1 == Int) { 7378 Int = DppCtrl::WAVE_ROL1; 7379 } else if (Prefix == "wave_shr" && 1 == Int) { 7380 Int = DppCtrl::WAVE_SHR1; 7381 } else if (Prefix == "wave_ror" && 1 == Int) { 7382 Int = DppCtrl::WAVE_ROR1; 7383 } else if (Prefix == "row_bcast") { 7384 if (Int == 15) { 7385 Int = DppCtrl::BCAST15; 7386 } else if (Int == 31) { 7387 Int = DppCtrl::BCAST31; 7388 } else { 7389 return MatchOperand_ParseFail; 7390 } 7391 } else if (Prefix == "row_share" && 0 <= Int && Int <= 15) { 7392 Int |= DppCtrl::ROW_SHARE_FIRST; 7393 } else if (Prefix == "row_xmask" && 0 <= Int && Int <= 15) { 7394 Int |= DppCtrl::ROW_XMASK_FIRST; 7395 } else { 7396 return MatchOperand_ParseFail; 7397 } 7398 } 7399 } 7400 7401 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl)); 7402 return MatchOperand_Success; 7403 } 7404 7405 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const { 7406 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask); 7407 } 7408 7409 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultEndpgmImmOperands() const { 7410 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyEndpgm); 7411 } 7412 7413 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const { 7414 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask); 7415 } 7416 7417 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const { 7418 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl); 7419 } 7420 7421 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultFI() const { 7422 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppFi); 7423 } 7424 7425 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) { 7426 OptionalImmIndexMap OptionalIdx; 7427 7428 unsigned I = 1; 7429 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 7430 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 7431 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 7432 } 7433 7434 int Fi = 0; 7435 for (unsigned E = Operands.size(); I != E; ++I) { 7436 auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(), 7437 MCOI::TIED_TO); 7438 if (TiedTo != -1) { 7439 assert((unsigned)TiedTo < Inst.getNumOperands()); 7440 // handle tied old or src2 for MAC instructions 7441 Inst.addOperand(Inst.getOperand(TiedTo)); 7442 } 7443 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 7444 // Add the register arguments 7445 if (Op.isReg() && validateVccOperand(Op.getReg())) { 7446 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token. 7447 // Skip it. 7448 continue; 7449 } 7450 7451 if (IsDPP8) { 7452 if (Op.isDPP8()) { 7453 Op.addImmOperands(Inst, 1); 7454 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 7455 Op.addRegWithFPInputModsOperands(Inst, 2); 7456 } else if (Op.isFI()) { 7457 Fi = Op.getImm(); 7458 } else if (Op.isReg()) { 7459 Op.addRegOperands(Inst, 1); 7460 } else { 7461 llvm_unreachable("Invalid operand type"); 7462 } 7463 } else { 7464 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 7465 Op.addRegWithFPInputModsOperands(Inst, 2); 7466 } else if (Op.isDPPCtrl()) { 7467 Op.addImmOperands(Inst, 1); 7468 } else if (Op.isImm()) { 7469 // Handle optional arguments 7470 OptionalIdx[Op.getImmTy()] = I; 7471 } else { 7472 llvm_unreachable("Invalid operand type"); 7473 } 7474 } 7475 } 7476 7477 if (IsDPP8) { 7478 using namespace llvm::AMDGPU::DPP; 7479 Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0)); 7480 } else { 7481 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 7482 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 7483 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 7484 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::fi) != -1) { 7485 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppFi); 7486 } 7487 } 7488 } 7489 7490 //===----------------------------------------------------------------------===// 7491 // sdwa 7492 //===----------------------------------------------------------------------===// 7493 7494 OperandMatchResultTy 7495 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix, 7496 AMDGPUOperand::ImmTy Type) { 7497 using namespace llvm::AMDGPU::SDWA; 7498 7499 SMLoc S = getLoc(); 7500 StringRef Value; 7501 OperandMatchResultTy res; 7502 7503 res = parseStringWithPrefix(Prefix, Value); 7504 if (res != MatchOperand_Success) { 7505 return res; 7506 } 7507 7508 int64_t Int; 7509 Int = StringSwitch<int64_t>(Value) 7510 .Case("BYTE_0", SdwaSel::BYTE_0) 7511 .Case("BYTE_1", SdwaSel::BYTE_1) 7512 .Case("BYTE_2", SdwaSel::BYTE_2) 7513 .Case("BYTE_3", SdwaSel::BYTE_3) 7514 .Case("WORD_0", SdwaSel::WORD_0) 7515 .Case("WORD_1", SdwaSel::WORD_1) 7516 .Case("DWORD", SdwaSel::DWORD) 7517 .Default(0xffffffff); 7518 7519 if (Int == 0xffffffff) { 7520 return MatchOperand_ParseFail; 7521 } 7522 7523 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type)); 7524 return MatchOperand_Success; 7525 } 7526 7527 OperandMatchResultTy 7528 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 7529 using namespace llvm::AMDGPU::SDWA; 7530 7531 SMLoc S = getLoc(); 7532 StringRef Value; 7533 OperandMatchResultTy res; 7534 7535 res = parseStringWithPrefix("dst_unused", Value); 7536 if (res != MatchOperand_Success) { 7537 return res; 7538 } 7539 7540 int64_t Int; 7541 Int = StringSwitch<int64_t>(Value) 7542 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD) 7543 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT) 7544 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE) 7545 .Default(0xffffffff); 7546 7547 if (Int == 0xffffffff) { 7548 return MatchOperand_ParseFail; 7549 } 7550 7551 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused)); 7552 return MatchOperand_Success; 7553 } 7554 7555 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) { 7556 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1); 7557 } 7558 7559 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) { 7560 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2); 7561 } 7562 7563 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) { 7564 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true, true); 7565 } 7566 7567 void AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands) { 7568 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, false, true); 7569 } 7570 7571 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) { 7572 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI()); 7573 } 7574 7575 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands, 7576 uint64_t BasicInstType, 7577 bool SkipDstVcc, 7578 bool SkipSrcVcc) { 7579 using namespace llvm::AMDGPU::SDWA; 7580 7581 OptionalImmIndexMap OptionalIdx; 7582 bool SkipVcc = SkipDstVcc || SkipSrcVcc; 7583 bool SkippedVcc = false; 7584 7585 unsigned I = 1; 7586 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 7587 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 7588 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 7589 } 7590 7591 for (unsigned E = Operands.size(); I != E; ++I) { 7592 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 7593 if (SkipVcc && !SkippedVcc && Op.isReg() && 7594 (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) { 7595 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst. 7596 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3) 7597 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand. 7598 // Skip VCC only if we didn't skip it on previous iteration. 7599 // Note that src0 and src1 occupy 2 slots each because of modifiers. 7600 if (BasicInstType == SIInstrFlags::VOP2 && 7601 ((SkipDstVcc && Inst.getNumOperands() == 1) || 7602 (SkipSrcVcc && Inst.getNumOperands() == 5))) { 7603 SkippedVcc = true; 7604 continue; 7605 } else if (BasicInstType == SIInstrFlags::VOPC && 7606 Inst.getNumOperands() == 0) { 7607 SkippedVcc = true; 7608 continue; 7609 } 7610 } 7611 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) { 7612 Op.addRegOrImmWithInputModsOperands(Inst, 2); 7613 } else if (Op.isImm()) { 7614 // Handle optional arguments 7615 OptionalIdx[Op.getImmTy()] = I; 7616 } else { 7617 llvm_unreachable("Invalid operand type"); 7618 } 7619 SkippedVcc = false; 7620 } 7621 7622 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx10 && 7623 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 && 7624 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) { 7625 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments 7626 switch (BasicInstType) { 7627 case SIInstrFlags::VOP1: 7628 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 7629 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { 7630 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); 7631 } 7632 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); 7633 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); 7634 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 7635 break; 7636 7637 case SIInstrFlags::VOP2: 7638 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 7639 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) { 7640 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0); 7641 } 7642 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD); 7643 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE); 7644 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 7645 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); 7646 break; 7647 7648 case SIInstrFlags::VOPC: 7649 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::clamp) != -1) 7650 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0); 7651 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD); 7652 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD); 7653 break; 7654 7655 default: 7656 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed"); 7657 } 7658 } 7659 7660 // special case v_mac_{f16, f32}: 7661 // it has src2 register operand that is tied to dst operand 7662 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi || 7663 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) { 7664 auto it = Inst.begin(); 7665 std::advance( 7666 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2)); 7667 Inst.insert(it, Inst.getOperand(0)); // src2 = dst 7668 } 7669 } 7670 7671 //===----------------------------------------------------------------------===// 7672 // mAI 7673 //===----------------------------------------------------------------------===// 7674 7675 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBLGP() const { 7676 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyBLGP); 7677 } 7678 7679 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultCBSZ() const { 7680 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyCBSZ); 7681 } 7682 7683 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultABID() const { 7684 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyABID); 7685 } 7686 7687 /// Force static initialization. 7688 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() { 7689 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget()); 7690 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget()); 7691 } 7692 7693 #define GET_REGISTER_MATCHER 7694 #define GET_MATCHER_IMPLEMENTATION 7695 #define GET_MNEMONIC_SPELL_CHECKER 7696 #define GET_MNEMONIC_CHECKER 7697 #include "AMDGPUGenAsmMatcher.inc" 7698 7699 // This fuction should be defined after auto-generated include so that we have 7700 // MatchClassKind enum defined 7701 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op, 7702 unsigned Kind) { 7703 // Tokens like "glc" would be parsed as immediate operands in ParseOperand(). 7704 // But MatchInstructionImpl() expects to meet token and fails to validate 7705 // operand. This method checks if we are given immediate operand but expect to 7706 // get corresponding token. 7707 AMDGPUOperand &Operand = (AMDGPUOperand&)Op; 7708 switch (Kind) { 7709 case MCK_addr64: 7710 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand; 7711 case MCK_gds: 7712 return Operand.isGDS() ? Match_Success : Match_InvalidOperand; 7713 case MCK_lds: 7714 return Operand.isLDS() ? Match_Success : Match_InvalidOperand; 7715 case MCK_glc: 7716 return Operand.isGLC() ? Match_Success : Match_InvalidOperand; 7717 case MCK_idxen: 7718 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand; 7719 case MCK_offen: 7720 return Operand.isOffen() ? Match_Success : Match_InvalidOperand; 7721 case MCK_SSrcB32: 7722 // When operands have expression values, they will return true for isToken, 7723 // because it is not possible to distinguish between a token and an 7724 // expression at parse time. MatchInstructionImpl() will always try to 7725 // match an operand as a token, when isToken returns true, and when the 7726 // name of the expression is not a valid token, the match will fail, 7727 // so we need to handle it here. 7728 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand; 7729 case MCK_SSrcF32: 7730 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand; 7731 case MCK_SoppBrTarget: 7732 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand; 7733 case MCK_VReg32OrOff: 7734 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand; 7735 case MCK_InterpSlot: 7736 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand; 7737 case MCK_Attr: 7738 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand; 7739 case MCK_AttrChan: 7740 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand; 7741 case MCK_ImmSMEMOffset: 7742 return Operand.isSMEMOffset() ? Match_Success : Match_InvalidOperand; 7743 case MCK_SReg_64: 7744 case MCK_SReg_64_XEXEC: 7745 // Null is defined as a 32-bit register but 7746 // it should also be enabled with 64-bit operands. 7747 // The following code enables it for SReg_64 operands 7748 // used as source and destination. Remaining source 7749 // operands are handled in isInlinableImm. 7750 return Operand.isNull() ? Match_Success : Match_InvalidOperand; 7751 default: 7752 return Match_InvalidOperand; 7753 } 7754 } 7755 7756 //===----------------------------------------------------------------------===// 7757 // endpgm 7758 //===----------------------------------------------------------------------===// 7759 7760 OperandMatchResultTy AMDGPUAsmParser::parseEndpgmOp(OperandVector &Operands) { 7761 SMLoc S = getLoc(); 7762 int64_t Imm = 0; 7763 7764 if (!parseExpr(Imm)) { 7765 // The operand is optional, if not present default to 0 7766 Imm = 0; 7767 } 7768 7769 if (!isUInt<16>(Imm)) { 7770 Error(S, "expected a 16-bit value"); 7771 return MatchOperand_ParseFail; 7772 } 7773 7774 Operands.push_back( 7775 AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm)); 7776 return MatchOperand_Success; 7777 } 7778 7779 bool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); } 7780