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