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