1 //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "AMDKernelCodeT.h"
11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
13 #include "SIDefines.h"
14 #include "Utils/AMDGPUBaseInfo.h"
15 #include "Utils/AMDKernelCodeTUtils.h"
16 #include "Utils/AMDGPUAsmUtils.h"
17 #include "llvm/ADT/APFloat.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "llvm/ADT/SmallBitVector.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/StringSwitch.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCInst.h"
26 #include "llvm/MC/MCInstrInfo.h"
27 #include "llvm/MC/MCParser/MCAsmLexer.h"
28 #include "llvm/MC/MCParser/MCAsmParser.h"
29 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
30 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
31 #include "llvm/MC/MCRegisterInfo.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSubtargetInfo.h"
34 #include "llvm/MC/MCSymbolELF.h"
35 #include "llvm/Support/Debug.h"
36 #include "llvm/Support/ELF.h"
37 #include "llvm/Support/SourceMgr.h"
38 #include "llvm/Support/TargetRegistry.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include "llvm/Support/MathExtras.h"
46 struct OptionalOperand;
48 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
50 class AMDGPUOperand : public MCParsedAsmOperand {
58 SMLoc StartLoc, EndLoc;
61 AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
63 typedef std::unique_ptr<AMDGPUOperand> Ptr;
70 bool hasFPModifiers() const { return Abs || Neg; }
71 bool hasIntModifiers() const { return Sext; }
72 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
74 int64_t getFPModifiersOperand() const {
76 Operand |= Abs ? SISrcMods::ABS : 0;
77 Operand |= Neg ? SISrcMods::NEG : 0;
81 int64_t getIntModifiersOperand() const {
83 Operand |= Sext ? SISrcMods::SEXT : 0;
87 int64_t getModifiersOperand() const {
88 assert(!(hasFPModifiers() && hasIntModifiers())
89 && "fp and int modifiers should not be used simultaneously");
90 if (hasFPModifiers()) {
91 return getFPModifiersOperand();
92 } else if (hasIntModifiers()) {
93 return getIntModifiersOperand();
99 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
148 const MCRegisterInfo *TRI;
149 const MCSubtargetInfo *STI;
160 bool isToken() const override {
164 if (Kind != Expression || !Expr)
167 // When parsing operands, we can't always tell if something was meant to be
168 // a token, like 'gds', or an expression that references a global variable.
169 // In this case, we assume the string is an expression, and if we need to
170 // interpret is a token, then we treat the symbol name as the token.
171 return isa<MCSymbolRefExpr>(Expr);
174 bool isImm() const override {
175 return Kind == Immediate;
178 bool isInlinableImm() const {
179 if (!isImmTy(ImmTyNone)) {
180 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
183 // TODO: We should avoid using host float here. It would be better to
184 // check the float bit values which is what a few other places do.
185 // We've had bot failures before due to weird NaN support on mips hosts.
186 const float F = BitsToFloat(Imm.Val);
187 // TODO: Add 1/(2*pi) for VI
188 return (Imm.Val <= 64 && Imm.Val >= -16) ||
189 (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 ||
190 F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0);
193 bool isRegKind() const {
194 return Kind == Register;
197 bool isReg() const override {
198 return isRegKind() && !Reg.Mods.hasModifiers();
201 bool isRegOrImmWithInputMods() const {
202 return isRegKind() || isInlinableImm();
205 bool isImmTy(ImmTy ImmT) const {
206 return isImm() && Imm.Type == ImmT;
209 bool isImmModifier() const {
210 return isImm() && Imm.Type != ImmTyNone;
213 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
214 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
215 bool isDMask() const { return isImmTy(ImmTyDMask); }
216 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
217 bool isDA() const { return isImmTy(ImmTyDA); }
218 bool isR128() const { return isImmTy(ImmTyUNorm); }
219 bool isLWE() const { return isImmTy(ImmTyLWE); }
220 bool isOffen() const { return isImmTy(ImmTyOffen); }
221 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
222 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
223 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
224 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
225 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
226 bool isGDS() const { return isImmTy(ImmTyGDS); }
227 bool isGLC() const { return isImmTy(ImmTyGLC); }
228 bool isSLC() const { return isImmTy(ImmTySLC); }
229 bool isTFE() const { return isImmTy(ImmTyTFE); }
230 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
231 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
232 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
233 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
234 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
235 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
236 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
239 return isClampSI() || isOModSI();
242 bool isRegOrImm() const {
243 return isReg() || isImm();
246 bool isRegClass(unsigned RCID) const {
247 return isReg() && Reg.TRI->getRegClass(RCID).contains(getReg());
250 bool isSCSrc32() const {
251 return isInlinableImm() || isRegClass(AMDGPU::SReg_32RegClassID);
254 bool isSCSrc64() const {
255 return isInlinableImm() || isRegClass(AMDGPU::SReg_64RegClassID);
258 bool isSSrc32() const {
259 return isImm() || isSCSrc32() || isExpr();
262 bool isSSrc64() const {
263 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
265 return isImm() || isSCSrc64();
268 bool isVCSrc32() const {
269 return isInlinableImm() || isRegClass(AMDGPU::VS_32RegClassID);
272 bool isVCSrc64() const {
273 return isInlinableImm() || isRegClass(AMDGPU::VS_64RegClassID);
276 bool isVSrc32() const {
277 return isImm() || isVCSrc32();
280 bool isVSrc64() const {
281 // TODO: Check if the 64-bit value (coming from assembly source) can be
282 // narrowed to 32 bits (in the instruction stream). That require knowledge
283 // of instruction type (unsigned/signed, floating or "untyped"/B64),
284 // see [AMD GCN3 ISA 6.3.1].
285 // TODO: How 64-bit values are formed from 32-bit literals in _B64 insns?
286 return isImm() || isVCSrc64();
289 bool isMem() const override {
293 bool isExpr() const {
294 return Kind == Expression;
297 bool isSoppBrTarget() const {
298 return isExpr() || isImm();
301 bool isSWaitCnt() const;
302 bool isHwreg() const;
303 bool isSendMsg() const;
304 bool isSMRDOffset() const;
305 bool isSMRDLiteralOffset() const;
306 bool isDPPCtrl() const;
308 StringRef getExpressionAsToken() const {
310 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
311 return S->getSymbol().getName();
315 StringRef getToken() const {
318 if (Kind == Expression)
319 return getExpressionAsToken();
321 return StringRef(Tok.Data, Tok.Length);
324 int64_t getImm() const {
329 enum ImmTy getImmTy() const {
334 unsigned getReg() const override {
338 SMLoc getStartLoc() const override {
342 SMLoc getEndLoc() const override {
346 Modifiers getModifiers() const {
347 assert(isRegKind() || isImmTy(ImmTyNone));
348 return isRegKind() ? Reg.Mods : Imm.Mods;
351 void setModifiers(Modifiers Mods) {
352 assert(isRegKind() || isImmTy(ImmTyNone));
359 bool hasModifiers() const {
360 return getModifiers().hasModifiers();
363 bool hasFPModifiers() const {
364 return getModifiers().hasFPModifiers();
367 bool hasIntModifiers() const {
368 return getModifiers().hasIntModifiers();
371 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const {
372 if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers()) {
373 // Apply modifiers to immediate value
374 int64_t Val = Imm.Val;
375 bool Negate = Imm.Mods.Neg; // Only negate can get here
377 APFloat F(BitsToFloat(Val));
381 Val = F.bitcastToAPInt().getZExtValue();
383 Val = Negate ? -Val : Val;
385 Inst.addOperand(MCOperand::createImm(Val));
387 Inst.addOperand(MCOperand::createImm(getImm()));
391 void addRegOperands(MCInst &Inst, unsigned N) const {
392 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI)));
395 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
397 addRegOperands(Inst, N);
399 Inst.addOperand(MCOperand::createExpr(Expr));
401 addImmOperands(Inst, N);
404 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
405 Modifiers Mods = getModifiers();
406 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
408 addRegOperands(Inst, N);
410 addImmOperands(Inst, N, false);
414 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
415 assert(!hasIntModifiers());
416 addRegOrImmWithInputModsOperands(Inst, N);
419 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
420 assert(!hasFPModifiers());
421 addRegOrImmWithInputModsOperands(Inst, N);
424 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
426 addImmOperands(Inst, N);
429 Inst.addOperand(MCOperand::createExpr(Expr));
433 void printImmTy(raw_ostream& OS, ImmTy Type) const {
435 case ImmTyNone: OS << "None"; break;
436 case ImmTyGDS: OS << "GDS"; break;
437 case ImmTyOffen: OS << "Offen"; break;
438 case ImmTyIdxen: OS << "Idxen"; break;
439 case ImmTyAddr64: OS << "Addr64"; break;
440 case ImmTyOffset: OS << "Offset"; break;
441 case ImmTyOffset0: OS << "Offset0"; break;
442 case ImmTyOffset1: OS << "Offset1"; break;
443 case ImmTyGLC: OS << "GLC"; break;
444 case ImmTySLC: OS << "SLC"; break;
445 case ImmTyTFE: OS << "TFE"; break;
446 case ImmTyClampSI: OS << "ClampSI"; break;
447 case ImmTyOModSI: OS << "OModSI"; break;
448 case ImmTyDppCtrl: OS << "DppCtrl"; break;
449 case ImmTyDppRowMask: OS << "DppRowMask"; break;
450 case ImmTyDppBankMask: OS << "DppBankMask"; break;
451 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
452 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
453 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
454 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
455 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
456 case ImmTyDMask: OS << "DMask"; break;
457 case ImmTyUNorm: OS << "UNorm"; break;
458 case ImmTyDA: OS << "DA"; break;
459 case ImmTyR128: OS << "R128"; break;
460 case ImmTyLWE: OS << "LWE"; break;
461 case ImmTyHwreg: OS << "Hwreg"; break;
462 case ImmTySendMsg: OS << "SendMsg"; break;
466 void print(raw_ostream &OS) const override {
469 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
472 OS << '<' << getImm();
473 if (getImmTy() != ImmTyNone) {
474 OS << " type: "; printImmTy(OS, getImmTy());
476 OS << " mods: " << Imm.Mods << '>';
479 OS << '\'' << getToken() << '\'';
482 OS << "<expr " << *Expr << '>';
487 static AMDGPUOperand::Ptr CreateImm(int64_t Val, SMLoc Loc,
488 enum ImmTy Type = ImmTyNone,
489 bool IsFPImm = false) {
490 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
492 Op->Imm.IsFPImm = IsFPImm;
494 Op->Imm.Mods = {false, false, false};
500 static AMDGPUOperand::Ptr CreateToken(StringRef Str, SMLoc Loc,
501 bool HasExplicitEncodingSize = true) {
502 auto Res = llvm::make_unique<AMDGPUOperand>(Token);
503 Res->Tok.Data = Str.data();
504 Res->Tok.Length = Str.size();
510 static AMDGPUOperand::Ptr CreateReg(unsigned RegNo, SMLoc S,
512 const MCRegisterInfo *TRI,
513 const MCSubtargetInfo *STI,
515 auto Op = llvm::make_unique<AMDGPUOperand>(Register);
516 Op->Reg.RegNo = RegNo;
519 Op->Reg.Mods = {false, false, false};
520 Op->Reg.IsForcedVOP3 = ForceVOP3;
526 static AMDGPUOperand::Ptr CreateExpr(const class MCExpr *Expr, SMLoc S) {
527 auto Op = llvm::make_unique<AMDGPUOperand>(Expression);
535 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
536 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
540 class AMDGPUAsmParser : public MCTargetAsmParser {
541 const MCInstrInfo &MII;
544 unsigned ForcedEncodingSize;
549 return AMDGPU::isSI(getSTI());
553 return AMDGPU::isCI(getSTI());
557 return AMDGPU::isVI(getSTI());
560 bool hasSGPR102_SGPR103() const {
564 /// @name Auto-generated Match Functions
567 #define GET_ASSEMBLER_HEADER
568 #include "AMDGPUGenAsmMatcher.inc"
573 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
574 bool ParseDirectiveHSACodeObjectVersion();
575 bool ParseDirectiveHSACodeObjectISA();
576 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
577 bool ParseDirectiveAMDKernelCodeT();
578 bool ParseSectionDirectiveHSAText();
579 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
580 bool ParseDirectiveAMDGPUHsaKernel();
581 bool ParseDirectiveAMDGPUHsaModuleGlobal();
582 bool ParseDirectiveAMDGPUHsaProgramGlobal();
583 bool ParseSectionDirectiveHSADataGlobalAgent();
584 bool ParseSectionDirectiveHSADataGlobalProgram();
585 bool ParseSectionDirectiveHSARodataReadonlyAgent();
586 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
587 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth);
588 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
591 enum AMDGPUMatchResultTy {
592 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
595 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
596 const MCInstrInfo &MII,
597 const MCTargetOptions &Options)
598 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
599 ForcedEncodingSize(0),
602 MCAsmParserExtension::Initialize(Parser);
604 if (getSTI().getFeatureBits().none()) {
605 // Set default features.
606 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
609 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
612 // TODO: make those pre-defined variables read-only.
613 // Currently there is none suitable machinery in the core llvm-mc for this.
614 // MCSymbol::isRedefinable is intended for another purpose, and
615 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
616 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
617 MCContext &Ctx = getContext();
618 MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
619 Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx));
620 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
621 Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx));
622 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
623 Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx));
627 AMDGPUTargetStreamer &getTargetStreamer() {
628 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
629 return static_cast<AMDGPUTargetStreamer &>(TS);
632 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
633 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
634 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
636 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
637 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
638 bool isForcedDPP() const { return ForcedDPP; }
639 bool isForcedSDWA() const { return ForcedSDWA; }
641 std::unique_ptr<AMDGPUOperand> parseRegister();
642 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
643 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
644 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
645 unsigned Kind) override;
646 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
647 OperandVector &Operands, MCStreamer &Out,
649 bool MatchingInlineAsm) override;
650 bool ParseDirective(AsmToken DirectiveID) override;
651 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
652 StringRef parseMnemonicSuffix(StringRef Name);
653 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
654 SMLoc NameLoc, OperandVector &Operands) override;
656 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
657 OperandMatchResultTy parseIntWithPrefix(const char *Prefix,
658 OperandVector &Operands,
659 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
660 bool (*ConvertResult)(int64_t&) = 0);
661 OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands,
662 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
663 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, StringRef &Value);
665 OperandMatchResultTy parseImm(OperandVector &Operands);
666 OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
667 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands);
668 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands);
670 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
671 void cvtDS(MCInst &Inst, const OperandVector &Operands);
673 bool parseCnt(int64_t &IntVal);
674 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
675 OperandMatchResultTy parseHwreg(OperandVector &Operands);
678 struct OperandInfoTy {
681 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
684 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
685 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
687 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
689 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
690 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
692 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
693 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
694 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
695 AMDGPUOperand::Ptr defaultGLC() const;
696 AMDGPUOperand::Ptr defaultSLC() const;
697 AMDGPUOperand::Ptr defaultTFE() const;
699 AMDGPUOperand::Ptr defaultDMask() const;
700 AMDGPUOperand::Ptr defaultUNorm() const;
701 AMDGPUOperand::Ptr defaultDA() const;
702 AMDGPUOperand::Ptr defaultR128() const;
703 AMDGPUOperand::Ptr defaultLWE() const;
704 AMDGPUOperand::Ptr defaultSMRDOffset() const;
705 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
707 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
709 void cvtId(MCInst &Inst, const OperandVector &Operands);
710 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
711 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
713 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
714 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
716 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
717 AMDGPUOperand::Ptr defaultRowMask() const;
718 AMDGPUOperand::Ptr defaultBankMask() const;
719 AMDGPUOperand::Ptr defaultBoundCtrl() const;
720 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
722 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
723 AMDGPUOperand::ImmTy Type);
724 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
725 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
726 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
727 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
728 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
729 uint64_t BasicInstType);
732 struct OptionalOperand {
734 AMDGPUOperand::ImmTy Type;
736 bool (*ConvertResult)(int64_t&);
741 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
745 case 1: return AMDGPU::VGPR_32RegClassID;
746 case 2: return AMDGPU::VReg_64RegClassID;
747 case 3: return AMDGPU::VReg_96RegClassID;
748 case 4: return AMDGPU::VReg_128RegClassID;
749 case 8: return AMDGPU::VReg_256RegClassID;
750 case 16: return AMDGPU::VReg_512RegClassID;
752 } else if (Is == IS_TTMP) {
755 case 1: return AMDGPU::TTMP_32RegClassID;
756 case 2: return AMDGPU::TTMP_64RegClassID;
757 case 4: return AMDGPU::TTMP_128RegClassID;
759 } else if (Is == IS_SGPR) {
762 case 1: return AMDGPU::SGPR_32RegClassID;
763 case 2: return AMDGPU::SGPR_64RegClassID;
764 case 4: return AMDGPU::SGPR_128RegClassID;
765 case 8: return AMDGPU::SReg_256RegClassID;
766 case 16: return AMDGPU::SReg_512RegClassID;
772 static unsigned getSpecialRegForName(StringRef RegName) {
773 return StringSwitch<unsigned>(RegName)
774 .Case("exec", AMDGPU::EXEC)
775 .Case("vcc", AMDGPU::VCC)
776 .Case("flat_scratch", AMDGPU::FLAT_SCR)
777 .Case("m0", AMDGPU::M0)
778 .Case("scc", AMDGPU::SCC)
779 .Case("tba", AMDGPU::TBA)
780 .Case("tma", AMDGPU::TMA)
781 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
782 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
783 .Case("vcc_lo", AMDGPU::VCC_LO)
784 .Case("vcc_hi", AMDGPU::VCC_HI)
785 .Case("exec_lo", AMDGPU::EXEC_LO)
786 .Case("exec_hi", AMDGPU::EXEC_HI)
787 .Case("tma_lo", AMDGPU::TMA_LO)
788 .Case("tma_hi", AMDGPU::TMA_HI)
789 .Case("tba_lo", AMDGPU::TBA_LO)
790 .Case("tba_hi", AMDGPU::TBA_HI)
794 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
795 auto R = parseRegister();
799 StartLoc = R->getStartLoc();
800 EndLoc = R->getEndLoc();
804 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum)
808 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; }
809 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; }
810 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; }
811 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; }
812 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; }
817 if (Reg1 != Reg + RegWidth) { return false; }
821 assert(false); return false;
825 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth)
827 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
828 if (getLexer().is(AsmToken::Identifier)) {
829 StringRef RegName = Parser.getTok().getString();
830 if ((Reg = getSpecialRegForName(RegName))) {
832 RegKind = IS_SPECIAL;
834 unsigned RegNumIndex = 0;
835 if (RegName[0] == 'v') {
838 } else if (RegName[0] == 's') {
841 } else if (RegName.startswith("ttmp")) {
842 RegNumIndex = strlen("ttmp");
847 if (RegName.size() > RegNumIndex) {
848 // Single 32-bit register: vXX.
849 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
854 // Range of registers: v[XX:YY]. ":YY" is optional.
856 int64_t RegLo, RegHi;
857 if (getLexer().isNot(AsmToken::LBrac))
861 if (getParser().parseAbsoluteExpression(RegLo))
864 const bool isRBrace = getLexer().is(AsmToken::RBrac);
865 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
872 if (getParser().parseAbsoluteExpression(RegHi))
875 if (getLexer().isNot(AsmToken::RBrac))
879 RegNum = (unsigned) RegLo;
880 RegWidth = (RegHi - RegLo) + 1;
883 } else if (getLexer().is(AsmToken::LBrac)) {
884 // List of consecutive registers: [s0,s1,s2,s3]
886 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth))
890 RegisterKind RegKind1;
891 unsigned Reg1, RegNum1, RegWidth1;
893 if (getLexer().is(AsmToken::Comma)) {
895 } else if (getLexer().is(AsmToken::RBrac)) {
898 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1)) {
899 if (RegWidth1 != 1) {
902 if (RegKind1 != RegKind) {
905 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
925 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
926 // SGPR and TTMP registers must be are aligned. Max required alignment is 4 dwords.
927 Size = std::min(RegWidth, 4u);
929 if (RegNum % Size != 0)
931 RegNum = RegNum / Size;
932 int RCID = getRegClass(RegKind, RegWidth);
935 const MCRegisterClass RC = TRI->getRegClass(RCID);
936 if (RegNum >= RC.getNumRegs())
938 Reg = RC.getRegister(RegNum);
943 assert(false); return false;
946 if (!subtargetHasRegister(*TRI, Reg))
951 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
952 const auto &Tok = Parser.getTok();
953 SMLoc StartLoc = Tok.getLoc();
954 SMLoc EndLoc = Tok.getEndLoc();
955 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
957 RegisterKind RegKind;
958 unsigned Reg, RegNum, RegWidth;
960 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) {
963 return AMDGPUOperand::CreateReg(Reg, StartLoc, EndLoc,
964 TRI, &getSTI(), false);
967 AMDGPUAsmParser::OperandMatchResultTy
968 AMDGPUAsmParser::parseImm(OperandVector &Operands) {
970 if (getLexer().getKind() == AsmToken::Minus) {
975 SMLoc S = Parser.getTok().getLoc();
976 switch(getLexer().getKind()) {
977 case AsmToken::Integer: {
979 if (getParser().parseAbsoluteExpression(IntVal))
980 return MatchOperand_ParseFail;
981 if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) {
982 Error(S, "invalid immediate: only 32-bit values are legal");
983 return MatchOperand_ParseFail;
988 Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S));
989 return MatchOperand_Success;
991 case AsmToken::Real: {
992 // FIXME: We should emit an error if a double precisions floating-point
993 // value is used. I'm not sure the best way to detect this.
995 if (getParser().parseAbsoluteExpression(IntVal))
996 return MatchOperand_ParseFail;
998 APFloat F((float)BitsToDouble(IntVal));
1002 AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S,
1003 AMDGPUOperand::ImmTyNone, true));
1004 return MatchOperand_Success;
1007 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1011 AMDGPUAsmParser::OperandMatchResultTy
1012 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) {
1013 auto res = parseImm(Operands);
1014 if (res != MatchOperand_NoMatch) {
1018 if (auto R = parseRegister()) {
1020 R->Reg.IsForcedVOP3 = isForcedVOP3();
1021 Operands.push_back(std::move(R));
1022 return MatchOperand_Success;
1024 return MatchOperand_ParseFail;
1027 AMDGPUAsmParser::OperandMatchResultTy
1028 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands) {
1029 // XXX: During parsing we can't determine if minus sign means
1030 // negate-modifier or negative immediate value.
1031 // By default we suppose it is modifier.
1032 bool Negate = false, Abs = false, Abs2 = false;
1034 if (getLexer().getKind()== AsmToken::Minus) {
1039 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") {
1042 if (getLexer().isNot(AsmToken::LParen)) {
1043 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1044 return MatchOperand_ParseFail;
1049 if (getLexer().getKind() == AsmToken::Pipe) {
1051 Error(Parser.getTok().getLoc(), "expected register or immediate");
1052 return MatchOperand_ParseFail;
1058 auto Res = parseRegOrImm(Operands);
1059 if (Res != MatchOperand_Success) {
1063 AMDGPUOperand::Modifiers Mods = {false, false, false};
1068 if (getLexer().getKind() != AsmToken::Pipe) {
1069 Error(Parser.getTok().getLoc(), "expected vertical bar");
1070 return MatchOperand_ParseFail;
1076 if (getLexer().isNot(AsmToken::RParen)) {
1077 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1078 return MatchOperand_ParseFail;
1084 if (Mods.hasFPModifiers()) {
1085 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1086 Op.setModifiers(Mods);
1088 return MatchOperand_Success;
1091 AMDGPUAsmParser::OperandMatchResultTy
1092 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands) {
1095 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") {
1098 if (getLexer().isNot(AsmToken::LParen)) {
1099 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1100 return MatchOperand_ParseFail;
1105 auto Res = parseRegOrImm(Operands);
1106 if (Res != MatchOperand_Success) {
1110 AMDGPUOperand::Modifiers Mods = {false, false, false};
1112 if (getLexer().isNot(AsmToken::RParen)) {
1113 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1114 return MatchOperand_ParseFail;
1120 if (Mods.hasIntModifiers()) {
1121 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1122 Op.setModifiers(Mods);
1124 return MatchOperand_Success;
1127 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1129 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1131 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1132 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1133 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1134 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1135 return Match_InvalidOperand;
1137 if ((TSFlags & SIInstrFlags::VOP3) &&
1138 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1139 getForcedEncodingSize() != 64)
1140 return Match_PreferE32;
1142 return Match_Success;
1145 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1146 OperandVector &Operands,
1148 uint64_t &ErrorInfo,
1149 bool MatchingInlineAsm) {
1152 switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
1156 Out.EmitInstruction(Inst, getSTI());
1158 case Match_MissingFeature:
1159 return Error(IDLoc, "instruction not supported on this GPU");
1161 case Match_MnemonicFail:
1162 return Error(IDLoc, "unrecognized instruction mnemonic");
1164 case Match_InvalidOperand: {
1165 SMLoc ErrorLoc = IDLoc;
1166 if (ErrorInfo != ~0ULL) {
1167 if (ErrorInfo >= Operands.size()) {
1168 return Error(IDLoc, "too few operands for instruction");
1170 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
1171 if (ErrorLoc == SMLoc())
1174 return Error(ErrorLoc, "invalid operand for instruction");
1176 case Match_PreferE32:
1177 return Error(IDLoc, "internal error: instruction without _e64 suffix "
1178 "should be encoded as e32");
1180 llvm_unreachable("Implement any new match types added!");
1183 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
1185 if (getLexer().isNot(AsmToken::Integer))
1186 return TokError("invalid major version");
1188 Major = getLexer().getTok().getIntVal();
1191 if (getLexer().isNot(AsmToken::Comma))
1192 return TokError("minor version number required, comma expected");
1195 if (getLexer().isNot(AsmToken::Integer))
1196 return TokError("invalid minor version");
1198 Minor = getLexer().getTok().getIntVal();
1204 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
1209 if (ParseDirectiveMajorMinor(Major, Minor))
1212 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
1216 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
1221 StringRef VendorName;
1224 // If this directive has no arguments, then use the ISA version for the
1226 if (getLexer().is(AsmToken::EndOfStatement)) {
1227 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
1228 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
1235 if (ParseDirectiveMajorMinor(Major, Minor))
1238 if (getLexer().isNot(AsmToken::Comma))
1239 return TokError("stepping version number required, comma expected");
1242 if (getLexer().isNot(AsmToken::Integer))
1243 return TokError("invalid stepping version");
1245 Stepping = getLexer().getTok().getIntVal();
1248 if (getLexer().isNot(AsmToken::Comma))
1249 return TokError("vendor name required, comma expected");
1252 if (getLexer().isNot(AsmToken::String))
1253 return TokError("invalid vendor name");
1255 VendorName = getLexer().getTok().getStringContents();
1258 if (getLexer().isNot(AsmToken::Comma))
1259 return TokError("arch name required, comma expected");
1262 if (getLexer().isNot(AsmToken::String))
1263 return TokError("invalid arch name");
1265 ArchName = getLexer().getTok().getStringContents();
1268 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
1269 VendorName, ArchName);
1273 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
1274 amd_kernel_code_t &Header) {
1275 SmallString<40> ErrStr;
1276 raw_svector_ostream Err(ErrStr);
1277 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
1278 return TokError(Err.str());
1284 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
1286 amd_kernel_code_t Header;
1287 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits());
1291 // Lex EndOfStatement. This is in a while loop, because lexing a comment
1292 // will set the current token to EndOfStatement.
1293 while(getLexer().is(AsmToken::EndOfStatement))
1296 if (getLexer().isNot(AsmToken::Identifier))
1297 return TokError("expected value identifier or .end_amd_kernel_code_t");
1299 StringRef ID = getLexer().getTok().getIdentifier();
1302 if (ID == ".end_amd_kernel_code_t")
1305 if (ParseAMDKernelCodeTValue(ID, Header))
1309 getTargetStreamer().EmitAMDKernelCodeT(Header);
1314 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
1315 getParser().getStreamer().SwitchSection(
1316 AMDGPU::getHSATextSection(getContext()));
1320 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
1321 if (getLexer().isNot(AsmToken::Identifier))
1322 return TokError("expected symbol name");
1324 StringRef KernelName = Parser.getTok().getString();
1326 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
1327 ELF::STT_AMDGPU_HSA_KERNEL);
1332 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
1333 if (getLexer().isNot(AsmToken::Identifier))
1334 return TokError("expected symbol name");
1336 StringRef GlobalName = Parser.getTok().getIdentifier();
1338 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
1343 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
1344 if (getLexer().isNot(AsmToken::Identifier))
1345 return TokError("expected symbol name");
1347 StringRef GlobalName = Parser.getTok().getIdentifier();
1349 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
1354 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
1355 getParser().getStreamer().SwitchSection(
1356 AMDGPU::getHSADataGlobalAgentSection(getContext()));
1360 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
1361 getParser().getStreamer().SwitchSection(
1362 AMDGPU::getHSADataGlobalProgramSection(getContext()));
1366 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
1367 getParser().getStreamer().SwitchSection(
1368 AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
1372 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
1373 StringRef IDVal = DirectiveID.getString();
1375 if (IDVal == ".hsa_code_object_version")
1376 return ParseDirectiveHSACodeObjectVersion();
1378 if (IDVal == ".hsa_code_object_isa")
1379 return ParseDirectiveHSACodeObjectISA();
1381 if (IDVal == ".amd_kernel_code_t")
1382 return ParseDirectiveAMDKernelCodeT();
1384 if (IDVal == ".hsatext")
1385 return ParseSectionDirectiveHSAText();
1387 if (IDVal == ".amdgpu_hsa_kernel")
1388 return ParseDirectiveAMDGPUHsaKernel();
1390 if (IDVal == ".amdgpu_hsa_module_global")
1391 return ParseDirectiveAMDGPUHsaModuleGlobal();
1393 if (IDVal == ".amdgpu_hsa_program_global")
1394 return ParseDirectiveAMDGPUHsaProgramGlobal();
1396 if (IDVal == ".hsadata_global_agent")
1397 return ParseSectionDirectiveHSADataGlobalAgent();
1399 if (IDVal == ".hsadata_global_program")
1400 return ParseSectionDirectiveHSADataGlobalProgram();
1402 if (IDVal == ".hsarodata_readonly_agent")
1403 return ParseSectionDirectiveHSARodataReadonlyAgent();
1408 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
1409 unsigned RegNo) const {
1416 case AMDGPU::FLAT_SCR:
1417 case AMDGPU::FLAT_SCR_LO:
1418 case AMDGPU::FLAT_SCR_HI:
1425 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
1427 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
1436 AMDGPUAsmParser::OperandMatchResultTy
1437 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1439 // Try to parse with a custom parser
1440 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1442 // If we successfully parsed the operand or if there as an error parsing,
1445 // If we are parsing after we reach EndOfStatement then this means we
1446 // are appending default values to the Operands list. This is only done
1447 // by custom parser, so we shouldn't continue on to the generic parsing.
1448 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
1449 getLexer().is(AsmToken::EndOfStatement))
1452 ResTy = parseRegOrImm(Operands);
1454 if (ResTy == MatchOperand_Success)
1457 if (getLexer().getKind() == AsmToken::Identifier) {
1458 // If this identifier is a symbol, we want to create an expression for it.
1459 // It is a little difficult to distinguish between a symbol name, and
1460 // an instruction flag like 'gds'. In order to do this, we parse
1461 // all tokens as expressions and then treate the symbol name as the token
1462 // string when we want to interpret the operand as a token.
1463 const auto &Tok = Parser.getTok();
1464 SMLoc S = Tok.getLoc();
1465 const MCExpr *Expr = nullptr;
1466 if (!Parser.parseExpression(Expr)) {
1467 Operands.push_back(AMDGPUOperand::CreateExpr(Expr, S));
1468 return MatchOperand_Success;
1471 Operands.push_back(AMDGPUOperand::CreateToken(Tok.getString(), Tok.getLoc()));
1473 return MatchOperand_Success;
1475 return MatchOperand_NoMatch;
1478 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
1479 // Clear any forced encodings from the previous instruction.
1480 setForcedEncodingSize(0);
1481 setForcedDPP(false);
1482 setForcedSDWA(false);
1484 if (Name.endswith("_e64")) {
1485 setForcedEncodingSize(64);
1486 return Name.substr(0, Name.size() - 4);
1487 } else if (Name.endswith("_e32")) {
1488 setForcedEncodingSize(32);
1489 return Name.substr(0, Name.size() - 4);
1490 } else if (Name.endswith("_dpp")) {
1492 return Name.substr(0, Name.size() - 4);
1493 } else if (Name.endswith("_sdwa")) {
1494 setForcedSDWA(true);
1495 return Name.substr(0, Name.size() - 5);
1500 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1502 SMLoc NameLoc, OperandVector &Operands) {
1503 // Add the instruction mnemonic
1504 Name = parseMnemonicSuffix(Name);
1505 Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
1507 while (!getLexer().is(AsmToken::EndOfStatement)) {
1508 AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
1510 // Eat the comma or space if there is one.
1511 if (getLexer().is(AsmToken::Comma))
1515 case MatchOperand_Success: break;
1516 case MatchOperand_ParseFail:
1517 Error(getLexer().getLoc(), "failed parsing operand.");
1518 while (!getLexer().is(AsmToken::EndOfStatement)) {
1522 case MatchOperand_NoMatch:
1523 Error(getLexer().getLoc(), "not a valid operand.");
1524 while (!getLexer().is(AsmToken::EndOfStatement)) {
1534 //===----------------------------------------------------------------------===//
1535 // Utility functions
1536 //===----------------------------------------------------------------------===//
1538 AMDGPUAsmParser::OperandMatchResultTy
1539 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
1540 switch(getLexer().getKind()) {
1541 default: return MatchOperand_NoMatch;
1542 case AsmToken::Identifier: {
1543 StringRef Name = Parser.getTok().getString();
1544 if (!Name.equals(Prefix)) {
1545 return MatchOperand_NoMatch;
1549 if (getLexer().isNot(AsmToken::Colon))
1550 return MatchOperand_ParseFail;
1553 if (getLexer().isNot(AsmToken::Integer))
1554 return MatchOperand_ParseFail;
1556 if (getParser().parseAbsoluteExpression(Int))
1557 return MatchOperand_ParseFail;
1561 return MatchOperand_Success;
1564 AMDGPUAsmParser::OperandMatchResultTy
1565 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1566 enum AMDGPUOperand::ImmTy ImmTy,
1567 bool (*ConvertResult)(int64_t&)) {
1569 SMLoc S = Parser.getTok().getLoc();
1572 AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
1573 if (Res != MatchOperand_Success)
1576 if (ConvertResult && !ConvertResult(Value)) {
1577 return MatchOperand_ParseFail;
1580 Operands.push_back(AMDGPUOperand::CreateImm(Value, S, ImmTy));
1581 return MatchOperand_Success;
1584 AMDGPUAsmParser::OperandMatchResultTy
1585 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
1586 enum AMDGPUOperand::ImmTy ImmTy) {
1588 SMLoc S = Parser.getTok().getLoc();
1590 // We are at the end of the statement, and this is a default argument, so
1591 // use a default value.
1592 if (getLexer().isNot(AsmToken::EndOfStatement)) {
1593 switch(getLexer().getKind()) {
1594 case AsmToken::Identifier: {
1595 StringRef Tok = Parser.getTok().getString();
1599 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
1603 return MatchOperand_NoMatch;
1608 return MatchOperand_NoMatch;
1612 Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy));
1613 return MatchOperand_Success;
1616 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
1618 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands,
1619 OptionalImmIndexMap& OptionalIdx,
1620 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) {
1621 auto i = OptionalIdx.find(ImmT);
1622 if (i != OptionalIdx.end()) {
1623 unsigned Idx = i->second;
1624 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
1626 Inst.addOperand(MCOperand::createImm(Default));
1630 AMDGPUAsmParser::OperandMatchResultTy
1631 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
1632 if (getLexer().isNot(AsmToken::Identifier)) {
1633 return MatchOperand_NoMatch;
1635 StringRef Tok = Parser.getTok().getString();
1636 if (Tok != Prefix) {
1637 return MatchOperand_NoMatch;
1641 if (getLexer().isNot(AsmToken::Colon)) {
1642 return MatchOperand_ParseFail;
1646 if (getLexer().isNot(AsmToken::Identifier)) {
1647 return MatchOperand_ParseFail;
1650 Value = Parser.getTok().getString();
1651 return MatchOperand_Success;
1654 //===----------------------------------------------------------------------===//
1656 //===----------------------------------------------------------------------===//
1658 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
1659 const OperandVector &Operands) {
1661 OptionalImmIndexMap OptionalIdx;
1663 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1664 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1666 // Add the register arguments
1668 Op.addRegOperands(Inst, 1);
1672 // Handle optional arguments
1673 OptionalIdx[Op.getImmTy()] = i;
1676 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
1677 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
1678 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1680 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1683 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
1685 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1686 bool GDSOnly = false;
1688 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1689 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1691 // Add the register arguments
1693 Op.addRegOperands(Inst, 1);
1697 if (Op.isToken() && Op.getToken() == "gds") {
1702 // Handle optional arguments
1703 OptionalIdx[Op.getImmTy()] = i;
1706 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
1707 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1710 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1712 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1716 //===----------------------------------------------------------------------===//
1718 //===----------------------------------------------------------------------===//
1720 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
1721 StringRef CntName = Parser.getTok().getString();
1725 if (getLexer().isNot(AsmToken::LParen))
1729 if (getLexer().isNot(AsmToken::Integer))
1732 if (getParser().parseAbsoluteExpression(CntVal))
1735 if (getLexer().isNot(AsmToken::RParen))
1739 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
1745 if (CntName == "vmcnt") {
1748 } else if (CntName == "expcnt") {
1751 } else if (CntName == "lgkmcnt") {
1758 IntVal &= ~(CntMask << CntShift);
1759 IntVal |= (CntVal << CntShift);
1763 AMDGPUAsmParser::OperandMatchResultTy
1764 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
1765 // Disable all counters by default.
1769 int64_t CntVal = 0xf7f;
1770 SMLoc S = Parser.getTok().getLoc();
1772 switch(getLexer().getKind()) {
1773 default: return MatchOperand_ParseFail;
1774 case AsmToken::Integer:
1775 // The operand can be an integer value.
1776 if (getParser().parseAbsoluteExpression(CntVal))
1777 return MatchOperand_ParseFail;
1780 case AsmToken::Identifier:
1782 if (parseCnt(CntVal))
1783 return MatchOperand_ParseFail;
1784 } while(getLexer().isNot(AsmToken::EndOfStatement));
1787 Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S));
1788 return MatchOperand_Success;
1791 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) {
1792 using namespace llvm::AMDGPU::Hwreg;
1794 if (Parser.getTok().getString() != "hwreg")
1798 if (getLexer().isNot(AsmToken::LParen))
1802 if (getLexer().is(AsmToken::Identifier)) {
1803 HwReg.IsSymbolic = true;
1804 HwReg.Id = ID_UNKNOWN_;
1805 const StringRef tok = Parser.getTok().getString();
1806 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
1807 if (tok == IdSymbolic[i]) {
1814 HwReg.IsSymbolic = false;
1815 if (getLexer().isNot(AsmToken::Integer))
1817 if (getParser().parseAbsoluteExpression(HwReg.Id))
1821 if (getLexer().is(AsmToken::RParen)) {
1827 if (getLexer().isNot(AsmToken::Comma))
1831 if (getLexer().isNot(AsmToken::Integer))
1833 if (getParser().parseAbsoluteExpression(Offset))
1836 if (getLexer().isNot(AsmToken::Comma))
1840 if (getLexer().isNot(AsmToken::Integer))
1842 if (getParser().parseAbsoluteExpression(Width))
1845 if (getLexer().isNot(AsmToken::RParen))
1852 AMDGPUAsmParser::OperandMatchResultTy
1853 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
1854 using namespace llvm::AMDGPU::Hwreg;
1856 int64_t Imm16Val = 0;
1857 SMLoc S = Parser.getTok().getLoc();
1859 switch(getLexer().getKind()) {
1860 default: return MatchOperand_NoMatch;
1861 case AsmToken::Integer:
1862 // The operand can be an integer value.
1863 if (getParser().parseAbsoluteExpression(Imm16Val))
1864 return MatchOperand_NoMatch;
1865 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
1866 Error(S, "invalid immediate: only 16-bit values are legal");
1867 // Do not return error code, but create an imm operand anyway and proceed
1868 // to the next operand, if any. That avoids unneccessary error messages.
1872 case AsmToken::Identifier: {
1873 OperandInfoTy HwReg(ID_UNKNOWN_);
1874 int64_t Offset = OFFSET_DEFAULT_;
1875 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
1876 if (parseHwregConstruct(HwReg, Offset, Width))
1877 return MatchOperand_ParseFail;
1878 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
1879 if (HwReg.IsSymbolic)
1880 Error(S, "invalid symbolic name of hardware register");
1882 Error(S, "invalid code of hardware register: only 6-bit values are legal");
1884 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
1885 Error(S, "invalid bit offset: only 5-bit values are legal");
1886 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
1887 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
1888 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
1892 Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
1893 return MatchOperand_Success;
1896 bool AMDGPUOperand::isSWaitCnt() const {
1900 bool AMDGPUOperand::isHwreg() const {
1901 return isImmTy(ImmTyHwreg);
1904 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
1905 using namespace llvm::AMDGPU::SendMsg;
1907 if (Parser.getTok().getString() != "sendmsg")
1911 if (getLexer().isNot(AsmToken::LParen))
1915 if (getLexer().is(AsmToken::Identifier)) {
1916 Msg.IsSymbolic = true;
1917 Msg.Id = ID_UNKNOWN_;
1918 const std::string tok = Parser.getTok().getString();
1919 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
1921 default: continue; // Omit gaps.
1922 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
1924 if (tok == IdSymbolic[i]) {
1931 Msg.IsSymbolic = false;
1932 if (getLexer().isNot(AsmToken::Integer))
1934 if (getParser().parseAbsoluteExpression(Msg.Id))
1936 if (getLexer().is(AsmToken::Integer))
1937 if (getParser().parseAbsoluteExpression(Msg.Id))
1938 Msg.Id = ID_UNKNOWN_;
1940 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
1943 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
1944 if (getLexer().isNot(AsmToken::RParen))
1950 if (getLexer().isNot(AsmToken::Comma))
1954 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
1955 Operation.Id = ID_UNKNOWN_;
1956 if (getLexer().is(AsmToken::Identifier)) {
1957 Operation.IsSymbolic = true;
1958 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
1959 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
1960 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
1961 const StringRef Tok = Parser.getTok().getString();
1962 for (int i = F; i < L; ++i) {
1970 Operation.IsSymbolic = false;
1971 if (getLexer().isNot(AsmToken::Integer))
1973 if (getParser().parseAbsoluteExpression(Operation.Id))
1977 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
1978 // Stream id is optional.
1979 if (getLexer().is(AsmToken::RParen)) {
1984 if (getLexer().isNot(AsmToken::Comma))
1988 if (getLexer().isNot(AsmToken::Integer))
1990 if (getParser().parseAbsoluteExpression(StreamId))
1994 if (getLexer().isNot(AsmToken::RParen))
2000 AMDGPUAsmParser::OperandMatchResultTy
2001 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
2002 using namespace llvm::AMDGPU::SendMsg;
2004 int64_t Imm16Val = 0;
2005 SMLoc S = Parser.getTok().getLoc();
2007 switch(getLexer().getKind()) {
2009 return MatchOperand_NoMatch;
2010 case AsmToken::Integer:
2011 // The operand can be an integer value.
2012 if (getParser().parseAbsoluteExpression(Imm16Val))
2013 return MatchOperand_NoMatch;
2014 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2015 Error(S, "invalid immediate: only 16-bit values are legal");
2016 // Do not return error code, but create an imm operand anyway and proceed
2017 // to the next operand, if any. That avoids unneccessary error messages.
2020 case AsmToken::Identifier: {
2021 OperandInfoTy Msg(ID_UNKNOWN_);
2022 OperandInfoTy Operation(OP_UNKNOWN_);
2023 int64_t StreamId = STREAM_ID_DEFAULT_;
2024 if (parseSendMsgConstruct(Msg, Operation, StreamId))
2025 return MatchOperand_ParseFail;
2027 // Validate and encode message ID.
2028 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
2029 || Msg.Id == ID_SYSMSG)) {
2031 Error(S, "invalid/unsupported symbolic name of message");
2033 Error(S, "invalid/unsupported code of message");
2036 Imm16Val = (Msg.Id << ID_SHIFT_);
2037 // Validate and encode operation ID.
2038 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
2039 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
2040 if (Operation.IsSymbolic)
2041 Error(S, "invalid symbolic name of GS_OP");
2043 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
2046 if (Operation.Id == OP_GS_NOP
2047 && Msg.Id != ID_GS_DONE) {
2048 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
2051 Imm16Val |= (Operation.Id << OP_SHIFT_);
2053 if (Msg.Id == ID_SYSMSG) {
2054 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
2055 if (Operation.IsSymbolic)
2056 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
2058 Error(S, "invalid/unsupported code of SYSMSG_OP");
2061 Imm16Val |= (Operation.Id << OP_SHIFT_);
2063 // Validate and encode stream ID.
2064 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2065 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
2066 Error(S, "invalid stream id: only 2-bit values are legal");
2069 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
2075 Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
2076 return MatchOperand_Success;
2079 bool AMDGPUOperand::isSendMsg() const {
2080 return isImmTy(ImmTySendMsg);
2083 //===----------------------------------------------------------------------===//
2084 // sopp branch targets
2085 //===----------------------------------------------------------------------===//
2087 AMDGPUAsmParser::OperandMatchResultTy
2088 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
2089 SMLoc S = Parser.getTok().getLoc();
2091 switch (getLexer().getKind()) {
2092 default: return MatchOperand_ParseFail;
2093 case AsmToken::Integer: {
2095 if (getParser().parseAbsoluteExpression(Imm))
2096 return MatchOperand_ParseFail;
2097 Operands.push_back(AMDGPUOperand::CreateImm(Imm, S));
2098 return MatchOperand_Success;
2101 case AsmToken::Identifier:
2102 Operands.push_back(AMDGPUOperand::CreateExpr(
2103 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
2104 Parser.getTok().getString()), getContext()), S));
2106 return MatchOperand_Success;
2110 //===----------------------------------------------------------------------===//
2112 //===----------------------------------------------------------------------===//
2114 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
2115 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyGLC);
2118 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
2119 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTySLC);
2122 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2123 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyTFE);
2126 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
2127 const OperandVector &Operands,
2128 bool IsAtomic, bool IsAtomicReturn) {
2129 OptionalImmIndexMap OptionalIdx;
2130 assert(IsAtomicReturn ? IsAtomic : true);
2132 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2133 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2135 // Add the register arguments
2137 Op.addRegOperands(Inst, 1);
2141 // Handle the case where soffset is an immediate
2142 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
2143 Op.addImmOperands(Inst, 1);
2147 // Handle tokens like 'offen' which are sometimes hard-coded into the
2148 // asm string. There are no MCInst operands for these.
2154 // Handle optional arguments
2155 OptionalIdx[Op.getImmTy()] = i;
2158 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2159 if (IsAtomicReturn) {
2160 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
2164 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2165 if (!IsAtomic) { // glc is hard-coded.
2166 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2168 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2169 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2172 //===----------------------------------------------------------------------===//
2174 //===----------------------------------------------------------------------===//
2176 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
2178 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2179 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2180 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2183 OptionalImmIndexMap OptionalIdx;
2185 for (unsigned E = Operands.size(); I != E; ++I) {
2186 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2188 // Add the register arguments
2189 if (Op.isRegOrImm()) {
2190 Op.addRegOrImmOperands(Inst, 1);
2192 } else if (Op.isImmModifier()) {
2193 OptionalIdx[Op.getImmTy()] = I;
2199 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2200 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2201 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2202 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2203 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2204 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2205 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2206 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2209 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
2211 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2212 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2213 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2216 // Add src, same as dst
2217 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
2219 OptionalImmIndexMap OptionalIdx;
2221 for (unsigned E = Operands.size(); I != E; ++I) {
2222 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2224 // Add the register arguments
2225 if (Op.isRegOrImm()) {
2226 Op.addRegOrImmOperands(Inst, 1);
2228 } else if (Op.isImmModifier()) {
2229 OptionalIdx[Op.getImmTy()] = I;
2235 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2236 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2237 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2238 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2239 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2240 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2241 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2242 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2245 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
2246 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDMask);
2249 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
2250 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
2253 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
2254 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDA);
2257 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
2258 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyR128);
2261 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
2262 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyLWE);
2265 //===----------------------------------------------------------------------===//
2267 //===----------------------------------------------------------------------===//
2269 bool AMDGPUOperand::isSMRDOffset() const {
2271 // FIXME: Support 20-bit offsets on VI. We need to to pass subtarget
2272 // information here.
2273 return isImm() && isUInt<8>(getImm());
2276 bool AMDGPUOperand::isSMRDLiteralOffset() const {
2277 // 32-bit literals are only supported on CI and we only want to use them
2278 // when the offset is > 8-bits.
2279 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
2282 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset() const {
2283 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyOffset);
2286 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
2287 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyOffset);
2290 //===----------------------------------------------------------------------===//
2292 //===----------------------------------------------------------------------===//
2294 static bool ConvertOmodMul(int64_t &Mul) {
2295 if (Mul != 1 && Mul != 2 && Mul != 4)
2302 static bool ConvertOmodDiv(int64_t &Div) {
2316 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
2317 if (BoundCtrl == 0) {
2320 } else if (BoundCtrl == -1) {
2327 // Note: the order in this table matches the order of operands in AsmString.
2328 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
2329 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
2330 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
2331 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
2332 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
2333 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
2334 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
2335 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
2336 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
2337 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
2338 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
2339 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
2340 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
2341 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
2342 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
2343 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
2344 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
2345 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
2346 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
2347 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
2348 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
2349 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
2350 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
2351 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
2352 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
2355 AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
2356 OperandMatchResultTy res;
2357 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
2358 // try to parse any optional operand here
2360 res = parseNamedBit(Op.Name, Operands, Op.Type);
2361 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
2362 res = parseOModOperand(Operands);
2363 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
2364 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
2365 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
2366 res = parseSDWASel(Operands, Op.Name, Op.Type);
2367 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
2368 res = parseSDWADstUnused(Operands);
2370 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
2372 if (res != MatchOperand_NoMatch) {
2376 return MatchOperand_NoMatch;
2379 AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands)
2381 StringRef Name = Parser.getTok().getString();
2382 if (Name == "mul") {
2383 return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
2384 } else if (Name == "div") {
2385 return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
2387 return MatchOperand_NoMatch;
2391 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
2393 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2394 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2395 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2397 for (unsigned E = Operands.size(); I != E; ++I)
2398 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
2401 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
2402 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2403 if (TSFlags & SIInstrFlags::VOP3) {
2404 cvtVOP3(Inst, Operands);
2406 cvtId(Inst, Operands);
2410 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
2411 OptionalImmIndexMap OptionalIdx;
2413 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2414 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2415 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2418 for (unsigned E = Operands.size(); I != E; ++I) {
2419 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2420 if (Op.isRegOrImmWithInputMods()) {
2421 // only fp modifiers allowed in VOP3
2422 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
2423 } else if (Op.isImm()) {
2424 OptionalIdx[Op.getImmTy()] = I;
2430 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
2431 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
2434 //===----------------------------------------------------------------------===//
2436 //===----------------------------------------------------------------------===//
2438 bool AMDGPUOperand::isDPPCtrl() const {
2439 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
2441 int64_t Imm = getImm();
2442 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
2443 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
2444 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
2445 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
2458 AMDGPUAsmParser::OperandMatchResultTy
2459 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
2460 SMLoc S = Parser.getTok().getLoc();
2464 if (getLexer().getKind() == AsmToken::Identifier) {
2465 Prefix = Parser.getTok().getString();
2467 return MatchOperand_NoMatch;
2470 if (Prefix == "row_mirror") {
2472 } else if (Prefix == "row_half_mirror") {
2475 // Check to prevent parseDPPCtrlOps from eating invalid tokens
2476 if (Prefix != "quad_perm"
2477 && Prefix != "row_shl"
2478 && Prefix != "row_shr"
2479 && Prefix != "row_ror"
2480 && Prefix != "wave_shl"
2481 && Prefix != "wave_rol"
2482 && Prefix != "wave_shr"
2483 && Prefix != "wave_ror"
2484 && Prefix != "row_bcast") {
2485 return MatchOperand_NoMatch;
2489 if (getLexer().isNot(AsmToken::Colon))
2490 return MatchOperand_ParseFail;
2492 if (Prefix == "quad_perm") {
2493 // quad_perm:[%d,%d,%d,%d]
2495 if (getLexer().isNot(AsmToken::LBrac))
2496 return MatchOperand_ParseFail;
2499 if (getLexer().isNot(AsmToken::Integer))
2500 return MatchOperand_ParseFail;
2501 Int = getLexer().getTok().getIntVal();
2504 if (getLexer().isNot(AsmToken::Comma))
2505 return MatchOperand_ParseFail;
2507 if (getLexer().isNot(AsmToken::Integer))
2508 return MatchOperand_ParseFail;
2509 Int += (getLexer().getTok().getIntVal() << 2);
2512 if (getLexer().isNot(AsmToken::Comma))
2513 return MatchOperand_ParseFail;
2515 if (getLexer().isNot(AsmToken::Integer))
2516 return MatchOperand_ParseFail;
2517 Int += (getLexer().getTok().getIntVal() << 4);
2520 if (getLexer().isNot(AsmToken::Comma))
2521 return MatchOperand_ParseFail;
2523 if (getLexer().isNot(AsmToken::Integer))
2524 return MatchOperand_ParseFail;
2525 Int += (getLexer().getTok().getIntVal() << 6);
2528 if (getLexer().isNot(AsmToken::RBrac))
2529 return MatchOperand_ParseFail;
2534 if (getLexer().isNot(AsmToken::Integer))
2535 return MatchOperand_ParseFail;
2536 Int = getLexer().getTok().getIntVal();
2538 if (Prefix == "row_shl") {
2540 } else if (Prefix == "row_shr") {
2542 } else if (Prefix == "row_ror") {
2544 } else if (Prefix == "wave_shl") {
2546 } else if (Prefix == "wave_rol") {
2548 } else if (Prefix == "wave_shr") {
2550 } else if (Prefix == "wave_ror") {
2552 } else if (Prefix == "row_bcast") {
2555 } else if (Int == 31) {
2558 return MatchOperand_ParseFail;
2561 return MatchOperand_ParseFail;
2565 Parser.Lex(); // eat last token
2567 Operands.push_back(AMDGPUOperand::CreateImm(Int, S,
2568 AMDGPUOperand::ImmTyDppCtrl));
2569 return MatchOperand_Success;
2572 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
2573 return AMDGPUOperand::CreateImm(0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
2576 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
2577 return AMDGPUOperand::CreateImm(0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
2580 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
2581 return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
2584 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
2585 OptionalImmIndexMap OptionalIdx;
2588 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2589 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2590 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2593 for (unsigned E = Operands.size(); I != E; ++I) {
2594 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2595 // Add the register arguments
2596 if (Op.isRegOrImmWithInputMods()) {
2597 // Only float modifiers supported in DPP
2598 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
2599 } else if (Op.isDPPCtrl()) {
2600 Op.addImmOperands(Inst, 1);
2601 } else if (Op.isImm()) {
2602 // Handle optional arguments
2603 OptionalIdx[Op.getImmTy()] = I;
2605 llvm_unreachable("Invalid operand type");
2609 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
2610 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
2611 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
2614 //===----------------------------------------------------------------------===//
2616 //===----------------------------------------------------------------------===//
2618 AMDGPUAsmParser::OperandMatchResultTy
2619 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
2620 AMDGPUOperand::ImmTy Type) {
2621 SMLoc S = Parser.getTok().getLoc();
2623 AMDGPUAsmParser::OperandMatchResultTy res;
2625 res = parseStringWithPrefix(Prefix, Value);
2626 if (res != MatchOperand_Success) {
2631 Int = StringSwitch<int64_t>(Value)
2639 .Default(0xffffffff);
2640 Parser.Lex(); // eat last token
2642 if (Int == 0xffffffff) {
2643 return MatchOperand_ParseFail;
2646 Operands.push_back(AMDGPUOperand::CreateImm(Int, S, Type));
2647 return MatchOperand_Success;
2650 AMDGPUAsmParser::OperandMatchResultTy
2651 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
2652 SMLoc S = Parser.getTok().getLoc();
2654 AMDGPUAsmParser::OperandMatchResultTy res;
2656 res = parseStringWithPrefix("dst_unused", Value);
2657 if (res != MatchOperand_Success) {
2662 Int = StringSwitch<int64_t>(Value)
2663 .Case("UNUSED_PAD", 0)
2664 .Case("UNUSED_SEXT", 1)
2665 .Case("UNUSED_PRESERVE", 2)
2666 .Default(0xffffffff);
2667 Parser.Lex(); // eat last token
2669 if (Int == 0xffffffff) {
2670 return MatchOperand_ParseFail;
2673 Operands.push_back(AMDGPUOperand::CreateImm(Int, S,
2674 AMDGPUOperand::ImmTySdwaDstUnused));
2675 return MatchOperand_Success;
2678 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
2679 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
2682 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
2683 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
2686 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
2687 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC);
2690 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
2691 uint64_t BasicInstType) {
2692 OptionalImmIndexMap OptionalIdx;
2695 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2696 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2697 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2700 for (unsigned E = Operands.size(); I != E; ++I) {
2701 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2702 // Add the register arguments
2703 if (BasicInstType == SIInstrFlags::VOPC &&
2705 Op.Reg.RegNo == AMDGPU::VCC) {
2706 // VOPC sdwa use "vcc" token as dst. Skip it.
2708 } else if (Op.isRegOrImmWithInputMods()) {
2709 Op.addRegOrImmWithInputModsOperands(Inst, 2);
2710 } else if (Op.isImm()) {
2711 // Handle optional arguments
2712 OptionalIdx[Op.getImmTy()] = I;
2714 llvm_unreachable("Invalid operand type");
2718 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
2720 if (Inst.getOpcode() == AMDGPU::V_NOP_sdwa) {
2721 // V_NOP_sdwa has no optional sdwa arguments
2724 switch (BasicInstType) {
2725 case SIInstrFlags::VOP1: {
2726 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2727 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2728 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2731 case SIInstrFlags::VOP2: {
2732 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2733 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2734 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2735 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
2738 case SIInstrFlags::VOPC: {
2739 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2740 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
2744 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
2748 /// Force static initialization.
2749 extern "C" void LLVMInitializeAMDGPUAsmParser() {
2750 RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
2751 RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget);
2754 #define GET_REGISTER_MATCHER
2755 #define GET_MATCHER_IMPLEMENTATION
2756 #include "AMDGPUGenAsmMatcher.inc"
2759 // This fuction should be defined after auto-generated include so that we have
2760 // MatchClassKind enum defined
2761 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
2763 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
2764 // But MatchInstructionImpl() expects to meet token and fails to validate
2765 // operand. This method checks if we are given immediate operand but expect to
2766 // get corresponding token.
2767 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
2770 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
2772 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
2774 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
2776 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
2778 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
2780 // When operands have expression values, they will return true for isToken,
2781 // because it is not possible to distinguish between a token and an
2782 // expression at parse time. MatchInstructionImpl() will always try to
2783 // match an operand as a token, when isToken returns true, and when the
2784 // name of the expression is not a valid token, the match will fail,
2785 // so we need to handle it here.
2786 return Operand.isSSrc32() ? Match_Success : Match_InvalidOperand;
2787 case MCK_SoppBrTarget:
2788 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
2789 default: return Match_InvalidOperand;