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/APInt.h"
19 #include "llvm/ADT/SmallBitVector.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/ADT/StringSwitch.h"
24 #include "llvm/ADT/Twine.h"
25 #include "llvm/CodeGen/MachineValueType.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCExpr.h"
29 #include "llvm/MC/MCInst.h"
30 #include "llvm/MC/MCInstrDesc.h"
31 #include "llvm/MC/MCInstrInfo.h"
32 #include "llvm/MC/MCParser/MCAsmLexer.h"
33 #include "llvm/MC/MCParser/MCAsmParser.h"
34 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
35 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
36 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
37 #include "llvm/MC/MCRegisterInfo.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSubtargetInfo.h"
40 #include "llvm/MC/MCSymbol.h"
41 #include "llvm/Support/Casting.h"
42 #include "llvm/Support/Debug.h"
43 #include "llvm/Support/ELF.h"
44 #include "llvm/Support/ErrorHandling.h"
45 #include "llvm/Support/MathExtras.h"
46 #include "llvm/Support/raw_ostream.h"
47 #include "llvm/Support/SMLoc.h"
48 #include "llvm/Support/TargetRegistry.h"
49 #include "llvm/Support/raw_ostream.h"
50 #include "llvm/Support/MathExtras.h"
62 using namespace llvm::AMDGPU;
66 class AMDGPUAsmParser;
68 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
70 //===----------------------------------------------------------------------===//
72 //===----------------------------------------------------------------------===//
74 class AMDGPUOperand : public MCParsedAsmOperand {
82 SMLoc StartLoc, EndLoc;
83 const AMDGPUAsmParser *AsmParser;
86 AMDGPUOperand(enum KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
87 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
89 typedef std::unique_ptr<AMDGPUOperand> Ptr;
96 bool hasFPModifiers() const { return Abs || Neg; }
97 bool hasIntModifiers() const { return Sext; }
98 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
100 int64_t getFPModifiersOperand() const {
102 Operand |= Abs ? SISrcMods::ABS : 0;
103 Operand |= Neg ? SISrcMods::NEG : 0;
107 int64_t getIntModifiersOperand() const {
109 Operand |= Sext ? SISrcMods::SEXT : 0;
113 int64_t getModifiersOperand() const {
114 assert(!(hasFPModifiers() && hasIntModifiers())
115 && "fp and int modifiers should not be used simultaneously");
116 if (hasFPModifiers()) {
117 return getFPModifiersOperand();
118 } else if (hasIntModifiers()) {
119 return getIntModifiersOperand();
125 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
191 bool isToken() const override {
195 if (Kind != Expression || !Expr)
198 // When parsing operands, we can't always tell if something was meant to be
199 // a token, like 'gds', or an expression that references a global variable.
200 // In this case, we assume the string is an expression, and if we need to
201 // interpret is a token, then we treat the symbol name as the token.
202 return isa<MCSymbolRefExpr>(Expr);
205 bool isImm() const override {
206 return Kind == Immediate;
209 bool isInlinableImm(MVT type) const;
210 bool isLiteralImm(MVT type) const;
212 bool isRegKind() const {
213 return Kind == Register;
216 bool isReg() const override {
217 return isRegKind() && !Reg.Mods.hasModifiers();
220 bool isRegOrImmWithInputMods(MVT type) const {
221 return isRegKind() || isInlinableImm(type);
224 bool isRegOrImmWithInt16InputMods() const {
225 return isRegOrImmWithInputMods(MVT::i16);
228 bool isRegOrImmWithInt32InputMods() const {
229 return isRegOrImmWithInputMods(MVT::i32);
232 bool isRegOrImmWithInt64InputMods() const {
233 return isRegOrImmWithInputMods(MVT::i64);
236 bool isRegOrImmWithFP16InputMods() const {
237 return isRegOrImmWithInputMods(MVT::f16);
240 bool isRegOrImmWithFP32InputMods() const {
241 return isRegOrImmWithInputMods(MVT::f32);
244 bool isRegOrImmWithFP64InputMods() const {
245 return isRegOrImmWithInputMods(MVT::f64);
248 bool isVReg32OrOff() const {
249 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
252 bool isImmTy(ImmTy ImmT) const {
253 return isImm() && Imm.Type == ImmT;
256 bool isImmModifier() const {
257 return isImm() && Imm.Type != ImmTyNone;
260 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
261 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
262 bool isDMask() const { return isImmTy(ImmTyDMask); }
263 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
264 bool isDA() const { return isImmTy(ImmTyDA); }
265 bool isR128() const { return isImmTy(ImmTyUNorm); }
266 bool isLWE() const { return isImmTy(ImmTyLWE); }
267 bool isOff() const { return isImmTy(ImmTyOff); }
268 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
269 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
270 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
271 bool isOffen() const { return isImmTy(ImmTyOffen); }
272 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
273 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
274 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
275 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
276 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
277 bool isGDS() const { return isImmTy(ImmTyGDS); }
278 bool isGLC() const { return isImmTy(ImmTyGLC); }
279 bool isSLC() const { return isImmTy(ImmTySLC); }
280 bool isTFE() const { return isImmTy(ImmTyTFE); }
281 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
282 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
283 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
284 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
285 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
286 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
287 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
288 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
289 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
290 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
293 return isClampSI() || isOModSI();
296 bool isRegOrImm() const {
297 return isReg() || isImm();
300 bool isRegClass(unsigned RCID) const;
302 bool isSCSrcB16() const {
303 return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::i16);
306 bool isSCSrcB32() const {
307 return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::i32);
310 bool isSCSrcB64() const {
311 return isRegClass(AMDGPU::SReg_64RegClassID) || isInlinableImm(MVT::i64);
314 bool isSCSrcF16() const {
315 return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::f16);
318 bool isSCSrcF32() const {
319 return isRegClass(AMDGPU::SReg_32RegClassID) || isInlinableImm(MVT::f32);
322 bool isSCSrcF64() const {
323 return isRegClass(AMDGPU::SReg_64RegClassID) || isInlinableImm(MVT::f64);
326 bool isSSrcB32() const {
327 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
330 bool isSSrcB16() const {
331 return isSCSrcB16() || isLiteralImm(MVT::i16);
334 bool isSSrcB64() const {
335 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
337 return isSCSrcB64() || isLiteralImm(MVT::i64);
340 bool isSSrcF32() const {
341 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
344 bool isSSrcF64() const {
345 return isSCSrcB64() || isLiteralImm(MVT::f64);
348 bool isSSrcF16() const {
349 return isSCSrcB16() || isLiteralImm(MVT::f16);
352 bool isVCSrcB32() const {
353 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::i32);
356 bool isVCSrcB64() const {
357 return isRegClass(AMDGPU::VS_64RegClassID) || isInlinableImm(MVT::i64);
360 bool isVCSrcB16() const {
361 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::i16);
364 bool isVCSrcF32() const {
365 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::f32);
368 bool isVCSrcF64() const {
369 return isRegClass(AMDGPU::VS_64RegClassID) || isInlinableImm(MVT::f64);
372 bool isVCSrcF16() const {
373 return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(MVT::f16);
376 bool isVSrcB32() const {
377 return isVCSrcF32() || isLiteralImm(MVT::i32);
380 bool isVSrcB64() const {
381 return isVCSrcF64() || isLiteralImm(MVT::i64);
384 bool isVSrcB16() const {
385 return isVCSrcF16() || isLiteralImm(MVT::i16);
388 bool isVSrcF32() const {
389 return isVCSrcF32() || isLiteralImm(MVT::f32);
392 bool isVSrcF64() const {
393 return isVCSrcF64() || isLiteralImm(MVT::f64);
396 bool isVSrcF16() const {
397 return isVCSrcF16() || isLiteralImm(MVT::f16);
400 bool isKImmFP32() const {
401 return isLiteralImm(MVT::f32);
404 bool isKImmFP16() const {
405 return isLiteralImm(MVT::f16);
408 bool isMem() const override {
412 bool isExpr() const {
413 return Kind == Expression;
416 bool isSoppBrTarget() const {
417 return isExpr() || isImm();
420 bool isSWaitCnt() const;
421 bool isHwreg() const;
422 bool isSendMsg() const;
423 bool isSMRDOffset8() const;
424 bool isSMRDOffset20() const;
425 bool isSMRDLiteralOffset() const;
426 bool isDPPCtrl() const;
427 bool isGPRIdxMode() const;
429 StringRef getExpressionAsToken() const {
431 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
432 return S->getSymbol().getName();
435 StringRef getToken() const {
438 if (Kind == Expression)
439 return getExpressionAsToken();
441 return StringRef(Tok.Data, Tok.Length);
444 int64_t getImm() const {
449 enum ImmTy getImmTy() const {
454 unsigned getReg() const override {
458 SMLoc getStartLoc() const override {
462 SMLoc getEndLoc() const override {
466 Modifiers getModifiers() const {
467 assert(isRegKind() || isImmTy(ImmTyNone));
468 return isRegKind() ? Reg.Mods : Imm.Mods;
471 void setModifiers(Modifiers Mods) {
472 assert(isRegKind() || isImmTy(ImmTyNone));
479 bool hasModifiers() const {
480 return getModifiers().hasModifiers();
483 bool hasFPModifiers() const {
484 return getModifiers().hasFPModifiers();
487 bool hasIntModifiers() const {
488 return getModifiers().hasIntModifiers();
491 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
493 void addLiteralImmOperand(MCInst &Inst, int64_t Val) const;
495 template <unsigned Bitwidth>
496 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
498 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
499 addKImmFPOperands<16>(Inst, N);
502 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
503 addKImmFPOperands<32>(Inst, N);
506 void addRegOperands(MCInst &Inst, unsigned N) const;
508 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
510 addRegOperands(Inst, N);
512 Inst.addOperand(MCOperand::createExpr(Expr));
514 addImmOperands(Inst, N);
517 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
518 Modifiers Mods = getModifiers();
519 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
521 addRegOperands(Inst, N);
523 addImmOperands(Inst, N, false);
527 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
528 assert(!hasIntModifiers());
529 addRegOrImmWithInputModsOperands(Inst, N);
532 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
533 assert(!hasFPModifiers());
534 addRegOrImmWithInputModsOperands(Inst, N);
537 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
539 addImmOperands(Inst, N);
542 Inst.addOperand(MCOperand::createExpr(Expr));
546 static void printImmTy(raw_ostream& OS, ImmTy Type) {
548 case ImmTyNone: OS << "None"; break;
549 case ImmTyGDS: OS << "GDS"; break;
550 case ImmTyOffen: OS << "Offen"; break;
551 case ImmTyIdxen: OS << "Idxen"; break;
552 case ImmTyAddr64: OS << "Addr64"; break;
553 case ImmTyOffset: OS << "Offset"; break;
554 case ImmTyOffset0: OS << "Offset0"; break;
555 case ImmTyOffset1: OS << "Offset1"; break;
556 case ImmTyGLC: OS << "GLC"; break;
557 case ImmTySLC: OS << "SLC"; break;
558 case ImmTyTFE: OS << "TFE"; break;
559 case ImmTyClampSI: OS << "ClampSI"; break;
560 case ImmTyOModSI: OS << "OModSI"; break;
561 case ImmTyDppCtrl: OS << "DppCtrl"; break;
562 case ImmTyDppRowMask: OS << "DppRowMask"; break;
563 case ImmTyDppBankMask: OS << "DppBankMask"; break;
564 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
565 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
566 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
567 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
568 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
569 case ImmTyDMask: OS << "DMask"; break;
570 case ImmTyUNorm: OS << "UNorm"; break;
571 case ImmTyDA: OS << "DA"; break;
572 case ImmTyR128: OS << "R128"; break;
573 case ImmTyLWE: OS << "LWE"; break;
574 case ImmTyOff: OS << "Off"; break;
575 case ImmTyExpTgt: OS << "ExpTgt"; break;
576 case ImmTyExpCompr: OS << "ExpCompr"; break;
577 case ImmTyExpVM: OS << "ExpVM"; break;
578 case ImmTyHwreg: OS << "Hwreg"; break;
579 case ImmTySendMsg: OS << "SendMsg"; break;
580 case ImmTyInterpSlot: OS << "InterpSlot"; break;
581 case ImmTyInterpAttr: OS << "InterpAttr"; break;
582 case ImmTyAttrChan: OS << "AttrChan"; break;
586 void print(raw_ostream &OS) const override {
589 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
592 OS << '<' << getImm();
593 if (getImmTy() != ImmTyNone) {
594 OS << " type: "; printImmTy(OS, getImmTy());
596 OS << " mods: " << Imm.Mods << '>';
599 OS << '\'' << getToken() << '\'';
602 OS << "<expr " << *Expr << '>';
607 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
608 int64_t Val, SMLoc Loc,
609 enum ImmTy Type = ImmTyNone,
610 bool IsFPImm = false) {
611 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
613 Op->Imm.IsFPImm = IsFPImm;
615 Op->Imm.Mods = Modifiers();
621 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
622 StringRef Str, SMLoc Loc,
623 bool HasExplicitEncodingSize = true) {
624 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
625 Res->Tok.Data = Str.data();
626 Res->Tok.Length = Str.size();
632 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
633 unsigned RegNo, SMLoc S,
636 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
637 Op->Reg.RegNo = RegNo;
638 Op->Reg.Mods = Modifiers();
639 Op->Reg.IsForcedVOP3 = ForceVOP3;
645 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
646 const class MCExpr *Expr, SMLoc S) {
647 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
655 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
656 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
660 //===----------------------------------------------------------------------===//
662 //===----------------------------------------------------------------------===//
664 // Holds info related to the current kernel, e.g. count of SGPRs used.
665 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
666 // .amdgpu_hsa_kernel or at EOF.
667 class KernelScopeInfo {
668 int SgprIndexUnusedMin;
669 int VgprIndexUnusedMin;
672 void usesSgprAt(int i) {
673 if (i >= SgprIndexUnusedMin) {
674 SgprIndexUnusedMin = ++i;
676 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
677 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
681 void usesVgprAt(int i) {
682 if (i >= VgprIndexUnusedMin) {
683 VgprIndexUnusedMin = ++i;
685 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
686 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
691 KernelScopeInfo() : SgprIndexUnusedMin(-1), VgprIndexUnusedMin(-1), Ctx(nullptr)
693 void initialize(MCContext &Context) {
695 usesSgprAt(SgprIndexUnusedMin = -1);
696 usesVgprAt(VgprIndexUnusedMin = -1);
698 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
700 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
701 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
707 class AMDGPUAsmParser : public MCTargetAsmParser {
708 const MCInstrInfo &MII;
711 unsigned ForcedEncodingSize;
714 KernelScopeInfo KernelScope;
716 /// @name Auto-generated Match Functions
719 #define GET_ASSEMBLER_HEADER
720 #include "AMDGPUGenAsmMatcher.inc"
725 bool ParseAsAbsoluteExpression(uint32_t &Ret);
726 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
727 bool ParseDirectiveHSACodeObjectVersion();
728 bool ParseDirectiveHSACodeObjectISA();
729 bool ParseDirectiveRuntimeMetadata();
730 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
731 bool ParseDirectiveAMDKernelCodeT();
732 bool ParseSectionDirectiveHSAText();
733 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
734 bool ParseDirectiveAMDGPUHsaKernel();
735 bool ParseDirectiveAMDGPUHsaModuleGlobal();
736 bool ParseDirectiveAMDGPUHsaProgramGlobal();
737 bool ParseSectionDirectiveHSADataGlobalAgent();
738 bool ParseSectionDirectiveHSADataGlobalProgram();
739 bool ParseSectionDirectiveHSARodataReadonlyAgent();
740 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
741 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex);
742 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
745 enum AMDGPUMatchResultTy {
746 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
749 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
750 const MCInstrInfo &MII,
751 const MCTargetOptions &Options)
752 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
753 ForcedEncodingSize(0),
756 MCAsmParserExtension::Initialize(Parser);
758 if (getSTI().getFeatureBits().none()) {
759 // Set default features.
760 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
763 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
766 // TODO: make those pre-defined variables read-only.
767 // Currently there is none suitable machinery in the core llvm-mc for this.
768 // MCSymbol::isRedefinable is intended for another purpose, and
769 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
770 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
771 MCContext &Ctx = getContext();
772 MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
773 Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx));
774 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
775 Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx));
776 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
777 Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx));
779 KernelScope.initialize(getContext());
783 return AMDGPU::isSI(getSTI());
787 return AMDGPU::isCI(getSTI());
791 return AMDGPU::isVI(getSTI());
794 bool hasInv2PiInlineImm() const {
795 return getSTI().getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
798 bool hasSGPR102_SGPR103() const {
802 AMDGPUTargetStreamer &getTargetStreamer() {
803 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
804 return static_cast<AMDGPUTargetStreamer &>(TS);
807 const MCRegisterInfo *getMRI() const {
808 // We need this const_cast because for some reason getContext() is not const
810 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
813 const MCInstrInfo *getMII() const {
817 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
818 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
819 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
821 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
822 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
823 bool isForcedDPP() const { return ForcedDPP; }
824 bool isForcedSDWA() const { return ForcedSDWA; }
826 std::unique_ptr<AMDGPUOperand> parseRegister();
827 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
828 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
829 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
830 unsigned Kind) override;
831 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
832 OperandVector &Operands, MCStreamer &Out,
834 bool MatchingInlineAsm) override;
835 bool ParseDirective(AsmToken DirectiveID) override;
836 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
837 StringRef parseMnemonicSuffix(StringRef Name);
838 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
839 SMLoc NameLoc, OperandVector &Operands) override;
840 //bool ProcessInstruction(MCInst &Inst);
842 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
844 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
845 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
846 bool (*ConvertResult)(int64_t &) = nullptr);
848 parseNamedBit(const char *Name, OperandVector &Operands,
849 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
850 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
853 OperandMatchResultTy parseImm(OperandVector &Operands);
854 OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
855 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands);
856 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands);
857 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
859 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
860 void cvtDS(MCInst &Inst, const OperandVector &Operands);
861 void cvtExp(MCInst &Inst, const OperandVector &Operands);
863 bool parseCnt(int64_t &IntVal);
864 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
865 OperandMatchResultTy parseHwreg(OperandVector &Operands);
868 struct OperandInfoTy {
871 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
874 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
875 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
878 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
881 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
883 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
884 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
885 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
886 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
887 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
889 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
890 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
891 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
892 AMDGPUOperand::Ptr defaultGLC() const;
893 AMDGPUOperand::Ptr defaultSLC() const;
894 AMDGPUOperand::Ptr defaultTFE() const;
896 AMDGPUOperand::Ptr defaultDMask() const;
897 AMDGPUOperand::Ptr defaultUNorm() const;
898 AMDGPUOperand::Ptr defaultDA() const;
899 AMDGPUOperand::Ptr defaultR128() const;
900 AMDGPUOperand::Ptr defaultLWE() const;
901 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
902 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
903 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
905 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
907 void cvtId(MCInst &Inst, const OperandVector &Operands);
908 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
909 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
911 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
912 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
914 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
915 AMDGPUOperand::Ptr defaultRowMask() const;
916 AMDGPUOperand::Ptr defaultBankMask() const;
917 AMDGPUOperand::Ptr defaultBoundCtrl() const;
918 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
920 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
921 AMDGPUOperand::ImmTy Type);
922 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
923 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
924 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
925 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
926 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
927 uint64_t BasicInstType);
930 struct OptionalOperand {
932 AMDGPUOperand::ImmTy Type;
934 bool (*ConvertResult)(int64_t&);
937 } // end anonymous namespace
939 // May be called with integer type with equivalent bitwidth.
940 static const fltSemantics *getFltSemantics(unsigned Size) {
943 return &APFloat::IEEEsingle();
945 return &APFloat::IEEEdouble();
947 return &APFloat::IEEEhalf();
949 llvm_unreachable("unsupported fp type");
953 static const fltSemantics *getFltSemantics(MVT VT) {
954 return getFltSemantics(VT.getSizeInBits() / 8);
957 //===----------------------------------------------------------------------===//
959 //===----------------------------------------------------------------------===//
961 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
964 // Convert literal to single precision
965 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
966 APFloat::rmNearestTiesToEven,
968 // We allow precision lost but not overflow or underflow
969 if (Status != APFloat::opOK &&
971 ((Status & APFloat::opOverflow) != 0 ||
972 (Status & APFloat::opUnderflow) != 0)) {
979 bool AMDGPUOperand::isInlinableImm(MVT type) const {
980 if (!isImmTy(ImmTyNone)) {
981 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
984 // TODO: We should avoid using host float here. It would be better to
985 // check the float bit values which is what a few other places do.
986 // We've had bot failures before due to weird NaN support on mips hosts.
988 APInt Literal(64, Imm.Val);
990 if (Imm.IsFPImm) { // We got fp literal token
991 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
992 return AMDGPU::isInlinableLiteral64(Imm.Val,
993 AsmParser->hasInv2PiInlineImm());
996 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
997 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1000 // Check if single precision literal is inlinable
1001 return AMDGPU::isInlinableLiteral32(
1002 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1003 AsmParser->hasInv2PiInlineImm());
1007 // We got int literal token.
1008 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1009 return AMDGPU::isInlinableLiteral64(Imm.Val,
1010 AsmParser->hasInv2PiInlineImm());
1013 if (type.getScalarSizeInBits() == 16) {
1014 return AMDGPU::isInlinableLiteral16(
1015 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1016 AsmParser->hasInv2PiInlineImm());
1019 return AMDGPU::isInlinableLiteral32(
1020 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1021 AsmParser->hasInv2PiInlineImm());
1024 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1025 // Check that this imediate can be added as literal
1026 if (!isImmTy(ImmTyNone)) {
1031 // We got int literal token.
1033 unsigned Size = type.getSizeInBits();
1037 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1039 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1042 // We got fp literal token
1043 if (type == MVT::f64) { // Expected 64-bit fp operand
1044 // We would set low 64-bits of literal to zeroes but we accept this literals
1048 if (type == MVT::i64) { // Expected 64-bit int operand
1049 // We don't allow fp literals in 64-bit integer instructions. It is
1050 // unclear how we should encode them.
1054 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1055 return canLosslesslyConvertToFPType(FPLiteral, type);
1058 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1059 return isReg() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1062 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1063 int64_t Val = Imm.Val;
1064 if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers() && Imm.Mods.Neg) {
1065 // Apply modifiers to immediate value. Only negate can get here
1067 APFloat F(BitsToDouble(Val));
1069 Val = F.bitcastToAPInt().getZExtValue();
1075 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1076 Inst.getNumOperands())) {
1077 addLiteralImmOperand(Inst, Val);
1079 Inst.addOperand(MCOperand::createImm(Val));
1083 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val) const {
1084 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1085 auto OpNum = Inst.getNumOperands();
1086 // Check that this operand accepts literals
1087 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1089 auto OpSize = AMDGPU::getOperandSize(InstDesc, OpNum); // expected operand size
1091 if (Imm.IsFPImm) { // We got fp literal token
1092 APInt Literal(64, Val);
1096 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1097 AsmParser->hasInv2PiInlineImm())) {
1098 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1103 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1104 // For fp operands we check if low 32 bits are zeros
1105 if (Literal.getLoBits(32) != 0) {
1106 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1107 "Can't encode literal as exact 64-bit floating-point operand. "
1108 "Low 32-bits will be set to zero");
1111 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1115 // We don't allow fp literals in 64-bit integer instructions. It is
1116 // unclear how we should encode them. This case should be checked earlier
1117 // in predicate methods (isLiteralImm())
1118 llvm_unreachable("fp literal in 64-bit integer instruction.");
1123 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1124 // Convert literal to single precision
1125 FPLiteral.convert(*getFltSemantics(OpSize),
1126 APFloat::rmNearestTiesToEven, &lost);
1127 // We allow precision lost but not overflow or underflow. This should be
1128 // checked earlier in isLiteralImm()
1129 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1133 llvm_unreachable("invalid operand size");
1139 // We got int literal token.
1140 // Only sign extend inline immediates.
1141 // FIXME: No errors on truncation
1144 if (isInt<32>(Val) &&
1145 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1146 AsmParser->hasInv2PiInlineImm())) {
1147 Inst.addOperand(MCOperand::createImm(Val));
1151 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1155 if (AMDGPU::isInlinableLiteral64(Val,
1156 AsmParser->hasInv2PiInlineImm())) {
1157 Inst.addOperand(MCOperand::createImm(Val));
1161 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1165 if (isInt<16>(Val) &&
1166 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1167 AsmParser->hasInv2PiInlineImm())) {
1168 Inst.addOperand(MCOperand::createImm(Val));
1172 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1176 llvm_unreachable("invalid operand size");
1180 template <unsigned Bitwidth>
1181 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1182 APInt Literal(64, Imm.Val);
1185 // We got int literal token.
1186 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1191 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1192 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1193 APFloat::rmNearestTiesToEven, &Lost);
1194 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1197 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1198 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1201 //===----------------------------------------------------------------------===//
1203 //===----------------------------------------------------------------------===//
1205 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1206 if (Is == IS_VGPR) {
1209 case 1: return AMDGPU::VGPR_32RegClassID;
1210 case 2: return AMDGPU::VReg_64RegClassID;
1211 case 3: return AMDGPU::VReg_96RegClassID;
1212 case 4: return AMDGPU::VReg_128RegClassID;
1213 case 8: return AMDGPU::VReg_256RegClassID;
1214 case 16: return AMDGPU::VReg_512RegClassID;
1216 } else if (Is == IS_TTMP) {
1219 case 1: return AMDGPU::TTMP_32RegClassID;
1220 case 2: return AMDGPU::TTMP_64RegClassID;
1221 case 4: return AMDGPU::TTMP_128RegClassID;
1223 } else if (Is == IS_SGPR) {
1226 case 1: return AMDGPU::SGPR_32RegClassID;
1227 case 2: return AMDGPU::SGPR_64RegClassID;
1228 case 4: return AMDGPU::SGPR_128RegClassID;
1229 case 8: return AMDGPU::SReg_256RegClassID;
1230 case 16: return AMDGPU::SReg_512RegClassID;
1236 static unsigned getSpecialRegForName(StringRef RegName) {
1237 return StringSwitch<unsigned>(RegName)
1238 .Case("exec", AMDGPU::EXEC)
1239 .Case("vcc", AMDGPU::VCC)
1240 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1241 .Case("m0", AMDGPU::M0)
1242 .Case("scc", AMDGPU::SCC)
1243 .Case("tba", AMDGPU::TBA)
1244 .Case("tma", AMDGPU::TMA)
1245 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1246 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1247 .Case("vcc_lo", AMDGPU::VCC_LO)
1248 .Case("vcc_hi", AMDGPU::VCC_HI)
1249 .Case("exec_lo", AMDGPU::EXEC_LO)
1250 .Case("exec_hi", AMDGPU::EXEC_HI)
1251 .Case("tma_lo", AMDGPU::TMA_LO)
1252 .Case("tma_hi", AMDGPU::TMA_HI)
1253 .Case("tba_lo", AMDGPU::TBA_LO)
1254 .Case("tba_hi", AMDGPU::TBA_HI)
1258 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
1259 auto R = parseRegister();
1260 if (!R) return true;
1262 RegNo = R->getReg();
1263 StartLoc = R->getStartLoc();
1264 EndLoc = R->getEndLoc();
1268 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum)
1272 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; }
1273 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; }
1274 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; }
1275 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; }
1276 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; }
1281 if (Reg1 != Reg + RegWidth) { return false; }
1285 llvm_unreachable("unexpected register kind");
1289 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex)
1291 if (DwordRegIndex) { *DwordRegIndex = 0; }
1292 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1293 if (getLexer().is(AsmToken::Identifier)) {
1294 StringRef RegName = Parser.getTok().getString();
1295 if ((Reg = getSpecialRegForName(RegName))) {
1297 RegKind = IS_SPECIAL;
1299 unsigned RegNumIndex = 0;
1300 if (RegName[0] == 'v') {
1303 } else if (RegName[0] == 's') {
1306 } else if (RegName.startswith("ttmp")) {
1307 RegNumIndex = strlen("ttmp");
1312 if (RegName.size() > RegNumIndex) {
1313 // Single 32-bit register: vXX.
1314 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1319 // Range of registers: v[XX:YY]. ":YY" is optional.
1321 int64_t RegLo, RegHi;
1322 if (getLexer().isNot(AsmToken::LBrac))
1326 if (getParser().parseAbsoluteExpression(RegLo))
1329 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1330 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1337 if (getParser().parseAbsoluteExpression(RegHi))
1340 if (getLexer().isNot(AsmToken::RBrac))
1344 RegNum = (unsigned) RegLo;
1345 RegWidth = (RegHi - RegLo) + 1;
1348 } else if (getLexer().is(AsmToken::LBrac)) {
1349 // List of consecutive registers: [s0,s1,s2,s3]
1351 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1355 RegisterKind RegKind1;
1356 unsigned Reg1, RegNum1, RegWidth1;
1358 if (getLexer().is(AsmToken::Comma)) {
1360 } else if (getLexer().is(AsmToken::RBrac)) {
1363 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1364 if (RegWidth1 != 1) {
1367 if (RegKind1 != RegKind) {
1370 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1390 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1391 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1392 Size = std::min(RegWidth, 4u);
1394 if (RegNum % Size != 0)
1396 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1397 RegNum = RegNum / Size;
1398 int RCID = getRegClass(RegKind, RegWidth);
1401 const MCRegisterClass RC = TRI->getRegClass(RCID);
1402 if (RegNum >= RC.getNumRegs())
1404 Reg = RC.getRegister(RegNum);
1409 llvm_unreachable("unexpected register kind");
1412 if (!subtargetHasRegister(*TRI, Reg))
1417 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1418 const auto &Tok = Parser.getTok();
1419 SMLoc StartLoc = Tok.getLoc();
1420 SMLoc EndLoc = Tok.getEndLoc();
1421 RegisterKind RegKind;
1422 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1424 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1427 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1428 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1431 OperandMatchResultTy
1432 AMDGPUAsmParser::parseImm(OperandVector &Operands) {
1433 // TODO: add syntactic sugar for 1/(2*PI)
1435 if (getLexer().getKind() == AsmToken::Minus) {
1440 SMLoc S = Parser.getTok().getLoc();
1441 switch(getLexer().getKind()) {
1442 case AsmToken::Integer: {
1444 if (getParser().parseAbsoluteExpression(IntVal))
1445 return MatchOperand_ParseFail;
1448 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1449 return MatchOperand_Success;
1451 case AsmToken::Real: {
1453 if (getParser().parseAbsoluteExpression(IntVal))
1454 return MatchOperand_ParseFail;
1456 APFloat F(BitsToDouble(IntVal));
1460 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1461 AMDGPUOperand::ImmTyNone, true));
1462 return MatchOperand_Success;
1465 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1469 OperandMatchResultTy
1470 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) {
1471 auto res = parseImm(Operands);
1472 if (res != MatchOperand_NoMatch) {
1476 if (auto R = parseRegister()) {
1478 R->Reg.IsForcedVOP3 = isForcedVOP3();
1479 Operands.push_back(std::move(R));
1480 return MatchOperand_Success;
1482 return MatchOperand_ParseFail;
1485 OperandMatchResultTy
1486 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands) {
1487 // XXX: During parsing we can't determine if minus sign means
1488 // negate-modifier or negative immediate value.
1489 // By default we suppose it is modifier.
1490 bool Negate = false, Abs = false, Abs2 = false;
1492 if (getLexer().getKind()== AsmToken::Minus) {
1497 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") {
1500 if (getLexer().isNot(AsmToken::LParen)) {
1501 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1502 return MatchOperand_ParseFail;
1507 if (getLexer().getKind() == AsmToken::Pipe) {
1509 Error(Parser.getTok().getLoc(), "expected register or immediate");
1510 return MatchOperand_ParseFail;
1516 auto Res = parseRegOrImm(Operands);
1517 if (Res != MatchOperand_Success) {
1521 AMDGPUOperand::Modifiers Mods;
1526 if (getLexer().getKind() != AsmToken::Pipe) {
1527 Error(Parser.getTok().getLoc(), "expected vertical bar");
1528 return MatchOperand_ParseFail;
1534 if (getLexer().isNot(AsmToken::RParen)) {
1535 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1536 return MatchOperand_ParseFail;
1542 if (Mods.hasFPModifiers()) {
1543 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1544 Op.setModifiers(Mods);
1546 return MatchOperand_Success;
1549 OperandMatchResultTy
1550 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands) {
1553 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") {
1556 if (getLexer().isNot(AsmToken::LParen)) {
1557 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1558 return MatchOperand_ParseFail;
1563 auto Res = parseRegOrImm(Operands);
1564 if (Res != MatchOperand_Success) {
1568 AMDGPUOperand::Modifiers Mods;
1570 if (getLexer().isNot(AsmToken::RParen)) {
1571 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1572 return MatchOperand_ParseFail;
1578 if (Mods.hasIntModifiers()) {
1579 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1580 Op.setModifiers(Mods);
1583 return MatchOperand_Success;
1586 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1587 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1589 Operands.push_back(std::move(Reg));
1590 return MatchOperand_Success;
1593 const AsmToken &Tok = Parser.getTok();
1594 if (Tok.getString() == "off") {
1595 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1596 AMDGPUOperand::ImmTyOff, false));
1598 return MatchOperand_Success;
1601 return MatchOperand_NoMatch;
1604 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1606 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1608 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1609 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1610 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1611 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1612 return Match_InvalidOperand;
1614 if ((TSFlags & SIInstrFlags::VOP3) &&
1615 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1616 getForcedEncodingSize() != 64)
1617 return Match_PreferE32;
1619 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1620 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1621 // v_mac_f32/16 allow only dst_sel == DWORD;
1623 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1624 const auto &Op = Inst.getOperand(OpNum);
1625 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1626 return Match_InvalidOperand;
1630 return Match_Success;
1633 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1634 OperandVector &Operands,
1636 uint64_t &ErrorInfo,
1637 bool MatchingInlineAsm) {
1638 // What asm variants we should check
1639 std::vector<unsigned> MatchedVariants;
1640 if (getForcedEncodingSize() == 32) {
1641 MatchedVariants = {AMDGPUAsmVariants::DEFAULT};
1642 } else if (isForcedVOP3()) {
1643 MatchedVariants = {AMDGPUAsmVariants::VOP3};
1644 } else if (isForcedSDWA()) {
1645 MatchedVariants = {AMDGPUAsmVariants::SDWA};
1646 } else if (isForcedDPP()) {
1647 MatchedVariants = {AMDGPUAsmVariants::DPP};
1649 MatchedVariants = {AMDGPUAsmVariants::DEFAULT,
1650 AMDGPUAsmVariants::VOP3,
1651 AMDGPUAsmVariants::SDWA,
1652 AMDGPUAsmVariants::DPP};
1656 unsigned Result = Match_Success;
1657 for (auto Variant : MatchedVariants) {
1659 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
1661 // We order match statuses from least to most specific. We use most specific
1662 // status as resulting
1663 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
1664 if ((R == Match_Success) ||
1665 (R == Match_PreferE32) ||
1666 (R == Match_MissingFeature && Result != Match_PreferE32) ||
1667 (R == Match_InvalidOperand && Result != Match_MissingFeature
1668 && Result != Match_PreferE32) ||
1669 (R == Match_MnemonicFail && Result != Match_InvalidOperand
1670 && Result != Match_MissingFeature
1671 && Result != Match_PreferE32)) {
1675 if (R == Match_Success)
1683 Out.EmitInstruction(Inst, getSTI());
1686 case Match_MissingFeature:
1687 return Error(IDLoc, "instruction not supported on this GPU");
1689 case Match_MnemonicFail:
1690 return Error(IDLoc, "unrecognized instruction mnemonic");
1692 case Match_InvalidOperand: {
1693 SMLoc ErrorLoc = IDLoc;
1694 if (ErrorInfo != ~0ULL) {
1695 if (ErrorInfo >= Operands.size()) {
1696 return Error(IDLoc, "too few operands for instruction");
1698 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
1699 if (ErrorLoc == SMLoc())
1702 return Error(ErrorLoc, "invalid operand for instruction");
1705 case Match_PreferE32:
1706 return Error(IDLoc, "internal error: instruction without _e64 suffix "
1707 "should be encoded as e32");
1709 llvm_unreachable("Implement any new match types added!");
1712 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
1714 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
1717 if (getParser().parseAbsoluteExpression(Tmp)) {
1720 Ret = static_cast<uint32_t>(Tmp);
1725 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
1727 if (ParseAsAbsoluteExpression(Major))
1728 return TokError("invalid major version");
1730 if (getLexer().isNot(AsmToken::Comma))
1731 return TokError("minor version number required, comma expected");
1734 if (ParseAsAbsoluteExpression(Minor))
1735 return TokError("invalid minor version");
1740 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
1745 if (ParseDirectiveMajorMinor(Major, Minor))
1748 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
1752 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
1756 StringRef VendorName;
1759 // If this directive has no arguments, then use the ISA version for the
1761 if (getLexer().is(AsmToken::EndOfStatement)) {
1762 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
1763 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
1769 if (ParseDirectiveMajorMinor(Major, Minor))
1772 if (getLexer().isNot(AsmToken::Comma))
1773 return TokError("stepping version number required, comma expected");
1776 if (ParseAsAbsoluteExpression(Stepping))
1777 return TokError("invalid stepping version");
1779 if (getLexer().isNot(AsmToken::Comma))
1780 return TokError("vendor name required, comma expected");
1783 if (getLexer().isNot(AsmToken::String))
1784 return TokError("invalid vendor name");
1786 VendorName = getLexer().getTok().getStringContents();
1789 if (getLexer().isNot(AsmToken::Comma))
1790 return TokError("arch name required, comma expected");
1793 if (getLexer().isNot(AsmToken::String))
1794 return TokError("invalid arch name");
1796 ArchName = getLexer().getTok().getStringContents();
1799 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
1800 VendorName, ArchName);
1804 bool AMDGPUAsmParser::ParseDirectiveRuntimeMetadata() {
1805 std::string Metadata;
1806 raw_string_ostream MS(Metadata);
1808 getLexer().setSkipSpace(false);
1810 bool FoundEnd = false;
1811 while (!getLexer().is(AsmToken::Eof)) {
1812 while (getLexer().is(AsmToken::Space)) {
1817 if (getLexer().is(AsmToken::Identifier)) {
1818 StringRef ID = getLexer().getTok().getIdentifier();
1819 if (ID == ".end_amdgpu_runtime_metadata") {
1826 MS << Parser.parseStringToEndOfStatement()
1827 << getContext().getAsmInfo()->getSeparatorString();
1829 Parser.eatToEndOfStatement();
1832 getLexer().setSkipSpace(true);
1834 if (getLexer().is(AsmToken::Eof) && !FoundEnd)
1835 return TokError("expected directive .end_amdgpu_runtime_metadata not found");
1839 getTargetStreamer().EmitRuntimeMetadata(Metadata);
1844 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
1845 amd_kernel_code_t &Header) {
1846 SmallString<40> ErrStr;
1847 raw_svector_ostream Err(ErrStr);
1848 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
1849 return TokError(Err.str());
1855 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
1856 amd_kernel_code_t Header;
1857 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits());
1860 // Lex EndOfStatement. This is in a while loop, because lexing a comment
1861 // will set the current token to EndOfStatement.
1862 while(getLexer().is(AsmToken::EndOfStatement))
1865 if (getLexer().isNot(AsmToken::Identifier))
1866 return TokError("expected value identifier or .end_amd_kernel_code_t");
1868 StringRef ID = getLexer().getTok().getIdentifier();
1871 if (ID == ".end_amd_kernel_code_t")
1874 if (ParseAMDKernelCodeTValue(ID, Header))
1878 getTargetStreamer().EmitAMDKernelCodeT(Header);
1883 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
1884 getParser().getStreamer().SwitchSection(
1885 AMDGPU::getHSATextSection(getContext()));
1889 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
1890 if (getLexer().isNot(AsmToken::Identifier))
1891 return TokError("expected symbol name");
1893 StringRef KernelName = Parser.getTok().getString();
1895 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
1896 ELF::STT_AMDGPU_HSA_KERNEL);
1898 KernelScope.initialize(getContext());
1902 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
1903 if (getLexer().isNot(AsmToken::Identifier))
1904 return TokError("expected symbol name");
1906 StringRef GlobalName = Parser.getTok().getIdentifier();
1908 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
1913 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
1914 if (getLexer().isNot(AsmToken::Identifier))
1915 return TokError("expected symbol name");
1917 StringRef GlobalName = Parser.getTok().getIdentifier();
1919 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
1924 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
1925 getParser().getStreamer().SwitchSection(
1926 AMDGPU::getHSADataGlobalAgentSection(getContext()));
1930 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
1931 getParser().getStreamer().SwitchSection(
1932 AMDGPU::getHSADataGlobalProgramSection(getContext()));
1936 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
1937 getParser().getStreamer().SwitchSection(
1938 AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
1942 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
1943 StringRef IDVal = DirectiveID.getString();
1945 if (IDVal == ".hsa_code_object_version")
1946 return ParseDirectiveHSACodeObjectVersion();
1948 if (IDVal == ".hsa_code_object_isa")
1949 return ParseDirectiveHSACodeObjectISA();
1951 if (IDVal == ".amdgpu_runtime_metadata")
1952 return ParseDirectiveRuntimeMetadata();
1954 if (IDVal == ".amd_kernel_code_t")
1955 return ParseDirectiveAMDKernelCodeT();
1957 if (IDVal == ".hsatext")
1958 return ParseSectionDirectiveHSAText();
1960 if (IDVal == ".amdgpu_hsa_kernel")
1961 return ParseDirectiveAMDGPUHsaKernel();
1963 if (IDVal == ".amdgpu_hsa_module_global")
1964 return ParseDirectiveAMDGPUHsaModuleGlobal();
1966 if (IDVal == ".amdgpu_hsa_program_global")
1967 return ParseDirectiveAMDGPUHsaProgramGlobal();
1969 if (IDVal == ".hsadata_global_agent")
1970 return ParseSectionDirectiveHSADataGlobalAgent();
1972 if (IDVal == ".hsadata_global_program")
1973 return ParseSectionDirectiveHSADataGlobalProgram();
1975 if (IDVal == ".hsarodata_readonly_agent")
1976 return ParseSectionDirectiveHSARodataReadonlyAgent();
1981 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
1982 unsigned RegNo) const {
1989 case AMDGPU::FLAT_SCR:
1990 case AMDGPU::FLAT_SCR_LO:
1991 case AMDGPU::FLAT_SCR_HI:
1998 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2000 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2009 OperandMatchResultTy
2010 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2012 // Try to parse with a custom parser
2013 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2015 // If we successfully parsed the operand or if there as an error parsing,
2018 // If we are parsing after we reach EndOfStatement then this means we
2019 // are appending default values to the Operands list. This is only done
2020 // by custom parser, so we shouldn't continue on to the generic parsing.
2021 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2022 getLexer().is(AsmToken::EndOfStatement))
2025 ResTy = parseRegOrImm(Operands);
2027 if (ResTy == MatchOperand_Success)
2030 if (getLexer().getKind() == AsmToken::Identifier) {
2031 // If this identifier is a symbol, we want to create an expression for it.
2032 // It is a little difficult to distinguish between a symbol name, and
2033 // an instruction flag like 'gds'. In order to do this, we parse
2034 // all tokens as expressions and then treate the symbol name as the token
2035 // string when we want to interpret the operand as a token.
2036 const auto &Tok = Parser.getTok();
2037 SMLoc S = Tok.getLoc();
2038 const MCExpr *Expr = nullptr;
2039 if (!Parser.parseExpression(Expr)) {
2040 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2041 return MatchOperand_Success;
2044 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2046 return MatchOperand_Success;
2048 return MatchOperand_NoMatch;
2051 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2052 // Clear any forced encodings from the previous instruction.
2053 setForcedEncodingSize(0);
2054 setForcedDPP(false);
2055 setForcedSDWA(false);
2057 if (Name.endswith("_e64")) {
2058 setForcedEncodingSize(64);
2059 return Name.substr(0, Name.size() - 4);
2060 } else if (Name.endswith("_e32")) {
2061 setForcedEncodingSize(32);
2062 return Name.substr(0, Name.size() - 4);
2063 } else if (Name.endswith("_dpp")) {
2065 return Name.substr(0, Name.size() - 4);
2066 } else if (Name.endswith("_sdwa")) {
2067 setForcedSDWA(true);
2068 return Name.substr(0, Name.size() - 5);
2073 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2075 SMLoc NameLoc, OperandVector &Operands) {
2076 // Add the instruction mnemonic
2077 Name = parseMnemonicSuffix(Name);
2078 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2080 while (!getLexer().is(AsmToken::EndOfStatement)) {
2081 OperandMatchResultTy Res = parseOperand(Operands, Name);
2083 // Eat the comma or space if there is one.
2084 if (getLexer().is(AsmToken::Comma))
2088 case MatchOperand_Success: break;
2089 case MatchOperand_ParseFail:
2090 Error(getLexer().getLoc(), "failed parsing operand.");
2091 while (!getLexer().is(AsmToken::EndOfStatement)) {
2095 case MatchOperand_NoMatch:
2096 Error(getLexer().getLoc(), "not a valid operand.");
2097 while (!getLexer().is(AsmToken::EndOfStatement)) {
2107 //===----------------------------------------------------------------------===//
2108 // Utility functions
2109 //===----------------------------------------------------------------------===//
2111 OperandMatchResultTy
2112 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2113 switch(getLexer().getKind()) {
2114 default: return MatchOperand_NoMatch;
2115 case AsmToken::Identifier: {
2116 StringRef Name = Parser.getTok().getString();
2117 if (!Name.equals(Prefix)) {
2118 return MatchOperand_NoMatch;
2122 if (getLexer().isNot(AsmToken::Colon))
2123 return MatchOperand_ParseFail;
2126 if (getLexer().isNot(AsmToken::Integer))
2127 return MatchOperand_ParseFail;
2129 if (getParser().parseAbsoluteExpression(Int))
2130 return MatchOperand_ParseFail;
2134 return MatchOperand_Success;
2137 OperandMatchResultTy
2138 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2139 enum AMDGPUOperand::ImmTy ImmTy,
2140 bool (*ConvertResult)(int64_t&)) {
2141 SMLoc S = Parser.getTok().getLoc();
2144 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2145 if (Res != MatchOperand_Success)
2148 if (ConvertResult && !ConvertResult(Value)) {
2149 return MatchOperand_ParseFail;
2152 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2153 return MatchOperand_Success;
2156 OperandMatchResultTy
2157 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2158 enum AMDGPUOperand::ImmTy ImmTy) {
2160 SMLoc S = Parser.getTok().getLoc();
2162 // We are at the end of the statement, and this is a default argument, so
2163 // use a default value.
2164 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2165 switch(getLexer().getKind()) {
2166 case AsmToken::Identifier: {
2167 StringRef Tok = Parser.getTok().getString();
2171 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2175 return MatchOperand_NoMatch;
2180 return MatchOperand_NoMatch;
2184 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2185 return MatchOperand_Success;
2188 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
2190 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands,
2191 OptionalImmIndexMap& OptionalIdx,
2192 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) {
2193 auto i = OptionalIdx.find(ImmT);
2194 if (i != OptionalIdx.end()) {
2195 unsigned Idx = i->second;
2196 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2198 Inst.addOperand(MCOperand::createImm(Default));
2202 OperandMatchResultTy
2203 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2204 if (getLexer().isNot(AsmToken::Identifier)) {
2205 return MatchOperand_NoMatch;
2207 StringRef Tok = Parser.getTok().getString();
2208 if (Tok != Prefix) {
2209 return MatchOperand_NoMatch;
2213 if (getLexer().isNot(AsmToken::Colon)) {
2214 return MatchOperand_ParseFail;
2218 if (getLexer().isNot(AsmToken::Identifier)) {
2219 return MatchOperand_ParseFail;
2222 Value = Parser.getTok().getString();
2223 return MatchOperand_Success;
2226 //===----------------------------------------------------------------------===//
2228 //===----------------------------------------------------------------------===//
2230 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2231 const OperandVector &Operands) {
2232 OptionalImmIndexMap OptionalIdx;
2234 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2235 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2237 // Add the register arguments
2239 Op.addRegOperands(Inst, 1);
2243 // Handle optional arguments
2244 OptionalIdx[Op.getImmTy()] = i;
2247 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2248 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2249 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2251 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2254 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
2255 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
2256 bool GDSOnly = false;
2258 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2259 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2261 // Add the register arguments
2263 Op.addRegOperands(Inst, 1);
2267 if (Op.isToken() && Op.getToken() == "gds") {
2272 // Handle optional arguments
2273 OptionalIdx[Op.getImmTy()] = i;
2276 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2277 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2280 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2282 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2285 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2286 OptionalImmIndexMap OptionalIdx;
2288 unsigned EnMask = 0;
2291 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2292 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2294 // Add the register arguments
2296 EnMask |= (1 << SrcIdx);
2297 Op.addRegOperands(Inst, 1);
2304 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2308 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2309 Op.addImmOperands(Inst, 1);
2313 if (Op.isToken() && Op.getToken() == "done")
2316 // Handle optional arguments
2317 OptionalIdx[Op.getImmTy()] = i;
2320 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2321 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2323 Inst.addOperand(MCOperand::createImm(EnMask));
2326 //===----------------------------------------------------------------------===//
2328 //===----------------------------------------------------------------------===//
2330 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2331 StringRef CntName = Parser.getTok().getString();
2335 if (getLexer().isNot(AsmToken::LParen))
2339 if (getLexer().isNot(AsmToken::Integer))
2342 if (getParser().parseAbsoluteExpression(CntVal))
2345 if (getLexer().isNot(AsmToken::RParen))
2349 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
2352 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2353 if (CntName == "vmcnt")
2354 IntVal = encodeVmcnt(IV, IntVal, CntVal);
2355 else if (CntName == "expcnt")
2356 IntVal = encodeExpcnt(IV, IntVal, CntVal);
2357 else if (CntName == "lgkmcnt")
2358 IntVal = encodeLgkmcnt(IV, IntVal, CntVal);
2365 OperandMatchResultTy
2366 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2367 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2368 int64_t Waitcnt = getWaitcntBitMask(IV);
2369 SMLoc S = Parser.getTok().getLoc();
2371 switch(getLexer().getKind()) {
2372 default: return MatchOperand_ParseFail;
2373 case AsmToken::Integer:
2374 // The operand can be an integer value.
2375 if (getParser().parseAbsoluteExpression(Waitcnt))
2376 return MatchOperand_ParseFail;
2379 case AsmToken::Identifier:
2381 if (parseCnt(Waitcnt))
2382 return MatchOperand_ParseFail;
2383 } while(getLexer().isNot(AsmToken::EndOfStatement));
2386 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
2387 return MatchOperand_Success;
2390 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) {
2391 using namespace llvm::AMDGPU::Hwreg;
2393 if (Parser.getTok().getString() != "hwreg")
2397 if (getLexer().isNot(AsmToken::LParen))
2401 if (getLexer().is(AsmToken::Identifier)) {
2402 HwReg.IsSymbolic = true;
2403 HwReg.Id = ID_UNKNOWN_;
2404 const StringRef tok = Parser.getTok().getString();
2405 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
2406 if (tok == IdSymbolic[i]) {
2413 HwReg.IsSymbolic = false;
2414 if (getLexer().isNot(AsmToken::Integer))
2416 if (getParser().parseAbsoluteExpression(HwReg.Id))
2420 if (getLexer().is(AsmToken::RParen)) {
2426 if (getLexer().isNot(AsmToken::Comma))
2430 if (getLexer().isNot(AsmToken::Integer))
2432 if (getParser().parseAbsoluteExpression(Offset))
2435 if (getLexer().isNot(AsmToken::Comma))
2439 if (getLexer().isNot(AsmToken::Integer))
2441 if (getParser().parseAbsoluteExpression(Width))
2444 if (getLexer().isNot(AsmToken::RParen))
2451 OperandMatchResultTy
2452 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
2453 using namespace llvm::AMDGPU::Hwreg;
2455 int64_t Imm16Val = 0;
2456 SMLoc S = Parser.getTok().getLoc();
2458 switch(getLexer().getKind()) {
2459 default: return MatchOperand_NoMatch;
2460 case AsmToken::Integer:
2461 // The operand can be an integer value.
2462 if (getParser().parseAbsoluteExpression(Imm16Val))
2463 return MatchOperand_NoMatch;
2464 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2465 Error(S, "invalid immediate: only 16-bit values are legal");
2466 // Do not return error code, but create an imm operand anyway and proceed
2467 // to the next operand, if any. That avoids unneccessary error messages.
2471 case AsmToken::Identifier: {
2472 OperandInfoTy HwReg(ID_UNKNOWN_);
2473 int64_t Offset = OFFSET_DEFAULT_;
2474 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
2475 if (parseHwregConstruct(HwReg, Offset, Width))
2476 return MatchOperand_ParseFail;
2477 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
2478 if (HwReg.IsSymbolic)
2479 Error(S, "invalid symbolic name of hardware register");
2481 Error(S, "invalid code of hardware register: only 6-bit values are legal");
2483 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
2484 Error(S, "invalid bit offset: only 5-bit values are legal");
2485 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
2486 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
2487 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
2491 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
2492 return MatchOperand_Success;
2495 bool AMDGPUOperand::isSWaitCnt() const {
2499 bool AMDGPUOperand::isHwreg() const {
2500 return isImmTy(ImmTyHwreg);
2503 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
2504 using namespace llvm::AMDGPU::SendMsg;
2506 if (Parser.getTok().getString() != "sendmsg")
2510 if (getLexer().isNot(AsmToken::LParen))
2514 if (getLexer().is(AsmToken::Identifier)) {
2515 Msg.IsSymbolic = true;
2516 Msg.Id = ID_UNKNOWN_;
2517 const std::string tok = Parser.getTok().getString();
2518 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
2520 default: continue; // Omit gaps.
2521 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
2523 if (tok == IdSymbolic[i]) {
2530 Msg.IsSymbolic = false;
2531 if (getLexer().isNot(AsmToken::Integer))
2533 if (getParser().parseAbsoluteExpression(Msg.Id))
2535 if (getLexer().is(AsmToken::Integer))
2536 if (getParser().parseAbsoluteExpression(Msg.Id))
2537 Msg.Id = ID_UNKNOWN_;
2539 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
2542 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
2543 if (getLexer().isNot(AsmToken::RParen))
2549 if (getLexer().isNot(AsmToken::Comma))
2553 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
2554 Operation.Id = ID_UNKNOWN_;
2555 if (getLexer().is(AsmToken::Identifier)) {
2556 Operation.IsSymbolic = true;
2557 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
2558 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
2559 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
2560 const StringRef Tok = Parser.getTok().getString();
2561 for (int i = F; i < L; ++i) {
2569 Operation.IsSymbolic = false;
2570 if (getLexer().isNot(AsmToken::Integer))
2572 if (getParser().parseAbsoluteExpression(Operation.Id))
2576 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2577 // Stream id is optional.
2578 if (getLexer().is(AsmToken::RParen)) {
2583 if (getLexer().isNot(AsmToken::Comma))
2587 if (getLexer().isNot(AsmToken::Integer))
2589 if (getParser().parseAbsoluteExpression(StreamId))
2593 if (getLexer().isNot(AsmToken::RParen))
2599 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
2600 if (getLexer().getKind() != AsmToken::Identifier)
2601 return MatchOperand_NoMatch;
2603 StringRef Str = Parser.getTok().getString();
2604 int Slot = StringSwitch<int>(Str)
2610 SMLoc S = Parser.getTok().getLoc();
2612 return MatchOperand_ParseFail;
2615 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
2616 AMDGPUOperand::ImmTyInterpSlot));
2617 return MatchOperand_Success;
2620 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
2621 if (getLexer().getKind() != AsmToken::Identifier)
2622 return MatchOperand_NoMatch;
2624 StringRef Str = Parser.getTok().getString();
2625 if (!Str.startswith("attr"))
2626 return MatchOperand_NoMatch;
2628 StringRef Chan = Str.take_back(2);
2629 int AttrChan = StringSwitch<int>(Chan)
2636 return MatchOperand_ParseFail;
2638 Str = Str.drop_back(2).drop_front(4);
2641 if (Str.getAsInteger(10, Attr))
2642 return MatchOperand_ParseFail;
2644 SMLoc S = Parser.getTok().getLoc();
2647 Error(S, "out of bounds attr");
2648 return MatchOperand_Success;
2651 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
2653 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
2654 AMDGPUOperand::ImmTyInterpAttr));
2655 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
2656 AMDGPUOperand::ImmTyAttrChan));
2657 return MatchOperand_Success;
2660 void AMDGPUAsmParser::errorExpTgt() {
2661 Error(Parser.getTok().getLoc(), "invalid exp target");
2664 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
2666 if (Str == "null") {
2668 return MatchOperand_Success;
2671 if (Str.startswith("mrt")) {
2672 Str = Str.drop_front(3);
2673 if (Str == "z") { // == mrtz
2675 return MatchOperand_Success;
2678 if (Str.getAsInteger(10, Val))
2679 return MatchOperand_ParseFail;
2684 return MatchOperand_Success;
2687 if (Str.startswith("pos")) {
2688 Str = Str.drop_front(3);
2689 if (Str.getAsInteger(10, Val))
2690 return MatchOperand_ParseFail;
2696 return MatchOperand_Success;
2699 if (Str.startswith("param")) {
2700 Str = Str.drop_front(5);
2701 if (Str.getAsInteger(10, Val))
2702 return MatchOperand_ParseFail;
2708 return MatchOperand_Success;
2711 if (Str.startswith("invalid_target_")) {
2712 Str = Str.drop_front(15);
2713 if (Str.getAsInteger(10, Val))
2714 return MatchOperand_ParseFail;
2717 return MatchOperand_Success;
2720 return MatchOperand_NoMatch;
2723 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
2725 StringRef Str = Parser.getTok().getString();
2727 auto Res = parseExpTgtImpl(Str, Val);
2728 if (Res != MatchOperand_Success)
2731 SMLoc S = Parser.getTok().getLoc();
2734 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
2735 AMDGPUOperand::ImmTyExpTgt));
2736 return MatchOperand_Success;
2739 OperandMatchResultTy
2740 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
2741 using namespace llvm::AMDGPU::SendMsg;
2743 int64_t Imm16Val = 0;
2744 SMLoc S = Parser.getTok().getLoc();
2746 switch(getLexer().getKind()) {
2748 return MatchOperand_NoMatch;
2749 case AsmToken::Integer:
2750 // The operand can be an integer value.
2751 if (getParser().parseAbsoluteExpression(Imm16Val))
2752 return MatchOperand_NoMatch;
2753 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2754 Error(S, "invalid immediate: only 16-bit values are legal");
2755 // Do not return error code, but create an imm operand anyway and proceed
2756 // to the next operand, if any. That avoids unneccessary error messages.
2759 case AsmToken::Identifier: {
2760 OperandInfoTy Msg(ID_UNKNOWN_);
2761 OperandInfoTy Operation(OP_UNKNOWN_);
2762 int64_t StreamId = STREAM_ID_DEFAULT_;
2763 if (parseSendMsgConstruct(Msg, Operation, StreamId))
2764 return MatchOperand_ParseFail;
2766 // Validate and encode message ID.
2767 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
2768 || Msg.Id == ID_SYSMSG)) {
2770 Error(S, "invalid/unsupported symbolic name of message");
2772 Error(S, "invalid/unsupported code of message");
2775 Imm16Val = (Msg.Id << ID_SHIFT_);
2776 // Validate and encode operation ID.
2777 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
2778 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
2779 if (Operation.IsSymbolic)
2780 Error(S, "invalid symbolic name of GS_OP");
2782 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
2785 if (Operation.Id == OP_GS_NOP
2786 && Msg.Id != ID_GS_DONE) {
2787 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
2790 Imm16Val |= (Operation.Id << OP_SHIFT_);
2792 if (Msg.Id == ID_SYSMSG) {
2793 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
2794 if (Operation.IsSymbolic)
2795 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
2797 Error(S, "invalid/unsupported code of SYSMSG_OP");
2800 Imm16Val |= (Operation.Id << OP_SHIFT_);
2802 // Validate and encode stream ID.
2803 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2804 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
2805 Error(S, "invalid stream id: only 2-bit values are legal");
2808 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
2814 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
2815 return MatchOperand_Success;
2818 bool AMDGPUOperand::isSendMsg() const {
2819 return isImmTy(ImmTySendMsg);
2822 //===----------------------------------------------------------------------===//
2823 // sopp branch targets
2824 //===----------------------------------------------------------------------===//
2826 OperandMatchResultTy
2827 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
2828 SMLoc S = Parser.getTok().getLoc();
2830 switch (getLexer().getKind()) {
2831 default: return MatchOperand_ParseFail;
2832 case AsmToken::Integer: {
2834 if (getParser().parseAbsoluteExpression(Imm))
2835 return MatchOperand_ParseFail;
2836 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
2837 return MatchOperand_Success;
2840 case AsmToken::Identifier:
2841 Operands.push_back(AMDGPUOperand::CreateExpr(this,
2842 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
2843 Parser.getTok().getString()), getContext()), S));
2845 return MatchOperand_Success;
2849 //===----------------------------------------------------------------------===//
2851 //===----------------------------------------------------------------------===//
2853 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
2854 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
2857 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
2858 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
2861 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2862 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
2865 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
2866 const OperandVector &Operands,
2867 bool IsAtomic, bool IsAtomicReturn) {
2868 OptionalImmIndexMap OptionalIdx;
2869 assert(IsAtomicReturn ? IsAtomic : true);
2871 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2872 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2874 // Add the register arguments
2876 Op.addRegOperands(Inst, 1);
2880 // Handle the case where soffset is an immediate
2881 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
2882 Op.addImmOperands(Inst, 1);
2886 // Handle tokens like 'offen' which are sometimes hard-coded into the
2887 // asm string. There are no MCInst operands for these.
2893 // Handle optional arguments
2894 OptionalIdx[Op.getImmTy()] = i;
2897 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2898 if (IsAtomicReturn) {
2899 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
2903 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2904 if (!IsAtomic) { // glc is hard-coded.
2905 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2907 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2908 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2911 //===----------------------------------------------------------------------===//
2913 //===----------------------------------------------------------------------===//
2915 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
2917 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2918 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2919 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2922 OptionalImmIndexMap OptionalIdx;
2924 for (unsigned E = Operands.size(); I != E; ++I) {
2925 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2927 // Add the register arguments
2928 if (Op.isRegOrImm()) {
2929 Op.addRegOrImmOperands(Inst, 1);
2931 } else if (Op.isImmModifier()) {
2932 OptionalIdx[Op.getImmTy()] = I;
2934 llvm_unreachable("unexpected operand type");
2938 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2939 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2940 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2941 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2942 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2943 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2944 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2945 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2948 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
2950 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2951 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2952 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2955 // Add src, same as dst
2956 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
2958 OptionalImmIndexMap OptionalIdx;
2960 for (unsigned E = Operands.size(); I != E; ++I) {
2961 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2963 // Add the register arguments
2964 if (Op.isRegOrImm()) {
2965 Op.addRegOrImmOperands(Inst, 1);
2967 } else if (Op.isImmModifier()) {
2968 OptionalIdx[Op.getImmTy()] = I;
2970 llvm_unreachable("unexpected operand type");
2974 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2975 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2976 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2977 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2978 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2979 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2980 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2981 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2984 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
2985 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
2988 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
2989 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
2992 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
2993 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
2996 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
2997 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3000 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3001 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3004 //===----------------------------------------------------------------------===//
3006 //===----------------------------------------------------------------------===//
3008 bool AMDGPUOperand::isSMRDOffset8() const {
3009 return isImm() && isUInt<8>(getImm());
3012 bool AMDGPUOperand::isSMRDOffset20() const {
3013 return isImm() && isUInt<20>(getImm());
3016 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3017 // 32-bit literals are only supported on CI and we only want to use them
3018 // when the offset is > 8-bits.
3019 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3022 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3023 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3026 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3027 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3030 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3031 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3034 //===----------------------------------------------------------------------===//
3036 //===----------------------------------------------------------------------===//
3038 static bool ConvertOmodMul(int64_t &Mul) {
3039 if (Mul != 1 && Mul != 2 && Mul != 4)
3046 static bool ConvertOmodDiv(int64_t &Div) {
3060 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
3061 if (BoundCtrl == 0) {
3066 if (BoundCtrl == -1) {
3074 // Note: the order in this table matches the order of operands in AsmString.
3075 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
3076 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
3077 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
3078 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
3079 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
3080 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
3081 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
3082 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
3083 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
3084 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
3085 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
3086 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
3087 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
3088 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
3089 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
3090 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
3091 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
3092 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
3093 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
3094 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
3095 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
3096 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
3097 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
3098 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
3099 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
3100 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
3103 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
3104 OperandMatchResultTy res;
3105 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
3106 // try to parse any optional operand here
3108 res = parseNamedBit(Op.Name, Operands, Op.Type);
3109 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
3110 res = parseOModOperand(Operands);
3111 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
3112 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
3113 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
3114 res = parseSDWASel(Operands, Op.Name, Op.Type);
3115 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
3116 res = parseSDWADstUnused(Operands);
3118 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
3120 if (res != MatchOperand_NoMatch) {
3124 return MatchOperand_NoMatch;
3127 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
3128 StringRef Name = Parser.getTok().getString();
3129 if (Name == "mul") {
3130 return parseIntWithPrefix("mul", Operands,
3131 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
3134 if (Name == "div") {
3135 return parseIntWithPrefix("div", Operands,
3136 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
3139 return MatchOperand_NoMatch;
3142 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
3144 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3145 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3146 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3148 for (unsigned E = Operands.size(); I != E; ++I)
3149 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
3152 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
3153 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3154 if (TSFlags & SIInstrFlags::VOP3) {
3155 cvtVOP3(Inst, Operands);
3157 cvtId(Inst, Operands);
3161 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
3162 // 1. This operand is input modifiers
3163 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
3164 // 2. This is not last operand
3165 && Desc.NumOperands > (OpNum + 1)
3166 // 3. Next operand is register class
3167 && Desc.OpInfo[OpNum + 1].RegClass != -1
3168 // 4. Next register is not tied to any other operand
3169 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
3172 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
3173 OptionalImmIndexMap OptionalIdx;
3175 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3176 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3177 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3180 for (unsigned E = Operands.size(); I != E; ++I) {
3181 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3182 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3183 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
3184 } else if (Op.isImm()) {
3185 OptionalIdx[Op.getImmTy()] = I;
3187 llvm_unreachable("unhandled operand type");
3191 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
3192 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
3194 // special case v_mac_{f16, f32}:
3195 // it has src2 register operand that is tied to dst operand
3196 // we don't allow modifiers for this operand in assembler so src2_modifiers
3198 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
3199 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
3200 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
3201 auto it = Inst.begin();
3204 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
3205 AMDGPU::V_MAC_F16_e64 :
3206 AMDGPU::V_MAC_F32_e64,
3207 AMDGPU::OpName::src2_modifiers));
3208 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
3210 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3214 //===----------------------------------------------------------------------===//
3216 //===----------------------------------------------------------------------===//
3218 bool AMDGPUOperand::isDPPCtrl() const {
3219 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
3221 int64_t Imm = getImm();
3222 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
3223 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
3224 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
3225 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
3238 bool AMDGPUOperand::isGPRIdxMode() const {
3239 return isImm() && isUInt<4>(getImm());
3242 OperandMatchResultTy
3243 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
3244 SMLoc S = Parser.getTok().getLoc();
3248 if (getLexer().getKind() == AsmToken::Identifier) {
3249 Prefix = Parser.getTok().getString();
3251 return MatchOperand_NoMatch;
3254 if (Prefix == "row_mirror") {
3257 } else if (Prefix == "row_half_mirror") {
3261 // Check to prevent parseDPPCtrlOps from eating invalid tokens
3262 if (Prefix != "quad_perm"
3263 && Prefix != "row_shl"
3264 && Prefix != "row_shr"
3265 && Prefix != "row_ror"
3266 && Prefix != "wave_shl"
3267 && Prefix != "wave_rol"
3268 && Prefix != "wave_shr"
3269 && Prefix != "wave_ror"
3270 && Prefix != "row_bcast") {
3271 return MatchOperand_NoMatch;
3275 if (getLexer().isNot(AsmToken::Colon))
3276 return MatchOperand_ParseFail;
3278 if (Prefix == "quad_perm") {
3279 // quad_perm:[%d,%d,%d,%d]
3281 if (getLexer().isNot(AsmToken::LBrac))
3282 return MatchOperand_ParseFail;
3285 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
3286 return MatchOperand_ParseFail;
3288 for (int i = 0; i < 3; ++i) {
3289 if (getLexer().isNot(AsmToken::Comma))
3290 return MatchOperand_ParseFail;
3294 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
3295 return MatchOperand_ParseFail;
3296 const int shift = i*2 + 2;
3297 Int += (Temp << shift);
3300 if (getLexer().isNot(AsmToken::RBrac))
3301 return MatchOperand_ParseFail;
3307 if (getParser().parseAbsoluteExpression(Int))
3308 return MatchOperand_ParseFail;
3310 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
3312 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
3314 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
3316 } else if (Prefix == "wave_shl" && 1 == Int) {
3318 } else if (Prefix == "wave_rol" && 1 == Int) {
3320 } else if (Prefix == "wave_shr" && 1 == Int) {
3322 } else if (Prefix == "wave_ror" && 1 == Int) {
3324 } else if (Prefix == "row_bcast") {
3327 } else if (Int == 31) {
3330 return MatchOperand_ParseFail;
3333 return MatchOperand_ParseFail;
3338 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
3339 return MatchOperand_Success;
3342 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
3343 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
3346 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
3347 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
3350 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
3351 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
3354 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
3355 OptionalImmIndexMap OptionalIdx;
3358 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3359 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3360 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3363 for (unsigned E = Operands.size(); I != E; ++I) {
3364 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3365 // Add the register arguments
3366 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
3367 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token.
3370 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3371 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
3372 } else if (Op.isDPPCtrl()) {
3373 Op.addImmOperands(Inst, 1);
3374 } else if (Op.isImm()) {
3375 // Handle optional arguments
3376 OptionalIdx[Op.getImmTy()] = I;
3378 llvm_unreachable("Invalid operand type");
3382 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
3383 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
3384 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
3386 // special case v_mac_{f16, f32}:
3387 // it has src2 register operand that is tied to dst operand
3388 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
3389 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
3390 auto it = Inst.begin();
3392 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3393 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3397 //===----------------------------------------------------------------------===//
3399 //===----------------------------------------------------------------------===//
3401 OperandMatchResultTy
3402 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
3403 AMDGPUOperand::ImmTy Type) {
3404 using namespace llvm::AMDGPU::SDWA;
3406 SMLoc S = Parser.getTok().getLoc();
3408 OperandMatchResultTy res;
3410 res = parseStringWithPrefix(Prefix, Value);
3411 if (res != MatchOperand_Success) {
3416 Int = StringSwitch<int64_t>(Value)
3417 .Case("BYTE_0", SdwaSel::BYTE_0)
3418 .Case("BYTE_1", SdwaSel::BYTE_1)
3419 .Case("BYTE_2", SdwaSel::BYTE_2)
3420 .Case("BYTE_3", SdwaSel::BYTE_3)
3421 .Case("WORD_0", SdwaSel::WORD_0)
3422 .Case("WORD_1", SdwaSel::WORD_1)
3423 .Case("DWORD", SdwaSel::DWORD)
3424 .Default(0xffffffff);
3425 Parser.Lex(); // eat last token
3427 if (Int == 0xffffffff) {
3428 return MatchOperand_ParseFail;
3431 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
3432 return MatchOperand_Success;
3435 OperandMatchResultTy
3436 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
3437 using namespace llvm::AMDGPU::SDWA;
3439 SMLoc S = Parser.getTok().getLoc();
3441 OperandMatchResultTy res;
3443 res = parseStringWithPrefix("dst_unused", Value);
3444 if (res != MatchOperand_Success) {
3449 Int = StringSwitch<int64_t>(Value)
3450 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
3451 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
3452 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
3453 .Default(0xffffffff);
3454 Parser.Lex(); // eat last token
3456 if (Int == 0xffffffff) {
3457 return MatchOperand_ParseFail;
3460 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
3461 return MatchOperand_Success;
3464 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
3465 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
3468 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
3469 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
3472 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
3473 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC);
3476 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
3477 uint64_t BasicInstType) {
3478 OptionalImmIndexMap OptionalIdx;
3481 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3482 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3483 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3486 for (unsigned E = Operands.size(); I != E; ++I) {
3487 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3488 // Add the register arguments
3489 if ((BasicInstType == SIInstrFlags::VOPC ||
3490 BasicInstType == SIInstrFlags::VOP2)&&
3492 Op.Reg.RegNo == AMDGPU::VCC) {
3493 // VOPC and VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
3496 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3497 Op.addRegOrImmWithInputModsOperands(Inst, 2);
3498 } else if (Op.isImm()) {
3499 // Handle optional arguments
3500 OptionalIdx[Op.getImmTy()] = I;
3502 llvm_unreachable("Invalid operand type");
3506 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
3508 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
3509 // V_NOP_sdwa_vi has no optional sdwa arguments
3510 switch (BasicInstType) {
3511 case SIInstrFlags::VOP1:
3512 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3513 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3514 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3517 case SIInstrFlags::VOP2:
3518 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3519 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3520 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3521 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3524 case SIInstrFlags::VOPC:
3525 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3526 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3530 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
3534 // special case v_mac_{f16, f32}:
3535 // it has src2 register operand that is tied to dst operand
3536 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
3537 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
3538 auto it = Inst.begin();
3540 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3541 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3546 /// Force static initialization.
3547 extern "C" void LLVMInitializeAMDGPUAsmParser() {
3548 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
3549 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
3552 #define GET_REGISTER_MATCHER
3553 #define GET_MATCHER_IMPLEMENTATION
3554 #include "AMDGPUGenAsmMatcher.inc"
3556 // This fuction should be defined after auto-generated include so that we have
3557 // MatchClassKind enum defined
3558 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
3560 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
3561 // But MatchInstructionImpl() expects to meet token and fails to validate
3562 // operand. This method checks if we are given immediate operand but expect to
3563 // get corresponding token.
3564 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
3567 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
3569 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
3571 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
3573 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
3575 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
3577 // When operands have expression values, they will return true for isToken,
3578 // because it is not possible to distinguish between a token and an
3579 // expression at parse time. MatchInstructionImpl() will always try to
3580 // match an operand as a token, when isToken returns true, and when the
3581 // name of the expression is not a valid token, the match will fail,
3582 // so we need to handle it here.
3583 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
3585 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
3586 case MCK_SoppBrTarget:
3587 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
3588 case MCK_VReg32OrOff:
3589 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
3590 case MCK_InterpSlot:
3591 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
3593 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
3595 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
3597 return Match_InvalidOperand;