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 "MCTargetDesc/AMDGPUMCTargetDesc.h" 11 #include "MCTargetDesc/AMDGPUTargetStreamer.h" 12 #include "Utils/AMDGPUBaseInfo.h" 13 #include "AMDKernelCodeT.h" 14 #include "SIDefines.h" 15 #include "llvm/ADT/APFloat.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/STLExtras.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/MCRegisterInfo.h" 29 #include "llvm/MC/MCStreamer.h" 30 #include "llvm/MC/MCSubtargetInfo.h" 31 #include "llvm/MC/MCTargetAsmParser.h" 32 #include "llvm/Support/SourceMgr.h" 33 #include "llvm/Support/TargetRegistry.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include "llvm/Support/Debug.h" 36 37 using namespace llvm; 38 39 namespace { 40 41 struct OptionalOperand; 42 43 class AMDGPUOperand : public MCParsedAsmOperand { 44 enum KindTy { 45 Token, 46 Immediate, 47 Register, 48 Expression 49 } Kind; 50 51 SMLoc StartLoc, EndLoc; 52 53 public: 54 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {} 55 56 MCContext *Ctx; 57 58 enum ImmTy { 59 ImmTyNone, 60 ImmTyDSOffset0, 61 ImmTyDSOffset1, 62 ImmTyGDS, 63 ImmTyOffset, 64 ImmTyGLC, 65 ImmTySLC, 66 ImmTyTFE, 67 ImmTyClamp, 68 ImmTyOMod 69 }; 70 71 struct TokOp { 72 const char *Data; 73 unsigned Length; 74 }; 75 76 struct ImmOp { 77 bool IsFPImm; 78 ImmTy Type; 79 int64_t Val; 80 }; 81 82 struct RegOp { 83 unsigned RegNo; 84 int Modifiers; 85 const MCRegisterInfo *TRI; 86 bool IsForcedVOP3; 87 }; 88 89 union { 90 TokOp Tok; 91 ImmOp Imm; 92 RegOp Reg; 93 const MCExpr *Expr; 94 }; 95 96 void addImmOperands(MCInst &Inst, unsigned N) const { 97 Inst.addOperand(MCOperand::createImm(getImm())); 98 } 99 100 StringRef getToken() const { 101 return StringRef(Tok.Data, Tok.Length); 102 } 103 104 void addRegOperands(MCInst &Inst, unsigned N) const { 105 Inst.addOperand(MCOperand::createReg(getReg())); 106 } 107 108 void addRegOrImmOperands(MCInst &Inst, unsigned N) const { 109 if (isReg()) 110 addRegOperands(Inst, N); 111 else 112 addImmOperands(Inst, N); 113 } 114 115 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const { 116 Inst.addOperand(MCOperand::createImm( 117 Reg.Modifiers == -1 ? 0 : Reg.Modifiers)); 118 addRegOperands(Inst, N); 119 } 120 121 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const { 122 if (isImm()) 123 addImmOperands(Inst, N); 124 else { 125 assert(isExpr()); 126 Inst.addOperand(MCOperand::createExpr(Expr)); 127 } 128 } 129 130 bool defaultTokenHasSuffix() const { 131 StringRef Token(Tok.Data, Tok.Length); 132 133 return Token.endswith("_e32") || Token.endswith("_e64"); 134 } 135 136 bool isToken() const override { 137 return Kind == Token; 138 } 139 140 bool isImm() const override { 141 return Kind == Immediate; 142 } 143 144 bool isInlineImm() const { 145 float F = BitsToFloat(Imm.Val); 146 // TODO: Add 0.5pi for VI 147 return isImm() && ((Imm.Val <= 64 && Imm.Val >= -16) || 148 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 || 149 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0)); 150 } 151 152 bool isDSOffset0() const { 153 assert(isImm()); 154 return Imm.Type == ImmTyDSOffset0; 155 } 156 157 bool isDSOffset1() const { 158 assert(isImm()); 159 return Imm.Type == ImmTyDSOffset1; 160 } 161 162 int64_t getImm() const { 163 return Imm.Val; 164 } 165 166 enum ImmTy getImmTy() const { 167 assert(isImm()); 168 return Imm.Type; 169 } 170 171 bool isRegKind() const { 172 return Kind == Register; 173 } 174 175 bool isReg() const override { 176 return Kind == Register && Reg.Modifiers == -1; 177 } 178 179 bool isRegWithInputMods() const { 180 return Kind == Register && (Reg.IsForcedVOP3 || Reg.Modifiers != -1); 181 } 182 183 void setModifiers(unsigned Mods) { 184 assert(isReg()); 185 Reg.Modifiers = Mods; 186 } 187 188 bool hasModifiers() const { 189 assert(isRegKind()); 190 return Reg.Modifiers != -1; 191 } 192 193 unsigned getReg() const override { 194 return Reg.RegNo; 195 } 196 197 bool isRegOrImm() const { 198 return isReg() || isImm(); 199 } 200 201 bool isRegClass(unsigned RCID) const { 202 return Reg.TRI->getRegClass(RCID).contains(getReg()); 203 } 204 205 bool isSCSrc32() const { 206 return isInlineImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); 207 } 208 209 bool isSSrc32() const { 210 return isImm() || (isReg() && isRegClass(AMDGPU::SReg_32RegClassID)); 211 } 212 213 bool isSSrc64() const { 214 return isImm() || isInlineImm() || 215 (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)); 216 } 217 218 bool isSCSrc64() const { 219 return (isReg() && isRegClass(AMDGPU::SReg_64RegClassID)) || isInlineImm(); 220 } 221 222 bool isVCSrc32() const { 223 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); 224 } 225 226 bool isVCSrc64() const { 227 return isInlineImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); 228 } 229 230 bool isVSrc32() const { 231 return isImm() || (isReg() && isRegClass(AMDGPU::VS_32RegClassID)); 232 } 233 234 bool isVSrc64() const { 235 return isImm() || (isReg() && isRegClass(AMDGPU::VS_64RegClassID)); 236 } 237 238 bool isMem() const override { 239 return false; 240 } 241 242 bool isExpr() const { 243 return Kind == Expression; 244 } 245 246 bool isSoppBrTarget() const { 247 return isExpr() || isImm(); 248 } 249 250 SMLoc getStartLoc() const override { 251 return StartLoc; 252 } 253 254 SMLoc getEndLoc() const override { 255 return EndLoc; 256 } 257 258 void print(raw_ostream &OS) const override { 259 switch (Kind) { 260 case Register: 261 OS << "<register " << getReg() << '>'; 262 break; 263 case Immediate: 264 OS << getImm(); 265 break; 266 case Token: 267 OS << '\'' << getToken() << '\''; 268 break; 269 case Expression: 270 OS << "<expr " << *Expr << '>'; 271 break; 272 } 273 } 274 275 static std::unique_ptr<AMDGPUOperand> CreateImm(int64_t Val, SMLoc Loc, 276 enum ImmTy Type = ImmTyNone, 277 bool IsFPImm = false) { 278 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate); 279 Op->Imm.Val = Val; 280 Op->Imm.IsFPImm = IsFPImm; 281 Op->Imm.Type = Type; 282 Op->StartLoc = Loc; 283 Op->EndLoc = Loc; 284 return Op; 285 } 286 287 static std::unique_ptr<AMDGPUOperand> CreateToken(StringRef Str, SMLoc Loc, 288 bool HasExplicitEncodingSize = true) { 289 auto Res = llvm::make_unique<AMDGPUOperand>(Token); 290 Res->Tok.Data = Str.data(); 291 Res->Tok.Length = Str.size(); 292 Res->StartLoc = Loc; 293 Res->EndLoc = Loc; 294 return Res; 295 } 296 297 static std::unique_ptr<AMDGPUOperand> CreateReg(unsigned RegNo, SMLoc S, 298 SMLoc E, 299 const MCRegisterInfo *TRI, 300 bool ForceVOP3) { 301 auto Op = llvm::make_unique<AMDGPUOperand>(Register); 302 Op->Reg.RegNo = RegNo; 303 Op->Reg.TRI = TRI; 304 Op->Reg.Modifiers = -1; 305 Op->Reg.IsForcedVOP3 = ForceVOP3; 306 Op->StartLoc = S; 307 Op->EndLoc = E; 308 return Op; 309 } 310 311 static std::unique_ptr<AMDGPUOperand> CreateExpr(const class MCExpr *Expr, SMLoc S) { 312 auto Op = llvm::make_unique<AMDGPUOperand>(Expression); 313 Op->Expr = Expr; 314 Op->StartLoc = S; 315 Op->EndLoc = S; 316 return Op; 317 } 318 319 bool isDSOffset() const; 320 bool isDSOffset01() const; 321 bool isSWaitCnt() const; 322 bool isMubufOffset() const; 323 bool isSMRDOffset() const; 324 bool isSMRDLiteralOffset() const; 325 }; 326 327 class AMDGPUAsmParser : public MCTargetAsmParser { 328 MCSubtargetInfo &STI; 329 const MCInstrInfo &MII; 330 MCAsmParser &Parser; 331 332 unsigned ForcedEncodingSize; 333 /// @name Auto-generated Match Functions 334 /// { 335 336 #define GET_ASSEMBLER_HEADER 337 #include "AMDGPUGenAsmMatcher.inc" 338 339 /// } 340 341 private: 342 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor); 343 bool ParseDirectiveHSACodeObjectVersion(); 344 bool ParseDirectiveHSACodeObjectISA(); 345 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header); 346 bool ParseDirectiveAMDKernelCodeT(); 347 348 public: 349 AMDGPUAsmParser(MCSubtargetInfo &STI, MCAsmParser &_Parser, 350 const MCInstrInfo &MII, 351 const MCTargetOptions &Options) 352 : MCTargetAsmParser(Options), STI(STI), MII(MII), Parser(_Parser), 353 ForcedEncodingSize(0){ 354 355 if (STI.getFeatureBits().none()) { 356 // Set default features. 357 STI.ToggleFeature("SOUTHERN_ISLANDS"); 358 } 359 360 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); 361 } 362 363 AMDGPUTargetStreamer &getTargetStreamer() { 364 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer(); 365 return static_cast<AMDGPUTargetStreamer &>(TS); 366 } 367 368 unsigned getForcedEncodingSize() const { 369 return ForcedEncodingSize; 370 } 371 372 void setForcedEncodingSize(unsigned Size) { 373 ForcedEncodingSize = Size; 374 } 375 376 bool isForcedVOP3() const { 377 return ForcedEncodingSize == 64; 378 } 379 380 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; 381 unsigned checkTargetMatchPredicate(MCInst &Inst) override; 382 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 383 OperandVector &Operands, MCStreamer &Out, 384 uint64_t &ErrorInfo, 385 bool MatchingInlineAsm) override; 386 bool ParseDirective(AsmToken DirectiveID) override; 387 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic); 388 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, 389 SMLoc NameLoc, OperandVector &Operands) override; 390 391 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int, 392 int64_t Default = 0); 393 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, 394 OperandVector &Operands, 395 enum AMDGPUOperand::ImmTy ImmTy = 396 AMDGPUOperand::ImmTyNone); 397 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands, 398 enum AMDGPUOperand::ImmTy ImmTy = 399 AMDGPUOperand::ImmTyNone); 400 OperandMatchResultTy parseOptionalOps( 401 const ArrayRef<OptionalOperand> &OptionalOps, 402 OperandVector &Operands); 403 404 405 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands); 406 void cvtDS(MCInst &Inst, const OperandVector &Operands); 407 OperandMatchResultTy parseDSOptionalOps(OperandVector &Operands); 408 OperandMatchResultTy parseDSOff01OptionalOps(OperandVector &Operands); 409 OperandMatchResultTy parseDSOffsetOptional(OperandVector &Operands); 410 411 bool parseCnt(int64_t &IntVal); 412 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands); 413 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands); 414 415 OperandMatchResultTy parseFlatOptionalOps(OperandVector &Operands); 416 OperandMatchResultTy parseFlatAtomicOptionalOps(OperandVector &Operands); 417 void cvtFlat(MCInst &Inst, const OperandVector &Operands); 418 419 void cvtMubuf(MCInst &Inst, const OperandVector &Operands); 420 OperandMatchResultTy parseOffset(OperandVector &Operands); 421 OperandMatchResultTy parseMubufOptionalOps(OperandVector &Operands); 422 OperandMatchResultTy parseGLC(OperandVector &Operands); 423 OperandMatchResultTy parseSLC(OperandVector &Operands); 424 OperandMatchResultTy parseTFE(OperandVector &Operands); 425 426 OperandMatchResultTy parseDMask(OperandVector &Operands); 427 OperandMatchResultTy parseUNorm(OperandVector &Operands); 428 OperandMatchResultTy parseR128(OperandVector &Operands); 429 430 void cvtVOP3(MCInst &Inst, const OperandVector &Operands); 431 OperandMatchResultTy parseVOP3OptionalOps(OperandVector &Operands); 432 }; 433 434 struct OptionalOperand { 435 const char *Name; 436 AMDGPUOperand::ImmTy Type; 437 bool IsBit; 438 int64_t Default; 439 bool (*ConvertResult)(int64_t&); 440 }; 441 442 } 443 444 static unsigned getRegClass(bool IsVgpr, unsigned RegWidth) { 445 if (IsVgpr) { 446 switch (RegWidth) { 447 default: llvm_unreachable("Unknown register width"); 448 case 1: return AMDGPU::VGPR_32RegClassID; 449 case 2: return AMDGPU::VReg_64RegClassID; 450 case 3: return AMDGPU::VReg_96RegClassID; 451 case 4: return AMDGPU::VReg_128RegClassID; 452 case 8: return AMDGPU::VReg_256RegClassID; 453 case 16: return AMDGPU::VReg_512RegClassID; 454 } 455 } 456 457 switch (RegWidth) { 458 default: llvm_unreachable("Unknown register width"); 459 case 1: return AMDGPU::SGPR_32RegClassID; 460 case 2: return AMDGPU::SGPR_64RegClassID; 461 case 4: return AMDGPU::SReg_128RegClassID; 462 case 8: return AMDGPU::SReg_256RegClassID; 463 case 16: return AMDGPU::SReg_512RegClassID; 464 } 465 } 466 467 static unsigned getRegForName(const StringRef &RegName) { 468 469 return StringSwitch<unsigned>(RegName) 470 .Case("exec", AMDGPU::EXEC) 471 .Case("vcc", AMDGPU::VCC) 472 .Case("flat_scr", AMDGPU::FLAT_SCR) 473 .Case("m0", AMDGPU::M0) 474 .Case("scc", AMDGPU::SCC) 475 .Case("flat_scr_lo", AMDGPU::FLAT_SCR_LO) 476 .Case("flat_scr_hi", AMDGPU::FLAT_SCR_HI) 477 .Case("vcc_lo", AMDGPU::VCC_LO) 478 .Case("vcc_hi", AMDGPU::VCC_HI) 479 .Case("exec_lo", AMDGPU::EXEC_LO) 480 .Case("exec_hi", AMDGPU::EXEC_HI) 481 .Default(0); 482 } 483 484 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { 485 const AsmToken Tok = Parser.getTok(); 486 StartLoc = Tok.getLoc(); 487 EndLoc = Tok.getEndLoc(); 488 StringRef RegName = Tok.getString(); 489 RegNo = getRegForName(RegName); 490 491 if (RegNo) { 492 Parser.Lex(); 493 return false; 494 } 495 496 // Match vgprs and sgprs 497 if (RegName[0] != 's' && RegName[0] != 'v') 498 return true; 499 500 bool IsVgpr = RegName[0] == 'v'; 501 unsigned RegWidth; 502 unsigned RegIndexInClass; 503 if (RegName.size() > 1) { 504 // We have a 32-bit register 505 RegWidth = 1; 506 if (RegName.substr(1).getAsInteger(10, RegIndexInClass)) 507 return true; 508 Parser.Lex(); 509 } else { 510 // We have a register greater than 32-bits. 511 512 int64_t RegLo, RegHi; 513 Parser.Lex(); 514 if (getLexer().isNot(AsmToken::LBrac)) 515 return true; 516 517 Parser.Lex(); 518 if (getParser().parseAbsoluteExpression(RegLo)) 519 return true; 520 521 if (getLexer().isNot(AsmToken::Colon)) 522 return true; 523 524 Parser.Lex(); 525 if (getParser().parseAbsoluteExpression(RegHi)) 526 return true; 527 528 if (getLexer().isNot(AsmToken::RBrac)) 529 return true; 530 531 Parser.Lex(); 532 RegWidth = (RegHi - RegLo) + 1; 533 if (IsVgpr) { 534 // VGPR registers aren't aligned. 535 RegIndexInClass = RegLo; 536 } else { 537 // SGPR registers are aligned. Max alignment is 4 dwords. 538 RegIndexInClass = RegLo / std::min(RegWidth, 4u); 539 } 540 } 541 542 const MCRegisterInfo *TRC = getContext().getRegisterInfo(); 543 unsigned RC = getRegClass(IsVgpr, RegWidth); 544 if (RegIndexInClass > TRC->getRegClass(RC).getNumRegs()) 545 return true; 546 RegNo = TRC->getRegClass(RC).getRegister(RegIndexInClass); 547 return false; 548 } 549 550 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) { 551 552 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags; 553 554 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) || 555 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3))) 556 return Match_InvalidOperand; 557 558 return Match_Success; 559 } 560 561 562 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, 563 OperandVector &Operands, 564 MCStreamer &Out, 565 uint64_t &ErrorInfo, 566 bool MatchingInlineAsm) { 567 MCInst Inst; 568 569 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) { 570 default: break; 571 case Match_Success: 572 Inst.setLoc(IDLoc); 573 Out.EmitInstruction(Inst, STI); 574 return false; 575 case Match_MissingFeature: 576 return Error(IDLoc, "instruction not supported on this GPU"); 577 578 case Match_MnemonicFail: 579 return Error(IDLoc, "unrecognized instruction mnemonic"); 580 581 case Match_InvalidOperand: { 582 SMLoc ErrorLoc = IDLoc; 583 if (ErrorInfo != ~0ULL) { 584 if (ErrorInfo >= Operands.size()) { 585 if (isForcedVOP3()) { 586 // If 64-bit encoding has been forced we can end up with no 587 // clamp or omod operands if none of the registers have modifiers, 588 // so we need to add these to the operand list. 589 AMDGPUOperand &LastOp = 590 ((AMDGPUOperand &)*Operands[Operands.size() - 1]); 591 if (LastOp.isRegKind() || 592 (LastOp.isImm() && 593 LastOp.getImmTy() != AMDGPUOperand::ImmTyNone)) { 594 SMLoc S = Parser.getTok().getLoc(); 595 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 596 AMDGPUOperand::ImmTyClamp)); 597 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 598 AMDGPUOperand::ImmTyOMod)); 599 bool Res = MatchAndEmitInstruction(IDLoc, Opcode, Operands, 600 Out, ErrorInfo, 601 MatchingInlineAsm); 602 if (!Res) 603 return Res; 604 } 605 606 } 607 return Error(IDLoc, "too few operands for instruction"); 608 } 609 610 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc(); 611 if (ErrorLoc == SMLoc()) 612 ErrorLoc = IDLoc; 613 } 614 return Error(ErrorLoc, "invalid operand for instruction"); 615 } 616 } 617 llvm_unreachable("Implement any new match types added!"); 618 } 619 620 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major, 621 uint32_t &Minor) { 622 if (getLexer().isNot(AsmToken::Integer)) 623 return TokError("invalid major version"); 624 625 Major = getLexer().getTok().getIntVal(); 626 Lex(); 627 628 if (getLexer().isNot(AsmToken::Comma)) 629 return TokError("minor version number required, comma expected"); 630 Lex(); 631 632 if (getLexer().isNot(AsmToken::Integer)) 633 return TokError("invalid minor version"); 634 635 Minor = getLexer().getTok().getIntVal(); 636 Lex(); 637 638 return false; 639 } 640 641 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() { 642 643 uint32_t Major; 644 uint32_t Minor; 645 646 if (ParseDirectiveMajorMinor(Major, Minor)) 647 return true; 648 649 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor); 650 return false; 651 } 652 653 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() { 654 655 uint32_t Major; 656 uint32_t Minor; 657 uint32_t Stepping; 658 StringRef VendorName; 659 StringRef ArchName; 660 661 // If this directive has no arguments, then use the ISA version for the 662 // targeted GPU. 663 if (getLexer().is(AsmToken::EndOfStatement)) { 664 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(STI.getFeatureBits()); 665 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor, 666 Isa.Stepping, 667 "AMD", "AMDGPU"); 668 return false; 669 } 670 671 672 if (ParseDirectiveMajorMinor(Major, Minor)) 673 return true; 674 675 if (getLexer().isNot(AsmToken::Comma)) 676 return TokError("stepping version number required, comma expected"); 677 Lex(); 678 679 if (getLexer().isNot(AsmToken::Integer)) 680 return TokError("invalid stepping version"); 681 682 Stepping = getLexer().getTok().getIntVal(); 683 Lex(); 684 685 if (getLexer().isNot(AsmToken::Comma)) 686 return TokError("vendor name required, comma expected"); 687 Lex(); 688 689 if (getLexer().isNot(AsmToken::String)) 690 return TokError("invalid vendor name"); 691 692 VendorName = getLexer().getTok().getStringContents(); 693 Lex(); 694 695 if (getLexer().isNot(AsmToken::Comma)) 696 return TokError("arch name required, comma expected"); 697 Lex(); 698 699 if (getLexer().isNot(AsmToken::String)) 700 return TokError("invalid arch name"); 701 702 ArchName = getLexer().getTok().getStringContents(); 703 Lex(); 704 705 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping, 706 VendorName, ArchName); 707 return false; 708 } 709 710 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID, 711 amd_kernel_code_t &Header) { 712 713 if (getLexer().isNot(AsmToken::Equal)) 714 return TokError("expected '='"); 715 Lex(); 716 717 if (getLexer().isNot(AsmToken::Integer)) 718 return TokError("amd_kernel_code_t values must be integers"); 719 720 uint64_t Value = getLexer().getTok().getIntVal(); 721 Lex(); 722 723 if (ID == "kernel_code_version_major") 724 Header.amd_kernel_code_version_major = Value; 725 else if (ID == "kernel_code_version_minor") 726 Header.amd_kernel_code_version_minor = Value; 727 else if (ID == "machine_kind") 728 Header.amd_machine_kind = Value; 729 else if (ID == "machine_version_major") 730 Header.amd_machine_version_major = Value; 731 else if (ID == "machine_version_minor") 732 Header.amd_machine_version_minor = Value; 733 else if (ID == "machine_version_stepping") 734 Header.amd_machine_version_stepping = Value; 735 else if (ID == "kernel_code_entry_byte_offset") 736 Header.kernel_code_entry_byte_offset = Value; 737 else if (ID == "kernel_code_prefetch_byte_size") 738 Header.kernel_code_prefetch_byte_size = Value; 739 else if (ID == "max_scratch_backing_memory_byte_size") 740 Header.max_scratch_backing_memory_byte_size = Value; 741 else if (ID == "compute_pgm_rsrc1_vgprs") 742 Header.compute_pgm_resource_registers |= S_00B848_VGPRS(Value); 743 else if (ID == "compute_pgm_rsrc1_sgprs") 744 Header.compute_pgm_resource_registers |= S_00B848_SGPRS(Value); 745 else if (ID == "compute_pgm_rsrc1_priority") 746 Header.compute_pgm_resource_registers |= S_00B848_PRIORITY(Value); 747 else if (ID == "compute_pgm_rsrc1_float_mode") 748 Header.compute_pgm_resource_registers |= S_00B848_FLOAT_MODE(Value); 749 else if (ID == "compute_pgm_rsrc1_priv") 750 Header.compute_pgm_resource_registers |= S_00B848_PRIV(Value); 751 else if (ID == "compute_pgm_rsrc1_dx10_clamp") 752 Header.compute_pgm_resource_registers |= S_00B848_DX10_CLAMP(Value); 753 else if (ID == "compute_pgm_rsrc1_debug_mode") 754 Header.compute_pgm_resource_registers |= S_00B848_DEBUG_MODE(Value); 755 else if (ID == "compute_pgm_rsrc1_ieee_mode") 756 Header.compute_pgm_resource_registers |= S_00B848_IEEE_MODE(Value); 757 else if (ID == "compute_pgm_rsrc2_scratch_en") 758 Header.compute_pgm_resource_registers |= (S_00B84C_SCRATCH_EN(Value) << 32); 759 else if (ID == "compute_pgm_rsrc2_user_sgpr") 760 Header.compute_pgm_resource_registers |= (S_00B84C_USER_SGPR(Value) << 32); 761 else if (ID == "compute_pgm_rsrc2_tgid_x_en") 762 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_X_EN(Value) << 32); 763 else if (ID == "compute_pgm_rsrc2_tgid_y_en") 764 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Y_EN(Value) << 32); 765 else if (ID == "compute_pgm_rsrc2_tgid_z_en") 766 Header.compute_pgm_resource_registers |= (S_00B84C_TGID_Z_EN(Value) << 32); 767 else if (ID == "compute_pgm_rsrc2_tg_size_en") 768 Header.compute_pgm_resource_registers |= (S_00B84C_TG_SIZE_EN(Value) << 32); 769 else if (ID == "compute_pgm_rsrc2_tidig_comp_cnt") 770 Header.compute_pgm_resource_registers |= 771 (S_00B84C_TIDIG_COMP_CNT(Value) << 32); 772 else if (ID == "compute_pgm_rsrc2_excp_en_msb") 773 Header.compute_pgm_resource_registers |= 774 (S_00B84C_EXCP_EN_MSB(Value) << 32); 775 else if (ID == "compute_pgm_rsrc2_lds_size") 776 Header.compute_pgm_resource_registers |= (S_00B84C_LDS_SIZE(Value) << 32); 777 else if (ID == "compute_pgm_rsrc2_excp_en") 778 Header.compute_pgm_resource_registers |= (S_00B84C_EXCP_EN(Value) << 32); 779 else if (ID == "compute_pgm_resource_registers") 780 Header.compute_pgm_resource_registers = Value; 781 else if (ID == "enable_sgpr_private_segment_buffer") 782 Header.code_properties |= 783 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER_SHIFT); 784 else if (ID == "enable_sgpr_dispatch_ptr") 785 Header.code_properties |= 786 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR_SHIFT); 787 else if (ID == "enable_sgpr_queue_ptr") 788 Header.code_properties |= 789 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR_SHIFT); 790 else if (ID == "enable_sgpr_kernarg_segment_ptr") 791 Header.code_properties |= 792 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR_SHIFT); 793 else if (ID == "enable_sgpr_dispatch_id") 794 Header.code_properties |= 795 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID_SHIFT); 796 else if (ID == "enable_sgpr_flat_scratch_init") 797 Header.code_properties |= 798 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT_SHIFT); 799 else if (ID == "enable_sgpr_private_segment_size") 800 Header.code_properties |= 801 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE_SHIFT); 802 else if (ID == "enable_sgpr_grid_workgroup_count_x") 803 Header.code_properties |= 804 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_X_SHIFT); 805 else if (ID == "enable_sgpr_grid_workgroup_count_y") 806 Header.code_properties |= 807 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Y_SHIFT); 808 else if (ID == "enable_sgpr_grid_workgroup_count_z") 809 Header.code_properties |= 810 (Value << AMD_CODE_PROPERTY_ENABLE_SGPR_GRID_WORKGROUP_COUNT_Z_SHIFT); 811 else if (ID == "enable_ordered_append_gds") 812 Header.code_properties |= 813 (Value << AMD_CODE_PROPERTY_ENABLE_ORDERED_APPEND_GDS_SHIFT); 814 else if (ID == "private_element_size") 815 Header.code_properties |= 816 (Value << AMD_CODE_PROPERTY_PRIVATE_ELEMENT_SIZE_SHIFT); 817 else if (ID == "is_ptr64") 818 Header.code_properties |= 819 (Value << AMD_CODE_PROPERTY_IS_PTR64_SHIFT); 820 else if (ID == "is_dynamic_callstack") 821 Header.code_properties |= 822 (Value << AMD_CODE_PROPERTY_IS_DYNAMIC_CALLSTACK_SHIFT); 823 else if (ID == "is_debug_enabled") 824 Header.code_properties |= 825 (Value << AMD_CODE_PROPERTY_IS_DEBUG_SUPPORTED_SHIFT); 826 else if (ID == "is_xnack_enabled") 827 Header.code_properties |= 828 (Value << AMD_CODE_PROPERTY_IS_XNACK_SUPPORTED_SHIFT); 829 else if (ID == "workitem_private_segment_byte_size") 830 Header.workitem_private_segment_byte_size = Value; 831 else if (ID == "workgroup_group_segment_byte_size") 832 Header.workgroup_group_segment_byte_size = Value; 833 else if (ID == "gds_segment_byte_size") 834 Header.gds_segment_byte_size = Value; 835 else if (ID == "kernarg_segment_byte_size") 836 Header.kernarg_segment_byte_size = Value; 837 else if (ID == "workgroup_fbarrier_count") 838 Header.workgroup_fbarrier_count = Value; 839 else if (ID == "wavefront_sgpr_count") 840 Header.wavefront_sgpr_count = Value; 841 else if (ID == "workitem_vgpr_count") 842 Header.workitem_vgpr_count = Value; 843 else if (ID == "reserved_vgpr_first") 844 Header.reserved_vgpr_first = Value; 845 else if (ID == "reserved_vgpr_count") 846 Header.reserved_vgpr_count = Value; 847 else if (ID == "reserved_sgpr_first") 848 Header.reserved_sgpr_first = Value; 849 else if (ID == "reserved_sgpr_count") 850 Header.reserved_sgpr_count = Value; 851 else if (ID == "debug_wavefront_private_segment_offset_sgpr") 852 Header.debug_wavefront_private_segment_offset_sgpr = Value; 853 else if (ID == "debug_private_segment_buffer_sgpr") 854 Header.debug_private_segment_buffer_sgpr = Value; 855 else if (ID == "kernarg_segment_alignment") 856 Header.kernarg_segment_alignment = Value; 857 else if (ID == "group_segment_alignment") 858 Header.group_segment_alignment = Value; 859 else if (ID == "private_segment_alignment") 860 Header.private_segment_alignment = Value; 861 else if (ID == "wavefront_size") 862 Header.wavefront_size = Value; 863 else if (ID == "call_convention") 864 Header.call_convention = Value; 865 else if (ID == "runtime_loader_kernel_symbol") 866 Header.runtime_loader_kernel_symbol = Value; 867 else 868 return TokError("amd_kernel_code_t value not recognized."); 869 870 return false; 871 } 872 873 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() { 874 875 amd_kernel_code_t Header; 876 AMDGPU::initDefaultAMDKernelCodeT(Header, STI.getFeatureBits()); 877 878 while (true) { 879 880 if (getLexer().isNot(AsmToken::EndOfStatement)) 881 return TokError("amd_kernel_code_t values must begin on a new line"); 882 883 // Lex EndOfStatement. This is in a while loop, because lexing a comment 884 // will set the current token to EndOfStatement. 885 while(getLexer().is(AsmToken::EndOfStatement)) 886 Lex(); 887 888 if (getLexer().isNot(AsmToken::Identifier)) 889 return TokError("expected value identifier or .end_amd_kernel_code_t"); 890 891 StringRef ID = getLexer().getTok().getIdentifier(); 892 Lex(); 893 894 if (ID == ".end_amd_kernel_code_t") 895 break; 896 897 if (ParseAMDKernelCodeTValue(ID, Header)) 898 return true; 899 } 900 901 getTargetStreamer().EmitAMDKernelCodeT(Header); 902 903 return false; 904 } 905 906 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) { 907 StringRef IDVal = DirectiveID.getString(); 908 909 if (IDVal == ".hsa_code_object_version") 910 return ParseDirectiveHSACodeObjectVersion(); 911 912 if (IDVal == ".hsa_code_object_isa") 913 return ParseDirectiveHSACodeObjectISA(); 914 915 if (IDVal == ".amd_kernel_code_t") 916 return ParseDirectiveAMDKernelCodeT(); 917 918 return true; 919 } 920 921 static bool operandsHaveModifiers(const OperandVector &Operands) { 922 923 for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 924 const AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 925 if (Op.isRegKind() && Op.hasModifiers()) 926 return true; 927 if (Op.isImm() && (Op.getImmTy() == AMDGPUOperand::ImmTyOMod || 928 Op.getImmTy() == AMDGPUOperand::ImmTyClamp)) 929 return true; 930 } 931 return false; 932 } 933 934 AMDGPUAsmParser::OperandMatchResultTy 935 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { 936 937 // Try to parse with a custom parser 938 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic); 939 940 // If we successfully parsed the operand or if there as an error parsing, 941 // we are done. 942 // 943 // If we are parsing after we reach EndOfStatement then this means we 944 // are appending default values to the Operands list. This is only done 945 // by custom parser, so we shouldn't continue on to the generic parsing. 946 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail || 947 getLexer().is(AsmToken::EndOfStatement)) 948 return ResTy; 949 950 bool Negate = false, Abs = false; 951 if (getLexer().getKind()== AsmToken::Minus) { 952 Parser.Lex(); 953 Negate = true; 954 } 955 956 if (getLexer().getKind() == AsmToken::Pipe) { 957 Parser.Lex(); 958 Abs = true; 959 } 960 961 switch(getLexer().getKind()) { 962 case AsmToken::Integer: { 963 SMLoc S = Parser.getTok().getLoc(); 964 int64_t IntVal; 965 if (getParser().parseAbsoluteExpression(IntVal)) 966 return MatchOperand_ParseFail; 967 APInt IntVal32(32, IntVal); 968 if (IntVal32.getSExtValue() != IntVal) { 969 Error(S, "invalid immediate: only 32-bit values are legal"); 970 return MatchOperand_ParseFail; 971 } 972 973 IntVal = IntVal32.getSExtValue(); 974 if (Negate) 975 IntVal *= -1; 976 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S)); 977 return MatchOperand_Success; 978 } 979 case AsmToken::Real: { 980 // FIXME: We should emit an error if a double precisions floating-point 981 // value is used. I'm not sure the best way to detect this. 982 SMLoc S = Parser.getTok().getLoc(); 983 int64_t IntVal; 984 if (getParser().parseAbsoluteExpression(IntVal)) 985 return MatchOperand_ParseFail; 986 987 APFloat F((float)BitsToDouble(IntVal)); 988 if (Negate) 989 F.changeSign(); 990 Operands.push_back( 991 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S)); 992 return MatchOperand_Success; 993 } 994 case AsmToken::Identifier: { 995 SMLoc S, E; 996 unsigned RegNo; 997 if (!ParseRegister(RegNo, S, E)) { 998 999 bool HasModifiers = operandsHaveModifiers(Operands); 1000 unsigned Modifiers = 0; 1001 1002 if (Negate) 1003 Modifiers |= 0x1; 1004 1005 if (Abs) { 1006 if (getLexer().getKind() != AsmToken::Pipe) 1007 return MatchOperand_ParseFail; 1008 Parser.Lex(); 1009 Modifiers |= 0x2; 1010 } 1011 1012 if (Modifiers && !HasModifiers) { 1013 // We are adding a modifier to src1 or src2 and previous sources 1014 // don't have modifiers, so we need to go back and empty modifers 1015 // for each previous source. 1016 for (unsigned PrevRegIdx = Operands.size() - 1; PrevRegIdx > 1; 1017 --PrevRegIdx) { 1018 1019 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[PrevRegIdx]); 1020 RegOp.setModifiers(0); 1021 } 1022 } 1023 1024 1025 Operands.push_back(AMDGPUOperand::CreateReg( 1026 RegNo, S, E, getContext().getRegisterInfo(), 1027 isForcedVOP3())); 1028 1029 if (HasModifiers || Modifiers) { 1030 AMDGPUOperand &RegOp = ((AMDGPUOperand&)*Operands[Operands.size() - 1]); 1031 RegOp.setModifiers(Modifiers); 1032 1033 } 1034 } else { 1035 Operands.push_back(AMDGPUOperand::CreateToken(Parser.getTok().getString(), 1036 S)); 1037 Parser.Lex(); 1038 } 1039 return MatchOperand_Success; 1040 } 1041 default: 1042 return MatchOperand_NoMatch; 1043 } 1044 } 1045 1046 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info, 1047 StringRef Name, 1048 SMLoc NameLoc, OperandVector &Operands) { 1049 1050 // Clear any forced encodings from the previous instruction. 1051 setForcedEncodingSize(0); 1052 1053 if (Name.endswith("_e64")) 1054 setForcedEncodingSize(64); 1055 else if (Name.endswith("_e32")) 1056 setForcedEncodingSize(32); 1057 1058 // Add the instruction mnemonic 1059 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc)); 1060 1061 while (!getLexer().is(AsmToken::EndOfStatement)) { 1062 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name); 1063 1064 // Eat the comma or space if there is one. 1065 if (getLexer().is(AsmToken::Comma)) 1066 Parser.Lex(); 1067 1068 switch (Res) { 1069 case MatchOperand_Success: break; 1070 case MatchOperand_ParseFail: return Error(getLexer().getLoc(), 1071 "failed parsing operand."); 1072 case MatchOperand_NoMatch: return Error(getLexer().getLoc(), 1073 "not a valid operand."); 1074 } 1075 } 1076 1077 // Once we reach end of statement, continue parsing so we can add default 1078 // values for optional arguments. 1079 AMDGPUAsmParser::OperandMatchResultTy Res; 1080 while ((Res = parseOperand(Operands, Name)) != MatchOperand_NoMatch) { 1081 if (Res != MatchOperand_Success) 1082 return Error(getLexer().getLoc(), "failed parsing operand."); 1083 } 1084 return false; 1085 } 1086 1087 //===----------------------------------------------------------------------===// 1088 // Utility functions 1089 //===----------------------------------------------------------------------===// 1090 1091 AMDGPUAsmParser::OperandMatchResultTy 1092 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int, 1093 int64_t Default) { 1094 1095 // We are at the end of the statement, and this is a default argument, so 1096 // use a default value. 1097 if (getLexer().is(AsmToken::EndOfStatement)) { 1098 Int = Default; 1099 return MatchOperand_Success; 1100 } 1101 1102 switch(getLexer().getKind()) { 1103 default: return MatchOperand_NoMatch; 1104 case AsmToken::Identifier: { 1105 StringRef OffsetName = Parser.getTok().getString(); 1106 if (!OffsetName.equals(Prefix)) 1107 return MatchOperand_NoMatch; 1108 1109 Parser.Lex(); 1110 if (getLexer().isNot(AsmToken::Colon)) 1111 return MatchOperand_ParseFail; 1112 1113 Parser.Lex(); 1114 if (getLexer().isNot(AsmToken::Integer)) 1115 return MatchOperand_ParseFail; 1116 1117 if (getParser().parseAbsoluteExpression(Int)) 1118 return MatchOperand_ParseFail; 1119 break; 1120 } 1121 } 1122 return MatchOperand_Success; 1123 } 1124 1125 AMDGPUAsmParser::OperandMatchResultTy 1126 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands, 1127 enum AMDGPUOperand::ImmTy ImmTy) { 1128 1129 SMLoc S = Parser.getTok().getLoc(); 1130 int64_t Offset = 0; 1131 1132 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Offset); 1133 if (Res != MatchOperand_Success) 1134 return Res; 1135 1136 Operands.push_back(AMDGPUOperand::CreateImm(Offset, S, ImmTy)); 1137 return MatchOperand_Success; 1138 } 1139 1140 AMDGPUAsmParser::OperandMatchResultTy 1141 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands, 1142 enum AMDGPUOperand::ImmTy ImmTy) { 1143 int64_t Bit = 0; 1144 SMLoc S = Parser.getTok().getLoc(); 1145 1146 // We are at the end of the statement, and this is a default argument, so 1147 // use a default value. 1148 if (getLexer().isNot(AsmToken::EndOfStatement)) { 1149 switch(getLexer().getKind()) { 1150 case AsmToken::Identifier: { 1151 StringRef Tok = Parser.getTok().getString(); 1152 if (Tok == Name) { 1153 Bit = 1; 1154 Parser.Lex(); 1155 } else if (Tok.startswith("no") && Tok.endswith(Name)) { 1156 Bit = 0; 1157 Parser.Lex(); 1158 } else { 1159 return MatchOperand_NoMatch; 1160 } 1161 break; 1162 } 1163 default: 1164 return MatchOperand_NoMatch; 1165 } 1166 } 1167 1168 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy)); 1169 return MatchOperand_Success; 1170 } 1171 1172 static bool operandsHasOptionalOp(const OperandVector &Operands, 1173 const OptionalOperand &OOp) { 1174 for (unsigned i = 0; i < Operands.size(); i++) { 1175 const AMDGPUOperand &ParsedOp = ((const AMDGPUOperand &)*Operands[i]); 1176 if ((ParsedOp.isImm() && ParsedOp.getImmTy() == OOp.Type) || 1177 (ParsedOp.isToken() && ParsedOp.getToken() == OOp.Name)) 1178 return true; 1179 1180 } 1181 return false; 1182 } 1183 1184 AMDGPUAsmParser::OperandMatchResultTy 1185 AMDGPUAsmParser::parseOptionalOps(const ArrayRef<OptionalOperand> &OptionalOps, 1186 OperandVector &Operands) { 1187 SMLoc S = Parser.getTok().getLoc(); 1188 for (const OptionalOperand &Op : OptionalOps) { 1189 if (operandsHasOptionalOp(Operands, Op)) 1190 continue; 1191 AMDGPUAsmParser::OperandMatchResultTy Res; 1192 int64_t Value; 1193 if (Op.IsBit) { 1194 Res = parseNamedBit(Op.Name, Operands, Op.Type); 1195 if (Res == MatchOperand_NoMatch) 1196 continue; 1197 return Res; 1198 } 1199 1200 Res = parseIntWithPrefix(Op.Name, Value, Op.Default); 1201 1202 if (Res == MatchOperand_NoMatch) 1203 continue; 1204 1205 if (Res != MatchOperand_Success) 1206 return Res; 1207 1208 if (Op.ConvertResult && !Op.ConvertResult(Value)) { 1209 return MatchOperand_ParseFail; 1210 } 1211 1212 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, Op.Type)); 1213 return MatchOperand_Success; 1214 } 1215 return MatchOperand_NoMatch; 1216 } 1217 1218 //===----------------------------------------------------------------------===// 1219 // ds 1220 //===----------------------------------------------------------------------===// 1221 1222 static const OptionalOperand DSOptionalOps [] = { 1223 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1224 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1225 }; 1226 1227 static const OptionalOperand DSOptionalOpsOff01 [] = { 1228 {"offset0", AMDGPUOperand::ImmTyDSOffset0, false, 0, nullptr}, 1229 {"offset1", AMDGPUOperand::ImmTyDSOffset1, false, 0, nullptr}, 1230 {"gds", AMDGPUOperand::ImmTyGDS, true, 0, nullptr} 1231 }; 1232 1233 AMDGPUAsmParser::OperandMatchResultTy 1234 AMDGPUAsmParser::parseDSOptionalOps(OperandVector &Operands) { 1235 return parseOptionalOps(DSOptionalOps, Operands); 1236 } 1237 AMDGPUAsmParser::OperandMatchResultTy 1238 AMDGPUAsmParser::parseDSOff01OptionalOps(OperandVector &Operands) { 1239 return parseOptionalOps(DSOptionalOpsOff01, Operands); 1240 } 1241 1242 AMDGPUAsmParser::OperandMatchResultTy 1243 AMDGPUAsmParser::parseDSOffsetOptional(OperandVector &Operands) { 1244 SMLoc S = Parser.getTok().getLoc(); 1245 AMDGPUAsmParser::OperandMatchResultTy Res = 1246 parseIntWithPrefix("offset", Operands, AMDGPUOperand::ImmTyOffset); 1247 if (Res == MatchOperand_NoMatch) { 1248 Operands.push_back(AMDGPUOperand::CreateImm(0, S, 1249 AMDGPUOperand::ImmTyOffset)); 1250 Res = MatchOperand_Success; 1251 } 1252 return Res; 1253 } 1254 1255 bool AMDGPUOperand::isDSOffset() const { 1256 return isImm() && isUInt<16>(getImm()); 1257 } 1258 1259 bool AMDGPUOperand::isDSOffset01() const { 1260 return isImm() && isUInt<8>(getImm()); 1261 } 1262 1263 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst, 1264 const OperandVector &Operands) { 1265 1266 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1267 1268 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1269 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1270 1271 // Add the register arguments 1272 if (Op.isReg()) { 1273 Op.addRegOperands(Inst, 1); 1274 continue; 1275 } 1276 1277 // Handle optional arguments 1278 OptionalIdx[Op.getImmTy()] = i; 1279 } 1280 1281 unsigned Offset0Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset0]; 1282 unsigned Offset1Idx = OptionalIdx[AMDGPUOperand::ImmTyDSOffset1]; 1283 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1284 1285 ((AMDGPUOperand &)*Operands[Offset0Idx]).addImmOperands(Inst, 1); // offset0 1286 ((AMDGPUOperand &)*Operands[Offset1Idx]).addImmOperands(Inst, 1); // offset1 1287 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1288 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1289 } 1290 1291 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) { 1292 1293 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1294 bool GDSOnly = false; 1295 1296 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1297 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1298 1299 // Add the register arguments 1300 if (Op.isReg()) { 1301 Op.addRegOperands(Inst, 1); 1302 continue; 1303 } 1304 1305 if (Op.isToken() && Op.getToken() == "gds") { 1306 GDSOnly = true; 1307 continue; 1308 } 1309 1310 // Handle optional arguments 1311 OptionalIdx[Op.getImmTy()] = i; 1312 } 1313 1314 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1315 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); // offset 1316 1317 if (!GDSOnly) { 1318 unsigned GDSIdx = OptionalIdx[AMDGPUOperand::ImmTyGDS]; 1319 ((AMDGPUOperand &)*Operands[GDSIdx]).addImmOperands(Inst, 1); // gds 1320 } 1321 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0 1322 } 1323 1324 1325 //===----------------------------------------------------------------------===// 1326 // s_waitcnt 1327 //===----------------------------------------------------------------------===// 1328 1329 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) { 1330 StringRef CntName = Parser.getTok().getString(); 1331 int64_t CntVal; 1332 1333 Parser.Lex(); 1334 if (getLexer().isNot(AsmToken::LParen)) 1335 return true; 1336 1337 Parser.Lex(); 1338 if (getLexer().isNot(AsmToken::Integer)) 1339 return true; 1340 1341 if (getParser().parseAbsoluteExpression(CntVal)) 1342 return true; 1343 1344 if (getLexer().isNot(AsmToken::RParen)) 1345 return true; 1346 1347 Parser.Lex(); 1348 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) 1349 Parser.Lex(); 1350 1351 int CntShift; 1352 int CntMask; 1353 1354 if (CntName == "vmcnt") { 1355 CntMask = 0xf; 1356 CntShift = 0; 1357 } else if (CntName == "expcnt") { 1358 CntMask = 0x7; 1359 CntShift = 4; 1360 } else if (CntName == "lgkmcnt") { 1361 CntMask = 0x7; 1362 CntShift = 8; 1363 } else { 1364 return true; 1365 } 1366 1367 IntVal &= ~(CntMask << CntShift); 1368 IntVal |= (CntVal << CntShift); 1369 return false; 1370 } 1371 1372 AMDGPUAsmParser::OperandMatchResultTy 1373 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) { 1374 // Disable all counters by default. 1375 // vmcnt [3:0] 1376 // expcnt [6:4] 1377 // lgkmcnt [10:8] 1378 int64_t CntVal = 0x77f; 1379 SMLoc S = Parser.getTok().getLoc(); 1380 1381 switch(getLexer().getKind()) { 1382 default: return MatchOperand_ParseFail; 1383 case AsmToken::Integer: 1384 // The operand can be an integer value. 1385 if (getParser().parseAbsoluteExpression(CntVal)) 1386 return MatchOperand_ParseFail; 1387 break; 1388 1389 case AsmToken::Identifier: 1390 do { 1391 if (parseCnt(CntVal)) 1392 return MatchOperand_ParseFail; 1393 } while(getLexer().isNot(AsmToken::EndOfStatement)); 1394 break; 1395 } 1396 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S)); 1397 return MatchOperand_Success; 1398 } 1399 1400 bool AMDGPUOperand::isSWaitCnt() const { 1401 return isImm(); 1402 } 1403 1404 //===----------------------------------------------------------------------===// 1405 // sopp branch targets 1406 //===----------------------------------------------------------------------===// 1407 1408 AMDGPUAsmParser::OperandMatchResultTy 1409 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) { 1410 SMLoc S = Parser.getTok().getLoc(); 1411 1412 switch (getLexer().getKind()) { 1413 default: return MatchOperand_ParseFail; 1414 case AsmToken::Integer: { 1415 int64_t Imm; 1416 if (getParser().parseAbsoluteExpression(Imm)) 1417 return MatchOperand_ParseFail; 1418 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S)); 1419 return MatchOperand_Success; 1420 } 1421 1422 case AsmToken::Identifier: 1423 Operands.push_back(AMDGPUOperand::CreateExpr( 1424 MCSymbolRefExpr::create(getContext().getOrCreateSymbol( 1425 Parser.getTok().getString()), getContext()), S)); 1426 Parser.Lex(); 1427 return MatchOperand_Success; 1428 } 1429 } 1430 1431 //===----------------------------------------------------------------------===// 1432 // flat 1433 //===----------------------------------------------------------------------===// 1434 1435 static const OptionalOperand FlatOptionalOps [] = { 1436 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1437 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1438 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1439 }; 1440 1441 static const OptionalOperand FlatAtomicOptionalOps [] = { 1442 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1443 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1444 }; 1445 1446 AMDGPUAsmParser::OperandMatchResultTy 1447 AMDGPUAsmParser::parseFlatOptionalOps(OperandVector &Operands) { 1448 return parseOptionalOps(FlatOptionalOps, Operands); 1449 } 1450 1451 AMDGPUAsmParser::OperandMatchResultTy 1452 AMDGPUAsmParser::parseFlatAtomicOptionalOps(OperandVector &Operands) { 1453 return parseOptionalOps(FlatAtomicOptionalOps, Operands); 1454 } 1455 1456 void AMDGPUAsmParser::cvtFlat(MCInst &Inst, 1457 const OperandVector &Operands) { 1458 std::map<AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1459 1460 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1461 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1462 1463 // Add the register arguments 1464 if (Op.isReg()) { 1465 Op.addRegOperands(Inst, 1); 1466 continue; 1467 } 1468 1469 // Handle 'glc' token which is sometimes hard-coded into the 1470 // asm string. There are no MCInst operands for these. 1471 if (Op.isToken()) 1472 continue; 1473 1474 // Handle optional arguments 1475 OptionalIdx[Op.getImmTy()] = i; 1476 1477 } 1478 1479 // flat atomic instructions don't have a glc argument. 1480 if (OptionalIdx.count(AMDGPUOperand::ImmTyGLC)) { 1481 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1482 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1483 } 1484 1485 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1486 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1487 1488 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1489 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1490 } 1491 1492 //===----------------------------------------------------------------------===// 1493 // mubuf 1494 //===----------------------------------------------------------------------===// 1495 1496 static const OptionalOperand MubufOptionalOps [] = { 1497 {"offset", AMDGPUOperand::ImmTyOffset, false, 0, nullptr}, 1498 {"glc", AMDGPUOperand::ImmTyGLC, true, 0, nullptr}, 1499 {"slc", AMDGPUOperand::ImmTySLC, true, 0, nullptr}, 1500 {"tfe", AMDGPUOperand::ImmTyTFE, true, 0, nullptr} 1501 }; 1502 1503 AMDGPUAsmParser::OperandMatchResultTy 1504 AMDGPUAsmParser::parseMubufOptionalOps(OperandVector &Operands) { 1505 return parseOptionalOps(MubufOptionalOps, Operands); 1506 } 1507 1508 AMDGPUAsmParser::OperandMatchResultTy 1509 AMDGPUAsmParser::parseOffset(OperandVector &Operands) { 1510 return parseIntWithPrefix("offset", Operands); 1511 } 1512 1513 AMDGPUAsmParser::OperandMatchResultTy 1514 AMDGPUAsmParser::parseGLC(OperandVector &Operands) { 1515 return parseNamedBit("glc", Operands); 1516 } 1517 1518 AMDGPUAsmParser::OperandMatchResultTy 1519 AMDGPUAsmParser::parseSLC(OperandVector &Operands) { 1520 return parseNamedBit("slc", Operands); 1521 } 1522 1523 AMDGPUAsmParser::OperandMatchResultTy 1524 AMDGPUAsmParser::parseTFE(OperandVector &Operands) { 1525 return parseNamedBit("tfe", Operands); 1526 } 1527 1528 bool AMDGPUOperand::isMubufOffset() const { 1529 return isImm() && isUInt<12>(getImm()); 1530 } 1531 1532 void AMDGPUAsmParser::cvtMubuf(MCInst &Inst, 1533 const OperandVector &Operands) { 1534 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1535 1536 for (unsigned i = 1, e = Operands.size(); i != e; ++i) { 1537 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1538 1539 // Add the register arguments 1540 if (Op.isReg()) { 1541 Op.addRegOperands(Inst, 1); 1542 continue; 1543 } 1544 1545 // Handle the case where soffset is an immediate 1546 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) { 1547 Op.addImmOperands(Inst, 1); 1548 continue; 1549 } 1550 1551 // Handle tokens like 'offen' which are sometimes hard-coded into the 1552 // asm string. There are no MCInst operands for these. 1553 if (Op.isToken()) { 1554 continue; 1555 } 1556 assert(Op.isImm()); 1557 1558 // Handle optional arguments 1559 OptionalIdx[Op.getImmTy()] = i; 1560 } 1561 1562 assert(OptionalIdx.size() == 4); 1563 1564 unsigned OffsetIdx = OptionalIdx[AMDGPUOperand::ImmTyOffset]; 1565 unsigned GLCIdx = OptionalIdx[AMDGPUOperand::ImmTyGLC]; 1566 unsigned SLCIdx = OptionalIdx[AMDGPUOperand::ImmTySLC]; 1567 unsigned TFEIdx = OptionalIdx[AMDGPUOperand::ImmTyTFE]; 1568 1569 ((AMDGPUOperand &)*Operands[OffsetIdx]).addImmOperands(Inst, 1); 1570 ((AMDGPUOperand &)*Operands[GLCIdx]).addImmOperands(Inst, 1); 1571 ((AMDGPUOperand &)*Operands[SLCIdx]).addImmOperands(Inst, 1); 1572 ((AMDGPUOperand &)*Operands[TFEIdx]).addImmOperands(Inst, 1); 1573 } 1574 1575 //===----------------------------------------------------------------------===// 1576 // mimg 1577 //===----------------------------------------------------------------------===// 1578 1579 AMDGPUAsmParser::OperandMatchResultTy 1580 AMDGPUAsmParser::parseDMask(OperandVector &Operands) { 1581 return parseIntWithPrefix("dmask", Operands); 1582 } 1583 1584 AMDGPUAsmParser::OperandMatchResultTy 1585 AMDGPUAsmParser::parseUNorm(OperandVector &Operands) { 1586 return parseNamedBit("unorm", Operands); 1587 } 1588 1589 AMDGPUAsmParser::OperandMatchResultTy 1590 AMDGPUAsmParser::parseR128(OperandVector &Operands) { 1591 return parseNamedBit("r128", Operands); 1592 } 1593 1594 //===----------------------------------------------------------------------===// 1595 // smrd 1596 //===----------------------------------------------------------------------===// 1597 1598 bool AMDGPUOperand::isSMRDOffset() const { 1599 1600 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget 1601 // information here. 1602 return isImm() && isUInt<8>(getImm()); 1603 } 1604 1605 bool AMDGPUOperand::isSMRDLiteralOffset() const { 1606 // 32-bit literals are only supported on CI and we only want to use them 1607 // when the offset is > 8-bits. 1608 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm()); 1609 } 1610 1611 //===----------------------------------------------------------------------===// 1612 // vop3 1613 //===----------------------------------------------------------------------===// 1614 1615 static bool ConvertOmodMul(int64_t &Mul) { 1616 if (Mul != 1 && Mul != 2 && Mul != 4) 1617 return false; 1618 1619 Mul >>= 1; 1620 return true; 1621 } 1622 1623 static bool ConvertOmodDiv(int64_t &Div) { 1624 if (Div == 1) { 1625 Div = 0; 1626 return true; 1627 } 1628 1629 if (Div == 2) { 1630 Div = 3; 1631 return true; 1632 } 1633 1634 return false; 1635 } 1636 1637 static const OptionalOperand VOP3OptionalOps [] = { 1638 {"clamp", AMDGPUOperand::ImmTyClamp, true, 0, nullptr}, 1639 {"mul", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodMul}, 1640 {"div", AMDGPUOperand::ImmTyOMod, false, 1, ConvertOmodDiv}, 1641 }; 1642 1643 static bool isVOP3(OperandVector &Operands) { 1644 if (operandsHaveModifiers(Operands)) 1645 return true; 1646 1647 AMDGPUOperand &DstOp = ((AMDGPUOperand&)*Operands[1]); 1648 1649 if (DstOp.isReg() && DstOp.isRegClass(AMDGPU::SGPR_64RegClassID)) 1650 return true; 1651 1652 if (Operands.size() >= 5) 1653 return true; 1654 1655 if (Operands.size() > 3) { 1656 AMDGPUOperand &Src1Op = ((AMDGPUOperand&)*Operands[3]); 1657 if (Src1Op.getReg() && (Src1Op.isRegClass(AMDGPU::SReg_32RegClassID) || 1658 Src1Op.isRegClass(AMDGPU::SReg_64RegClassID))) 1659 return true; 1660 } 1661 return false; 1662 } 1663 1664 AMDGPUAsmParser::OperandMatchResultTy 1665 AMDGPUAsmParser::parseVOP3OptionalOps(OperandVector &Operands) { 1666 1667 // The value returned by this function may change after parsing 1668 // an operand so store the original value here. 1669 bool HasModifiers = operandsHaveModifiers(Operands); 1670 1671 bool IsVOP3 = isVOP3(Operands); 1672 if (HasModifiers || IsVOP3 || 1673 getLexer().isNot(AsmToken::EndOfStatement) || 1674 getForcedEncodingSize() == 64) { 1675 1676 AMDGPUAsmParser::OperandMatchResultTy Res = 1677 parseOptionalOps(VOP3OptionalOps, Operands); 1678 1679 if (!HasModifiers && Res == MatchOperand_Success) { 1680 // We have added a modifier operation, so we need to make sure all 1681 // previous register operands have modifiers 1682 for (unsigned i = 2, e = Operands.size(); i != e; ++i) { 1683 AMDGPUOperand &Op = ((AMDGPUOperand&)*Operands[i]); 1684 if (Op.isReg()) 1685 Op.setModifiers(0); 1686 } 1687 } 1688 return Res; 1689 } 1690 return MatchOperand_NoMatch; 1691 } 1692 1693 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) { 1694 ((AMDGPUOperand &)*Operands[1]).addRegOperands(Inst, 1); 1695 unsigned i = 2; 1696 1697 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx; 1698 1699 if (operandsHaveModifiers(Operands)) { 1700 for (unsigned e = Operands.size(); i != e; ++i) { 1701 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]); 1702 1703 if (Op.isRegWithInputMods()) { 1704 ((AMDGPUOperand &)*Operands[i]).addRegWithInputModsOperands(Inst, 2); 1705 continue; 1706 } 1707 OptionalIdx[Op.getImmTy()] = i; 1708 } 1709 1710 unsigned ClampIdx = OptionalIdx[AMDGPUOperand::ImmTyClamp]; 1711 unsigned OModIdx = OptionalIdx[AMDGPUOperand::ImmTyOMod]; 1712 1713 ((AMDGPUOperand &)*Operands[ClampIdx]).addImmOperands(Inst, 1); 1714 ((AMDGPUOperand &)*Operands[OModIdx]).addImmOperands(Inst, 1); 1715 } else { 1716 for (unsigned e = Operands.size(); i != e; ++i) 1717 ((AMDGPUOperand &)*Operands[i]).addRegOrImmOperands(Inst, 1); 1718 } 1719 } 1720 1721 /// Force static initialization. 1722 extern "C" void LLVMInitializeAMDGPUAsmParser() { 1723 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget); 1724 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget); 1725 } 1726 1727 #define GET_REGISTER_MATCHER 1728 #define GET_MATCHER_IMPLEMENTATION 1729 #include "AMDGPUGenAsmMatcher.inc" 1730 1731