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 "llvm/ADT/APFloat.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/SmallString.h" 19 #include "llvm/ADT/StringSwitch.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/MC/MCContext.h" 22 #include "llvm/MC/MCExpr.h" 23 #include "llvm/MC/MCInst.h" 24 #include "llvm/MC/MCInstrInfo.h" 25 #include "llvm/MC/MCParser/MCAsmLexer.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 28 #include "llvm/MC/MCParser/MCTargetAsmParser.h" 29 #include "llvm/MC/MCRegisterInfo.h" 30 #include "llvm/MC/MCStreamer.h" 31 #include "llvm/MC/MCSubtargetInfo.h" 32 #include "llvm/MC/MCSymbolELF.h" 33 #include "llvm/Support/Debug.h" 34 #include "llvm/Support/ELF.h" 35 #include "llvm/Support/SourceMgr.h" 36 #include "llvm/Support/TargetRegistry.h" 37 #include "llvm/Support/raw_ostream.h" 38 39 using namespace llvm; 40 41 namespace { 42 43 struct OptionalOperand; 44 45 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL }; 46 47 class AMDGPUOperand : public MCParsedAsmOperand { 48 enum KindTy { 49 Token, 50 Immediate, 51 Register, 52 Expression 53 } Kind; 54 55 SMLoc StartLoc, EndLoc; 56 57 public: 58 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {} 59 60 MCContext *Ctx; 61 62 enum ImmTy { 63 ImmTyNone, 64 ImmTyGDS, 65 ImmTyOffen, 66 ImmTyIdxen, 67 ImmTyAddr64, 68 ImmTyOffset, 69 ImmTyOffset0, 70 ImmTyOffset1, 71 ImmTyGLC, 72 ImmTySLC, 73 ImmTyTFE, 74 ImmTyClampSI, 75 ImmTyOModSI, 76 ImmTyDppCtrl, 77 ImmTyDppRowMask, 78 ImmTyDppBankMask, 79 ImmTyDppBoundCtrl, 80 ImmTySdwaSel, 81 ImmTySdwaDstUnused, 82 ImmTyDMask, 83 ImmTyUNorm, 84 ImmTyDA, 85 ImmTyR128, 86 ImmTyLWE, 87 ImmTyHwreg, 88 }; 89 90 struct TokOp { 91 const char *Data; 92 unsigned Length; 93 }; 94 95 struct ImmOp { 96 bool IsFPImm; 97 ImmTy Type; 98 int64_t Val; 99 int Modifiers; 100 }; 101 102 struct RegOp { 103 unsigned RegNo; 104 int Modifiers; 105 const MCRegisterInfo *TRI; 106 const MCSubtargetInfo *STI; 107 bool IsForcedVOP3; 108 }; 109 110 union { 111 TokOp Tok; 112 ImmOp Imm; 113 RegOp Reg; 114 const MCExpr *Expr; 115 }; 116 117 void addImmOperands(MCInst &Inst, unsigned N) const { 118 Inst.addOperand(MCOperand::createImm(getImm())); 119 } 120 121 StringRef getToken() const { 122 return StringRef(Tok.Data, Tok.Length); 123 } 124 125 void addRegOperands(MCInst &Inst, unsigned N) const { 126 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI))); 127 } 128 129 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 130 if (isRegKind()) 131 addRegOperands(Inst, N); 132 else 133 addImmOperands(Inst, N); 134 } 135 136 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const { 137 if (isRegKind()) { 138 Inst.addOperand(MCOperand::createImm(Reg.Modifiers)); 139 addRegOperands(Inst, N); 140 } else { 141 Inst.addOperand(MCOperand::createImm(Imm.Modifiers)); 142 addImmOperands(Inst, N); 143 } 144 } 145 146 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 147 if (isImm()) 148 addImmOperands(Inst, N); 149 else { 150 assert(isExpr()); 151 Inst.addOperand(MCOperand::createExpr(Expr)); 152 } 153 } 154 155 bool isToken() const override { 156 return Kind == Token; 157 } 158 159 bool isImm() const override { 160 return Kind == Immediate; 161 } 162 163 bool isInlinableImm() const { 164 if (!isImm() || Imm.Type != AMDGPUOperand::ImmTyNone /* Only plain 165 immediates are inlinable (e.g. "clamp" attribute is not) */ ) 166 return false; 167 // TODO: We should avoid using host float here. It would be better to 168 // check the float bit values which is what a few other places do. 169 // We've had bot failures before due to weird NaN support on mips hosts. 170 const float F = BitsToFloat(Imm.Val); 171 // TODO: Add 1/(2*pi) for VI 172 return (Imm.Val <= 64 && Imm.Val >= -16) || 173 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 || 174 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0); 175 } 176 177 int64_t getImm() const { 178 return Imm.Val; 179 } 180 181 enum ImmTy getImmTy() const { 182 assert(isImm()); 183 return Imm.Type; 184 } 185 186 bool isRegKind() const { 187 return Kind == Register; 188 } 189 190 bool isReg() const override { 191 return Kind == Register && Reg.Modifiers == 0; 192 } 193 194 bool isRegOrImmWithInputMods() const { 195 return Kind == Register || isInlinableImm(); 196 } 197 198 bool isImmTy(ImmTy ImmT) const { 199 return isImm() && Imm.Type == ImmT; 200 } 201 202 bool isClampSI() const { 203 return isImmTy(ImmTyClampSI); 204 } 205 206 bool isOModSI() const { 207 return isImmTy(ImmTyOModSI); 208 } 209 210 bool isImmModifier() const { 211 return Kind == Immediate && Imm.Type != ImmTyNone; 212 } 213 214 bool isDMask() const { 215 return isImmTy(ImmTyDMask); 216 } 217 218 bool isUNorm() const { return isImmTy(ImmTyUNorm); } 219 bool isDA() const { return isImmTy(ImmTyDA); } 220 bool isR128() const { return isImmTy(ImmTyUNorm); } 221 bool isLWE() const { return isImmTy(ImmTyLWE); } 222 223 bool isMod() const { 224 return isClampSI() || isOModSI(); 225 } 226 227 bool isOffen() const { return isImmTy(ImmTyOffen); } 228 bool isIdxen() const { return isImmTy(ImmTyIdxen); } 229 bool isAddr64() const { return isImmTy(ImmTyAddr64); } 230 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); } 231 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); } 232 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); } 233 bool isGDS() const { return isImmTy(ImmTyGDS); } 234 bool isGLC() const { return isImmTy(ImmTyGLC); } 235 bool isSLC() const { return isImmTy(ImmTySLC); } 236 bool isTFE() const { return isImmTy(ImmTyTFE); } 237 238 bool isBankMask() const { 239 return isImmTy(ImmTyDppBankMask); 240 } 241 242 bool isRowMask() const { 243 return isImmTy(ImmTyDppRowMask); 244 } 245 246 bool isBoundCtrl() const { 247 return isImmTy(ImmTyDppBoundCtrl); 248 } 249 250 bool isSDWASel() const { 251 return isImmTy(ImmTySdwaSel); 252 } 253 254 bool isSDWADstUnused() const { 255 return isImmTy(ImmTySdwaDstUnused); 256 } 257 258 void setModifiers(unsigned Mods) { 259 assert(isReg() || (isImm() && Imm.Modifiers == 0)); 260 if (isReg()) 261 Reg.Modifiers = Mods; 262 else 263 Imm.Modifiers = Mods; 264 } 265 266 bool hasModifiers() const { 267 assert(isRegKind() || isImm()); 268 return isRegKind() ? Reg.Modifiers != 0 : Imm.Modifiers != 0; 269 } 270 271 unsigned getReg() const override { 272 return Reg.RegNo; 273 } 274 275 bool isRegOrImm() const { 276 return isReg() || isImm(); 277 } 278 279 bool isRegClass(unsigned RCID) const { 280 return isReg() && Reg.TRI->getRegClass(RCID).contains(getReg()); 281 } 282 283 bool isSCSrc32() const { 284 return isInlinableImm() || isRegClass(AMDGPU::SReg_32RegClassID); 285 } 286 287 bool isSCSrc64() const { 288 return isInlinableImm() || isRegClass(AMDGPU::SReg_64RegClassID); 289 } 290 291 bool isSSrc32() const { 292 return isImm() || isSCSrc32(); 293 } 294 295 bool isSSrc64() const { 296 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits. 297 // See isVSrc64(). 298 return isImm() || isSCSrc64(); 299 } 300 301 bool isVCSrc32() const { 302 return isInlinableImm() || isRegClass(AMDGPU::VS_32RegClassID); 303 } 304 305 bool isVCSrc64() const { 306 return isInlinableImm() || isRegClass(AMDGPU::VS_64RegClassID); 307 } 308 309 bool isVSrc32() const { 310 return isImm() || isVCSrc32(); 311 } 312 313 bool isVSrc64() const { 314 // TODO: Check if the 64-bit value (coming from assembly source) can be 315 // narrowed to 32 bits (in the instruction stream). That require knowledge 316 // of instruction type (unsigned/signed, floating or "untyped"/B64), 317 // see [AMD GCN3 ISA 6.3.1]. 318 // TODO: How 64-bit values are formed from 32-bit literals in _B64 insns? 319 return isImm() || isVCSrc64(); 320 } 321 322 bool isMem() const override { 323 return false; 324 } 325 326 bool isExpr() const { 327 return Kind == Expression; 328 } 329 330 bool isSoppBrTarget() const { 331 return isExpr() || isImm(); 332 } 333 334 SMLoc getStartLoc() const override { 335 return StartLoc; 336 } 337 338 SMLoc getEndLoc() const override { 339 return EndLoc; 340 } 341 342 void printImmTy(raw_ostream& OS, ImmTy Type) const { 343 switch (Type) { 344 case ImmTyNone: OS << "None"; break; 345 case ImmTyGDS: OS << "GDS"; break; 346 case ImmTyOffen: OS << "Offen"; break; 347 case ImmTyIdxen: OS << "Idxen"; break; 348 case ImmTyAddr64: OS << "Addr64"; break; 349 case ImmTyOffset: OS << "Offset"; break; 350 case ImmTyOffset0: OS << "Offset0"; break; 351 case ImmTyOffset1: OS << "Offset1"; break; 352 case ImmTyGLC: OS << "GLC"; break; 353 case ImmTySLC: OS << "SLC"; break; 354 case ImmTyTFE: OS << "TFE"; break; 355 case ImmTyClampSI: OS << "ClampSI"; break; 356 case ImmTyOModSI: OS << "OModSI"; break; 357 case ImmTyDppCtrl: OS << "DppCtrl"; break; 358 case ImmTyDppRowMask: OS << "DppRowMask"; break; 359 case ImmTyDppBankMask: OS << "DppBankMask"; break; 360 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break; 361 case ImmTySdwaSel: OS << "SdwaSel"; break; 362 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break; 363 case ImmTyDMask: OS << "DMask"; break; 364 case ImmTyUNorm: OS << "UNorm"; break; 365 case ImmTyDA: OS << "DA"; break; 366 case ImmTyR128: OS << "R128"; break; 367 case ImmTyLWE: OS << "LWE"; break; 368 case ImmTyHwreg: OS << "Hwreg"; break; 369 } 370 } 371 372 void print(raw_ostream &OS) const override { 373 switch (Kind) { 374 case Register: 375 OS << "<register " << getReg() << " mods: " << Reg.Modifiers << '>'; 376 break; 377 case Immediate: 378 OS << '<' << getImm(); 379 if (getImmTy() != ImmTyNone) { 380 OS << " type: "; printImmTy(OS, getImmTy()); 381 } 382 OS << " mods: " << Imm.Modifiers << '>'; 383 break; 384 case Token: 385 OS << '\'' << getToken() << '\''; 386 break; 387 case Expression: 388 OS << "<expr " << *Expr << '>'; 389 break; 390 } 391 } 392 393 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val, SMLoc Loc, 394 enum ImmTy Type = ImmTyNone, 395 bool IsFPImm = false) { 396 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate); 397 Op->Imm.Val = Val; 398 Op->Imm.IsFPImm = IsFPImm; 399 Op->Imm.Type = Type; 400 Op->Imm.Modifiers = 0; 401 Op->StartLoc = Loc; 402 Op->EndLoc = Loc; 403 return Op; 404 } 405 406 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc, 407 bool HasExplicitEncodingSize = true) { 408 auto Res = llvm::make_unique<AMDGPUOperand>(Token); 409 Res->Tok.Data = Str.data(); 410 Res->Tok.Length = Str.size(); 411 Res->StartLoc = Loc; 412 Res->EndLoc = Loc; 413 return Res; 414 } 415 416 static std::unique_ptr<AMDGPUOperand> CreateReg(unsigned RegNo, SMLoc S, 417 SMLoc E, 418 const MCRegisterInfo *TRI, 419 const MCSubtargetInfo *STI, 420 bool ForceVOP3) { 421 auto Op = llvm::make_unique<AMDGPUOperand>(Register); 422 Op->Reg.RegNo = RegNo; 423 Op->Reg.TRI = TRI; 424 Op->Reg.STI = STI; 425 Op->Reg.Modifiers = 0; 426 Op->Reg.IsForcedVOP3 = ForceVOP3; 427 Op->StartLoc = S; 428 Op->EndLoc = E; 429 return Op; 430 } 431 432 static std::unique_ptr<AMDGPUOperand> CreateExpr(const class MCExpr *Expr, SMLoc S) { 433 auto Op = llvm::make_unique<AMDGPUOperand>(Expression); 434 Op->Expr = Expr; 435 Op->StartLoc = S; 436 Op->EndLoc = S; 437 return Op; 438 } 439 440 bool isSWaitCnt() const; 441 bool isHwreg() const; 442 bool isMubufOffset() const; 443 bool isSMRDOffset() const; 444 bool isSMRDLiteralOffset() const; 445 bool isDPPCtrl() const; 446 }; 447 448 class AMDGPUAsmParser : public MCTargetAsmParser { 449 const MCInstrInfo &MII; 450 MCAsmParser &Parser; 451 452 unsigned ForcedEncodingSize; 453 454 bool isSI() const { 455 return AMDGPU::isSI(getSTI()); 456 } 457 458 bool isCI() const { 459 return AMDGPU::isCI(getSTI()); 460 } 461 462 bool isVI() const { 463 return AMDGPU::isVI(getSTI()); 464 } 465 466 bool hasSGPR102_SGPR103() const { 467 return !isVI(); 468 } 469 470 /// @name Auto-generated Match Functions 471 /// { 472 473 #define GET_ASSEMBLER_HEADER 474 #include "AMDGPUGenAsmMatcher.inc" 475 476 /// } 477 478 private: 479 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 480 bool ParseDirectiveHSACodeObjectVersion(); 481 bool ParseDirectiveHSACodeObjectISA(); 482 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 483 bool ParseDirectiveAMDKernelCodeT(); 484 bool ParseSectionDirectiveHSAText(); 485 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; 486 bool ParseDirectiveAMDGPUHsaKernel(); 487 bool ParseDirectiveAMDGPUHsaModuleGlobal(); 488 bool ParseDirectiveAMDGPUHsaProgramGlobal(); 489 bool ParseSectionDirectiveHSADataGlobalAgent(); 490 bool ParseSectionDirectiveHSADataGlobalProgram(); 491 bool ParseSectionDirectiveHSARodataReadonlyAgent(); 492 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum); 493 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth); 494 495 public: 496 enum AMDGPUMatchResultTy { 497 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY 498 }; 499 500 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser, 501 const MCInstrInfo &MII, 502 const MCTargetOptions &Options) 503 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser), 504 ForcedEncodingSize(0) { 505 MCAsmParserExtension::Initialize(Parser); 506 507 if (getSTI().getFeatureBits().none()) { 508 // Set default features. 509 copySTI().ToggleFeature("SOUTHERN_ISLANDS"); 510 } 511 512 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); 513 } 514 515 AMDGPUTargetStreamer &getTargetStreamer() { 516 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 517 return static_cast<AMDGPUTargetStreamer &>(TS); 518 } 519 520 unsigned getForcedEncodingSize() const { 521 return ForcedEncodingSize; 522 } 523 524 void setForcedEncodingSize(unsigned Size) { 525 ForcedEncodingSize = Size; 526 } 527 528 bool isForcedVOP3() const { 529 return ForcedEncodingSize == 64; 530 } 531 532 std::unique_ptr<AMDGPUOperand> parseRegister(); 533 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 534 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 535 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 536 OperandVector &Operands, MCStreamer &Out, 537 uint64_t &ErrorInfo, 538 bool MatchingInlineAsm) override; 539 bool ParseDirective(AsmToken DirectiveID) override; 540 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); 541 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 542 SMLoc NameLoc, OperandVector &Operands) override; 543 544 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int, 545 int64_t Default = 0, bool AddDefault = false); 546 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, 547 OperandVector &Operands, 548 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone, 549 int64_t Default = 0, bool AddDefault = false, 550 bool (*ConvertResult)(int64_t&) = 0); 551 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands, 552 enum AMDGPUOperand::ImmTy ImmTy = 553 AMDGPUOperand::ImmTyNone, 554 bool AddDefault = false); 555 OperandMatchResultTy parseOptionalOps( 556 const ArrayRef<OptionalOperand> &OptionalOps, 557 OperandVector &Operands); 558 OperandMatchResultTy parseStringWithPrefix(const char *Prefix, StringRef &Value); 559 560 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands, const OptionalOperand& Op, bool AddDefault); 561 OperandMatchResultTy parseAMDGPUOperand(OperandVector &Operands, StringRef Name); 562 563 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 564 void cvtDS(MCInst &Inst, const OperandVector &Operands); 565 566 bool parseCnt(int64_t &IntVal); 567 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 568 bool parseHwregOperand(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier); 569 OperandMatchResultTy parseHwreg(OperandVector &Operands); 570 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 571 572 void cvtFlat(MCInst &Inst, const OperandVector &Operands); 573 void cvtFlatAtomic(MCInst &Inst, const OperandVector &Operands); 574 575 void cvtMubuf(MCInst &Inst, const OperandVector &Operands); 576 OperandMatchResultTy parseOModSI(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "omod"); } 577 OperandMatchResultTy parseClampSI(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "clamp"); } 578 OperandMatchResultTy parseSMRDOffset(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "smrd_offset"); } 579 OperandMatchResultTy parseSMRDLiteralOffset(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "smrd_literal_offset"); } 580 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "dpp_ctrl"); } 581 OperandMatchResultTy parseRowMask(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "row_mask"); } 582 OperandMatchResultTy parseBankMask(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "bank_mask"); } 583 OperandMatchResultTy parseBoundCtrl(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "bound_ctrl"); } 584 OperandMatchResultTy parseOffen(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "offen"); } 585 OperandMatchResultTy parseIdxen(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "idxen"); } 586 OperandMatchResultTy parseAddr64(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "addr64"); } 587 OperandMatchResultTy parseOffset(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "offset"); } 588 OperandMatchResultTy parseOffset0(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "offset0"); } 589 OperandMatchResultTy parseOffset1(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "offset1"); } 590 OperandMatchResultTy parseGLC(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "glc"); } 591 OperandMatchResultTy parseSLC(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "slc"); } 592 OperandMatchResultTy parseTFE(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "tfe"); } 593 OperandMatchResultTy parseGDS(OperandVector &Operands) { return parseAMDGPUOperand(Operands, "gds"); } 594 595 OperandMatchResultTy parseDMask(OperandVector &Operands); 596 OperandMatchResultTy parseUNorm(OperandVector &Operands); 597 OperandMatchResultTy parseDA(OperandVector &Operands); 598 OperandMatchResultTy parseR128(OperandVector &Operands); 599 OperandMatchResultTy parseLWE(OperandVector &Operands); 600 601 OperandMatchResultTy parseOModOperand(OperandVector &Operands); 602 603 void cvtId(MCInst &Inst, const OperandVector &Operands); 604 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands); 605 void cvtVOP3_2_nomod(MCInst &Inst, const OperandVector &Operands); 606 void cvtVOP3_only(MCInst &Inst, const OperandVector &Operands); 607 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 608 609 void cvtMIMG(MCInst &Inst, const OperandVector &Operands); 610 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands); 611 612 OperandMatchResultTy parseDPPCtrlOps(OperandVector &Operands, bool AddDefault); 613 void cvtDPP_mod(MCInst &Inst, const OperandVector &Operands); 614 void cvtDPP_nomod(MCInst &Inst, const OperandVector &Operands); 615 void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool HasMods); 616 617 OperandMatchResultTy parseSDWASel(OperandVector &Operands); 618 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands); 619 }; 620 621 struct OptionalOperand { 622 const char *Name; 623 AMDGPUOperand::ImmTy Type; 624 bool IsBit; 625 int64_t Default; 626 bool (*ConvertResult)(int64_t&); 627 }; 628 629 } 630 631 static int getRegClass(RegisterKind Is, unsigned RegWidth) { 632 if (Is == IS_VGPR) { 633 switch (RegWidth) { 634 default: return -1; 635 case 1: return AMDGPU::VGPR_32RegClassID; 636 case 2: return AMDGPU::VReg_64RegClassID; 637 case 3: return AMDGPU::VReg_96RegClassID; 638 case 4: return AMDGPU::VReg_128RegClassID; 639 case 8: return AMDGPU::VReg_256RegClassID; 640 case 16: return AMDGPU::VReg_512RegClassID; 641 } 642 } else if (Is == IS_TTMP) { 643 switch (RegWidth) { 644 default: return -1; 645 case 1: return AMDGPU::TTMP_32RegClassID; 646 case 2: return AMDGPU::TTMP_64RegClassID; 647 case 4: return AMDGPU::TTMP_128RegClassID; 648 } 649 } else if (Is == IS_SGPR) { 650 switch (RegWidth) { 651 default: return -1; 652 case 1: return AMDGPU::SGPR_32RegClassID; 653 case 2: return AMDGPU::SGPR_64RegClassID; 654 case 4: return AMDGPU::SGPR_128RegClassID; 655 case 8: return AMDGPU::SReg_256RegClassID; 656 case 16: return AMDGPU::SReg_512RegClassID; 657 } 658 } 659 return -1; 660 } 661 662 static unsigned getSpecialRegForName(StringRef RegName) { 663 return StringSwitch<unsigned>(RegName) 664 .Case("exec", AMDGPU::EXEC) 665 .Case("vcc", AMDGPU::VCC) 666 .Case("flat_scratch", AMDGPU::FLAT_SCR) 667 .Case("m0", AMDGPU::M0) 668 .Case("scc", AMDGPU::SCC) 669 .Case("tba", AMDGPU::TBA) 670 .Case("tma", AMDGPU::TMA) 671 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO) 672 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI) 673 .Case("vcc_lo", AMDGPU::VCC_LO) 674 .Case("vcc_hi", AMDGPU::VCC_HI) 675 .Case("exec_lo", AMDGPU::EXEC_LO) 676 .Case("exec_hi", AMDGPU::EXEC_HI) 677 .Case("tma_lo", AMDGPU::TMA_LO) 678 .Case("tma_hi", AMDGPU::TMA_HI) 679 .Case("tba_lo", AMDGPU::TBA_LO) 680 .Case("tba_hi", AMDGPU::TBA_HI) 681 .Default(0); 682 } 683 684 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { 685 auto R = parseRegister(); 686 if (!R) return true; 687 assert(R->isReg()); 688 RegNo = R->getReg(); 689 StartLoc = R->getStartLoc(); 690 EndLoc = R->getEndLoc(); 691 return false; 692 } 693 694 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum) 695 { 696 switch (RegKind) { 697 case IS_SPECIAL: 698 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; } 699 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; } 700 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; } 701 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; } 702 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; } 703 return false; 704 case IS_VGPR: 705 case IS_SGPR: 706 case IS_TTMP: 707 if (Reg1 != Reg + RegWidth) { return false; } 708 RegWidth++; 709 return true; 710 default: 711 assert(false); return false; 712 } 713 } 714 715 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth) 716 { 717 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 718 if (getLexer().is(AsmToken::Identifier)) { 719 StringRef RegName = Parser.getTok().getString(); 720 if ((Reg = getSpecialRegForName(RegName))) { 721 Parser.Lex(); 722 RegKind = IS_SPECIAL; 723 } else { 724 unsigned RegNumIndex = 0; 725 if (RegName[0] == 'v') { RegNumIndex = 1; RegKind = IS_VGPR; } 726 else if (RegName[0] == 's') { RegNumIndex = 1; RegKind = IS_SGPR; } 727 else if (RegName.startswith("ttmp")) { RegNumIndex = strlen("ttmp"); RegKind = IS_TTMP; } 728 else { return false; } 729 if (RegName.size() > RegNumIndex) { 730 // Single 32-bit register: vXX. 731 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum)) { return false; } 732 Parser.Lex(); 733 RegWidth = 1; 734 } else { 735 // Range of registers: v[XX:YY]. 736 Parser.Lex(); 737 int64_t RegLo, RegHi; 738 if (getLexer().isNot(AsmToken::LBrac)) { return false; } 739 Parser.Lex(); 740 741 if (getParser().parseAbsoluteExpression(RegLo)) { return false; } 742 743 if (getLexer().isNot(AsmToken::Colon)) { return false; } 744 Parser.Lex(); 745 746 if (getParser().parseAbsoluteExpression(RegHi)) { return false; } 747 748 if (getLexer().isNot(AsmToken::RBrac)) { return false; } 749 Parser.Lex(); 750 751 RegNum = (unsigned) RegLo; 752 RegWidth = (RegHi - RegLo) + 1; 753 } 754 } 755 } else if (getLexer().is(AsmToken::LBrac)) { 756 // List of consecutive registers: [s0,s1,s2,s3] 757 Parser.Lex(); 758 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { return false; } 759 if (RegWidth != 1) { return false; } 760 RegisterKind RegKind1; 761 unsigned Reg1, RegNum1, RegWidth1; 762 do { 763 if (getLexer().is(AsmToken::Comma)) { 764 Parser.Lex(); 765 } else if (getLexer().is(AsmToken::RBrac)) { 766 Parser.Lex(); 767 break; 768 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1)) { 769 if (RegWidth1 != 1) { return false; } 770 if (RegKind1 != RegKind) { return false; } 771 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) { return false; } 772 } else { 773 return false; 774 } 775 } while (true); 776 } else { 777 return false; 778 } 779 switch (RegKind) { 780 case IS_SPECIAL: 781 RegNum = 0; 782 RegWidth = 1; 783 break; 784 case IS_VGPR: 785 case IS_SGPR: 786 case IS_TTMP: 787 { 788 unsigned Size = 1; 789 if (RegKind == IS_SGPR || RegKind == IS_TTMP) { 790 // SGPR and TTMP registers must be are aligned. Max required alignment is 4 dwords. 791 Size = std::min(RegWidth, 4u); 792 } 793 if (RegNum % Size != 0) { return false; } 794 RegNum = RegNum / Size; 795 int RCID = getRegClass(RegKind, RegWidth); 796 if (RCID == -1) { return false; } 797 const MCRegisterClass RC = TRI->getRegClass(RCID); 798 if (RegNum >= RC.getNumRegs()) { return false; } 799 Reg = RC.getRegister(RegNum); 800 break; 801 } 802 803 default: 804 assert(false); return false; 805 } 806 807 if (!subtargetHasRegister(*TRI, Reg)) { return false; } 808 return true; 809 } 810 811 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() { 812 const auto &Tok = Parser.getTok(); 813 SMLoc StartLoc = Tok.getLoc(); 814 SMLoc EndLoc = Tok.getEndLoc(); 815 const MCRegisterInfo *TRI = getContext().getRegisterInfo(); 816 817 RegisterKind RegKind; 818 unsigned Reg, RegNum, RegWidth; 819 820 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) { 821 return nullptr; 822 } 823 return AMDGPUOperand::CreateReg(Reg, StartLoc, EndLoc, 824 TRI, &getSTI(), false); 825 } 826 827 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 828 829 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 830 831 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 832 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3))) 833 return Match_InvalidOperand; 834 835 if ((TSFlags & SIInstrFlags::VOP3) && 836 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) && 837 getForcedEncodingSize() != 64) 838 return Match_PreferE32; 839 840 return Match_Success; 841 } 842 843 844 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 845 OperandVector &Operands, 846 MCStreamer &Out, 847 uint64_t &ErrorInfo, 848 bool MatchingInlineAsm) { 849 MCInst Inst; 850 851 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 852 default: break; 853 case Match_Success: 854 Inst.setLoc(IDLoc); 855 Out.EmitInstruction(Inst, getSTI()); 856 return false; 857 case Match_MissingFeature: 858 return Error(IDLoc, "instruction not supported on this GPU"); 859 860 case Match_MnemonicFail: 861 return Error(IDLoc, "unrecognized instruction mnemonic"); 862 863 case Match_InvalidOperand: { 864 SMLoc ErrorLoc = IDLoc; 865 if (ErrorInfo != ~0ULL) { 866 if (ErrorInfo >= Operands.size()) { 867 return Error(IDLoc, "too few operands for instruction"); 868 } 869 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 870 if (ErrorLoc == SMLoc()) 871 ErrorLoc = IDLoc; 872 } 873 return Error(ErrorLoc, "invalid operand for instruction"); 874 } 875 case Match_PreferE32: 876 return Error(IDLoc, "internal error: instruction without _e64 suffix " 877 "should be encoded as e32"); 878 } 879 llvm_unreachable("Implement any new match types added!"); 880 } 881 882 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 883 uint32_t &Minor) { 884 if (getLexer().isNot(AsmToken::Integer)) 885 return TokError("invalid major version"); 886 887 Major = getLexer().getTok().getIntVal(); 888 Lex(); 889 890 if (getLexer().isNot(AsmToken::Comma)) 891 return TokError("minor version number required, comma expected"); 892 Lex(); 893 894 if (getLexer().isNot(AsmToken::Integer)) 895 return TokError("invalid minor version"); 896 897 Minor = getLexer().getTok().getIntVal(); 898 Lex(); 899 900 return false; 901 } 902 903 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 904 905 uint32_t Major; 906 uint32_t Minor; 907 908 if (ParseDirectiveMajorMinor(Major, Minor)) 909 return true; 910 911 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 912 return false; 913 } 914 915 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 916 917 uint32_t Major; 918 uint32_t Minor; 919 uint32_t Stepping; 920 StringRef VendorName; 921 StringRef ArchName; 922 923 // If this directive has no arguments, then use the ISA version for the 924 // targeted GPU. 925 if (getLexer().is(AsmToken::EndOfStatement)) { 926 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits()); 927 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor, 928 Isa.Stepping, 929 "AMD", "AMDGPU"); 930 return false; 931 } 932 933 934 if (ParseDirectiveMajorMinor(Major, Minor)) 935 return true; 936 937 if (getLexer().isNot(AsmToken::Comma)) 938 return TokError("stepping version number required, comma expected"); 939 Lex(); 940 941 if (getLexer().isNot(AsmToken::Integer)) 942 return TokError("invalid stepping version"); 943 944 Stepping = getLexer().getTok().getIntVal(); 945 Lex(); 946 947 if (getLexer().isNot(AsmToken::Comma)) 948 return TokError("vendor name required, comma expected"); 949 Lex(); 950 951 if (getLexer().isNot(AsmToken::String)) 952 return TokError("invalid vendor name"); 953 954 VendorName = getLexer().getTok().getStringContents(); 955 Lex(); 956 957 if (getLexer().isNot(AsmToken::Comma)) 958 return TokError("arch name required, comma expected"); 959 Lex(); 960 961 if (getLexer().isNot(AsmToken::String)) 962 return TokError("invalid arch name"); 963 964 ArchName = getLexer().getTok().getStringContents(); 965 Lex(); 966 967 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 968 VendorName, ArchName); 969 return false; 970 } 971 972 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 973 amd_kernel_code_t &Header) { 974 SmallString<40> ErrStr; 975 raw_svector_ostream Err(ErrStr); 976 if (!parseAmdKernelCodeField(ID, getLexer(), Header, Err)) { 977 return TokError(Err.str()); 978 } 979 Lex(); 980 return false; 981 } 982 983 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 984 985 amd_kernel_code_t Header; 986 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits()); 987 988 while (true) { 989 990 if (getLexer().isNot(AsmToken::EndOfStatement)) 991 return TokError("amd_kernel_code_t values must begin on a new line"); 992 993 // Lex EndOfStatement. This is in a while loop, because lexing a comment 994 // will set the current token to EndOfStatement. 995 while(getLexer().is(AsmToken::EndOfStatement)) 996 Lex(); 997 998 if (getLexer().isNot(AsmToken::Identifier)) 999 return TokError("expected value identifier or .end_amd_kernel_code_t"); 1000 1001 StringRef ID = getLexer().getTok().getIdentifier(); 1002 Lex(); 1003 1004 if (ID == ".end_amd_kernel_code_t") 1005 break; 1006 1007 if (ParseAMDKernelCodeTValue(ID, Header)) 1008 return true; 1009 } 1010 1011 getTargetStreamer().EmitAMDKernelCodeT(Header); 1012 1013 return false; 1014 } 1015 1016 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() { 1017 getParser().getStreamer().SwitchSection( 1018 AMDGPU::getHSATextSection(getContext())); 1019 return false; 1020 } 1021 1022 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() { 1023 if (getLexer().isNot(AsmToken::Identifier)) 1024 return TokError("expected symbol name"); 1025 1026 StringRef KernelName = Parser.getTok().getString(); 1027 1028 getTargetStreamer().EmitAMDGPUSymbolType(KernelName, 1029 ELF::STT_AMDGPU_HSA_KERNEL); 1030 Lex(); 1031 return false; 1032 } 1033 1034 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() { 1035 if (getLexer().isNot(AsmToken::Identifier)) 1036 return TokError("expected symbol name"); 1037 1038 StringRef GlobalName = Parser.getTok().getIdentifier(); 1039 1040 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName); 1041 Lex(); 1042 return false; 1043 } 1044 1045 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() { 1046 if (getLexer().isNot(AsmToken::Identifier)) 1047 return TokError("expected symbol name"); 1048 1049 StringRef GlobalName = Parser.getTok().getIdentifier(); 1050 1051 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName); 1052 Lex(); 1053 return false; 1054 } 1055 1056 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() { 1057 getParser().getStreamer().SwitchSection( 1058 AMDGPU::getHSADataGlobalAgentSection(getContext())); 1059 return false; 1060 } 1061 1062 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() { 1063 getParser().getStreamer().SwitchSection( 1064 AMDGPU::getHSADataGlobalProgramSection(getContext())); 1065 return false; 1066 } 1067 1068 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() { 1069 getParser().getStreamer().SwitchSection( 1070 AMDGPU::getHSARodataReadonlyAgentSection(getContext())); 1071 return false; 1072 } 1073 1074 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 1075 StringRef IDVal = DirectiveID.getString(); 1076 1077 if (IDVal == ".hsa_code_object_version") 1078 return ParseDirectiveHSACodeObjectVersion(); 1079 1080 if (IDVal == ".hsa_code_object_isa") 1081 return ParseDirectiveHSACodeObjectISA(); 1082 1083 if (IDVal == ".amd_kernel_code_t") 1084 return ParseDirectiveAMDKernelCodeT(); 1085 1086 if (IDVal == ".hsatext" || IDVal == ".text") 1087 return ParseSectionDirectiveHSAText(); 1088 1089 if (IDVal == ".amdgpu_hsa_kernel") 1090 return ParseDirectiveAMDGPUHsaKernel(); 1091 1092 if (IDVal == ".amdgpu_hsa_module_global") 1093 return ParseDirectiveAMDGPUHsaModuleGlobal(); 1094 1095 if (IDVal == ".amdgpu_hsa_program_global") 1096 return ParseDirectiveAMDGPUHsaProgramGlobal(); 1097 1098 if (IDVal == ".hsadata_global_agent") 1099 return ParseSectionDirectiveHSADataGlobalAgent(); 1100 1101 if (IDVal == ".hsadata_global_program") 1102 return ParseSectionDirectiveHSADataGlobalProgram(); 1103 1104 if (IDVal == ".hsarodata_readonly_agent") 1105 return ParseSectionDirectiveHSARodataReadonlyAgent(); 1106 1107 return true; 1108 } 1109 1110 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI, 1111 unsigned RegNo) const { 1112 if (isCI()) 1113 return true; 1114 1115 if (isSI()) { 1116 // No flat_scr 1117 switch (RegNo) { 1118 case AMDGPU::FLAT_SCR: 1119 case AMDGPU::FLAT_SCR_LO: 1120 case AMDGPU::FLAT_SCR_HI: 1121 return false; 1122 default: 1123 return true; 1124 } 1125 } 1126 1127 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that 1128 // SI/CI have. 1129 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true); 1130 R.isValid(); ++R) { 1131 if (*R == RegNo) 1132 return false; 1133 } 1134 1135 return true; 1136 } 1137 1138 static bool operandsHaveModifiers(const OperandVector &Operands) { 1139 1140 for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 1141 const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 1142 if (Op.isRegKind() && Op.hasModifiers()) 1143 return true; 1144 if (Op.isImm() && Op.hasModifiers()) 1145 return true; 1146 if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOModSI || 1147 Op.getImmTy() == AMDGPUOperand::ImmTyClampSI)) 1148 return true; 1149 } 1150 return false; 1151 } 1152 1153 AMDGPUAsmParser::OperandMatchResultTy 1154 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 1155 1156 // Try to parse with a custom parser 1157 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 1158 1159 // If we successfully parsed the operand or if there as an error parsing, 1160 // we are done. 1161 // 1162 // If we are parsing after we reach EndOfStatement then this means we 1163 // are appending default values to the Operands list. This is only done 1164 // by custom parser, so we shouldn't continue on to the generic parsing. 1165 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail|| 1166 getLexer().is(AsmToken::EndOfStatement)) 1167 return ResTy; 1168 1169 bool Negate = false, Abs = false, Abs2 = false; 1170 1171 if (getLexer().getKind()== AsmToken::Minus) { 1172 Parser.Lex(); 1173 Negate = true; 1174 } 1175 1176 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") { 1177 Parser.Lex(); 1178 Abs2 = true; 1179 if (getLexer().isNot(AsmToken::LParen)) { 1180 Error(Parser.getTok().getLoc(), "expected left paren after abs"); 1181 return MatchOperand_ParseFail; 1182 } 1183 Parser.Lex(); 1184 } 1185 1186 if (getLexer().getKind() == AsmToken::Pipe) { 1187 Parser.Lex(); 1188 Abs = true; 1189 } 1190 1191 switch(getLexer().getKind()) { 1192 case AsmToken::Integer: { 1193 SMLoc S = Parser.getTok().getLoc(); 1194 int64_t IntVal; 1195 if (getParser().parseAbsoluteExpression(IntVal)) 1196 return MatchOperand_ParseFail; 1197 if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) { 1198 Error(S, "invalid immediate: only 32-bit values are legal"); 1199 return MatchOperand_ParseFail; 1200 } 1201 1202 if (Negate) 1203 IntVal *= -1; 1204 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S)); 1205 return MatchOperand_Success; 1206 } 1207 case AsmToken::Real: { 1208 // FIXME: We should emit an error if a double precisions floating-point 1209 // value is used. I'm not sure the best way to detect this. 1210 SMLoc S = Parser.getTok().getLoc(); 1211 int64_t IntVal; 1212 if (getParser().parseAbsoluteExpression(IntVal)) 1213 return MatchOperand_ParseFail; 1214 1215 APFloat F((float)BitsToDouble(IntVal)); 1216 if (Negate) 1217 F.changeSign(); 1218 Operands.push_back( 1219 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); 1220 return MatchOperand_Success; 1221 } 1222 case AsmToken::LBrac: 1223 case AsmToken::Identifier: { 1224 if (auto R = parseRegister()) { 1225 unsigned Modifiers = 0; 1226 1227 if (Negate) 1228 Modifiers |= 0x1; 1229 1230 if (Abs) { 1231 if (getLexer().getKind() != AsmToken::Pipe) 1232 return MatchOperand_ParseFail; 1233 Parser.Lex(); 1234 Modifiers |= 0x2; 1235 } 1236 if (Abs2) { 1237 if (getLexer().isNot(AsmToken::RParen)) { 1238 return MatchOperand_ParseFail; 1239 } 1240 Parser.Lex(); 1241 Modifiers |= 0x2; 1242 } 1243 assert(R->isReg()); 1244 R->Reg.IsForcedVOP3 = isForcedVOP3(); 1245 if (Modifiers) { 1246 R->setModifiers(Modifiers); 1247 } 1248 Operands.push_back(std::move(R)); 1249 } else { 1250 if (ResTy == MatchOperand_NoMatch) { 1251 const auto &Tok = Parser.getTok(); 1252 Operands.push_back(AMDGPUOperand::CreateToken(Tok.getString(), 1253 Tok.getLoc())); 1254 Parser.Lex(); 1255 if (getLexer().is(AsmToken::Colon)) { 1256 Parser.Lex(); 1257 if (getLexer().is(AsmToken::Identifier)) { 1258 Parser.Lex(); 1259 } 1260 } 1261 } else { 1262 return ResTy; 1263 } 1264 } 1265 return MatchOperand_Success; 1266 } 1267 default: 1268 return MatchOperand_NoMatch; 1269 } 1270 } 1271 1272 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1273 StringRef Name, 1274 SMLoc NameLoc, OperandVector &Operands) { 1275 1276 // Clear any forced encodings from the previous instruction. 1277 setForcedEncodingSize(0); 1278 1279 if (Name.endswith("_e64")) 1280 setForcedEncodingSize(64); 1281 else if (Name.endswith("_e32")) 1282 setForcedEncodingSize(32); 1283 1284 // Add the instruction mnemonic 1285 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); 1286 1287 1288 if (Name.endswith("_e64")) { Name = Name.substr(0, Name.size() - 4); } 1289 if (Name.endswith("_e32")) { Name = Name.substr(0, Name.size() - 4); } 1290 1291 while (!getLexer().is(AsmToken::EndOfStatement)) { 1292 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); 1293 1294 // Eat the comma or space if there is one. 1295 if (getLexer().is(AsmToken::Comma)) 1296 Parser.Lex(); 1297 1298 switch (Res) { 1299 case MatchOperand_Success: break; 1300 case MatchOperand_ParseFail: return Error(getLexer().getLoc(), 1301 "failed parsing operand."); 1302 case MatchOperand_NoMatch: return Error(getLexer().getLoc(), 1303 "not a valid operand."); 1304 } 1305 } 1306 1307 return false; 1308 } 1309 1310 //===----------------------------------------------------------------------===// 1311 // Utility functions 1312 //===----------------------------------------------------------------------===// 1313 1314 AMDGPUAsmParser::OperandMatchResultTy 1315 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int, 1316 int64_t Default, bool AddDefault) { 1317 // We are at the end of the statement, and this is a default argument, so 1318 // use a default value. 1319 if (getLexer().is(AsmToken::EndOfStatement)) { 1320 Int = Default; 1321 return MatchOperand_Success; 1322 } 1323 1324 switch(getLexer().getKind()) { 1325 default: return MatchOperand_NoMatch; 1326 case AsmToken::Identifier: { 1327 StringRef Name = Parser.getTok().getString(); 1328 if (!Name.equals(Prefix)) { 1329 if (AddDefault) { 1330 Int = Default; 1331 return MatchOperand_Success; 1332 } 1333 return MatchOperand_NoMatch; 1334 } 1335 1336 Parser.Lex(); 1337 if (getLexer().isNot(AsmToken::Colon)) 1338 return MatchOperand_ParseFail; 1339 1340 Parser.Lex(); 1341 if (getLexer().isNot(AsmToken::Integer)) 1342 return MatchOperand_ParseFail; 1343 1344 if (getParser().parseAbsoluteExpression(Int)) 1345 return MatchOperand_ParseFail; 1346 break; 1347 } 1348 } 1349 return MatchOperand_Success; 1350 } 1351 1352 AMDGPUAsmParser::OperandMatchResultTy 1353 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1354 enum AMDGPUOperand::ImmTy ImmTy, 1355 int64_t Default, bool AddDefault, 1356 bool (*ConvertResult)(int64_t&)) { 1357 1358 SMLoc S = Parser.getTok().getLoc(); 1359 int64_t Value = 0; 1360 1361 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value, Default, AddDefault); 1362 if (Res != MatchOperand_Success) 1363 return Res; 1364 1365 if (ConvertResult && !ConvertResult(Value)) { 1366 return MatchOperand_ParseFail; 1367 } 1368 1369 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, ImmTy)); 1370 return MatchOperand_Success; 1371 } 1372 1373 AMDGPUAsmParser::OperandMatchResultTy 1374 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 1375 enum AMDGPUOperand::ImmTy ImmTy, 1376 bool AddDefault) { 1377 int64_t Bit = 0; 1378 SMLoc S = Parser.getTok().getLoc(); 1379 1380 // We are at the end of the statement, and this is a default argument, so 1381 // use a default value. 1382 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1383 switch(getLexer().getKind()) { 1384 case AsmToken::Identifier: { 1385 StringRef Tok = Parser.getTok().getString(); 1386 if (Tok == Name) { 1387 Bit = 1; 1388 Parser.Lex(); 1389 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 1390 Bit = 0; 1391 Parser.Lex(); 1392 } else { 1393 if (AddDefault) { 1394 Bit = 0; 1395 } else { 1396 return MatchOperand_NoMatch; 1397 } 1398 } 1399 break; 1400 } 1401 default: 1402 return MatchOperand_NoMatch; 1403 } 1404 } 1405 1406 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy)); 1407 return MatchOperand_Success; 1408 } 1409 1410 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap; 1411 1412 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands, 1413 OptionalImmIndexMap& OptionalIdx, 1414 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) { 1415 auto i = OptionalIdx.find(ImmT); 1416 if (i != OptionalIdx.end()) { 1417 unsigned Idx = i->second; 1418 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1); 1419 } else { 1420 Inst.addOperand(MCOperand::createImm(Default)); 1421 } 1422 } 1423 1424 static bool operandsHasOptionalOp(const OperandVector &Operands, 1425 const OptionalOperand &OOp) { 1426 for (unsigned i = 0; i < Operands.size(); i++) { 1427 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]); 1428 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) || 1429 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name)) 1430 return true; 1431 1432 } 1433 return false; 1434 } 1435 1436 AMDGPUAsmParser::OperandMatchResultTy 1437 AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps, 1438 OperandVector &Operands) { 1439 SMLoc S = Parser.getTok().getLoc(); 1440 for (const OptionalOperand &Op : OptionalOps) { 1441 if (operandsHasOptionalOp(Operands, Op)) 1442 continue; 1443 AMDGPUAsmParser::OperandMatchResultTy Res; 1444 int64_t Value; 1445 if (Op.IsBit) { 1446 Res = parseNamedBit(Op.Name, Operands, Op.Type); 1447 if (Res == MatchOperand_NoMatch) 1448 continue; 1449 return Res; 1450 } 1451 1452 Res = parseIntWithPrefix(Op.Name, Value, Op.Default); 1453 1454 if (Res == MatchOperand_NoMatch) 1455 continue; 1456 1457 if (Res != MatchOperand_Success) 1458 return Res; 1459 1460 bool DefaultValue = (Value == Op.Default); 1461 1462 if (Op.ConvertResult && !Op.ConvertResult(Value)) { 1463 return MatchOperand_ParseFail; 1464 } 1465 1466 if (!DefaultValue) { 1467 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type)); 1468 } 1469 return MatchOperand_Success; 1470 } 1471 return MatchOperand_NoMatch; 1472 } 1473 1474 AMDGPUAsmParser::OperandMatchResultTy 1475 AMDGPUAsmParser::parseStringWithPrefix(const char *Prefix, StringRef &Value) { 1476 if (getLexer().isNot(AsmToken::Identifier)) { 1477 return MatchOperand_NoMatch; 1478 } 1479 StringRef Tok = Parser.getTok().getString(); 1480 if (Tok != Prefix) { 1481 return MatchOperand_NoMatch; 1482 } 1483 1484 Parser.Lex(); 1485 if (getLexer().isNot(AsmToken::Colon)) { 1486 return MatchOperand_ParseFail; 1487 } 1488 1489 Parser.Lex(); 1490 if (getLexer().isNot(AsmToken::Identifier)) { 1491 return MatchOperand_ParseFail; 1492 } 1493 1494 Value = Parser.getTok().getString(); 1495 return MatchOperand_Success; 1496 } 1497 1498 //===----------------------------------------------------------------------===// 1499 // ds 1500 //===----------------------------------------------------------------------===// 1501 1502 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 1503 const OperandVector &Operands) { 1504 1505 OptionalImmIndexMap OptionalIdx; 1506 1507 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1508 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1509 1510 // Add the register arguments 1511 if (Op.isReg()) { 1512 Op.addRegOperands(Inst, 1); 1513 continue; 1514 } 1515 1516 // Handle optional arguments 1517 OptionalIdx[Op.getImmTy()] = i; 1518 } 1519 1520 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0); 1521 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1); 1522 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1523 1524 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1525 } 1526 1527 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 1528 1529 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1530 bool GDSOnly = false; 1531 1532 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1533 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1534 1535 // Add the register arguments 1536 if (Op.isReg()) { 1537 Op.addRegOperands(Inst, 1); 1538 continue; 1539 } 1540 1541 if (Op.isToken() && Op.getToken() == "gds") { 1542 GDSOnly = true; 1543 continue; 1544 } 1545 1546 // Handle optional arguments 1547 OptionalIdx[Op.getImmTy()] = i; 1548 } 1549 1550 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 1551 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1552 1553 if (!GDSOnly) { 1554 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS); 1555 } 1556 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1557 } 1558 1559 1560 //===----------------------------------------------------------------------===// 1561 // s_waitcnt 1562 //===----------------------------------------------------------------------===// 1563 1564 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 1565 StringRef CntName = Parser.getTok().getString(); 1566 int64_t CntVal; 1567 1568 Parser.Lex(); 1569 if (getLexer().isNot(AsmToken::LParen)) 1570 return true; 1571 1572 Parser.Lex(); 1573 if (getLexer().isNot(AsmToken::Integer)) 1574 return true; 1575 1576 if (getParser().parseAbsoluteExpression(CntVal)) 1577 return true; 1578 1579 if (getLexer().isNot(AsmToken::RParen)) 1580 return true; 1581 1582 Parser.Lex(); 1583 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 1584 Parser.Lex(); 1585 1586 int CntShift; 1587 int CntMask; 1588 1589 if (CntName == "vmcnt") { 1590 CntMask = 0xf; 1591 CntShift = 0; 1592 } else if (CntName == "expcnt") { 1593 CntMask = 0x7; 1594 CntShift = 4; 1595 } else if (CntName == "lgkmcnt") { 1596 CntMask = 0xf; 1597 CntShift = 8; 1598 } else { 1599 return true; 1600 } 1601 1602 IntVal &= ~(CntMask << CntShift); 1603 IntVal |= (CntVal << CntShift); 1604 return false; 1605 } 1606 1607 AMDGPUAsmParser::OperandMatchResultTy 1608 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 1609 // Disable all counters by default. 1610 // vmcnt [3:0] 1611 // expcnt [6:4] 1612 // lgkmcnt [11:8] 1613 int64_t CntVal = 0xf7f; 1614 SMLoc S = Parser.getTok().getLoc(); 1615 1616 switch(getLexer().getKind()) { 1617 default: return MatchOperand_ParseFail; 1618 case AsmToken::Integer: 1619 // The operand can be an integer value. 1620 if (getParser().parseAbsoluteExpression(CntVal)) 1621 return MatchOperand_ParseFail; 1622 break; 1623 1624 case AsmToken::Identifier: 1625 do { 1626 if (parseCnt(CntVal)) 1627 return MatchOperand_ParseFail; 1628 } while(getLexer().isNot(AsmToken::EndOfStatement)); 1629 break; 1630 } 1631 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S)); 1632 return MatchOperand_Success; 1633 } 1634 1635 bool AMDGPUAsmParser::parseHwregOperand(int64_t &HwRegCode, int64_t &Offset, int64_t &Width, bool &IsIdentifier) { 1636 if (Parser.getTok().getString() != "hwreg") 1637 return true; 1638 Parser.Lex(); 1639 1640 if (getLexer().isNot(AsmToken::LParen)) 1641 return true; 1642 Parser.Lex(); 1643 1644 if (getLexer().is(AsmToken::Identifier)) { 1645 IsIdentifier = true; 1646 HwRegCode = StringSwitch<unsigned>(Parser.getTok().getString()) 1647 .Case("HW_REG_MODE" , 1) 1648 .Case("HW_REG_STATUS" , 2) 1649 .Case("HW_REG_TRAPSTS" , 3) 1650 .Case("HW_REG_HW_ID" , 4) 1651 .Case("HW_REG_GPR_ALLOC", 5) 1652 .Case("HW_REG_LDS_ALLOC", 6) 1653 .Case("HW_REG_IB_STS" , 7) 1654 .Default(-1); 1655 Parser.Lex(); 1656 } else { 1657 IsIdentifier = false; 1658 if (getLexer().isNot(AsmToken::Integer)) 1659 return true; 1660 if (getParser().parseAbsoluteExpression(HwRegCode)) 1661 return true; 1662 } 1663 1664 if (getLexer().is(AsmToken::RParen)) { 1665 Parser.Lex(); 1666 return false; 1667 } 1668 1669 // optional params 1670 if (getLexer().isNot(AsmToken::Comma)) 1671 return true; 1672 Parser.Lex(); 1673 1674 if (getLexer().isNot(AsmToken::Integer)) 1675 return true; 1676 if (getParser().parseAbsoluteExpression(Offset)) 1677 return true; 1678 1679 if (getLexer().isNot(AsmToken::Comma)) 1680 return true; 1681 Parser.Lex(); 1682 1683 if (getLexer().isNot(AsmToken::Integer)) 1684 return true; 1685 if (getParser().parseAbsoluteExpression(Width)) 1686 return true; 1687 1688 if (getLexer().isNot(AsmToken::RParen)) 1689 return true; 1690 Parser.Lex(); 1691 1692 return false; 1693 } 1694 1695 AMDGPUAsmParser::OperandMatchResultTy 1696 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) { 1697 int64_t Imm16Val = 0; 1698 SMLoc S = Parser.getTok().getLoc(); 1699 1700 switch(getLexer().getKind()) { 1701 default: return MatchOperand_ParseFail; 1702 case AsmToken::Integer: 1703 // The operand can be an integer value. 1704 if (getParser().parseAbsoluteExpression(Imm16Val)) 1705 return MatchOperand_ParseFail; 1706 if (!isInt<16>(Imm16Val) && !isUInt<16>(Imm16Val)) { 1707 Error(S, "invalid immediate: only 16-bit values are legal"); 1708 // Do not return error code, but create an imm operand anyway and proceed 1709 // to the next operand, if any. That avoids unneccessary error messages. 1710 } 1711 break; 1712 1713 case AsmToken::Identifier: { 1714 bool IsIdentifier = false; 1715 int64_t HwRegCode = -1; 1716 int64_t Offset = 0; // default 1717 int64_t Width = 32; // default 1718 if (parseHwregOperand(HwRegCode, Offset, Width, IsIdentifier)) 1719 return MatchOperand_ParseFail; 1720 // HwRegCode (6) [5:0] 1721 // Offset (5) [10:6] 1722 // WidthMinusOne (5) [15:11] 1723 if (HwRegCode < 0 || HwRegCode > 63) { 1724 if (IsIdentifier) 1725 Error(S, "invalid symbolic name of hardware register"); 1726 else 1727 Error(S, "invalid code of hardware register: only 6-bit values are legal"); 1728 } 1729 if (Offset < 0 || Offset > 31) 1730 Error(S, "invalid bit offset: only 5-bit values are legal"); 1731 if (Width < 1 || Width > 32) 1732 Error(S, "invalid bitfield width: only values from 1 to 32 are legal"); 1733 Imm16Val = HwRegCode | (Offset << 6) | ((Width-1) << 11); 1734 } 1735 break; 1736 } 1737 Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg)); 1738 return MatchOperand_Success; 1739 } 1740 1741 bool AMDGPUOperand::isSWaitCnt() const { 1742 return isImm(); 1743 } 1744 1745 bool AMDGPUOperand::isHwreg() const { 1746 return isImmTy(ImmTyHwreg); 1747 } 1748 1749 //===----------------------------------------------------------------------===// 1750 // sopp branch targets 1751 //===----------------------------------------------------------------------===// 1752 1753 AMDGPUAsmParser::OperandMatchResultTy 1754 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 1755 SMLoc S = Parser.getTok().getLoc(); 1756 1757 switch (getLexer().getKind()) { 1758 default: return MatchOperand_ParseFail; 1759 case AsmToken::Integer: { 1760 int64_t Imm; 1761 if (getParser().parseAbsoluteExpression(Imm)) 1762 return MatchOperand_ParseFail; 1763 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S)); 1764 return MatchOperand_Success; 1765 } 1766 1767 case AsmToken::Identifier: 1768 Operands.push_back(AMDGPUOperand::CreateExpr( 1769 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 1770 Parser.getTok().getString()), getContext()), S)); 1771 Parser.Lex(); 1772 return MatchOperand_Success; 1773 } 1774 } 1775 1776 //===----------------------------------------------------------------------===// 1777 // flat 1778 //===----------------------------------------------------------------------===// 1779 1780 void AMDGPUAsmParser::cvtFlat(MCInst &Inst, 1781 const OperandVector &Operands) { 1782 OptionalImmIndexMap OptionalIdx; 1783 1784 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1785 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1786 1787 // Add the register arguments 1788 if (Op.isReg()) { 1789 Op.addRegOperands(Inst, 1); 1790 continue; 1791 } 1792 1793 OptionalIdx[Op.getImmTy()] = i; 1794 } 1795 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 1796 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1797 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1798 } 1799 1800 1801 void AMDGPUAsmParser::cvtFlatAtomic(MCInst &Inst, 1802 const OperandVector &Operands) { 1803 OptionalImmIndexMap OptionalIdx; 1804 1805 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1806 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1807 1808 // Add the register arguments 1809 if (Op.isReg()) { 1810 Op.addRegOperands(Inst, 1); 1811 continue; 1812 } 1813 1814 // Handle 'glc' token for flat atomics. 1815 if (Op.isToken()) { 1816 continue; 1817 } 1818 1819 // Handle optional arguments 1820 OptionalIdx[Op.getImmTy()] = i; 1821 } 1822 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1823 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1824 } 1825 1826 //===----------------------------------------------------------------------===// 1827 // mubuf 1828 //===----------------------------------------------------------------------===// 1829 1830 bool AMDGPUOperand::isMubufOffset() const { 1831 return isImmTy(ImmTyOffset) && isUInt<12>(getImm()); 1832 } 1833 1834 void AMDGPUAsmParser::cvtMubuf(MCInst &Inst, 1835 const OperandVector &Operands) { 1836 OptionalImmIndexMap OptionalIdx; 1837 1838 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1839 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1840 1841 // Add the register arguments 1842 if (Op.isReg()) { 1843 Op.addRegOperands(Inst, 1); 1844 continue; 1845 } 1846 1847 // Handle the case where soffset is an immediate 1848 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 1849 Op.addImmOperands(Inst, 1); 1850 continue; 1851 } 1852 1853 // Handle tokens like 'offen' which are sometimes hard-coded into the 1854 // asm string. There are no MCInst operands for these. 1855 if (Op.isToken()) { 1856 continue; 1857 } 1858 assert(Op.isImm()); 1859 1860 // Handle optional arguments 1861 OptionalIdx[Op.getImmTy()] = i; 1862 } 1863 1864 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset); 1865 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 1866 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 1867 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 1868 } 1869 1870 //===----------------------------------------------------------------------===// 1871 // mimg 1872 //===----------------------------------------------------------------------===// 1873 1874 AMDGPUAsmParser::OperandMatchResultTy 1875 AMDGPUAsmParser::parseDMask(OperandVector &Operands) { 1876 return parseIntWithPrefix("dmask", Operands, AMDGPUOperand::ImmTyDMask); 1877 } 1878 1879 AMDGPUAsmParser::OperandMatchResultTy 1880 AMDGPUAsmParser::parseUNorm(OperandVector &Operands) { 1881 return parseNamedBit("unorm", Operands, AMDGPUOperand::ImmTyUNorm); 1882 } 1883 1884 AMDGPUAsmParser::OperandMatchResultTy 1885 AMDGPUAsmParser::parseDA(OperandVector &Operands) { 1886 return parseNamedBit("da", Operands, AMDGPUOperand::ImmTyDA); 1887 } 1888 1889 AMDGPUAsmParser::OperandMatchResultTy 1890 AMDGPUAsmParser::parseR128(OperandVector &Operands) { 1891 return parseNamedBit("r128", Operands, AMDGPUOperand::ImmTyR128); 1892 } 1893 1894 AMDGPUAsmParser::OperandMatchResultTy 1895 AMDGPUAsmParser::parseLWE(OperandVector &Operands) { 1896 return parseNamedBit("lwe", Operands, AMDGPUOperand::ImmTyLWE); 1897 } 1898 1899 //===----------------------------------------------------------------------===// 1900 // smrd 1901 //===----------------------------------------------------------------------===// 1902 1903 bool AMDGPUOperand::isSMRDOffset() const { 1904 1905 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget 1906 // information here. 1907 return isImm() && isUInt<8>(getImm()); 1908 } 1909 1910 bool AMDGPUOperand::isSMRDLiteralOffset() const { 1911 // 32-bit literals are only supported on CI and we only want to use them 1912 // when the offset is > 8-bits. 1913 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 1914 } 1915 1916 //===----------------------------------------------------------------------===// 1917 // vop3 1918 //===----------------------------------------------------------------------===// 1919 1920 static bool ConvertOmodMul(int64_t &Mul) { 1921 if (Mul != 1 && Mul != 2 && Mul != 4) 1922 return false; 1923 1924 Mul >>= 1; 1925 return true; 1926 } 1927 1928 static bool ConvertOmodDiv(int64_t &Div) { 1929 if (Div == 1) { 1930 Div = 0; 1931 return true; 1932 } 1933 1934 if (Div == 2) { 1935 Div = 3; 1936 return true; 1937 } 1938 1939 return false; 1940 } 1941 1942 static bool ConvertBoundCtrl(int64_t &BoundCtrl) { 1943 if (BoundCtrl == 0) { 1944 BoundCtrl = 1; 1945 return true; 1946 } else if (BoundCtrl == -1) { 1947 BoundCtrl = 0; 1948 return true; 1949 } 1950 return false; 1951 } 1952 1953 // Note: the order in this table matches the order of operands in AsmString. 1954 static const OptionalOperand AMDGPUOperandTable[] = { 1955 {"offen", AMDGPUOperand::ImmTyOffen, true, 0, nullptr}, 1956 {"offset0", AMDGPUOperand::ImmTyOffset0, false, 0, nullptr}, 1957 {"offset1", AMDGPUOperand::ImmTyOffset1, false, 0, nullptr}, 1958 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr}, 1959 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1960 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1961 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1962 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr}, 1963 {"clamp", AMDGPUOperand::ImmTyClampSI, true, 0, nullptr}, 1964 {"omod", AMDGPUOperand::ImmTyOModSI, false, 1, ConvertOmodMul}, 1965 {"unorm", AMDGPUOperand::ImmTyUNorm, true, 0, nullptr}, 1966 {"da", AMDGPUOperand::ImmTyDA, true, 0, nullptr}, 1967 {"r128", AMDGPUOperand::ImmTyR128, true, 0, nullptr}, 1968 {"lwe", AMDGPUOperand::ImmTyLWE, true, 0, nullptr}, 1969 {"dmask", AMDGPUOperand::ImmTyDMask, false, 0, nullptr}, 1970 {"dpp_ctrl", AMDGPUOperand::ImmTyDppCtrl, false, -1, nullptr}, 1971 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, 0xf, nullptr}, 1972 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, 0xf, nullptr}, 1973 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, -1, ConvertBoundCtrl}, 1974 }; 1975 1976 AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands, const OptionalOperand& Op, bool AddDefault) 1977 { 1978 if (Op.IsBit) { 1979 return parseNamedBit(Op.Name, Operands, Op.Type, AddDefault); 1980 } else if (Op.Type == AMDGPUOperand::ImmTyDppCtrl) { 1981 return parseDPPCtrlOps(Operands, AddDefault); 1982 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) { 1983 return parseOModOperand(Operands); 1984 } else { 1985 return parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.Default, AddDefault, Op.ConvertResult); 1986 } 1987 } 1988 1989 AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseAMDGPUOperand(OperandVector &Operands, StringRef Name) 1990 { 1991 StringRef Tok; 1992 if (getLexer().is(AsmToken::Identifier)) { 1993 Tok = Parser.getTok().getString(); 1994 } 1995 bool optional = false; 1996 if (Tok == "mul" || Tok == "div") { optional = true; } 1997 for (const OptionalOperand &Op1 : AMDGPUOperandTable) { 1998 if (Op1.Name == Tok) { optional = true; break; } 1999 } 2000 // Attemp to parse current optional operand. 2001 for (const OptionalOperand &Op : AMDGPUOperandTable) { 2002 // TODO: For now, omod is handled separately because 2003 // token name does not match name in table. 2004 bool parseThis = 2005 Name == "" || 2006 (Op.Name == Name) || 2007 (Name == "omod" && Op.Type == AMDGPUOperand::ImmTyOModSI); 2008 if (parseThis && Tok == Name) { 2009 // Exactly the expected token for optional operand. 2010 // Parse it and add operand normally. 2011 return parseOptionalOperand(Operands, Op, true); 2012 } else if (parseThis) { 2013 // Token for optional operand which is later in the table 2014 // than the one we expect. If needed, add default value 2015 // for the operand we expect, do not consume anything 2016 // and return MatchOperand_NoMatch. Parsing will continue. 2017 return parseOptionalOperand(Operands, Op, optional); 2018 } else if (Op.Name == Tok) { 2019 // This looks like optional operand, but we do not expect it. 2020 // This is the case when AsmString has token in it. 2021 return MatchOperand_NoMatch; 2022 } 2023 } 2024 return MatchOperand_NoMatch; 2025 } 2026 2027 AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) 2028 { 2029 StringRef Name = Parser.getTok().getString(); 2030 if (Name == "mul") { 2031 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI, 0, false, ConvertOmodMul); 2032 } else if (Name == "div") { 2033 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI, 0, false, ConvertOmodDiv); 2034 } else { 2035 return MatchOperand_NoMatch; 2036 } 2037 } 2038 2039 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) { 2040 unsigned I = 1; 2041 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2042 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2043 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2044 } 2045 for (unsigned E = Operands.size(); I != E; ++I) 2046 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1); 2047 } 2048 2049 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) { 2050 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 2051 if (TSFlags & SIInstrFlags::VOP3) { 2052 cvtVOP3(Inst, Operands); 2053 } else { 2054 cvtId(Inst, Operands); 2055 } 2056 } 2057 2058 void AMDGPUAsmParser::cvtVOP3_2_nomod(MCInst &Inst, const OperandVector &Operands) { 2059 if (operandsHaveModifiers(Operands)) { 2060 cvtVOP3(Inst, Operands); 2061 } else { 2062 cvtId(Inst, Operands); 2063 } 2064 } 2065 2066 void AMDGPUAsmParser::cvtVOP3_only(MCInst &Inst, const OperandVector &Operands) { 2067 cvtVOP3(Inst, Operands); 2068 } 2069 2070 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 2071 OptionalImmIndexMap OptionalIdx; 2072 unsigned I = 1; 2073 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2074 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2075 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2076 } 2077 2078 for (unsigned E = Operands.size(); I != E; ++I) { 2079 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2080 if (Op.isRegOrImmWithInputMods()) { 2081 Op.addRegOrImmWithInputModsOperands(Inst, 2); 2082 } else if (Op.isImm()) { 2083 OptionalIdx[Op.getImmTy()] = I; 2084 } else { 2085 assert(false); 2086 } 2087 } 2088 2089 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI); 2090 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI); 2091 } 2092 2093 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) { 2094 unsigned I = 1; 2095 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2096 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2097 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2098 } 2099 2100 OptionalImmIndexMap OptionalIdx; 2101 2102 for (unsigned E = Operands.size(); I != E; ++I) { 2103 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2104 2105 // Add the register arguments 2106 if (Op.isRegOrImm()) { 2107 Op.addRegOrImmOperands(Inst, 1); 2108 continue; 2109 } else if (Op.isImmModifier()) { 2110 OptionalIdx[Op.getImmTy()] = I; 2111 } else { 2112 assert(false); 2113 } 2114 } 2115 2116 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 2117 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 2118 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 2119 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 2120 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 2121 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 2122 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 2123 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 2124 } 2125 2126 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) { 2127 unsigned I = 1; 2128 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2129 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2130 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2131 } 2132 2133 // Add src, same as dst 2134 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1); 2135 2136 OptionalImmIndexMap OptionalIdx; 2137 2138 for (unsigned E = Operands.size(); I != E; ++I) { 2139 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2140 2141 // Add the register arguments 2142 if (Op.isRegOrImm()) { 2143 Op.addRegOrImmOperands(Inst, 1); 2144 continue; 2145 } else if (Op.isImmModifier()) { 2146 OptionalIdx[Op.getImmTy()] = I; 2147 } else { 2148 assert(false); 2149 } 2150 } 2151 2152 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask); 2153 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm); 2154 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC); 2155 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA); 2156 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128); 2157 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE); 2158 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE); 2159 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC); 2160 } 2161 2162 //===----------------------------------------------------------------------===// 2163 // dpp 2164 //===----------------------------------------------------------------------===// 2165 2166 bool AMDGPUOperand::isDPPCtrl() const { 2167 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm()); 2168 if (result) { 2169 int64_t Imm = getImm(); 2170 return ((Imm >= 0x000) && (Imm <= 0x0ff)) || 2171 ((Imm >= 0x101) && (Imm <= 0x10f)) || 2172 ((Imm >= 0x111) && (Imm <= 0x11f)) || 2173 ((Imm >= 0x121) && (Imm <= 0x12f)) || 2174 (Imm == 0x130) || 2175 (Imm == 0x134) || 2176 (Imm == 0x138) || 2177 (Imm == 0x13c) || 2178 (Imm == 0x140) || 2179 (Imm == 0x141) || 2180 (Imm == 0x142) || 2181 (Imm == 0x143); 2182 } 2183 return false; 2184 } 2185 2186 AMDGPUAsmParser::OperandMatchResultTy 2187 AMDGPUAsmParser::parseDPPCtrlOps(OperandVector &Operands, bool AddDefault) { 2188 SMLoc S = Parser.getTok().getLoc(); 2189 StringRef Prefix; 2190 int64_t Int; 2191 2192 if (getLexer().getKind() == AsmToken::Identifier) { 2193 Prefix = Parser.getTok().getString(); 2194 } else { 2195 return MatchOperand_NoMatch; 2196 } 2197 2198 if (Prefix == "row_mirror") { 2199 Int = 0x140; 2200 } else if (Prefix == "row_half_mirror") { 2201 Int = 0x141; 2202 } else { 2203 // Check to prevent parseDPPCtrlOps from eating invalid tokens 2204 if (Prefix != "quad_perm" 2205 && Prefix != "row_shl" 2206 && Prefix != "row_shr" 2207 && Prefix != "row_ror" 2208 && Prefix != "wave_shl" 2209 && Prefix != "wave_rol" 2210 && Prefix != "wave_shr" 2211 && Prefix != "wave_ror" 2212 && Prefix != "row_bcast") { 2213 if (AddDefault) { 2214 Operands.push_back(AMDGPUOperand::CreateImm(0, S, AMDGPUOperand::ImmTyDppCtrl)); 2215 return MatchOperand_Success; 2216 } else { 2217 return MatchOperand_NoMatch; 2218 } 2219 } 2220 2221 Parser.Lex(); 2222 if (getLexer().isNot(AsmToken::Colon)) 2223 return MatchOperand_ParseFail; 2224 2225 if (Prefix == "quad_perm") { 2226 // quad_perm:[%d,%d,%d,%d] 2227 Parser.Lex(); 2228 if (getLexer().isNot(AsmToken::LBrac)) 2229 return MatchOperand_ParseFail; 2230 2231 Parser.Lex(); 2232 if (getLexer().isNot(AsmToken::Integer)) 2233 return MatchOperand_ParseFail; 2234 Int = getLexer().getTok().getIntVal(); 2235 2236 Parser.Lex(); 2237 if (getLexer().isNot(AsmToken::Comma)) 2238 return MatchOperand_ParseFail; 2239 Parser.Lex(); 2240 if (getLexer().isNot(AsmToken::Integer)) 2241 return MatchOperand_ParseFail; 2242 Int += (getLexer().getTok().getIntVal() << 2); 2243 2244 Parser.Lex(); 2245 if (getLexer().isNot(AsmToken::Comma)) 2246 return MatchOperand_ParseFail; 2247 Parser.Lex(); 2248 if (getLexer().isNot(AsmToken::Integer)) 2249 return MatchOperand_ParseFail; 2250 Int += (getLexer().getTok().getIntVal() << 4); 2251 2252 Parser.Lex(); 2253 if (getLexer().isNot(AsmToken::Comma)) 2254 return MatchOperand_ParseFail; 2255 Parser.Lex(); 2256 if (getLexer().isNot(AsmToken::Integer)) 2257 return MatchOperand_ParseFail; 2258 Int += (getLexer().getTok().getIntVal() << 6); 2259 2260 Parser.Lex(); 2261 if (getLexer().isNot(AsmToken::RBrac)) 2262 return MatchOperand_ParseFail; 2263 2264 } else { 2265 // sel:%d 2266 Parser.Lex(); 2267 if (getLexer().isNot(AsmToken::Integer)) 2268 return MatchOperand_ParseFail; 2269 Int = getLexer().getTok().getIntVal(); 2270 2271 if (Prefix == "row_shl") { 2272 Int |= 0x100; 2273 } else if (Prefix == "row_shr") { 2274 Int |= 0x110; 2275 } else if (Prefix == "row_ror") { 2276 Int |= 0x120; 2277 } else if (Prefix == "wave_shl") { 2278 Int = 0x130; 2279 } else if (Prefix == "wave_rol") { 2280 Int = 0x134; 2281 } else if (Prefix == "wave_shr") { 2282 Int = 0x138; 2283 } else if (Prefix == "wave_ror") { 2284 Int = 0x13C; 2285 } else if (Prefix == "row_bcast") { 2286 if (Int == 15) { 2287 Int = 0x142; 2288 } else if (Int == 31) { 2289 Int = 0x143; 2290 } 2291 } else { 2292 return MatchOperand_ParseFail; 2293 } 2294 } 2295 } 2296 Parser.Lex(); // eat last token 2297 2298 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2299 AMDGPUOperand::ImmTyDppCtrl)); 2300 return MatchOperand_Success; 2301 } 2302 2303 void AMDGPUAsmParser::cvtDPP_mod(MCInst &Inst, const OperandVector &Operands) { 2304 cvtDPP(Inst, Operands, true); 2305 } 2306 2307 void AMDGPUAsmParser::cvtDPP_nomod(MCInst &Inst, const OperandVector &Operands) { 2308 cvtDPP(Inst, Operands, false); 2309 } 2310 2311 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, 2312 bool HasMods) { 2313 OptionalImmIndexMap OptionalIdx; 2314 2315 unsigned I = 1; 2316 const MCInstrDesc &Desc = MII.get(Inst.getOpcode()); 2317 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) { 2318 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1); 2319 } 2320 2321 for (unsigned E = Operands.size(); I != E; ++I) { 2322 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]); 2323 // Add the register arguments 2324 if (!HasMods && Op.isReg()) { 2325 Op.addRegOperands(Inst, 1); 2326 } else if (HasMods && Op.isRegOrImmWithInputMods()) { 2327 Op.addRegOrImmWithInputModsOperands(Inst, 2); 2328 } else if (Op.isDPPCtrl()) { 2329 Op.addImmOperands(Inst, 1); 2330 } else if (Op.isImm()) { 2331 // Handle optional arguments 2332 OptionalIdx[Op.getImmTy()] = I; 2333 } else { 2334 llvm_unreachable("Invalid operand type"); 2335 } 2336 } 2337 2338 // ToDo: fix default values for row_mask and bank_mask 2339 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf); 2340 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf); 2341 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl); 2342 } 2343 2344 //===----------------------------------------------------------------------===// 2345 // sdwa 2346 //===----------------------------------------------------------------------===// 2347 2348 AMDGPUAsmParser::OperandMatchResultTy 2349 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands) { 2350 SMLoc S = Parser.getTok().getLoc(); 2351 StringRef Value; 2352 AMDGPUAsmParser::OperandMatchResultTy res; 2353 2354 res = parseStringWithPrefix("dst_sel", Value); 2355 if (res == MatchOperand_ParseFail) { 2356 return MatchOperand_ParseFail; 2357 } else if (res == MatchOperand_NoMatch) { 2358 res = parseStringWithPrefix("src0_sel", Value); 2359 if (res == MatchOperand_ParseFail) { 2360 return MatchOperand_ParseFail; 2361 } else if (res == MatchOperand_NoMatch) { 2362 res = parseStringWithPrefix("src1_sel", Value); 2363 if (res != MatchOperand_Success) { 2364 return res; 2365 } 2366 } 2367 } 2368 2369 int64_t Int; 2370 Int = StringSwitch<int64_t>(Value) 2371 .Case("BYTE_0", 0) 2372 .Case("BYTE_1", 1) 2373 .Case("BYTE_2", 2) 2374 .Case("BYTE_3", 3) 2375 .Case("WORD_0", 4) 2376 .Case("WORD_1", 5) 2377 .Case("DWORD", 6) 2378 .Default(0xffffffff); 2379 Parser.Lex(); // eat last token 2380 2381 if (Int == 0xffffffff) { 2382 return MatchOperand_ParseFail; 2383 } 2384 2385 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2386 AMDGPUOperand::ImmTySdwaSel)); 2387 return MatchOperand_Success; 2388 } 2389 2390 AMDGPUAsmParser::OperandMatchResultTy 2391 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) { 2392 SMLoc S = Parser.getTok().getLoc(); 2393 StringRef Value; 2394 AMDGPUAsmParser::OperandMatchResultTy res; 2395 2396 res = parseStringWithPrefix("dst_unused", Value); 2397 if (res != MatchOperand_Success) { 2398 return res; 2399 } 2400 2401 int64_t Int; 2402 Int = StringSwitch<int64_t>(Value) 2403 .Case("UNUSED_PAD", 0) 2404 .Case("UNUSED_SEXT", 1) 2405 .Case("UNUSED_PRESERVE", 2) 2406 .Default(0xffffffff); 2407 Parser.Lex(); // eat last token 2408 2409 if (Int == 0xffffffff) { 2410 return MatchOperand_ParseFail; 2411 } 2412 2413 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, 2414 AMDGPUOperand::ImmTySdwaDstUnused)); 2415 return MatchOperand_Success; 2416 } 2417 2418 2419 /// Force static initialization. 2420 extern "C" void LLVMInitializeAMDGPUAsmParser() { 2421 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget); 2422 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget); 2423 } 2424 2425 #define GET_REGISTER_MATCHER 2426 #define GET_MATCHER_IMPLEMENTATION 2427 #include "AMDGPUGenAsmMatcher.inc" 2428