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