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