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() && !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 isVReg() const {
249 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
250 isRegClass(AMDGPU::VReg_64RegClassID) ||
251 isRegClass(AMDGPU::VReg_96RegClassID) ||
252 isRegClass(AMDGPU::VReg_128RegClassID) ||
253 isRegClass(AMDGPU::VReg_256RegClassID) ||
254 isRegClass(AMDGPU::VReg_512RegClassID);
257 bool isVReg32OrOff() const {
258 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
261 bool isImmTy(ImmTy ImmT) const {
262 return isImm() && Imm.Type == ImmT;
265 bool isImmModifier() const {
266 return isImm() && Imm.Type != ImmTyNone;
269 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
270 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
271 bool isDMask() const { return isImmTy(ImmTyDMask); }
272 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
273 bool isDA() const { return isImmTy(ImmTyDA); }
274 bool isR128() const { return isImmTy(ImmTyUNorm); }
275 bool isLWE() const { return isImmTy(ImmTyLWE); }
276 bool isOff() const { return isImmTy(ImmTyOff); }
277 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
278 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
279 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
280 bool isOffen() const { return isImmTy(ImmTyOffen); }
281 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
282 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
283 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
284 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
285 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
286 bool isGDS() const { return isImmTy(ImmTyGDS); }
287 bool isGLC() const { return isImmTy(ImmTyGLC); }
288 bool isSLC() const { return isImmTy(ImmTySLC); }
289 bool isTFE() const { return isImmTy(ImmTyTFE); }
290 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
291 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
292 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
293 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
294 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
295 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
296 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
297 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
298 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
299 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
302 return isClampSI() || isOModSI();
305 bool isRegOrImm() const {
306 return isReg() || isImm();
309 bool isRegClass(unsigned RCID) const;
311 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
312 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
315 bool isSCSrcB16() const {
316 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
319 bool isSCSrcB32() const {
320 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
323 bool isSCSrcB64() const {
324 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
327 bool isSCSrcF16() const {
328 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
331 bool isSCSrcF32() const {
332 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
335 bool isSCSrcF64() const {
336 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
339 bool isSSrcB32() const {
340 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
343 bool isSSrcB16() const {
344 return isSCSrcB16() || isLiteralImm(MVT::i16);
347 bool isSSrcB64() const {
348 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
350 return isSCSrcB64() || isLiteralImm(MVT::i64);
353 bool isSSrcF32() const {
354 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
357 bool isSSrcF64() const {
358 return isSCSrcB64() || isLiteralImm(MVT::f64);
361 bool isSSrcF16() const {
362 return isSCSrcB16() || isLiteralImm(MVT::f16);
365 bool isVCSrcB32() const {
366 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
369 bool isVCSrcB64() const {
370 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
373 bool isVCSrcB16() const {
374 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
377 bool isVCSrcF32() const {
378 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
381 bool isVCSrcF64() const {
382 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
385 bool isVCSrcF16() const {
386 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
389 bool isVSrcB32() const {
390 return isVCSrcF32() || isLiteralImm(MVT::i32);
393 bool isVSrcB64() const {
394 return isVCSrcF64() || isLiteralImm(MVT::i64);
397 bool isVSrcB16() const {
398 return isVCSrcF16() || isLiteralImm(MVT::i16);
401 bool isVSrcF32() const {
402 return isVCSrcF32() || isLiteralImm(MVT::f32);
405 bool isVSrcF64() const {
406 return isVCSrcF64() || isLiteralImm(MVT::f64);
409 bool isVSrcF16() const {
410 return isVCSrcF16() || isLiteralImm(MVT::f16);
413 bool isKImmFP32() const {
414 return isLiteralImm(MVT::f32);
417 bool isKImmFP16() const {
418 return isLiteralImm(MVT::f16);
421 bool isMem() const override {
425 bool isExpr() const {
426 return Kind == Expression;
429 bool isSoppBrTarget() const {
430 return isExpr() || isImm();
433 bool isSWaitCnt() const;
434 bool isHwreg() const;
435 bool isSendMsg() const;
436 bool isSMRDOffset8() const;
437 bool isSMRDOffset20() const;
438 bool isSMRDLiteralOffset() const;
439 bool isDPPCtrl() const;
440 bool isGPRIdxMode() const;
442 StringRef getExpressionAsToken() const {
444 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
445 return S->getSymbol().getName();
448 StringRef getToken() const {
451 if (Kind == Expression)
452 return getExpressionAsToken();
454 return StringRef(Tok.Data, Tok.Length);
457 int64_t getImm() const {
462 enum ImmTy getImmTy() const {
467 unsigned getReg() const override {
471 SMLoc getStartLoc() const override {
475 SMLoc getEndLoc() const override {
479 Modifiers getModifiers() const {
480 assert(isRegKind() || isImmTy(ImmTyNone));
481 return isRegKind() ? Reg.Mods : Imm.Mods;
484 void setModifiers(Modifiers Mods) {
485 assert(isRegKind() || isImmTy(ImmTyNone));
492 bool hasModifiers() const {
493 return getModifiers().hasModifiers();
496 bool hasFPModifiers() const {
497 return getModifiers().hasFPModifiers();
500 bool hasIntModifiers() const {
501 return getModifiers().hasIntModifiers();
504 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
506 void addLiteralImmOperand(MCInst &Inst, int64_t Val) const;
508 template <unsigned Bitwidth>
509 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
511 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
512 addKImmFPOperands<16>(Inst, N);
515 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
516 addKImmFPOperands<32>(Inst, N);
519 void addRegOperands(MCInst &Inst, unsigned N) const;
521 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
523 addRegOperands(Inst, N);
525 Inst.addOperand(MCOperand::createExpr(Expr));
527 addImmOperands(Inst, N);
530 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
531 Modifiers Mods = getModifiers();
532 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
534 addRegOperands(Inst, N);
536 addImmOperands(Inst, N, false);
540 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
541 assert(!hasIntModifiers());
542 addRegOrImmWithInputModsOperands(Inst, N);
545 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
546 assert(!hasFPModifiers());
547 addRegOrImmWithInputModsOperands(Inst, N);
550 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
551 Modifiers Mods = getModifiers();
552 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
554 addRegOperands(Inst, N);
557 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
558 assert(!hasIntModifiers());
559 addRegWithInputModsOperands(Inst, N);
562 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
563 assert(!hasFPModifiers());
564 addRegWithInputModsOperands(Inst, N);
567 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
569 addImmOperands(Inst, N);
572 Inst.addOperand(MCOperand::createExpr(Expr));
576 static void printImmTy(raw_ostream& OS, ImmTy Type) {
578 case ImmTyNone: OS << "None"; break;
579 case ImmTyGDS: OS << "GDS"; break;
580 case ImmTyOffen: OS << "Offen"; break;
581 case ImmTyIdxen: OS << "Idxen"; break;
582 case ImmTyAddr64: OS << "Addr64"; break;
583 case ImmTyOffset: OS << "Offset"; break;
584 case ImmTyOffset0: OS << "Offset0"; break;
585 case ImmTyOffset1: OS << "Offset1"; break;
586 case ImmTyGLC: OS << "GLC"; break;
587 case ImmTySLC: OS << "SLC"; break;
588 case ImmTyTFE: OS << "TFE"; break;
589 case ImmTyClampSI: OS << "ClampSI"; break;
590 case ImmTyOModSI: OS << "OModSI"; break;
591 case ImmTyDppCtrl: OS << "DppCtrl"; break;
592 case ImmTyDppRowMask: OS << "DppRowMask"; break;
593 case ImmTyDppBankMask: OS << "DppBankMask"; break;
594 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
595 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
596 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
597 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
598 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
599 case ImmTyDMask: OS << "DMask"; break;
600 case ImmTyUNorm: OS << "UNorm"; break;
601 case ImmTyDA: OS << "DA"; break;
602 case ImmTyR128: OS << "R128"; break;
603 case ImmTyLWE: OS << "LWE"; break;
604 case ImmTyOff: OS << "Off"; break;
605 case ImmTyExpTgt: OS << "ExpTgt"; break;
606 case ImmTyExpCompr: OS << "ExpCompr"; break;
607 case ImmTyExpVM: OS << "ExpVM"; break;
608 case ImmTyHwreg: OS << "Hwreg"; break;
609 case ImmTySendMsg: OS << "SendMsg"; break;
610 case ImmTyInterpSlot: OS << "InterpSlot"; break;
611 case ImmTyInterpAttr: OS << "InterpAttr"; break;
612 case ImmTyAttrChan: OS << "AttrChan"; break;
616 void print(raw_ostream &OS) const override {
619 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
622 OS << '<' << getImm();
623 if (getImmTy() != ImmTyNone) {
624 OS << " type: "; printImmTy(OS, getImmTy());
626 OS << " mods: " << Imm.Mods << '>';
629 OS << '\'' << getToken() << '\'';
632 OS << "<expr " << *Expr << '>';
637 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
638 int64_t Val, SMLoc Loc,
639 enum ImmTy Type = ImmTyNone,
640 bool IsFPImm = false) {
641 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
643 Op->Imm.IsFPImm = IsFPImm;
645 Op->Imm.Mods = Modifiers();
651 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
652 StringRef Str, SMLoc Loc,
653 bool HasExplicitEncodingSize = true) {
654 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
655 Res->Tok.Data = Str.data();
656 Res->Tok.Length = Str.size();
662 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
663 unsigned RegNo, SMLoc S,
666 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
667 Op->Reg.RegNo = RegNo;
668 Op->Reg.Mods = Modifiers();
669 Op->Reg.IsForcedVOP3 = ForceVOP3;
675 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
676 const class MCExpr *Expr, SMLoc S) {
677 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
685 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
686 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
690 //===----------------------------------------------------------------------===//
692 //===----------------------------------------------------------------------===//
694 // Holds info related to the current kernel, e.g. count of SGPRs used.
695 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
696 // .amdgpu_hsa_kernel or at EOF.
697 class KernelScopeInfo {
698 int SgprIndexUnusedMin;
699 int VgprIndexUnusedMin;
702 void usesSgprAt(int i) {
703 if (i >= SgprIndexUnusedMin) {
704 SgprIndexUnusedMin = ++i;
706 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
707 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
711 void usesVgprAt(int i) {
712 if (i >= VgprIndexUnusedMin) {
713 VgprIndexUnusedMin = ++i;
715 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
716 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
721 KernelScopeInfo() : SgprIndexUnusedMin(-1), VgprIndexUnusedMin(-1), Ctx(nullptr)
723 void initialize(MCContext &Context) {
725 usesSgprAt(SgprIndexUnusedMin = -1);
726 usesVgprAt(VgprIndexUnusedMin = -1);
728 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
730 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
731 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
737 class AMDGPUAsmParser : public MCTargetAsmParser {
738 const MCInstrInfo &MII;
741 unsigned ForcedEncodingSize;
744 KernelScopeInfo KernelScope;
746 /// @name Auto-generated Match Functions
749 #define GET_ASSEMBLER_HEADER
750 #include "AMDGPUGenAsmMatcher.inc"
755 bool ParseAsAbsoluteExpression(uint32_t &Ret);
756 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
757 bool ParseDirectiveHSACodeObjectVersion();
758 bool ParseDirectiveHSACodeObjectISA();
759 bool ParseDirectiveRuntimeMetadata();
760 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
761 bool ParseDirectiveAMDKernelCodeT();
762 bool ParseSectionDirectiveHSAText();
763 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
764 bool ParseDirectiveAMDGPUHsaKernel();
765 bool ParseDirectiveAMDGPUHsaModuleGlobal();
766 bool ParseDirectiveAMDGPUHsaProgramGlobal();
767 bool ParseSectionDirectiveHSADataGlobalAgent();
768 bool ParseSectionDirectiveHSADataGlobalProgram();
769 bool ParseSectionDirectiveHSARodataReadonlyAgent();
770 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
771 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex);
772 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
775 enum AMDGPUMatchResultTy {
776 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
779 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
780 const MCInstrInfo &MII,
781 const MCTargetOptions &Options)
782 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
783 ForcedEncodingSize(0),
786 MCAsmParserExtension::Initialize(Parser);
788 if (getSTI().getFeatureBits().none()) {
789 // Set default features.
790 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
793 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
796 // TODO: make those pre-defined variables read-only.
797 // Currently there is none suitable machinery in the core llvm-mc for this.
798 // MCSymbol::isRedefinable is intended for another purpose, and
799 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
800 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
801 MCContext &Ctx = getContext();
802 MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
803 Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx));
804 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
805 Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx));
806 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
807 Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx));
809 KernelScope.initialize(getContext());
813 return AMDGPU::isSI(getSTI());
817 return AMDGPU::isCI(getSTI());
821 return AMDGPU::isVI(getSTI());
824 bool hasInv2PiInlineImm() const {
825 return getSTI().getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
828 bool hasSGPR102_SGPR103() const {
832 AMDGPUTargetStreamer &getTargetStreamer() {
833 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
834 return static_cast<AMDGPUTargetStreamer &>(TS);
837 const MCRegisterInfo *getMRI() const {
838 // We need this const_cast because for some reason getContext() is not const
840 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
843 const MCInstrInfo *getMII() const {
847 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
848 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
849 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
851 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
852 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
853 bool isForcedDPP() const { return ForcedDPP; }
854 bool isForcedSDWA() const { return ForcedSDWA; }
855 ArrayRef<unsigned> getMatchedVariants() const;
857 std::unique_ptr<AMDGPUOperand> parseRegister();
858 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
859 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
860 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
861 unsigned Kind) override;
862 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
863 OperandVector &Operands, MCStreamer &Out,
865 bool MatchingInlineAsm) override;
866 bool ParseDirective(AsmToken DirectiveID) override;
867 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
868 StringRef parseMnemonicSuffix(StringRef Name);
869 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
870 SMLoc NameLoc, OperandVector &Operands) override;
871 //bool ProcessInstruction(MCInst &Inst);
873 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
875 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
876 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
877 bool (*ConvertResult)(int64_t &) = nullptr);
879 parseNamedBit(const char *Name, OperandVector &Operands,
880 enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
881 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
884 OperandMatchResultTy parseImm(OperandVector &Operands);
885 OperandMatchResultTy parseReg(OperandVector &Operands);
886 OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
887 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
888 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
889 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
890 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
891 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
893 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
894 void cvtDS(MCInst &Inst, const OperandVector &Operands);
895 void cvtExp(MCInst &Inst, const OperandVector &Operands);
897 bool parseCnt(int64_t &IntVal);
898 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
899 OperandMatchResultTy parseHwreg(OperandVector &Operands);
902 struct OperandInfoTy {
905 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
908 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
909 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
912 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
915 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
917 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
918 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
919 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
920 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
921 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
923 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
924 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
925 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
926 AMDGPUOperand::Ptr defaultGLC() const;
927 AMDGPUOperand::Ptr defaultSLC() const;
928 AMDGPUOperand::Ptr defaultTFE() const;
930 AMDGPUOperand::Ptr defaultDMask() const;
931 AMDGPUOperand::Ptr defaultUNorm() const;
932 AMDGPUOperand::Ptr defaultDA() const;
933 AMDGPUOperand::Ptr defaultR128() const;
934 AMDGPUOperand::Ptr defaultLWE() const;
935 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
936 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
937 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
939 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
941 void cvtId(MCInst &Inst, const OperandVector &Operands);
942 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
943 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
945 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
946 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
948 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
949 AMDGPUOperand::Ptr defaultRowMask() const;
950 AMDGPUOperand::Ptr defaultBankMask() const;
951 AMDGPUOperand::Ptr defaultBoundCtrl() const;
952 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
954 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
955 AMDGPUOperand::ImmTy Type);
956 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
957 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
958 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
959 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
960 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
961 uint64_t BasicInstType);
964 struct OptionalOperand {
966 AMDGPUOperand::ImmTy Type;
968 bool (*ConvertResult)(int64_t&);
971 } // end anonymous namespace
973 // May be called with integer type with equivalent bitwidth.
974 static const fltSemantics *getFltSemantics(unsigned Size) {
977 return &APFloat::IEEEsingle();
979 return &APFloat::IEEEdouble();
981 return &APFloat::IEEEhalf();
983 llvm_unreachable("unsupported fp type");
987 static const fltSemantics *getFltSemantics(MVT VT) {
988 return getFltSemantics(VT.getSizeInBits() / 8);
991 //===----------------------------------------------------------------------===//
993 //===----------------------------------------------------------------------===//
995 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
998 // Convert literal to single precision
999 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1000 APFloat::rmNearestTiesToEven,
1002 // We allow precision lost but not overflow or underflow
1003 if (Status != APFloat::opOK &&
1005 ((Status & APFloat::opOverflow) != 0 ||
1006 (Status & APFloat::opUnderflow) != 0)) {
1013 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1014 if (!isImmTy(ImmTyNone)) {
1015 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1018 // TODO: We should avoid using host float here. It would be better to
1019 // check the float bit values which is what a few other places do.
1020 // We've had bot failures before due to weird NaN support on mips hosts.
1022 APInt Literal(64, Imm.Val);
1024 if (Imm.IsFPImm) { // We got fp literal token
1025 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1026 return AMDGPU::isInlinableLiteral64(Imm.Val,
1027 AsmParser->hasInv2PiInlineImm());
1030 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1031 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1034 // Check if single precision literal is inlinable
1035 return AMDGPU::isInlinableLiteral32(
1036 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1037 AsmParser->hasInv2PiInlineImm());
1041 // We got int literal token.
1042 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1043 return AMDGPU::isInlinableLiteral64(Imm.Val,
1044 AsmParser->hasInv2PiInlineImm());
1047 if (type.getScalarSizeInBits() == 16) {
1048 return AMDGPU::isInlinableLiteral16(
1049 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1050 AsmParser->hasInv2PiInlineImm());
1053 return AMDGPU::isInlinableLiteral32(
1054 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1055 AsmParser->hasInv2PiInlineImm());
1058 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1059 // Check that this imediate can be added as literal
1060 if (!isImmTy(ImmTyNone)) {
1065 // We got int literal token.
1067 unsigned Size = type.getSizeInBits();
1071 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1073 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1076 // We got fp literal token
1077 if (type == MVT::f64) { // Expected 64-bit fp operand
1078 // We would set low 64-bits of literal to zeroes but we accept this literals
1082 if (type == MVT::i64) { // Expected 64-bit int operand
1083 // We don't allow fp literals in 64-bit integer instructions. It is
1084 // unclear how we should encode them.
1088 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1089 return canLosslesslyConvertToFPType(FPLiteral, type);
1092 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1093 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1096 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1097 int64_t Val = Imm.Val;
1098 if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers() && Imm.Mods.Neg) {
1099 // Apply modifiers to immediate value. Only negate can get here
1101 APFloat F(BitsToDouble(Val));
1103 Val = F.bitcastToAPInt().getZExtValue();
1109 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1110 Inst.getNumOperands())) {
1111 addLiteralImmOperand(Inst, Val);
1113 Inst.addOperand(MCOperand::createImm(Val));
1117 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val) const {
1118 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1119 auto OpNum = Inst.getNumOperands();
1120 // Check that this operand accepts literals
1121 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1123 auto OpSize = AMDGPU::getOperandSize(InstDesc, OpNum); // expected operand size
1125 if (Imm.IsFPImm) { // We got fp literal token
1126 APInt Literal(64, Val);
1130 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1131 AsmParser->hasInv2PiInlineImm())) {
1132 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1137 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1138 // For fp operands we check if low 32 bits are zeros
1139 if (Literal.getLoBits(32) != 0) {
1140 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1141 "Can't encode literal as exact 64-bit floating-point operand. "
1142 "Low 32-bits will be set to zero");
1145 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1149 // We don't allow fp literals in 64-bit integer instructions. It is
1150 // unclear how we should encode them. This case should be checked earlier
1151 // in predicate methods (isLiteralImm())
1152 llvm_unreachable("fp literal in 64-bit integer instruction.");
1157 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1158 // Convert literal to single precision
1159 FPLiteral.convert(*getFltSemantics(OpSize),
1160 APFloat::rmNearestTiesToEven, &lost);
1161 // We allow precision lost but not overflow or underflow. This should be
1162 // checked earlier in isLiteralImm()
1163 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1167 llvm_unreachable("invalid operand size");
1173 // We got int literal token.
1174 // Only sign extend inline immediates.
1175 // FIXME: No errors on truncation
1178 if (isInt<32>(Val) &&
1179 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1180 AsmParser->hasInv2PiInlineImm())) {
1181 Inst.addOperand(MCOperand::createImm(Val));
1185 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1189 if (AMDGPU::isInlinableLiteral64(Val,
1190 AsmParser->hasInv2PiInlineImm())) {
1191 Inst.addOperand(MCOperand::createImm(Val));
1195 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1199 if (isInt<16>(Val) &&
1200 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1201 AsmParser->hasInv2PiInlineImm())) {
1202 Inst.addOperand(MCOperand::createImm(Val));
1206 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1210 llvm_unreachable("invalid operand size");
1214 template <unsigned Bitwidth>
1215 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1216 APInt Literal(64, Imm.Val);
1219 // We got int literal token.
1220 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1225 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1226 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1227 APFloat::rmNearestTiesToEven, &Lost);
1228 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1231 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1232 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1235 //===----------------------------------------------------------------------===//
1237 //===----------------------------------------------------------------------===//
1239 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1240 if (Is == IS_VGPR) {
1243 case 1: return AMDGPU::VGPR_32RegClassID;
1244 case 2: return AMDGPU::VReg_64RegClassID;
1245 case 3: return AMDGPU::VReg_96RegClassID;
1246 case 4: return AMDGPU::VReg_128RegClassID;
1247 case 8: return AMDGPU::VReg_256RegClassID;
1248 case 16: return AMDGPU::VReg_512RegClassID;
1250 } else if (Is == IS_TTMP) {
1253 case 1: return AMDGPU::TTMP_32RegClassID;
1254 case 2: return AMDGPU::TTMP_64RegClassID;
1255 case 4: return AMDGPU::TTMP_128RegClassID;
1257 } else if (Is == IS_SGPR) {
1260 case 1: return AMDGPU::SGPR_32RegClassID;
1261 case 2: return AMDGPU::SGPR_64RegClassID;
1262 case 4: return AMDGPU::SGPR_128RegClassID;
1263 case 8: return AMDGPU::SReg_256RegClassID;
1264 case 16: return AMDGPU::SReg_512RegClassID;
1270 static unsigned getSpecialRegForName(StringRef RegName) {
1271 return StringSwitch<unsigned>(RegName)
1272 .Case("exec", AMDGPU::EXEC)
1273 .Case("vcc", AMDGPU::VCC)
1274 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1275 .Case("m0", AMDGPU::M0)
1276 .Case("scc", AMDGPU::SCC)
1277 .Case("tba", AMDGPU::TBA)
1278 .Case("tma", AMDGPU::TMA)
1279 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1280 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1281 .Case("vcc_lo", AMDGPU::VCC_LO)
1282 .Case("vcc_hi", AMDGPU::VCC_HI)
1283 .Case("exec_lo", AMDGPU::EXEC_LO)
1284 .Case("exec_hi", AMDGPU::EXEC_HI)
1285 .Case("tma_lo", AMDGPU::TMA_LO)
1286 .Case("tma_hi", AMDGPU::TMA_HI)
1287 .Case("tba_lo", AMDGPU::TBA_LO)
1288 .Case("tba_hi", AMDGPU::TBA_HI)
1292 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
1293 auto R = parseRegister();
1294 if (!R) return true;
1296 RegNo = R->getReg();
1297 StartLoc = R->getStartLoc();
1298 EndLoc = R->getEndLoc();
1302 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum)
1306 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; }
1307 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; }
1308 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; }
1309 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; }
1310 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; }
1315 if (Reg1 != Reg + RegWidth) { return false; }
1319 llvm_unreachable("unexpected register kind");
1323 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth, unsigned *DwordRegIndex)
1325 if (DwordRegIndex) { *DwordRegIndex = 0; }
1326 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1327 if (getLexer().is(AsmToken::Identifier)) {
1328 StringRef RegName = Parser.getTok().getString();
1329 if ((Reg = getSpecialRegForName(RegName))) {
1331 RegKind = IS_SPECIAL;
1333 unsigned RegNumIndex = 0;
1334 if (RegName[0] == 'v') {
1337 } else if (RegName[0] == 's') {
1340 } else if (RegName.startswith("ttmp")) {
1341 RegNumIndex = strlen("ttmp");
1346 if (RegName.size() > RegNumIndex) {
1347 // Single 32-bit register: vXX.
1348 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1353 // Range of registers: v[XX:YY]. ":YY" is optional.
1355 int64_t RegLo, RegHi;
1356 if (getLexer().isNot(AsmToken::LBrac))
1360 if (getParser().parseAbsoluteExpression(RegLo))
1363 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1364 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1371 if (getParser().parseAbsoluteExpression(RegHi))
1374 if (getLexer().isNot(AsmToken::RBrac))
1378 RegNum = (unsigned) RegLo;
1379 RegWidth = (RegHi - RegLo) + 1;
1382 } else if (getLexer().is(AsmToken::LBrac)) {
1383 // List of consecutive registers: [s0,s1,s2,s3]
1385 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1389 RegisterKind RegKind1;
1390 unsigned Reg1, RegNum1, RegWidth1;
1392 if (getLexer().is(AsmToken::Comma)) {
1394 } else if (getLexer().is(AsmToken::RBrac)) {
1397 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1398 if (RegWidth1 != 1) {
1401 if (RegKind1 != RegKind) {
1404 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1424 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1425 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1426 Size = std::min(RegWidth, 4u);
1428 if (RegNum % Size != 0)
1430 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1431 RegNum = RegNum / Size;
1432 int RCID = getRegClass(RegKind, RegWidth);
1435 const MCRegisterClass RC = TRI->getRegClass(RCID);
1436 if (RegNum >= RC.getNumRegs())
1438 Reg = RC.getRegister(RegNum);
1443 llvm_unreachable("unexpected register kind");
1446 if (!subtargetHasRegister(*TRI, Reg))
1451 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1452 const auto &Tok = Parser.getTok();
1453 SMLoc StartLoc = Tok.getLoc();
1454 SMLoc EndLoc = Tok.getEndLoc();
1455 RegisterKind RegKind;
1456 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1458 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1461 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1462 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1465 OperandMatchResultTy
1466 AMDGPUAsmParser::parseImm(OperandVector &Operands) {
1467 // TODO: add syntactic sugar for 1/(2*PI)
1469 if (getLexer().getKind() == AsmToken::Minus) {
1474 SMLoc S = Parser.getTok().getLoc();
1475 switch(getLexer().getKind()) {
1476 case AsmToken::Integer: {
1478 if (getParser().parseAbsoluteExpression(IntVal))
1479 return MatchOperand_ParseFail;
1482 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1483 return MatchOperand_Success;
1485 case AsmToken::Real: {
1487 if (getParser().parseAbsoluteExpression(IntVal))
1488 return MatchOperand_ParseFail;
1490 APFloat F(BitsToDouble(IntVal));
1494 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1495 AMDGPUOperand::ImmTyNone, true));
1496 return MatchOperand_Success;
1499 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1503 OperandMatchResultTy
1504 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1505 if (auto R = parseRegister()) {
1507 R->Reg.IsForcedVOP3 = isForcedVOP3();
1508 Operands.push_back(std::move(R));
1509 return MatchOperand_Success;
1511 return MatchOperand_NoMatch;
1514 OperandMatchResultTy
1515 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) {
1516 auto res = parseImm(Operands);
1517 if (res != MatchOperand_NoMatch) {
1521 return parseReg(Operands);
1524 OperandMatchResultTy
1525 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm) {
1526 // XXX: During parsing we can't determine if minus sign means
1527 // negate-modifier or negative immediate value.
1528 // By default we suppose it is modifier.
1529 bool Negate = false, Abs = false, Abs2 = false;
1531 if (getLexer().getKind()== AsmToken::Minus) {
1536 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") {
1539 if (getLexer().isNot(AsmToken::LParen)) {
1540 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1541 return MatchOperand_ParseFail;
1546 if (getLexer().getKind() == AsmToken::Pipe) {
1548 Error(Parser.getTok().getLoc(), "expected register or immediate");
1549 return MatchOperand_ParseFail;
1555 OperandMatchResultTy Res;
1557 Res = parseRegOrImm(Operands);
1559 Res = parseReg(Operands);
1561 if (Res != MatchOperand_Success) {
1565 AMDGPUOperand::Modifiers Mods;
1570 if (getLexer().getKind() != AsmToken::Pipe) {
1571 Error(Parser.getTok().getLoc(), "expected vertical bar");
1572 return MatchOperand_ParseFail;
1578 if (getLexer().isNot(AsmToken::RParen)) {
1579 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1580 return MatchOperand_ParseFail;
1586 if (Mods.hasFPModifiers()) {
1587 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1588 Op.setModifiers(Mods);
1590 return MatchOperand_Success;
1593 OperandMatchResultTy
1594 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm) {
1597 if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") {
1600 if (getLexer().isNot(AsmToken::LParen)) {
1601 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1602 return MatchOperand_ParseFail;
1607 OperandMatchResultTy Res;
1609 Res = parseRegOrImm(Operands);
1611 Res = parseReg(Operands);
1613 if (Res != MatchOperand_Success) {
1617 AMDGPUOperand::Modifiers Mods;
1619 if (getLexer().isNot(AsmToken::RParen)) {
1620 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1621 return MatchOperand_ParseFail;
1627 if (Mods.hasIntModifiers()) {
1628 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1629 Op.setModifiers(Mods);
1632 return MatchOperand_Success;
1635 OperandMatchResultTy
1636 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1637 return parseRegOrImmWithFPInputMods(Operands, false);
1640 OperandMatchResultTy
1641 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1642 return parseRegOrImmWithIntInputMods(Operands, false);
1645 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1646 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1648 Operands.push_back(std::move(Reg));
1649 return MatchOperand_Success;
1652 const AsmToken &Tok = Parser.getTok();
1653 if (Tok.getString() == "off") {
1654 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1655 AMDGPUOperand::ImmTyOff, false));
1657 return MatchOperand_Success;
1660 return MatchOperand_NoMatch;
1663 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1665 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1667 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1668 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1669 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1670 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1671 return Match_InvalidOperand;
1673 if ((TSFlags & SIInstrFlags::VOP3) &&
1674 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1675 getForcedEncodingSize() != 64)
1676 return Match_PreferE32;
1678 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1679 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1680 // v_mac_f32/16 allow only dst_sel == DWORD;
1682 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1683 const auto &Op = Inst.getOperand(OpNum);
1684 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1685 return Match_InvalidOperand;
1689 return Match_Success;
1692 // What asm variants we should check
1693 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
1694 if (getForcedEncodingSize() == 32) {
1695 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
1696 return makeArrayRef(Variants);
1699 if (isForcedVOP3()) {
1700 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
1701 return makeArrayRef(Variants);
1704 if (isForcedSDWA()) {
1705 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA};
1706 return makeArrayRef(Variants);
1709 if (isForcedDPP()) {
1710 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
1711 return makeArrayRef(Variants);
1714 static const unsigned Variants[] = {
1715 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
1716 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::DPP
1719 return makeArrayRef(Variants);
1722 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1723 OperandVector &Operands,
1725 uint64_t &ErrorInfo,
1726 bool MatchingInlineAsm) {
1728 unsigned Result = Match_Success;
1729 for (auto Variant : getMatchedVariants()) {
1731 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
1733 // We order match statuses from least to most specific. We use most specific
1734 // status as resulting
1735 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
1736 if ((R == Match_Success) ||
1737 (R == Match_PreferE32) ||
1738 (R == Match_MissingFeature && Result != Match_PreferE32) ||
1739 (R == Match_InvalidOperand && Result != Match_MissingFeature
1740 && Result != Match_PreferE32) ||
1741 (R == Match_MnemonicFail && Result != Match_InvalidOperand
1742 && Result != Match_MissingFeature
1743 && Result != Match_PreferE32)) {
1747 if (R == Match_Success)
1755 Out.EmitInstruction(Inst, getSTI());
1758 case Match_MissingFeature:
1759 return Error(IDLoc, "instruction not supported on this GPU");
1761 case Match_MnemonicFail:
1762 return Error(IDLoc, "unrecognized instruction mnemonic");
1764 case Match_InvalidOperand: {
1765 SMLoc ErrorLoc = IDLoc;
1766 if (ErrorInfo != ~0ULL) {
1767 if (ErrorInfo >= Operands.size()) {
1768 return Error(IDLoc, "too few operands for instruction");
1770 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
1771 if (ErrorLoc == SMLoc())
1774 return Error(ErrorLoc, "invalid operand for instruction");
1777 case Match_PreferE32:
1778 return Error(IDLoc, "internal error: instruction without _e64 suffix "
1779 "should be encoded as e32");
1781 llvm_unreachable("Implement any new match types added!");
1784 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
1786 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
1789 if (getParser().parseAbsoluteExpression(Tmp)) {
1792 Ret = static_cast<uint32_t>(Tmp);
1797 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
1799 if (ParseAsAbsoluteExpression(Major))
1800 return TokError("invalid major version");
1802 if (getLexer().isNot(AsmToken::Comma))
1803 return TokError("minor version number required, comma expected");
1806 if (ParseAsAbsoluteExpression(Minor))
1807 return TokError("invalid minor version");
1812 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
1817 if (ParseDirectiveMajorMinor(Major, Minor))
1820 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
1824 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
1828 StringRef VendorName;
1831 // If this directive has no arguments, then use the ISA version for the
1833 if (getLexer().is(AsmToken::EndOfStatement)) {
1834 AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
1835 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
1841 if (ParseDirectiveMajorMinor(Major, Minor))
1844 if (getLexer().isNot(AsmToken::Comma))
1845 return TokError("stepping version number required, comma expected");
1848 if (ParseAsAbsoluteExpression(Stepping))
1849 return TokError("invalid stepping version");
1851 if (getLexer().isNot(AsmToken::Comma))
1852 return TokError("vendor name required, comma expected");
1855 if (getLexer().isNot(AsmToken::String))
1856 return TokError("invalid vendor name");
1858 VendorName = getLexer().getTok().getStringContents();
1861 if (getLexer().isNot(AsmToken::Comma))
1862 return TokError("arch name required, comma expected");
1865 if (getLexer().isNot(AsmToken::String))
1866 return TokError("invalid arch name");
1868 ArchName = getLexer().getTok().getStringContents();
1871 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
1872 VendorName, ArchName);
1876 bool AMDGPUAsmParser::ParseDirectiveRuntimeMetadata() {
1877 std::string Metadata;
1878 raw_string_ostream MS(Metadata);
1880 getLexer().setSkipSpace(false);
1882 bool FoundEnd = false;
1883 while (!getLexer().is(AsmToken::Eof)) {
1884 while (getLexer().is(AsmToken::Space)) {
1889 if (getLexer().is(AsmToken::Identifier)) {
1890 StringRef ID = getLexer().getTok().getIdentifier();
1891 if (ID == ".end_amdgpu_runtime_metadata") {
1898 MS << Parser.parseStringToEndOfStatement()
1899 << getContext().getAsmInfo()->getSeparatorString();
1901 Parser.eatToEndOfStatement();
1904 getLexer().setSkipSpace(true);
1906 if (getLexer().is(AsmToken::Eof) && !FoundEnd)
1907 return TokError("expected directive .end_amdgpu_runtime_metadata not found");
1911 getTargetStreamer().EmitRuntimeMetadata(Metadata);
1916 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
1917 amd_kernel_code_t &Header) {
1918 SmallString<40> ErrStr;
1919 raw_svector_ostream Err(ErrStr);
1920 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
1921 return TokError(Err.str());
1927 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
1928 amd_kernel_code_t Header;
1929 AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits());
1932 // Lex EndOfStatement. This is in a while loop, because lexing a comment
1933 // will set the current token to EndOfStatement.
1934 while(getLexer().is(AsmToken::EndOfStatement))
1937 if (getLexer().isNot(AsmToken::Identifier))
1938 return TokError("expected value identifier or .end_amd_kernel_code_t");
1940 StringRef ID = getLexer().getTok().getIdentifier();
1943 if (ID == ".end_amd_kernel_code_t")
1946 if (ParseAMDKernelCodeTValue(ID, Header))
1950 getTargetStreamer().EmitAMDKernelCodeT(Header);
1955 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
1956 getParser().getStreamer().SwitchSection(
1957 AMDGPU::getHSATextSection(getContext()));
1961 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
1962 if (getLexer().isNot(AsmToken::Identifier))
1963 return TokError("expected symbol name");
1965 StringRef KernelName = Parser.getTok().getString();
1967 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
1968 ELF::STT_AMDGPU_HSA_KERNEL);
1970 KernelScope.initialize(getContext());
1974 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
1975 if (getLexer().isNot(AsmToken::Identifier))
1976 return TokError("expected symbol name");
1978 StringRef GlobalName = Parser.getTok().getIdentifier();
1980 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
1985 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
1986 if (getLexer().isNot(AsmToken::Identifier))
1987 return TokError("expected symbol name");
1989 StringRef GlobalName = Parser.getTok().getIdentifier();
1991 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
1996 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
1997 getParser().getStreamer().SwitchSection(
1998 AMDGPU::getHSADataGlobalAgentSection(getContext()));
2002 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
2003 getParser().getStreamer().SwitchSection(
2004 AMDGPU::getHSADataGlobalProgramSection(getContext()));
2008 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
2009 getParser().getStreamer().SwitchSection(
2010 AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
2014 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2015 StringRef IDVal = DirectiveID.getString();
2017 if (IDVal == ".hsa_code_object_version")
2018 return ParseDirectiveHSACodeObjectVersion();
2020 if (IDVal == ".hsa_code_object_isa")
2021 return ParseDirectiveHSACodeObjectISA();
2023 if (IDVal == ".amdgpu_runtime_metadata")
2024 return ParseDirectiveRuntimeMetadata();
2026 if (IDVal == ".amd_kernel_code_t")
2027 return ParseDirectiveAMDKernelCodeT();
2029 if (IDVal == ".hsatext")
2030 return ParseSectionDirectiveHSAText();
2032 if (IDVal == ".amdgpu_hsa_kernel")
2033 return ParseDirectiveAMDGPUHsaKernel();
2035 if (IDVal == ".amdgpu_hsa_module_global")
2036 return ParseDirectiveAMDGPUHsaModuleGlobal();
2038 if (IDVal == ".amdgpu_hsa_program_global")
2039 return ParseDirectiveAMDGPUHsaProgramGlobal();
2041 if (IDVal == ".hsadata_global_agent")
2042 return ParseSectionDirectiveHSADataGlobalAgent();
2044 if (IDVal == ".hsadata_global_program")
2045 return ParseSectionDirectiveHSADataGlobalProgram();
2047 if (IDVal == ".hsarodata_readonly_agent")
2048 return ParseSectionDirectiveHSARodataReadonlyAgent();
2053 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2054 unsigned RegNo) const {
2061 case AMDGPU::FLAT_SCR:
2062 case AMDGPU::FLAT_SCR_LO:
2063 case AMDGPU::FLAT_SCR_HI:
2070 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2072 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2081 OperandMatchResultTy
2082 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2084 // Try to parse with a custom parser
2085 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2087 // If we successfully parsed the operand or if there as an error parsing,
2090 // If we are parsing after we reach EndOfStatement then this means we
2091 // are appending default values to the Operands list. This is only done
2092 // by custom parser, so we shouldn't continue on to the generic parsing.
2093 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2094 getLexer().is(AsmToken::EndOfStatement))
2097 ResTy = parseRegOrImm(Operands);
2099 if (ResTy == MatchOperand_Success)
2102 if (getLexer().getKind() == AsmToken::Identifier) {
2103 // If this identifier is a symbol, we want to create an expression for it.
2104 // It is a little difficult to distinguish between a symbol name, and
2105 // an instruction flag like 'gds'. In order to do this, we parse
2106 // all tokens as expressions and then treate the symbol name as the token
2107 // string when we want to interpret the operand as a token.
2108 const auto &Tok = Parser.getTok();
2109 SMLoc S = Tok.getLoc();
2110 const MCExpr *Expr = nullptr;
2111 if (!Parser.parseExpression(Expr)) {
2112 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2113 return MatchOperand_Success;
2116 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2118 return MatchOperand_Success;
2120 return MatchOperand_NoMatch;
2123 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2124 // Clear any forced encodings from the previous instruction.
2125 setForcedEncodingSize(0);
2126 setForcedDPP(false);
2127 setForcedSDWA(false);
2129 if (Name.endswith("_e64")) {
2130 setForcedEncodingSize(64);
2131 return Name.substr(0, Name.size() - 4);
2132 } else if (Name.endswith("_e32")) {
2133 setForcedEncodingSize(32);
2134 return Name.substr(0, Name.size() - 4);
2135 } else if (Name.endswith("_dpp")) {
2137 return Name.substr(0, Name.size() - 4);
2138 } else if (Name.endswith("_sdwa")) {
2139 setForcedSDWA(true);
2140 return Name.substr(0, Name.size() - 5);
2145 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2147 SMLoc NameLoc, OperandVector &Operands) {
2148 // Add the instruction mnemonic
2149 Name = parseMnemonicSuffix(Name);
2150 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2152 while (!getLexer().is(AsmToken::EndOfStatement)) {
2153 OperandMatchResultTy Res = parseOperand(Operands, Name);
2155 // Eat the comma or space if there is one.
2156 if (getLexer().is(AsmToken::Comma))
2160 case MatchOperand_Success: break;
2161 case MatchOperand_ParseFail:
2162 Error(getLexer().getLoc(), "failed parsing operand.");
2163 while (!getLexer().is(AsmToken::EndOfStatement)) {
2167 case MatchOperand_NoMatch:
2168 Error(getLexer().getLoc(), "not a valid operand.");
2169 while (!getLexer().is(AsmToken::EndOfStatement)) {
2179 //===----------------------------------------------------------------------===//
2180 // Utility functions
2181 //===----------------------------------------------------------------------===//
2183 OperandMatchResultTy
2184 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2185 switch(getLexer().getKind()) {
2186 default: return MatchOperand_NoMatch;
2187 case AsmToken::Identifier: {
2188 StringRef Name = Parser.getTok().getString();
2189 if (!Name.equals(Prefix)) {
2190 return MatchOperand_NoMatch;
2194 if (getLexer().isNot(AsmToken::Colon))
2195 return MatchOperand_ParseFail;
2198 if (getLexer().isNot(AsmToken::Integer))
2199 return MatchOperand_ParseFail;
2201 if (getParser().parseAbsoluteExpression(Int))
2202 return MatchOperand_ParseFail;
2206 return MatchOperand_Success;
2209 OperandMatchResultTy
2210 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2211 enum AMDGPUOperand::ImmTy ImmTy,
2212 bool (*ConvertResult)(int64_t&)) {
2213 SMLoc S = Parser.getTok().getLoc();
2216 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2217 if (Res != MatchOperand_Success)
2220 if (ConvertResult && !ConvertResult(Value)) {
2221 return MatchOperand_ParseFail;
2224 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2225 return MatchOperand_Success;
2228 OperandMatchResultTy
2229 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2230 enum AMDGPUOperand::ImmTy ImmTy) {
2232 SMLoc S = Parser.getTok().getLoc();
2234 // We are at the end of the statement, and this is a default argument, so
2235 // use a default value.
2236 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2237 switch(getLexer().getKind()) {
2238 case AsmToken::Identifier: {
2239 StringRef Tok = Parser.getTok().getString();
2243 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2247 return MatchOperand_NoMatch;
2252 return MatchOperand_NoMatch;
2256 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2257 return MatchOperand_Success;
2260 typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
2262 void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands,
2263 OptionalImmIndexMap& OptionalIdx,
2264 enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) {
2265 auto i = OptionalIdx.find(ImmT);
2266 if (i != OptionalIdx.end()) {
2267 unsigned Idx = i->second;
2268 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2270 Inst.addOperand(MCOperand::createImm(Default));
2274 OperandMatchResultTy
2275 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2276 if (getLexer().isNot(AsmToken::Identifier)) {
2277 return MatchOperand_NoMatch;
2279 StringRef Tok = Parser.getTok().getString();
2280 if (Tok != Prefix) {
2281 return MatchOperand_NoMatch;
2285 if (getLexer().isNot(AsmToken::Colon)) {
2286 return MatchOperand_ParseFail;
2290 if (getLexer().isNot(AsmToken::Identifier)) {
2291 return MatchOperand_ParseFail;
2294 Value = Parser.getTok().getString();
2295 return MatchOperand_Success;
2298 //===----------------------------------------------------------------------===//
2300 //===----------------------------------------------------------------------===//
2302 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2303 const OperandVector &Operands) {
2304 OptionalImmIndexMap OptionalIdx;
2306 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2307 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2309 // Add the register arguments
2311 Op.addRegOperands(Inst, 1);
2315 // Handle optional arguments
2316 OptionalIdx[Op.getImmTy()] = i;
2319 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2320 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2321 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2323 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2326 void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
2327 std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
2328 bool GDSOnly = false;
2330 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2331 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2333 // Add the register arguments
2335 Op.addRegOperands(Inst, 1);
2339 if (Op.isToken() && Op.getToken() == "gds") {
2344 // Handle optional arguments
2345 OptionalIdx[Op.getImmTy()] = i;
2348 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2349 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2352 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2354 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2357 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2358 OptionalImmIndexMap OptionalIdx;
2360 unsigned EnMask = 0;
2363 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2364 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2366 // Add the register arguments
2368 EnMask |= (1 << SrcIdx);
2369 Op.addRegOperands(Inst, 1);
2376 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2380 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2381 Op.addImmOperands(Inst, 1);
2385 if (Op.isToken() && Op.getToken() == "done")
2388 // Handle optional arguments
2389 OptionalIdx[Op.getImmTy()] = i;
2392 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2393 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2395 Inst.addOperand(MCOperand::createImm(EnMask));
2398 //===----------------------------------------------------------------------===//
2400 //===----------------------------------------------------------------------===//
2402 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2403 StringRef CntName = Parser.getTok().getString();
2407 if (getLexer().isNot(AsmToken::LParen))
2411 if (getLexer().isNot(AsmToken::Integer))
2414 if (getParser().parseAbsoluteExpression(CntVal))
2417 if (getLexer().isNot(AsmToken::RParen))
2421 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
2424 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2425 if (CntName == "vmcnt")
2426 IntVal = encodeVmcnt(IV, IntVal, CntVal);
2427 else if (CntName == "expcnt")
2428 IntVal = encodeExpcnt(IV, IntVal, CntVal);
2429 else if (CntName == "lgkmcnt")
2430 IntVal = encodeLgkmcnt(IV, IntVal, CntVal);
2437 OperandMatchResultTy
2438 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2439 IsaVersion IV = getIsaVersion(getSTI().getFeatureBits());
2440 int64_t Waitcnt = getWaitcntBitMask(IV);
2441 SMLoc S = Parser.getTok().getLoc();
2443 switch(getLexer().getKind()) {
2444 default: return MatchOperand_ParseFail;
2445 case AsmToken::Integer:
2446 // The operand can be an integer value.
2447 if (getParser().parseAbsoluteExpression(Waitcnt))
2448 return MatchOperand_ParseFail;
2451 case AsmToken::Identifier:
2453 if (parseCnt(Waitcnt))
2454 return MatchOperand_ParseFail;
2455 } while(getLexer().isNot(AsmToken::EndOfStatement));
2458 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
2459 return MatchOperand_Success;
2462 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) {
2463 using namespace llvm::AMDGPU::Hwreg;
2465 if (Parser.getTok().getString() != "hwreg")
2469 if (getLexer().isNot(AsmToken::LParen))
2473 if (getLexer().is(AsmToken::Identifier)) {
2474 HwReg.IsSymbolic = true;
2475 HwReg.Id = ID_UNKNOWN_;
2476 const StringRef tok = Parser.getTok().getString();
2477 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
2478 if (tok == IdSymbolic[i]) {
2485 HwReg.IsSymbolic = false;
2486 if (getLexer().isNot(AsmToken::Integer))
2488 if (getParser().parseAbsoluteExpression(HwReg.Id))
2492 if (getLexer().is(AsmToken::RParen)) {
2498 if (getLexer().isNot(AsmToken::Comma))
2502 if (getLexer().isNot(AsmToken::Integer))
2504 if (getParser().parseAbsoluteExpression(Offset))
2507 if (getLexer().isNot(AsmToken::Comma))
2511 if (getLexer().isNot(AsmToken::Integer))
2513 if (getParser().parseAbsoluteExpression(Width))
2516 if (getLexer().isNot(AsmToken::RParen))
2523 OperandMatchResultTy
2524 AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
2525 using namespace llvm::AMDGPU::Hwreg;
2527 int64_t Imm16Val = 0;
2528 SMLoc S = Parser.getTok().getLoc();
2530 switch(getLexer().getKind()) {
2531 default: return MatchOperand_NoMatch;
2532 case AsmToken::Integer:
2533 // The operand can be an integer value.
2534 if (getParser().parseAbsoluteExpression(Imm16Val))
2535 return MatchOperand_NoMatch;
2536 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2537 Error(S, "invalid immediate: only 16-bit values are legal");
2538 // Do not return error code, but create an imm operand anyway and proceed
2539 // to the next operand, if any. That avoids unneccessary error messages.
2543 case AsmToken::Identifier: {
2544 OperandInfoTy HwReg(ID_UNKNOWN_);
2545 int64_t Offset = OFFSET_DEFAULT_;
2546 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
2547 if (parseHwregConstruct(HwReg, Offset, Width))
2548 return MatchOperand_ParseFail;
2549 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
2550 if (HwReg.IsSymbolic)
2551 Error(S, "invalid symbolic name of hardware register");
2553 Error(S, "invalid code of hardware register: only 6-bit values are legal");
2555 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
2556 Error(S, "invalid bit offset: only 5-bit values are legal");
2557 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
2558 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
2559 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
2563 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
2564 return MatchOperand_Success;
2567 bool AMDGPUOperand::isSWaitCnt() const {
2571 bool AMDGPUOperand::isHwreg() const {
2572 return isImmTy(ImmTyHwreg);
2575 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
2576 using namespace llvm::AMDGPU::SendMsg;
2578 if (Parser.getTok().getString() != "sendmsg")
2582 if (getLexer().isNot(AsmToken::LParen))
2586 if (getLexer().is(AsmToken::Identifier)) {
2587 Msg.IsSymbolic = true;
2588 Msg.Id = ID_UNKNOWN_;
2589 const std::string tok = Parser.getTok().getString();
2590 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
2592 default: continue; // Omit gaps.
2593 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
2595 if (tok == IdSymbolic[i]) {
2602 Msg.IsSymbolic = false;
2603 if (getLexer().isNot(AsmToken::Integer))
2605 if (getParser().parseAbsoluteExpression(Msg.Id))
2607 if (getLexer().is(AsmToken::Integer))
2608 if (getParser().parseAbsoluteExpression(Msg.Id))
2609 Msg.Id = ID_UNKNOWN_;
2611 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
2614 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
2615 if (getLexer().isNot(AsmToken::RParen))
2621 if (getLexer().isNot(AsmToken::Comma))
2625 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
2626 Operation.Id = ID_UNKNOWN_;
2627 if (getLexer().is(AsmToken::Identifier)) {
2628 Operation.IsSymbolic = true;
2629 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
2630 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
2631 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
2632 const StringRef Tok = Parser.getTok().getString();
2633 for (int i = F; i < L; ++i) {
2641 Operation.IsSymbolic = false;
2642 if (getLexer().isNot(AsmToken::Integer))
2644 if (getParser().parseAbsoluteExpression(Operation.Id))
2648 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2649 // Stream id is optional.
2650 if (getLexer().is(AsmToken::RParen)) {
2655 if (getLexer().isNot(AsmToken::Comma))
2659 if (getLexer().isNot(AsmToken::Integer))
2661 if (getParser().parseAbsoluteExpression(StreamId))
2665 if (getLexer().isNot(AsmToken::RParen))
2671 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
2672 if (getLexer().getKind() != AsmToken::Identifier)
2673 return MatchOperand_NoMatch;
2675 StringRef Str = Parser.getTok().getString();
2676 int Slot = StringSwitch<int>(Str)
2682 SMLoc S = Parser.getTok().getLoc();
2684 return MatchOperand_ParseFail;
2687 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
2688 AMDGPUOperand::ImmTyInterpSlot));
2689 return MatchOperand_Success;
2692 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
2693 if (getLexer().getKind() != AsmToken::Identifier)
2694 return MatchOperand_NoMatch;
2696 StringRef Str = Parser.getTok().getString();
2697 if (!Str.startswith("attr"))
2698 return MatchOperand_NoMatch;
2700 StringRef Chan = Str.take_back(2);
2701 int AttrChan = StringSwitch<int>(Chan)
2708 return MatchOperand_ParseFail;
2710 Str = Str.drop_back(2).drop_front(4);
2713 if (Str.getAsInteger(10, Attr))
2714 return MatchOperand_ParseFail;
2716 SMLoc S = Parser.getTok().getLoc();
2719 Error(S, "out of bounds attr");
2720 return MatchOperand_Success;
2723 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
2725 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
2726 AMDGPUOperand::ImmTyInterpAttr));
2727 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
2728 AMDGPUOperand::ImmTyAttrChan));
2729 return MatchOperand_Success;
2732 void AMDGPUAsmParser::errorExpTgt() {
2733 Error(Parser.getTok().getLoc(), "invalid exp target");
2736 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
2738 if (Str == "null") {
2740 return MatchOperand_Success;
2743 if (Str.startswith("mrt")) {
2744 Str = Str.drop_front(3);
2745 if (Str == "z") { // == mrtz
2747 return MatchOperand_Success;
2750 if (Str.getAsInteger(10, Val))
2751 return MatchOperand_ParseFail;
2756 return MatchOperand_Success;
2759 if (Str.startswith("pos")) {
2760 Str = Str.drop_front(3);
2761 if (Str.getAsInteger(10, Val))
2762 return MatchOperand_ParseFail;
2768 return MatchOperand_Success;
2771 if (Str.startswith("param")) {
2772 Str = Str.drop_front(5);
2773 if (Str.getAsInteger(10, Val))
2774 return MatchOperand_ParseFail;
2780 return MatchOperand_Success;
2783 if (Str.startswith("invalid_target_")) {
2784 Str = Str.drop_front(15);
2785 if (Str.getAsInteger(10, Val))
2786 return MatchOperand_ParseFail;
2789 return MatchOperand_Success;
2792 return MatchOperand_NoMatch;
2795 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
2797 StringRef Str = Parser.getTok().getString();
2799 auto Res = parseExpTgtImpl(Str, Val);
2800 if (Res != MatchOperand_Success)
2803 SMLoc S = Parser.getTok().getLoc();
2806 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
2807 AMDGPUOperand::ImmTyExpTgt));
2808 return MatchOperand_Success;
2811 OperandMatchResultTy
2812 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
2813 using namespace llvm::AMDGPU::SendMsg;
2815 int64_t Imm16Val = 0;
2816 SMLoc S = Parser.getTok().getLoc();
2818 switch(getLexer().getKind()) {
2820 return MatchOperand_NoMatch;
2821 case AsmToken::Integer:
2822 // The operand can be an integer value.
2823 if (getParser().parseAbsoluteExpression(Imm16Val))
2824 return MatchOperand_NoMatch;
2825 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2826 Error(S, "invalid immediate: only 16-bit values are legal");
2827 // Do not return error code, but create an imm operand anyway and proceed
2828 // to the next operand, if any. That avoids unneccessary error messages.
2831 case AsmToken::Identifier: {
2832 OperandInfoTy Msg(ID_UNKNOWN_);
2833 OperandInfoTy Operation(OP_UNKNOWN_);
2834 int64_t StreamId = STREAM_ID_DEFAULT_;
2835 if (parseSendMsgConstruct(Msg, Operation, StreamId))
2836 return MatchOperand_ParseFail;
2838 // Validate and encode message ID.
2839 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
2840 || Msg.Id == ID_SYSMSG)) {
2842 Error(S, "invalid/unsupported symbolic name of message");
2844 Error(S, "invalid/unsupported code of message");
2847 Imm16Val = (Msg.Id << ID_SHIFT_);
2848 // Validate and encode operation ID.
2849 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
2850 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
2851 if (Operation.IsSymbolic)
2852 Error(S, "invalid symbolic name of GS_OP");
2854 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
2857 if (Operation.Id == OP_GS_NOP
2858 && Msg.Id != ID_GS_DONE) {
2859 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
2862 Imm16Val |= (Operation.Id << OP_SHIFT_);
2864 if (Msg.Id == ID_SYSMSG) {
2865 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
2866 if (Operation.IsSymbolic)
2867 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
2869 Error(S, "invalid/unsupported code of SYSMSG_OP");
2872 Imm16Val |= (Operation.Id << OP_SHIFT_);
2874 // Validate and encode stream ID.
2875 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2876 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
2877 Error(S, "invalid stream id: only 2-bit values are legal");
2880 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
2886 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
2887 return MatchOperand_Success;
2890 bool AMDGPUOperand::isSendMsg() const {
2891 return isImmTy(ImmTySendMsg);
2894 //===----------------------------------------------------------------------===//
2895 // sopp branch targets
2896 //===----------------------------------------------------------------------===//
2898 OperandMatchResultTy
2899 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
2900 SMLoc S = Parser.getTok().getLoc();
2902 switch (getLexer().getKind()) {
2903 default: return MatchOperand_ParseFail;
2904 case AsmToken::Integer: {
2906 if (getParser().parseAbsoluteExpression(Imm))
2907 return MatchOperand_ParseFail;
2908 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
2909 return MatchOperand_Success;
2912 case AsmToken::Identifier:
2913 Operands.push_back(AMDGPUOperand::CreateExpr(this,
2914 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
2915 Parser.getTok().getString()), getContext()), S));
2917 return MatchOperand_Success;
2921 //===----------------------------------------------------------------------===//
2923 //===----------------------------------------------------------------------===//
2925 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
2926 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
2929 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
2930 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
2933 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2934 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
2937 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
2938 const OperandVector &Operands,
2939 bool IsAtomic, bool IsAtomicReturn) {
2940 OptionalImmIndexMap OptionalIdx;
2941 assert(IsAtomicReturn ? IsAtomic : true);
2943 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2944 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2946 // Add the register arguments
2948 Op.addRegOperands(Inst, 1);
2952 // Handle the case where soffset is an immediate
2953 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
2954 Op.addImmOperands(Inst, 1);
2958 // Handle tokens like 'offen' which are sometimes hard-coded into the
2959 // asm string. There are no MCInst operands for these.
2965 // Handle optional arguments
2966 OptionalIdx[Op.getImmTy()] = i;
2969 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2970 if (IsAtomicReturn) {
2971 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
2975 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2976 if (!IsAtomic) { // glc is hard-coded.
2977 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2979 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2980 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2983 //===----------------------------------------------------------------------===//
2985 //===----------------------------------------------------------------------===//
2987 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
2989 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2990 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2991 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2994 OptionalImmIndexMap OptionalIdx;
2996 for (unsigned E = Operands.size(); I != E; ++I) {
2997 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2999 // Add the register arguments
3000 if (Op.isRegOrImm()) {
3001 Op.addRegOrImmOperands(Inst, 1);
3003 } else if (Op.isImmModifier()) {
3004 OptionalIdx[Op.getImmTy()] = I;
3006 llvm_unreachable("unexpected operand type");
3010 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3011 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3012 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3013 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3014 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3015 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3016 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3017 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3020 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
3022 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3023 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3024 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3027 // Add src, same as dst
3028 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
3030 OptionalImmIndexMap OptionalIdx;
3032 for (unsigned E = Operands.size(); I != E; ++I) {
3033 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3035 // Add the register arguments
3036 if (Op.isRegOrImm()) {
3037 Op.addRegOrImmOperands(Inst, 1);
3039 } else if (Op.isImmModifier()) {
3040 OptionalIdx[Op.getImmTy()] = I;
3042 llvm_unreachable("unexpected operand type");
3046 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3047 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3048 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3049 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3050 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3051 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3052 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3053 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3056 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
3057 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
3060 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
3061 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
3064 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
3065 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
3068 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
3069 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3072 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3073 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3076 //===----------------------------------------------------------------------===//
3078 //===----------------------------------------------------------------------===//
3080 bool AMDGPUOperand::isSMRDOffset8() const {
3081 return isImm() && isUInt<8>(getImm());
3084 bool AMDGPUOperand::isSMRDOffset20() const {
3085 return isImm() && isUInt<20>(getImm());
3088 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3089 // 32-bit literals are only supported on CI and we only want to use them
3090 // when the offset is > 8-bits.
3091 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3094 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3095 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3098 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3099 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3102 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3103 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3106 //===----------------------------------------------------------------------===//
3108 //===----------------------------------------------------------------------===//
3110 static bool ConvertOmodMul(int64_t &Mul) {
3111 if (Mul != 1 && Mul != 2 && Mul != 4)
3118 static bool ConvertOmodDiv(int64_t &Div) {
3132 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
3133 if (BoundCtrl == 0) {
3138 if (BoundCtrl == -1) {
3146 // Note: the order in this table matches the order of operands in AsmString.
3147 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
3148 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
3149 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
3150 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
3151 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
3152 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
3153 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
3154 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
3155 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
3156 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
3157 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
3158 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
3159 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
3160 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
3161 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
3162 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
3163 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
3164 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
3165 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
3166 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
3167 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
3168 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
3169 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
3170 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
3171 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
3172 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
3175 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
3176 OperandMatchResultTy res;
3177 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
3178 // try to parse any optional operand here
3180 res = parseNamedBit(Op.Name, Operands, Op.Type);
3181 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
3182 res = parseOModOperand(Operands);
3183 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
3184 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
3185 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
3186 res = parseSDWASel(Operands, Op.Name, Op.Type);
3187 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
3188 res = parseSDWADstUnused(Operands);
3190 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
3192 if (res != MatchOperand_NoMatch) {
3196 return MatchOperand_NoMatch;
3199 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
3200 StringRef Name = Parser.getTok().getString();
3201 if (Name == "mul") {
3202 return parseIntWithPrefix("mul", Operands,
3203 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
3206 if (Name == "div") {
3207 return parseIntWithPrefix("div", Operands,
3208 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
3211 return MatchOperand_NoMatch;
3214 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
3216 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3217 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3218 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3220 for (unsigned E = Operands.size(); I != E; ++I)
3221 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
3224 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
3225 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3226 if (TSFlags & SIInstrFlags::VOP3) {
3227 cvtVOP3(Inst, Operands);
3229 cvtId(Inst, Operands);
3233 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
3234 // 1. This operand is input modifiers
3235 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
3236 // 2. This is not last operand
3237 && Desc.NumOperands > (OpNum + 1)
3238 // 3. Next operand is register class
3239 && Desc.OpInfo[OpNum + 1].RegClass != -1
3240 // 4. Next register is not tied to any other operand
3241 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
3244 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
3245 OptionalImmIndexMap OptionalIdx;
3247 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3248 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3249 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3252 for (unsigned E = Operands.size(); I != E; ++I) {
3253 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3254 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3255 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
3256 } else if (Op.isImm()) {
3257 OptionalIdx[Op.getImmTy()] = I;
3259 llvm_unreachable("unhandled operand type");
3263 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
3264 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
3266 // special case v_mac_{f16, f32}:
3267 // it has src2 register operand that is tied to dst operand
3268 // we don't allow modifiers for this operand in assembler so src2_modifiers
3270 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
3271 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
3272 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
3273 auto it = Inst.begin();
3276 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
3277 AMDGPU::V_MAC_F16_e64 :
3278 AMDGPU::V_MAC_F32_e64,
3279 AMDGPU::OpName::src2_modifiers));
3280 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
3282 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3286 //===----------------------------------------------------------------------===//
3288 //===----------------------------------------------------------------------===//
3290 bool AMDGPUOperand::isDPPCtrl() const {
3291 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
3293 int64_t Imm = getImm();
3294 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
3295 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
3296 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
3297 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
3310 bool AMDGPUOperand::isGPRIdxMode() const {
3311 return isImm() && isUInt<4>(getImm());
3314 OperandMatchResultTy
3315 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
3316 SMLoc S = Parser.getTok().getLoc();
3320 if (getLexer().getKind() == AsmToken::Identifier) {
3321 Prefix = Parser.getTok().getString();
3323 return MatchOperand_NoMatch;
3326 if (Prefix == "row_mirror") {
3329 } else if (Prefix == "row_half_mirror") {
3333 // Check to prevent parseDPPCtrlOps from eating invalid tokens
3334 if (Prefix != "quad_perm"
3335 && Prefix != "row_shl"
3336 && Prefix != "row_shr"
3337 && Prefix != "row_ror"
3338 && Prefix != "wave_shl"
3339 && Prefix != "wave_rol"
3340 && Prefix != "wave_shr"
3341 && Prefix != "wave_ror"
3342 && Prefix != "row_bcast") {
3343 return MatchOperand_NoMatch;
3347 if (getLexer().isNot(AsmToken::Colon))
3348 return MatchOperand_ParseFail;
3350 if (Prefix == "quad_perm") {
3351 // quad_perm:[%d,%d,%d,%d]
3353 if (getLexer().isNot(AsmToken::LBrac))
3354 return MatchOperand_ParseFail;
3357 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
3358 return MatchOperand_ParseFail;
3360 for (int i = 0; i < 3; ++i) {
3361 if (getLexer().isNot(AsmToken::Comma))
3362 return MatchOperand_ParseFail;
3366 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
3367 return MatchOperand_ParseFail;
3368 const int shift = i*2 + 2;
3369 Int += (Temp << shift);
3372 if (getLexer().isNot(AsmToken::RBrac))
3373 return MatchOperand_ParseFail;
3379 if (getParser().parseAbsoluteExpression(Int))
3380 return MatchOperand_ParseFail;
3382 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
3384 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
3386 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
3388 } else if (Prefix == "wave_shl" && 1 == Int) {
3390 } else if (Prefix == "wave_rol" && 1 == Int) {
3392 } else if (Prefix == "wave_shr" && 1 == Int) {
3394 } else if (Prefix == "wave_ror" && 1 == Int) {
3396 } else if (Prefix == "row_bcast") {
3399 } else if (Int == 31) {
3402 return MatchOperand_ParseFail;
3405 return MatchOperand_ParseFail;
3410 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
3411 return MatchOperand_Success;
3414 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
3415 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
3418 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
3419 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
3422 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
3423 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
3426 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
3427 OptionalImmIndexMap OptionalIdx;
3430 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3431 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3432 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3435 for (unsigned E = Operands.size(); I != E; ++I) {
3436 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3437 // Add the register arguments
3438 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
3439 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token.
3442 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3443 Op.addRegWithFPInputModsOperands(Inst, 2);
3444 } else if (Op.isDPPCtrl()) {
3445 Op.addImmOperands(Inst, 1);
3446 } else if (Op.isImm()) {
3447 // Handle optional arguments
3448 OptionalIdx[Op.getImmTy()] = I;
3450 llvm_unreachable("Invalid operand type");
3454 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
3455 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
3456 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
3458 // special case v_mac_{f16, f32}:
3459 // it has src2 register operand that is tied to dst operand
3460 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
3461 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
3462 auto it = Inst.begin();
3464 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3465 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3469 //===----------------------------------------------------------------------===//
3471 //===----------------------------------------------------------------------===//
3473 OperandMatchResultTy
3474 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
3475 AMDGPUOperand::ImmTy Type) {
3476 using namespace llvm::AMDGPU::SDWA;
3478 SMLoc S = Parser.getTok().getLoc();
3480 OperandMatchResultTy res;
3482 res = parseStringWithPrefix(Prefix, Value);
3483 if (res != MatchOperand_Success) {
3488 Int = StringSwitch<int64_t>(Value)
3489 .Case("BYTE_0", SdwaSel::BYTE_0)
3490 .Case("BYTE_1", SdwaSel::BYTE_1)
3491 .Case("BYTE_2", SdwaSel::BYTE_2)
3492 .Case("BYTE_3", SdwaSel::BYTE_3)
3493 .Case("WORD_0", SdwaSel::WORD_0)
3494 .Case("WORD_1", SdwaSel::WORD_1)
3495 .Case("DWORD", SdwaSel::DWORD)
3496 .Default(0xffffffff);
3497 Parser.Lex(); // eat last token
3499 if (Int == 0xffffffff) {
3500 return MatchOperand_ParseFail;
3503 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
3504 return MatchOperand_Success;
3507 OperandMatchResultTy
3508 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
3509 using namespace llvm::AMDGPU::SDWA;
3511 SMLoc S = Parser.getTok().getLoc();
3513 OperandMatchResultTy res;
3515 res = parseStringWithPrefix("dst_unused", Value);
3516 if (res != MatchOperand_Success) {
3521 Int = StringSwitch<int64_t>(Value)
3522 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
3523 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
3524 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
3525 .Default(0xffffffff);
3526 Parser.Lex(); // eat last token
3528 if (Int == 0xffffffff) {
3529 return MatchOperand_ParseFail;
3532 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
3533 return MatchOperand_Success;
3536 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
3537 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
3540 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
3541 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
3544 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
3545 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC);
3548 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
3549 uint64_t BasicInstType) {
3550 OptionalImmIndexMap OptionalIdx;
3553 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3554 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3555 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3558 for (unsigned E = Operands.size(); I != E; ++I) {
3559 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3560 // Add the register arguments
3561 if ((BasicInstType == SIInstrFlags::VOPC ||
3562 BasicInstType == SIInstrFlags::VOP2)&&
3564 Op.Reg.RegNo == AMDGPU::VCC) {
3565 // VOPC and VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
3568 } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3569 Op.addRegWithInputModsOperands(Inst, 2);
3570 } else if (Op.isImm()) {
3571 // Handle optional arguments
3572 OptionalIdx[Op.getImmTy()] = I;
3574 llvm_unreachable("Invalid operand type");
3578 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
3580 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
3581 // V_NOP_sdwa_vi has no optional sdwa arguments
3582 switch (BasicInstType) {
3583 case SIInstrFlags::VOP1:
3584 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3585 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3586 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3589 case SIInstrFlags::VOP2:
3590 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
3591 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
3592 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3593 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3596 case SIInstrFlags::VOPC:
3597 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
3598 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
3602 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
3606 // special case v_mac_{f16, f32}:
3607 // it has src2 register operand that is tied to dst operand
3608 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
3609 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
3610 auto it = Inst.begin();
3612 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
3613 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3618 /// Force static initialization.
3619 extern "C" void LLVMInitializeAMDGPUAsmParser() {
3620 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
3621 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
3624 #define GET_REGISTER_MATCHER
3625 #define GET_MATCHER_IMPLEMENTATION
3626 #include "AMDGPUGenAsmMatcher.inc"
3628 // This fuction should be defined after auto-generated include so that we have
3629 // MatchClassKind enum defined
3630 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
3632 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
3633 // But MatchInstructionImpl() expects to meet token and fails to validate
3634 // operand. This method checks if we are given immediate operand but expect to
3635 // get corresponding token.
3636 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
3639 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
3641 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
3643 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
3645 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
3647 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
3649 // When operands have expression values, they will return true for isToken,
3650 // because it is not possible to distinguish between a token and an
3651 // expression at parse time. MatchInstructionImpl() will always try to
3652 // match an operand as a token, when isToken returns true, and when the
3653 // name of the expression is not a valid token, the match will fail,
3654 // so we need to handle it here.
3655 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
3657 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
3658 case MCK_SoppBrTarget:
3659 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
3660 case MCK_VReg32OrOff:
3661 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
3662 case MCK_InterpSlot:
3663 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
3665 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
3667 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
3669 return Match_InvalidOperand;