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