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/ArrayRef.h"
20 #include "llvm/ADT/SmallBitVector.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/STLExtras.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/CodeGen/MachineValueType.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/MC/MCContext.h"
29 #include "llvm/MC/MCExpr.h"
30 #include "llvm/MC/MCInst.h"
31 #include "llvm/MC/MCInstrDesc.h"
32 #include "llvm/MC/MCInstrInfo.h"
33 #include "llvm/MC/MCParser/MCAsmLexer.h"
34 #include "llvm/MC/MCParser/MCAsmParser.h"
35 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
36 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
37 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
38 #include "llvm/MC/MCRegisterInfo.h"
39 #include "llvm/MC/MCStreamer.h"
40 #include "llvm/MC/MCSubtargetInfo.h"
41 #include "llvm/MC/MCSymbol.h"
42 #include "llvm/Support/Casting.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"
59 using namespace llvm::AMDGPU;
63 class AMDGPUAsmParser;
65 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
67 //===----------------------------------------------------------------------===//
69 //===----------------------------------------------------------------------===//
71 class AMDGPUOperand : public MCParsedAsmOperand {
79 SMLoc StartLoc, EndLoc;
80 const AMDGPUAsmParser *AsmParser;
83 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
84 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
86 typedef std::unique_ptr<AMDGPUOperand> Ptr;
93 bool hasFPModifiers() const { return Abs || Neg; }
94 bool hasIntModifiers() const { return Sext; }
95 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
97 int64_t getFPModifiersOperand() const {
99 Operand |= Abs ? SISrcMods::ABS : 0;
100 Operand |= Neg ? SISrcMods::NEG : 0;
104 int64_t getIntModifiersOperand() const {
106 Operand |= Sext ? SISrcMods::SEXT : 0;
110 int64_t getModifiersOperand() const {
111 assert(!(hasFPModifiers() && hasIntModifiers())
112 && "fp and int modifiers should not be used simultaneously");
113 if (hasFPModifiers()) {
114 return getFPModifiersOperand();
115 } else if (hasIntModifiers()) {
116 return getIntModifiersOperand();
122 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
192 bool isToken() const override {
196 if (Kind != Expression || !Expr)
199 // When parsing operands, we can't always tell if something was meant to be
200 // a token, like 'gds', or an expression that references a global variable.
201 // In this case, we assume the string is an expression, and if we need to
202 // interpret is a token, then we treat the symbol name as the token.
203 return isa<MCSymbolRefExpr>(Expr);
206 bool isImm() const override {
207 return Kind == Immediate;
210 bool isInlinableImm(MVT type) const;
211 bool isLiteralImm(MVT type) const;
213 bool isRegKind() const {
214 return Kind == Register;
217 bool isReg() const override {
218 return isRegKind() && !hasModifiers();
221 bool isRegOrImmWithInputMods(MVT type) const {
222 return isRegKind() || isInlinableImm(type);
225 bool isRegOrImmWithInt16InputMods() const {
226 return isRegOrImmWithInputMods(MVT::i16);
229 bool isRegOrImmWithInt32InputMods() const {
230 return isRegOrImmWithInputMods(MVT::i32);
233 bool isRegOrImmWithInt64InputMods() const {
234 return isRegOrImmWithInputMods(MVT::i64);
237 bool isRegOrImmWithFP16InputMods() const {
238 return isRegOrImmWithInputMods(MVT::f16);
241 bool isRegOrImmWithFP32InputMods() const {
242 return isRegOrImmWithInputMods(MVT::f32);
245 bool isRegOrImmWithFP64InputMods() const {
246 return isRegOrImmWithInputMods(MVT::f64);
249 bool isVReg() const {
250 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
251 isRegClass(AMDGPU::VReg_64RegClassID) ||
252 isRegClass(AMDGPU::VReg_96RegClassID) ||
253 isRegClass(AMDGPU::VReg_128RegClassID) ||
254 isRegClass(AMDGPU::VReg_256RegClassID) ||
255 isRegClass(AMDGPU::VReg_512RegClassID);
258 bool isVReg32OrOff() const {
259 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
262 bool isImmTy(ImmTy ImmT) const {
263 return isImm() && Imm.Type == ImmT;
266 bool isImmModifier() const {
267 return isImm() && Imm.Type != ImmTyNone;
270 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
271 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
272 bool isDMask() const { return isImmTy(ImmTyDMask); }
273 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
274 bool isDA() const { return isImmTy(ImmTyDA); }
275 bool isR128() const { return isImmTy(ImmTyUNorm); }
276 bool isLWE() const { return isImmTy(ImmTyLWE); }
277 bool isOff() const { return isImmTy(ImmTyOff); }
278 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
279 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
280 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
281 bool isOffen() const { return isImmTy(ImmTyOffen); }
282 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
283 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
284 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
285 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
286 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
287 bool isGDS() const { return isImmTy(ImmTyGDS); }
288 bool isGLC() const { return isImmTy(ImmTyGLC); }
289 bool isSLC() const { return isImmTy(ImmTySLC); }
290 bool isTFE() const { return isImmTy(ImmTyTFE); }
291 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
292 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
293 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
294 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
295 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
296 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
297 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
298 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
299 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
300 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
301 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
302 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
303 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
304 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
307 return isClampSI() || isOModSI();
310 bool isRegOrImm() const {
311 return isReg() || isImm();
314 bool isRegClass(unsigned RCID) const;
316 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
317 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
320 bool isSCSrcB16() const {
321 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
324 bool isSCSrcV2B16() const {
328 bool isSCSrcB32() const {
329 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
332 bool isSCSrcB64() const {
333 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
336 bool isSCSrcF16() const {
337 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
340 bool isSCSrcV2F16() const {
344 bool isSCSrcF32() const {
345 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
348 bool isSCSrcF64() const {
349 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
352 bool isSSrcB32() const {
353 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
356 bool isSSrcB16() const {
357 return isSCSrcB16() || isLiteralImm(MVT::i16);
360 bool isSSrcV2B16() const {
361 llvm_unreachable("cannot happen");
365 bool isSSrcB64() const {
366 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
368 return isSCSrcB64() || isLiteralImm(MVT::i64);
371 bool isSSrcF32() const {
372 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
375 bool isSSrcF64() const {
376 return isSCSrcB64() || isLiteralImm(MVT::f64);
379 bool isSSrcF16() const {
380 return isSCSrcB16() || isLiteralImm(MVT::f16);
383 bool isSSrcV2F16() const {
384 llvm_unreachable("cannot happen");
388 bool isVCSrcB32() const {
389 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
392 bool isVCSrcB64() const {
393 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
396 bool isVCSrcB16() const {
397 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
400 bool isVCSrcV2B16() const {
404 bool isVCSrcF32() const {
405 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
408 bool isVCSrcF64() const {
409 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
412 bool isVCSrcF16() const {
413 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
416 bool isVCSrcV2F16() const {
420 bool isVSrcB32() const {
421 return isVCSrcF32() || isLiteralImm(MVT::i32);
424 bool isVSrcB64() const {
425 return isVCSrcF64() || isLiteralImm(MVT::i64);
428 bool isVSrcB16() const {
429 return isVCSrcF16() || isLiteralImm(MVT::i16);
432 bool isVSrcV2B16() const {
433 llvm_unreachable("cannot happen");
437 bool isVSrcF32() const {
438 return isVCSrcF32() || isLiteralImm(MVT::f32);
441 bool isVSrcF64() const {
442 return isVCSrcF64() || isLiteralImm(MVT::f64);
445 bool isVSrcF16() const {
446 return isVCSrcF16() || isLiteralImm(MVT::f16);
449 bool isVSrcV2F16() const {
450 llvm_unreachable("cannot happen");
454 bool isKImmFP32() const {
455 return isLiteralImm(MVT::f32);
458 bool isKImmFP16() const {
459 return isLiteralImm(MVT::f16);
462 bool isMem() const override {
466 bool isExpr() const {
467 return Kind == Expression;
470 bool isSoppBrTarget() const {
471 return isExpr() || isImm();
474 bool isSWaitCnt() const;
475 bool isHwreg() const;
476 bool isSendMsg() const;
477 bool isSMRDOffset8() const;
478 bool isSMRDOffset20() const;
479 bool isSMRDLiteralOffset() const;
480 bool isDPPCtrl() const;
481 bool isGPRIdxMode() const;
482 bool isS16Imm() const;
483 bool isU16Imm() const;
485 StringRef getExpressionAsToken() const {
487 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
488 return S->getSymbol().getName();
491 StringRef getToken() const {
494 if (Kind == Expression)
495 return getExpressionAsToken();
497 return StringRef(Tok.Data, Tok.Length);
500 int64_t getImm() const {
505 ImmTy getImmTy() const {
510 unsigned getReg() const override {
514 SMLoc getStartLoc() const override {
518 SMLoc getEndLoc() const override {
522 Modifiers getModifiers() const {
523 assert(isRegKind() || isImmTy(ImmTyNone));
524 return isRegKind() ? Reg.Mods : Imm.Mods;
527 void setModifiers(Modifiers Mods) {
528 assert(isRegKind() || isImmTy(ImmTyNone));
535 bool hasModifiers() const {
536 return getModifiers().hasModifiers();
539 bool hasFPModifiers() const {
540 return getModifiers().hasFPModifiers();
543 bool hasIntModifiers() const {
544 return getModifiers().hasIntModifiers();
547 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
549 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
551 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
553 template <unsigned Bitwidth>
554 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
556 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
557 addKImmFPOperands<16>(Inst, N);
560 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
561 addKImmFPOperands<32>(Inst, N);
564 void addRegOperands(MCInst &Inst, unsigned N) const;
566 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
568 addRegOperands(Inst, N);
570 Inst.addOperand(MCOperand::createExpr(Expr));
572 addImmOperands(Inst, N);
575 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
576 Modifiers Mods = getModifiers();
577 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
579 addRegOperands(Inst, N);
581 addImmOperands(Inst, N, false);
585 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
586 assert(!hasIntModifiers());
587 addRegOrImmWithInputModsOperands(Inst, N);
590 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
591 assert(!hasFPModifiers());
592 addRegOrImmWithInputModsOperands(Inst, N);
595 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
596 Modifiers Mods = getModifiers();
597 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
599 addRegOperands(Inst, N);
602 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
603 assert(!hasIntModifiers());
604 addRegWithInputModsOperands(Inst, N);
607 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
608 assert(!hasFPModifiers());
609 addRegWithInputModsOperands(Inst, N);
612 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
614 addImmOperands(Inst, N);
617 Inst.addOperand(MCOperand::createExpr(Expr));
621 static void printImmTy(raw_ostream& OS, ImmTy Type) {
623 case ImmTyNone: OS << "None"; break;
624 case ImmTyGDS: OS << "GDS"; break;
625 case ImmTyOffen: OS << "Offen"; break;
626 case ImmTyIdxen: OS << "Idxen"; break;
627 case ImmTyAddr64: OS << "Addr64"; break;
628 case ImmTyOffset: OS << "Offset"; break;
629 case ImmTyOffset0: OS << "Offset0"; break;
630 case ImmTyOffset1: OS << "Offset1"; break;
631 case ImmTyGLC: OS << "GLC"; break;
632 case ImmTySLC: OS << "SLC"; break;
633 case ImmTyTFE: OS << "TFE"; break;
634 case ImmTyClampSI: OS << "ClampSI"; break;
635 case ImmTyOModSI: OS << "OModSI"; break;
636 case ImmTyDppCtrl: OS << "DppCtrl"; break;
637 case ImmTyDppRowMask: OS << "DppRowMask"; break;
638 case ImmTyDppBankMask: OS << "DppBankMask"; break;
639 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
640 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
641 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
642 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
643 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
644 case ImmTyDMask: OS << "DMask"; break;
645 case ImmTyUNorm: OS << "UNorm"; break;
646 case ImmTyDA: OS << "DA"; break;
647 case ImmTyR128: OS << "R128"; break;
648 case ImmTyLWE: OS << "LWE"; break;
649 case ImmTyOff: OS << "Off"; break;
650 case ImmTyExpTgt: OS << "ExpTgt"; break;
651 case ImmTyExpCompr: OS << "ExpCompr"; break;
652 case ImmTyExpVM: OS << "ExpVM"; break;
653 case ImmTyHwreg: OS << "Hwreg"; break;
654 case ImmTySendMsg: OS << "SendMsg"; break;
655 case ImmTyInterpSlot: OS << "InterpSlot"; break;
656 case ImmTyInterpAttr: OS << "InterpAttr"; break;
657 case ImmTyAttrChan: OS << "AttrChan"; break;
658 case ImmTyOpSel: OS << "OpSel"; break;
659 case ImmTyOpSelHi: OS << "OpSelHi"; break;
660 case ImmTyNegLo: OS << "NegLo"; break;
661 case ImmTyNegHi: OS << "NegHi"; break;
665 void print(raw_ostream &OS) const override {
668 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
671 OS << '<' << getImm();
672 if (getImmTy() != ImmTyNone) {
673 OS << " type: "; printImmTy(OS, getImmTy());
675 OS << " mods: " << Imm.Mods << '>';
678 OS << '\'' << getToken() << '\'';
681 OS << "<expr " << *Expr << '>';
686 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
687 int64_t Val, SMLoc Loc,
688 ImmTy Type = ImmTyNone,
689 bool IsFPImm = false) {
690 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
692 Op->Imm.IsFPImm = IsFPImm;
694 Op->Imm.Mods = Modifiers();
700 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
701 StringRef Str, SMLoc Loc,
702 bool HasExplicitEncodingSize = true) {
703 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
704 Res->Tok.Data = Str.data();
705 Res->Tok.Length = Str.size();
711 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
712 unsigned RegNo, SMLoc S,
715 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
716 Op->Reg.RegNo = RegNo;
717 Op->Reg.Mods = Modifiers();
718 Op->Reg.IsForcedVOP3 = ForceVOP3;
724 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
725 const class MCExpr *Expr, SMLoc S) {
726 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
734 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
735 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
739 //===----------------------------------------------------------------------===//
741 //===----------------------------------------------------------------------===//
743 // Holds info related to the current kernel, e.g. count of SGPRs used.
744 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
745 // .amdgpu_hsa_kernel or at EOF.
746 class KernelScopeInfo {
747 int SgprIndexUnusedMin = -1;
748 int VgprIndexUnusedMin = -1;
749 MCContext *Ctx = nullptr;
751 void usesSgprAt(int i) {
752 if (i >= SgprIndexUnusedMin) {
753 SgprIndexUnusedMin = ++i;
755 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
756 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
761 void usesVgprAt(int i) {
762 if (i >= VgprIndexUnusedMin) {
763 VgprIndexUnusedMin = ++i;
765 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
766 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
772 KernelScopeInfo() = default;
774 void initialize(MCContext &Context) {
776 usesSgprAt(SgprIndexUnusedMin = -1);
777 usesVgprAt(VgprIndexUnusedMin = -1);
780 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
782 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
783 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
789 class AMDGPUAsmParser : public MCTargetAsmParser {
790 const MCInstrInfo &MII;
793 unsigned ForcedEncodingSize = 0;
794 bool ForcedDPP = false;
795 bool ForcedSDWA = false;
796 KernelScopeInfo KernelScope;
798 /// @name Auto-generated Match Functions
801 #define GET_ASSEMBLER_HEADER
802 #include "AMDGPUGenAsmMatcher.inc"
807 bool ParseAsAbsoluteExpression(uint32_t &Ret);
808 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
809 bool ParseDirectiveHSACodeObjectVersion();
810 bool ParseDirectiveHSACodeObjectISA();
811 bool ParseDirectiveCodeObjectMetadata();
812 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
813 bool ParseDirectiveAMDKernelCodeT();
814 bool ParseSectionDirectiveHSAText();
815 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
816 bool ParseDirectiveAMDGPUHsaKernel();
817 bool ParseDirectiveAMDGPUHsaModuleGlobal();
818 bool ParseDirectiveAMDGPUHsaProgramGlobal();
819 bool ParseSectionDirectiveHSADataGlobalAgent();
820 bool ParseSectionDirectiveHSADataGlobalProgram();
821 bool ParseSectionDirectiveHSARodataReadonlyAgent();
822 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
823 RegisterKind RegKind, unsigned Reg1,
825 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
826 unsigned& RegNum, unsigned& RegWidth,
827 unsigned *DwordRegIndex);
828 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
829 bool IsAtomic, bool IsAtomicReturn);
830 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
831 bool IsGdsHardcoded);
834 enum AMDGPUMatchResultTy {
835 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
838 typedef std::map<AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
840 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
841 const MCInstrInfo &MII,
842 const MCTargetOptions &Options)
843 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser) {
844 MCAsmParserExtension::Initialize(Parser);
846 if (getFeatureBits().none()) {
847 // Set default features.
848 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
851 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
854 // TODO: make those pre-defined variables read-only.
855 // Currently there is none suitable machinery in the core llvm-mc for this.
856 // MCSymbol::isRedefinable is intended for another purpose, and
857 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
858 AMDGPU::IsaInfo::IsaVersion ISA =
859 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
860 MCContext &Ctx = getContext();
862 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
863 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
864 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
865 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
866 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
867 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
869 KernelScope.initialize(getContext());
873 return AMDGPU::isSI(getSTI());
877 return AMDGPU::isCI(getSTI());
881 return AMDGPU::isVI(getSTI());
884 bool isGFX9() const {
885 return AMDGPU::isGFX9(getSTI());
888 bool hasInv2PiInlineImm() const {
889 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
892 bool hasSGPR102_SGPR103() const {
896 AMDGPUTargetStreamer &getTargetStreamer() {
897 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
898 return static_cast<AMDGPUTargetStreamer &>(TS);
901 const MCRegisterInfo *getMRI() const {
902 // We need this const_cast because for some reason getContext() is not const
904 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
907 const MCInstrInfo *getMII() const {
911 const FeatureBitset &getFeatureBits() const {
912 return getSTI().getFeatureBits();
915 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
916 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
917 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
919 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
920 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
921 bool isForcedDPP() const { return ForcedDPP; }
922 bool isForcedSDWA() const { return ForcedSDWA; }
923 ArrayRef<unsigned> getMatchedVariants() const;
925 std::unique_ptr<AMDGPUOperand> parseRegister();
926 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
927 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
928 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
929 unsigned Kind) override;
930 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
931 OperandVector &Operands, MCStreamer &Out,
933 bool MatchingInlineAsm) override;
934 bool ParseDirective(AsmToken DirectiveID) override;
935 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
936 StringRef parseMnemonicSuffix(StringRef Name);
937 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
938 SMLoc NameLoc, OperandVector &Operands) override;
939 //bool ProcessInstruction(MCInst &Inst);
941 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
944 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
945 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
946 bool (*ConvertResult)(int64_t &) = nullptr);
948 OperandMatchResultTy parseOperandArrayWithPrefix(
950 OperandVector &Operands,
951 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
952 bool (*ConvertResult)(int64_t&) = nullptr);
955 parseNamedBit(const char *Name, OperandVector &Operands,
956 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
957 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
960 bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
961 OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
962 OperandMatchResultTy parseReg(OperandVector &Operands);
963 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
964 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
965 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
966 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
967 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
968 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
970 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
971 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
972 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
973 void cvtExp(MCInst &Inst, const OperandVector &Operands);
975 bool parseCnt(int64_t &IntVal);
976 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
977 OperandMatchResultTy parseHwreg(OperandVector &Operands);
980 struct OperandInfoTy {
983 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
986 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
987 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
990 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
992 bool validateOperandLimitations(const MCInst &Inst);
993 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
994 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
995 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
998 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1000 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1001 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1002 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1003 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1004 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1006 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1007 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1008 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1009 AMDGPUOperand::Ptr defaultGLC() const;
1010 AMDGPUOperand::Ptr defaultSLC() const;
1011 AMDGPUOperand::Ptr defaultTFE() const;
1013 AMDGPUOperand::Ptr defaultDMask() const;
1014 AMDGPUOperand::Ptr defaultUNorm() const;
1015 AMDGPUOperand::Ptr defaultDA() const;
1016 AMDGPUOperand::Ptr defaultR128() const;
1017 AMDGPUOperand::Ptr defaultLWE() const;
1018 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1019 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1020 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1022 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1024 void cvtId(MCInst &Inst, const OperandVector &Operands);
1025 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
1027 void cvtVOP3Impl(MCInst &Inst,
1028 const OperandVector &Operands,
1029 OptionalImmIndexMap &OptionalIdx);
1030 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1031 void cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands);
1032 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1034 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
1035 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1037 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1038 AMDGPUOperand::Ptr defaultRowMask() const;
1039 AMDGPUOperand::Ptr defaultBankMask() const;
1040 AMDGPUOperand::Ptr defaultBoundCtrl() const;
1041 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1043 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1044 AMDGPUOperand::ImmTy Type);
1045 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1046 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1047 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1048 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1049 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1050 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1051 uint64_t BasicInstType, bool skipVcc = false);
1054 struct OptionalOperand {
1056 AMDGPUOperand::ImmTy Type;
1058 bool (*ConvertResult)(int64_t&);
1061 } // end anonymous namespace
1063 // May be called with integer type with equivalent bitwidth.
1064 static const fltSemantics *getFltSemantics(unsigned Size) {
1067 return &APFloat::IEEEsingle();
1069 return &APFloat::IEEEdouble();
1071 return &APFloat::IEEEhalf();
1073 llvm_unreachable("unsupported fp type");
1077 static const fltSemantics *getFltSemantics(MVT VT) {
1078 return getFltSemantics(VT.getSizeInBits() / 8);
1081 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1082 switch (OperandType) {
1083 case AMDGPU::OPERAND_REG_IMM_INT32:
1084 case AMDGPU::OPERAND_REG_IMM_FP32:
1085 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1086 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1087 return &APFloat::IEEEsingle();
1088 case AMDGPU::OPERAND_REG_IMM_INT64:
1089 case AMDGPU::OPERAND_REG_IMM_FP64:
1090 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1091 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1092 return &APFloat::IEEEdouble();
1093 case AMDGPU::OPERAND_REG_IMM_INT16:
1094 case AMDGPU::OPERAND_REG_IMM_FP16:
1095 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1096 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1097 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1098 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1099 return &APFloat::IEEEhalf();
1101 llvm_unreachable("unsupported fp type");
1105 //===----------------------------------------------------------------------===//
1107 //===----------------------------------------------------------------------===//
1109 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1112 // Convert literal to single precision
1113 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1114 APFloat::rmNearestTiesToEven,
1116 // We allow precision lost but not overflow or underflow
1117 if (Status != APFloat::opOK &&
1119 ((Status & APFloat::opOverflow) != 0 ||
1120 (Status & APFloat::opUnderflow) != 0)) {
1127 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1128 if (!isImmTy(ImmTyNone)) {
1129 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1132 // TODO: We should avoid using host float here. It would be better to
1133 // check the float bit values which is what a few other places do.
1134 // We've had bot failures before due to weird NaN support on mips hosts.
1136 APInt Literal(64, Imm.Val);
1138 if (Imm.IsFPImm) { // We got fp literal token
1139 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1140 return AMDGPU::isInlinableLiteral64(Imm.Val,
1141 AsmParser->hasInv2PiInlineImm());
1144 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1145 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1148 if (type.getScalarSizeInBits() == 16) {
1149 return AMDGPU::isInlinableLiteral16(
1150 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1151 AsmParser->hasInv2PiInlineImm());
1154 // Check if single precision literal is inlinable
1155 return AMDGPU::isInlinableLiteral32(
1156 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1157 AsmParser->hasInv2PiInlineImm());
1160 // We got int literal token.
1161 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1162 return AMDGPU::isInlinableLiteral64(Imm.Val,
1163 AsmParser->hasInv2PiInlineImm());
1166 if (type.getScalarSizeInBits() == 16) {
1167 return AMDGPU::isInlinableLiteral16(
1168 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1169 AsmParser->hasInv2PiInlineImm());
1172 return AMDGPU::isInlinableLiteral32(
1173 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1174 AsmParser->hasInv2PiInlineImm());
1177 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1178 // Check that this imediate can be added as literal
1179 if (!isImmTy(ImmTyNone)) {
1184 // We got int literal token.
1186 if (type == MVT::f64 && hasFPModifiers()) {
1187 // Cannot apply fp modifiers to int literals preserving the same semantics
1188 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1189 // disable these cases.
1193 unsigned Size = type.getSizeInBits();
1197 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1199 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1202 // We got fp literal token
1203 if (type == MVT::f64) { // Expected 64-bit fp operand
1204 // We would set low 64-bits of literal to zeroes but we accept this literals
1208 if (type == MVT::i64) { // Expected 64-bit int operand
1209 // We don't allow fp literals in 64-bit integer instructions. It is
1210 // unclear how we should encode them.
1214 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1215 return canLosslesslyConvertToFPType(FPLiteral, type);
1218 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1219 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1222 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1224 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1225 assert(Size == 2 || Size == 4 || Size == 8);
1227 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1239 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1241 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1242 Inst.getNumOperands())) {
1243 addLiteralImmOperand(Inst, Imm.Val,
1245 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1247 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1248 Inst.addOperand(MCOperand::createImm(Imm.Val));
1252 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1253 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1254 auto OpNum = Inst.getNumOperands();
1255 // Check that this operand accepts literals
1256 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1258 if (ApplyModifiers) {
1259 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1260 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1261 Val = applyInputFPModifiers(Val, Size);
1264 APInt Literal(64, Val);
1265 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1267 if (Imm.IsFPImm) { // We got fp literal token
1269 case AMDGPU::OPERAND_REG_IMM_INT64:
1270 case AMDGPU::OPERAND_REG_IMM_FP64:
1271 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1272 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1273 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1274 AsmParser->hasInv2PiInlineImm())) {
1275 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1280 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1281 // For fp operands we check if low 32 bits are zeros
1282 if (Literal.getLoBits(32) != 0) {
1283 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1284 "Can't encode literal as exact 64-bit floating-point operand. "
1285 "Low 32-bits will be set to zero");
1288 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1292 // We don't allow fp literals in 64-bit integer instructions. It is
1293 // unclear how we should encode them. This case should be checked earlier
1294 // in predicate methods (isLiteralImm())
1295 llvm_unreachable("fp literal in 64-bit integer instruction.");
1297 case AMDGPU::OPERAND_REG_IMM_INT32:
1298 case AMDGPU::OPERAND_REG_IMM_FP32:
1299 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1300 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1301 case AMDGPU::OPERAND_REG_IMM_INT16:
1302 case AMDGPU::OPERAND_REG_IMM_FP16:
1303 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1304 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1305 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1306 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1308 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1309 // Convert literal to single precision
1310 FPLiteral.convert(*getOpFltSemantics(OpTy),
1311 APFloat::rmNearestTiesToEven, &lost);
1312 // We allow precision lost but not overflow or underflow. This should be
1313 // checked earlier in isLiteralImm()
1315 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1316 if (OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
1317 OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
1318 ImmVal |= (ImmVal << 16);
1321 Inst.addOperand(MCOperand::createImm(ImmVal));
1325 llvm_unreachable("invalid operand size");
1331 // We got int literal token.
1332 // Only sign extend inline immediates.
1333 // FIXME: No errors on truncation
1335 case AMDGPU::OPERAND_REG_IMM_INT32:
1336 case AMDGPU::OPERAND_REG_IMM_FP32:
1337 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1338 case AMDGPU::OPERAND_REG_INLINE_C_FP32: {
1339 if (isInt<32>(Val) &&
1340 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1341 AsmParser->hasInv2PiInlineImm())) {
1342 Inst.addOperand(MCOperand::createImm(Val));
1346 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1349 case AMDGPU::OPERAND_REG_IMM_INT64:
1350 case AMDGPU::OPERAND_REG_IMM_FP64:
1351 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1352 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1353 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1354 Inst.addOperand(MCOperand::createImm(Val));
1358 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1361 case AMDGPU::OPERAND_REG_IMM_INT16:
1362 case AMDGPU::OPERAND_REG_IMM_FP16:
1363 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1364 case AMDGPU::OPERAND_REG_INLINE_C_FP16: {
1365 if (isInt<16>(Val) &&
1366 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1367 AsmParser->hasInv2PiInlineImm())) {
1368 Inst.addOperand(MCOperand::createImm(Val));
1372 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1375 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1376 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1377 auto LiteralVal = static_cast<uint16_t>(Literal.getLoBits(16).getZExtValue());
1378 assert(AMDGPU::isInlinableLiteral16(LiteralVal,
1379 AsmParser->hasInv2PiInlineImm()));
1381 uint32_t ImmVal = static_cast<uint32_t>(LiteralVal) << 16 |
1382 static_cast<uint32_t>(LiteralVal);
1383 Inst.addOperand(MCOperand::createImm(ImmVal));
1387 llvm_unreachable("invalid operand size");
1391 template <unsigned Bitwidth>
1392 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1393 APInt Literal(64, Imm.Val);
1396 // We got int literal token.
1397 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1402 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1403 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1404 APFloat::rmNearestTiesToEven, &Lost);
1405 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1408 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1409 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1412 //===----------------------------------------------------------------------===//
1414 //===----------------------------------------------------------------------===//
1416 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1417 if (Is == IS_VGPR) {
1420 case 1: return AMDGPU::VGPR_32RegClassID;
1421 case 2: return AMDGPU::VReg_64RegClassID;
1422 case 3: return AMDGPU::VReg_96RegClassID;
1423 case 4: return AMDGPU::VReg_128RegClassID;
1424 case 8: return AMDGPU::VReg_256RegClassID;
1425 case 16: return AMDGPU::VReg_512RegClassID;
1427 } else if (Is == IS_TTMP) {
1430 case 1: return AMDGPU::TTMP_32RegClassID;
1431 case 2: return AMDGPU::TTMP_64RegClassID;
1432 case 4: return AMDGPU::TTMP_128RegClassID;
1434 } else if (Is == IS_SGPR) {
1437 case 1: return AMDGPU::SGPR_32RegClassID;
1438 case 2: return AMDGPU::SGPR_64RegClassID;
1439 case 4: return AMDGPU::SGPR_128RegClassID;
1440 case 8: return AMDGPU::SReg_256RegClassID;
1441 case 16: return AMDGPU::SReg_512RegClassID;
1447 static unsigned getSpecialRegForName(StringRef RegName) {
1448 return StringSwitch<unsigned>(RegName)
1449 .Case("exec", AMDGPU::EXEC)
1450 .Case("vcc", AMDGPU::VCC)
1451 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1452 .Case("m0", AMDGPU::M0)
1453 .Case("scc", AMDGPU::SCC)
1454 .Case("tba", AMDGPU::TBA)
1455 .Case("tma", AMDGPU::TMA)
1456 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1457 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1458 .Case("vcc_lo", AMDGPU::VCC_LO)
1459 .Case("vcc_hi", AMDGPU::VCC_HI)
1460 .Case("exec_lo", AMDGPU::EXEC_LO)
1461 .Case("exec_hi", AMDGPU::EXEC_HI)
1462 .Case("tma_lo", AMDGPU::TMA_LO)
1463 .Case("tma_hi", AMDGPU::TMA_HI)
1464 .Case("tba_lo", AMDGPU::TBA_LO)
1465 .Case("tba_hi", AMDGPU::TBA_HI)
1469 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1471 auto R = parseRegister();
1472 if (!R) return true;
1474 RegNo = R->getReg();
1475 StartLoc = R->getStartLoc();
1476 EndLoc = R->getEndLoc();
1480 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1481 RegisterKind RegKind, unsigned Reg1,
1485 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1490 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1491 Reg = AMDGPU::FLAT_SCR;
1495 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1500 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1505 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1514 if (Reg1 != Reg + RegWidth) {
1520 llvm_unreachable("unexpected register kind");
1524 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1525 unsigned &RegNum, unsigned &RegWidth,
1526 unsigned *DwordRegIndex) {
1527 if (DwordRegIndex) { *DwordRegIndex = 0; }
1528 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1529 if (getLexer().is(AsmToken::Identifier)) {
1530 StringRef RegName = Parser.getTok().getString();
1531 if ((Reg = getSpecialRegForName(RegName))) {
1533 RegKind = IS_SPECIAL;
1535 unsigned RegNumIndex = 0;
1536 if (RegName[0] == 'v') {
1539 } else if (RegName[0] == 's') {
1542 } else if (RegName.startswith("ttmp")) {
1543 RegNumIndex = strlen("ttmp");
1548 if (RegName.size() > RegNumIndex) {
1549 // Single 32-bit register: vXX.
1550 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1555 // Range of registers: v[XX:YY]. ":YY" is optional.
1557 int64_t RegLo, RegHi;
1558 if (getLexer().isNot(AsmToken::LBrac))
1562 if (getParser().parseAbsoluteExpression(RegLo))
1565 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1566 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1573 if (getParser().parseAbsoluteExpression(RegHi))
1576 if (getLexer().isNot(AsmToken::RBrac))
1580 RegNum = (unsigned) RegLo;
1581 RegWidth = (RegHi - RegLo) + 1;
1584 } else if (getLexer().is(AsmToken::LBrac)) {
1585 // List of consecutive registers: [s0,s1,s2,s3]
1587 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1591 RegisterKind RegKind1;
1592 unsigned Reg1, RegNum1, RegWidth1;
1594 if (getLexer().is(AsmToken::Comma)) {
1596 } else if (getLexer().is(AsmToken::RBrac)) {
1599 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1600 if (RegWidth1 != 1) {
1603 if (RegKind1 != RegKind) {
1606 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1626 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1627 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1628 Size = std::min(RegWidth, 4u);
1630 if (RegNum % Size != 0)
1632 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1633 RegNum = RegNum / Size;
1634 int RCID = getRegClass(RegKind, RegWidth);
1637 const MCRegisterClass RC = TRI->getRegClass(RCID);
1638 if (RegNum >= RC.getNumRegs())
1640 Reg = RC.getRegister(RegNum);
1645 llvm_unreachable("unexpected register kind");
1648 if (!subtargetHasRegister(*TRI, Reg))
1653 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1654 const auto &Tok = Parser.getTok();
1655 SMLoc StartLoc = Tok.getLoc();
1656 SMLoc EndLoc = Tok.getEndLoc();
1657 RegisterKind RegKind;
1658 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1660 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1663 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1664 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1668 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) {
1669 if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) &&
1670 (getLexer().getKind() == AsmToken::Integer ||
1671 getLexer().getKind() == AsmToken::Real)) {
1673 // This is a workaround for handling operands like these:
1676 // This syntax is not compatible with syntax of standard
1677 // MC expressions (due to the trailing '|').
1682 if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1686 return !Expr->evaluateAsAbsolute(Val);
1689 return getParser().parseAbsoluteExpression(Val);
1692 OperandMatchResultTy
1693 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
1694 // TODO: add syntactic sugar for 1/(2*PI)
1696 if (getLexer().getKind() == AsmToken::Minus) {
1701 SMLoc S = Parser.getTok().getLoc();
1702 switch(getLexer().getKind()) {
1703 case AsmToken::Integer: {
1705 if (parseAbsoluteExpr(IntVal, AbsMod))
1706 return MatchOperand_ParseFail;
1709 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1710 return MatchOperand_Success;
1712 case AsmToken::Real: {
1714 if (parseAbsoluteExpr(IntVal, AbsMod))
1715 return MatchOperand_ParseFail;
1717 APFloat F(BitsToDouble(IntVal));
1721 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1722 AMDGPUOperand::ImmTyNone, true));
1723 return MatchOperand_Success;
1726 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1730 OperandMatchResultTy
1731 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1732 if (auto R = parseRegister()) {
1734 R->Reg.IsForcedVOP3 = isForcedVOP3();
1735 Operands.push_back(std::move(R));
1736 return MatchOperand_Success;
1738 return MatchOperand_NoMatch;
1741 OperandMatchResultTy
1742 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
1743 auto res = parseImm(Operands, AbsMod);
1744 if (res != MatchOperand_NoMatch) {
1748 return parseReg(Operands);
1751 OperandMatchResultTy
1752 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
1754 bool Negate = false, Negate2 = false, Abs = false, Abs2 = false;
1756 if (getLexer().getKind()== AsmToken::Minus) {
1757 const AsmToken NextToken = getLexer().peekTok();
1759 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
1760 if (NextToken.is(AsmToken::Minus)) {
1761 Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier");
1762 return MatchOperand_ParseFail;
1765 // '-' followed by an integer literal N should be interpreted as integer
1766 // negation rather than a floating-point NEG modifier applied to N.
1767 // Beside being contr-intuitive, such use of floating-point NEG modifier
1768 // results in different meaning of integer literals used with VOP1/2/C
1769 // and VOP3, for example:
1770 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
1771 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
1772 // Negative fp literals should be handled likewise for unifomtity
1773 if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) {
1779 if (getLexer().getKind() == AsmToken::Identifier &&
1780 Parser.getTok().getString() == "neg") {
1782 Error(Parser.getTok().getLoc(), "expected register or immediate");
1783 return MatchOperand_ParseFail;
1787 if (getLexer().isNot(AsmToken::LParen)) {
1788 Error(Parser.getTok().getLoc(), "expected left paren after neg");
1789 return MatchOperand_ParseFail;
1794 if (getLexer().getKind() == AsmToken::Identifier &&
1795 Parser.getTok().getString() == "abs") {
1798 if (getLexer().isNot(AsmToken::LParen)) {
1799 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1800 return MatchOperand_ParseFail;
1805 if (getLexer().getKind() == AsmToken::Pipe) {
1807 Error(Parser.getTok().getLoc(), "expected register or immediate");
1808 return MatchOperand_ParseFail;
1814 OperandMatchResultTy Res;
1816 Res = parseRegOrImm(Operands, Abs);
1818 Res = parseReg(Operands);
1820 if (Res != MatchOperand_Success) {
1824 AMDGPUOperand::Modifiers Mods;
1826 if (getLexer().getKind() != AsmToken::Pipe) {
1827 Error(Parser.getTok().getLoc(), "expected vertical bar");
1828 return MatchOperand_ParseFail;
1834 if (getLexer().isNot(AsmToken::RParen)) {
1835 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1836 return MatchOperand_ParseFail;
1844 } else if (Negate2) {
1845 if (getLexer().isNot(AsmToken::RParen)) {
1846 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1847 return MatchOperand_ParseFail;
1853 if (Mods.hasFPModifiers()) {
1854 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1855 Op.setModifiers(Mods);
1857 return MatchOperand_Success;
1860 OperandMatchResultTy
1861 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
1865 if (getLexer().getKind() == AsmToken::Identifier &&
1866 Parser.getTok().getString() == "sext") {
1869 if (getLexer().isNot(AsmToken::LParen)) {
1870 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1871 return MatchOperand_ParseFail;
1876 OperandMatchResultTy Res;
1878 Res = parseRegOrImm(Operands);
1880 Res = parseReg(Operands);
1882 if (Res != MatchOperand_Success) {
1886 AMDGPUOperand::Modifiers Mods;
1888 if (getLexer().isNot(AsmToken::RParen)) {
1889 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1890 return MatchOperand_ParseFail;
1896 if (Mods.hasIntModifiers()) {
1897 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1898 Op.setModifiers(Mods);
1901 return MatchOperand_Success;
1904 OperandMatchResultTy
1905 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1906 return parseRegOrImmWithFPInputMods(Operands, false);
1909 OperandMatchResultTy
1910 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1911 return parseRegOrImmWithIntInputMods(Operands, false);
1914 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1915 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1917 Operands.push_back(std::move(Reg));
1918 return MatchOperand_Success;
1921 const AsmToken &Tok = Parser.getTok();
1922 if (Tok.getString() == "off") {
1923 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1924 AMDGPUOperand::ImmTyOff, false));
1926 return MatchOperand_Success;
1929 return MatchOperand_NoMatch;
1932 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1933 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1935 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1936 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1937 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1938 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1939 return Match_InvalidOperand;
1941 if ((TSFlags & SIInstrFlags::VOP3) &&
1942 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1943 getForcedEncodingSize() != 64)
1944 return Match_PreferE32;
1946 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1947 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1948 // v_mac_f32/16 allow only dst_sel == DWORD;
1950 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1951 const auto &Op = Inst.getOperand(OpNum);
1952 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1953 return Match_InvalidOperand;
1957 return Match_Success;
1960 // What asm variants we should check
1961 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
1962 if (getForcedEncodingSize() == 32) {
1963 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
1964 return makeArrayRef(Variants);
1967 if (isForcedVOP3()) {
1968 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
1969 return makeArrayRef(Variants);
1972 if (isForcedSDWA()) {
1973 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
1974 AMDGPUAsmVariants::SDWA9};
1975 return makeArrayRef(Variants);
1978 if (isForcedDPP()) {
1979 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
1980 return makeArrayRef(Variants);
1983 static const unsigned Variants[] = {
1984 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
1985 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
1988 return makeArrayRef(Variants);
1991 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
1992 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
1993 const unsigned Num = Desc.getNumImplicitUses();
1994 for (unsigned i = 0; i < Num; ++i) {
1995 unsigned Reg = Desc.ImplicitUses[i];
1997 case AMDGPU::FLAT_SCR:
2005 return AMDGPU::NoRegister;
2008 // NB: This code is correct only when used to check constant
2009 // bus limitations because GFX7 support no f16 inline constants.
2010 // Note that there are no cases when a GFX7 opcode violates
2011 // constant bus limitations due to the use of an f16 constant.
2012 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2013 unsigned OpIdx) const {
2014 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2016 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2020 const MCOperand &MO = Inst.getOperand(OpIdx);
2022 int64_t Val = MO.getImm();
2023 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2025 switch (OpSize) { // expected operand size
2027 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2029 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2031 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2032 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2033 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
2034 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2036 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2040 llvm_unreachable("invalid operand size");
2044 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2045 const MCOperand &MO = Inst.getOperand(OpIdx);
2047 return !isInlineConstant(Inst, OpIdx);
2049 return !MO.isReg() ||
2050 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
2053 bool AMDGPUAsmParser::validateOperandLimitations(const MCInst &Inst) {
2054 const unsigned Opcode = Inst.getOpcode();
2055 const MCInstrDesc &Desc = MII.get(Opcode);
2056 unsigned ConstantBusUseCount = 0;
2059 (SIInstrFlags::VOPC |
2060 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
2061 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2062 SIInstrFlags::SDWA)) {
2064 // Check special imm operands (used by madmk, etc)
2065 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2066 ++ConstantBusUseCount;
2069 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2070 if (SGPRUsed != AMDGPU::NoRegister) {
2071 ++ConstantBusUseCount;
2074 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2075 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2076 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2078 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2080 for (int OpIdx : OpIndices) {
2081 if (OpIdx == -1) break;
2083 const MCOperand &MO = Inst.getOperand(OpIdx);
2084 if (usesConstantBus(Inst, OpIdx)) {
2086 const unsigned Reg = mc2PseudoReg(MO.getReg());
2087 // Pairs of registers with a partial intersections like these
2089 // flat_scratch_lo, flat_scratch
2090 // flat_scratch_lo, flat_scratch_hi
2091 // are theoretically valid but they are disabled anyway.
2092 // Note that this code mimics SIInstrInfo::verifyInstruction
2093 if (Reg != SGPRUsed) {
2094 ++ConstantBusUseCount;
2097 } else { // Expression or a literal
2098 ++ConstantBusUseCount;
2104 return ConstantBusUseCount <= 1;
2107 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2108 OperandVector &Operands,
2110 uint64_t &ErrorInfo,
2111 bool MatchingInlineAsm) {
2113 unsigned Result = Match_Success;
2114 for (auto Variant : getMatchedVariants()) {
2116 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2118 // We order match statuses from least to most specific. We use most specific
2119 // status as resulting
2120 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
2121 if ((R == Match_Success) ||
2122 (R == Match_PreferE32) ||
2123 (R == Match_MissingFeature && Result != Match_PreferE32) ||
2124 (R == Match_InvalidOperand && Result != Match_MissingFeature
2125 && Result != Match_PreferE32) ||
2126 (R == Match_MnemonicFail && Result != Match_InvalidOperand
2127 && Result != Match_MissingFeature
2128 && Result != Match_PreferE32)) {
2132 if (R == Match_Success)
2139 if (!validateOperandLimitations(Inst)) {
2141 "invalid operand (violates constant bus restrictions)");
2144 Out.EmitInstruction(Inst, getSTI());
2147 case Match_MissingFeature:
2148 return Error(IDLoc, "instruction not supported on this GPU");
2150 case Match_MnemonicFail:
2151 return Error(IDLoc, "unrecognized instruction mnemonic");
2153 case Match_InvalidOperand: {
2154 SMLoc ErrorLoc = IDLoc;
2155 if (ErrorInfo != ~0ULL) {
2156 if (ErrorInfo >= Operands.size()) {
2157 return Error(IDLoc, "too few operands for instruction");
2159 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2160 if (ErrorLoc == SMLoc())
2163 return Error(ErrorLoc, "invalid operand for instruction");
2166 case Match_PreferE32:
2167 return Error(IDLoc, "internal error: instruction without _e64 suffix "
2168 "should be encoded as e32");
2170 llvm_unreachable("Implement any new match types added!");
2173 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
2175 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
2178 if (getParser().parseAbsoluteExpression(Tmp)) {
2181 Ret = static_cast<uint32_t>(Tmp);
2185 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
2187 if (ParseAsAbsoluteExpression(Major))
2188 return TokError("invalid major version");
2190 if (getLexer().isNot(AsmToken::Comma))
2191 return TokError("minor version number required, comma expected");
2194 if (ParseAsAbsoluteExpression(Minor))
2195 return TokError("invalid minor version");
2200 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2204 if (ParseDirectiveMajorMinor(Major, Minor))
2207 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2211 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2215 StringRef VendorName;
2218 // If this directive has no arguments, then use the ISA version for the
2220 if (getLexer().is(AsmToken::EndOfStatement)) {
2221 AMDGPU::IsaInfo::IsaVersion ISA =
2222 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2223 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2229 if (ParseDirectiveMajorMinor(Major, Minor))
2232 if (getLexer().isNot(AsmToken::Comma))
2233 return TokError("stepping version number required, comma expected");
2236 if (ParseAsAbsoluteExpression(Stepping))
2237 return TokError("invalid stepping version");
2239 if (getLexer().isNot(AsmToken::Comma))
2240 return TokError("vendor name required, comma expected");
2243 if (getLexer().isNot(AsmToken::String))
2244 return TokError("invalid vendor name");
2246 VendorName = getLexer().getTok().getStringContents();
2249 if (getLexer().isNot(AsmToken::Comma))
2250 return TokError("arch name required, comma expected");
2253 if (getLexer().isNot(AsmToken::String))
2254 return TokError("invalid arch name");
2256 ArchName = getLexer().getTok().getStringContents();
2259 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2260 VendorName, ArchName);
2264 bool AMDGPUAsmParser::ParseDirectiveCodeObjectMetadata() {
2265 std::string YamlString;
2266 raw_string_ostream YamlStream(YamlString);
2268 getLexer().setSkipSpace(false);
2270 bool FoundEnd = false;
2271 while (!getLexer().is(AsmToken::Eof)) {
2272 while (getLexer().is(AsmToken::Space)) {
2273 YamlStream << getLexer().getTok().getString();
2277 if (getLexer().is(AsmToken::Identifier)) {
2278 StringRef ID = getLexer().getTok().getIdentifier();
2279 if (ID == AMDGPU::CodeObject::MetadataAssemblerDirectiveEnd) {
2286 YamlStream << Parser.parseStringToEndOfStatement()
2287 << getContext().getAsmInfo()->getSeparatorString();
2289 Parser.eatToEndOfStatement();
2292 getLexer().setSkipSpace(true);
2294 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
2296 "expected directive .end_amdgpu_code_object_metadata not found");
2301 if (!getTargetStreamer().EmitCodeObjectMetadata(YamlString))
2302 return Error(getParser().getTok().getLoc(), "invalid code object metadata");
2307 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
2308 amd_kernel_code_t &Header) {
2309 SmallString<40> ErrStr;
2310 raw_svector_ostream Err(ErrStr);
2311 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
2312 return TokError(Err.str());
2318 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
2319 amd_kernel_code_t Header;
2320 AMDGPU::initDefaultAMDKernelCodeT(Header, getFeatureBits());
2323 // Lex EndOfStatement. This is in a while loop, because lexing a comment
2324 // will set the current token to EndOfStatement.
2325 while(getLexer().is(AsmToken::EndOfStatement))
2328 if (getLexer().isNot(AsmToken::Identifier))
2329 return TokError("expected value identifier or .end_amd_kernel_code_t");
2331 StringRef ID = getLexer().getTok().getIdentifier();
2334 if (ID == ".end_amd_kernel_code_t")
2337 if (ParseAMDKernelCodeTValue(ID, Header))
2341 getTargetStreamer().EmitAMDKernelCodeT(Header);
2346 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
2347 getParser().getStreamer().SwitchSection(
2348 AMDGPU::getHSATextSection(getContext()));
2352 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
2353 if (getLexer().isNot(AsmToken::Identifier))
2354 return TokError("expected symbol name");
2356 StringRef KernelName = Parser.getTok().getString();
2358 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
2359 ELF::STT_AMDGPU_HSA_KERNEL);
2361 KernelScope.initialize(getContext());
2365 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
2366 if (getLexer().isNot(AsmToken::Identifier))
2367 return TokError("expected symbol name");
2369 StringRef GlobalName = Parser.getTok().getIdentifier();
2371 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
2376 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
2377 if (getLexer().isNot(AsmToken::Identifier))
2378 return TokError("expected symbol name");
2380 StringRef GlobalName = Parser.getTok().getIdentifier();
2382 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
2387 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
2388 getParser().getStreamer().SwitchSection(
2389 AMDGPU::getHSADataGlobalAgentSection(getContext()));
2393 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
2394 getParser().getStreamer().SwitchSection(
2395 AMDGPU::getHSADataGlobalProgramSection(getContext()));
2399 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
2400 getParser().getStreamer().SwitchSection(
2401 AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
2405 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2406 StringRef IDVal = DirectiveID.getString();
2408 if (IDVal == ".hsa_code_object_version")
2409 return ParseDirectiveHSACodeObjectVersion();
2411 if (IDVal == ".hsa_code_object_isa")
2412 return ParseDirectiveHSACodeObjectISA();
2414 if (IDVal == AMDGPU::CodeObject::MetadataAssemblerDirectiveBegin)
2415 return ParseDirectiveCodeObjectMetadata();
2417 if (IDVal == ".amd_kernel_code_t")
2418 return ParseDirectiveAMDKernelCodeT();
2420 if (IDVal == ".hsatext")
2421 return ParseSectionDirectiveHSAText();
2423 if (IDVal == ".amdgpu_hsa_kernel")
2424 return ParseDirectiveAMDGPUHsaKernel();
2426 if (IDVal == ".amdgpu_hsa_module_global")
2427 return ParseDirectiveAMDGPUHsaModuleGlobal();
2429 if (IDVal == ".amdgpu_hsa_program_global")
2430 return ParseDirectiveAMDGPUHsaProgramGlobal();
2432 if (IDVal == ".hsadata_global_agent")
2433 return ParseSectionDirectiveHSADataGlobalAgent();
2435 if (IDVal == ".hsadata_global_program")
2436 return ParseSectionDirectiveHSADataGlobalProgram();
2438 if (IDVal == ".hsarodata_readonly_agent")
2439 return ParseSectionDirectiveHSARodataReadonlyAgent();
2444 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2445 unsigned RegNo) const {
2452 case AMDGPU::FLAT_SCR:
2453 case AMDGPU::FLAT_SCR_LO:
2454 case AMDGPU::FLAT_SCR_HI:
2461 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2463 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2472 OperandMatchResultTy
2473 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2474 // Try to parse with a custom parser
2475 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2477 // If we successfully parsed the operand or if there as an error parsing,
2480 // If we are parsing after we reach EndOfStatement then this means we
2481 // are appending default values to the Operands list. This is only done
2482 // by custom parser, so we shouldn't continue on to the generic parsing.
2483 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2484 getLexer().is(AsmToken::EndOfStatement))
2487 ResTy = parseRegOrImm(Operands);
2489 if (ResTy == MatchOperand_Success)
2492 if (getLexer().getKind() == AsmToken::Identifier) {
2493 // If this identifier is a symbol, we want to create an expression for it.
2494 // It is a little difficult to distinguish between a symbol name, and
2495 // an instruction flag like 'gds'. In order to do this, we parse
2496 // all tokens as expressions and then treate the symbol name as the token
2497 // string when we want to interpret the operand as a token.
2498 const auto &Tok = Parser.getTok();
2499 SMLoc S = Tok.getLoc();
2500 const MCExpr *Expr = nullptr;
2501 if (!Parser.parseExpression(Expr)) {
2502 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2503 return MatchOperand_Success;
2506 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2508 return MatchOperand_Success;
2510 return MatchOperand_NoMatch;
2513 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2514 // Clear any forced encodings from the previous instruction.
2515 setForcedEncodingSize(0);
2516 setForcedDPP(false);
2517 setForcedSDWA(false);
2519 if (Name.endswith("_e64")) {
2520 setForcedEncodingSize(64);
2521 return Name.substr(0, Name.size() - 4);
2522 } else if (Name.endswith("_e32")) {
2523 setForcedEncodingSize(32);
2524 return Name.substr(0, Name.size() - 4);
2525 } else if (Name.endswith("_dpp")) {
2527 return Name.substr(0, Name.size() - 4);
2528 } else if (Name.endswith("_sdwa")) {
2529 setForcedSDWA(true);
2530 return Name.substr(0, Name.size() - 5);
2535 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2537 SMLoc NameLoc, OperandVector &Operands) {
2538 // Add the instruction mnemonic
2539 Name = parseMnemonicSuffix(Name);
2540 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2542 while (!getLexer().is(AsmToken::EndOfStatement)) {
2543 OperandMatchResultTy Res = parseOperand(Operands, Name);
2545 // Eat the comma or space if there is one.
2546 if (getLexer().is(AsmToken::Comma))
2550 case MatchOperand_Success: break;
2551 case MatchOperand_ParseFail:
2552 Error(getLexer().getLoc(), "failed parsing operand.");
2553 while (!getLexer().is(AsmToken::EndOfStatement)) {
2557 case MatchOperand_NoMatch:
2558 Error(getLexer().getLoc(), "not a valid operand.");
2559 while (!getLexer().is(AsmToken::EndOfStatement)) {
2569 //===----------------------------------------------------------------------===//
2570 // Utility functions
2571 //===----------------------------------------------------------------------===//
2573 OperandMatchResultTy
2574 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2575 switch(getLexer().getKind()) {
2576 default: return MatchOperand_NoMatch;
2577 case AsmToken::Identifier: {
2578 StringRef Name = Parser.getTok().getString();
2579 if (!Name.equals(Prefix)) {
2580 return MatchOperand_NoMatch;
2584 if (getLexer().isNot(AsmToken::Colon))
2585 return MatchOperand_ParseFail;
2588 if (getLexer().isNot(AsmToken::Integer))
2589 return MatchOperand_ParseFail;
2591 if (getParser().parseAbsoluteExpression(Int))
2592 return MatchOperand_ParseFail;
2596 return MatchOperand_Success;
2599 OperandMatchResultTy
2600 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2601 AMDGPUOperand::ImmTy ImmTy,
2602 bool (*ConvertResult)(int64_t&)) {
2603 SMLoc S = Parser.getTok().getLoc();
2606 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2607 if (Res != MatchOperand_Success)
2610 if (ConvertResult && !ConvertResult(Value)) {
2611 return MatchOperand_ParseFail;
2614 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2615 return MatchOperand_Success;
2618 OperandMatchResultTy AMDGPUAsmParser::parseOperandArrayWithPrefix(
2620 OperandVector &Operands,
2621 AMDGPUOperand::ImmTy ImmTy,
2622 bool (*ConvertResult)(int64_t&)) {
2623 StringRef Name = Parser.getTok().getString();
2624 if (!Name.equals(Prefix))
2625 return MatchOperand_NoMatch;
2628 if (getLexer().isNot(AsmToken::Colon))
2629 return MatchOperand_ParseFail;
2632 if (getLexer().isNot(AsmToken::LBrac))
2633 return MatchOperand_ParseFail;
2637 SMLoc S = Parser.getTok().getLoc();
2639 // FIXME: How to verify the number of elements matches the number of src
2641 for (int I = 0; I < 3; ++I) {
2643 if (getLexer().is(AsmToken::RBrac))
2646 if (getLexer().isNot(AsmToken::Comma))
2647 return MatchOperand_ParseFail;
2651 if (getLexer().isNot(AsmToken::Integer))
2652 return MatchOperand_ParseFail;
2655 if (getParser().parseAbsoluteExpression(Op))
2656 return MatchOperand_ParseFail;
2658 if (Op != 0 && Op != 1)
2659 return MatchOperand_ParseFail;
2664 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
2665 return MatchOperand_Success;
2668 OperandMatchResultTy
2669 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2670 AMDGPUOperand::ImmTy ImmTy) {
2672 SMLoc S = Parser.getTok().getLoc();
2674 // We are at the end of the statement, and this is a default argument, so
2675 // use a default value.
2676 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2677 switch(getLexer().getKind()) {
2678 case AsmToken::Identifier: {
2679 StringRef Tok = Parser.getTok().getString();
2683 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2687 return MatchOperand_NoMatch;
2692 return MatchOperand_NoMatch;
2696 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2697 return MatchOperand_Success;
2700 static void addOptionalImmOperand(
2701 MCInst& Inst, const OperandVector& Operands,
2702 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
2703 AMDGPUOperand::ImmTy ImmT,
2704 int64_t Default = 0) {
2705 auto i = OptionalIdx.find(ImmT);
2706 if (i != OptionalIdx.end()) {
2707 unsigned Idx = i->second;
2708 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2710 Inst.addOperand(MCOperand::createImm(Default));
2714 OperandMatchResultTy
2715 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2716 if (getLexer().isNot(AsmToken::Identifier)) {
2717 return MatchOperand_NoMatch;
2719 StringRef Tok = Parser.getTok().getString();
2720 if (Tok != Prefix) {
2721 return MatchOperand_NoMatch;
2725 if (getLexer().isNot(AsmToken::Colon)) {
2726 return MatchOperand_ParseFail;
2730 if (getLexer().isNot(AsmToken::Identifier)) {
2731 return MatchOperand_ParseFail;
2734 Value = Parser.getTok().getString();
2735 return MatchOperand_Success;
2738 //===----------------------------------------------------------------------===//
2740 //===----------------------------------------------------------------------===//
2742 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2743 const OperandVector &Operands) {
2744 OptionalImmIndexMap OptionalIdx;
2746 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2747 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2749 // Add the register arguments
2751 Op.addRegOperands(Inst, 1);
2755 // Handle optional arguments
2756 OptionalIdx[Op.getImmTy()] = i;
2759 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2760 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2761 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2763 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2766 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
2767 bool IsGdsHardcoded) {
2768 OptionalImmIndexMap OptionalIdx;
2770 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2771 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2773 // Add the register arguments
2775 Op.addRegOperands(Inst, 1);
2779 if (Op.isToken() && Op.getToken() == "gds") {
2780 IsGdsHardcoded = true;
2784 // Handle optional arguments
2785 OptionalIdx[Op.getImmTy()] = i;
2788 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2789 if (!IsGdsHardcoded) {
2790 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2792 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2795 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2796 OptionalImmIndexMap OptionalIdx;
2798 unsigned OperandIdx[4];
2799 unsigned EnMask = 0;
2802 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2803 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2805 // Add the register arguments
2808 OperandIdx[SrcIdx] = Inst.size();
2809 Op.addRegOperands(Inst, 1);
2816 OperandIdx[SrcIdx] = Inst.size();
2817 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2822 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2823 Op.addImmOperands(Inst, 1);
2827 if (Op.isToken() && Op.getToken() == "done")
2830 // Handle optional arguments
2831 OptionalIdx[Op.getImmTy()] = i;
2834 assert(SrcIdx == 4);
2837 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
2839 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
2840 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
2841 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
2844 for (auto i = 0; i < SrcIdx; ++i) {
2845 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
2846 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
2850 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2851 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2853 Inst.addOperand(MCOperand::createImm(EnMask));
2856 //===----------------------------------------------------------------------===//
2858 //===----------------------------------------------------------------------===//
2862 const AMDGPU::IsaInfo::IsaVersion ISA,
2866 unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned),
2867 unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned))
2869 bool Failed = false;
2871 IntVal = encode(ISA, IntVal, CntVal);
2872 if (CntVal != decode(ISA, IntVal)) {
2874 IntVal = encode(ISA, IntVal, -1);
2882 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2883 StringRef CntName = Parser.getTok().getString();
2887 if (getLexer().isNot(AsmToken::LParen))
2891 if (getLexer().isNot(AsmToken::Integer))
2894 if (getParser().parseAbsoluteExpression(CntVal))
2897 AMDGPU::IsaInfo::IsaVersion ISA =
2898 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2901 bool Sat = CntName.endswith("_sat");
2903 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
2904 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
2905 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
2906 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
2907 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
2908 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
2911 // To improve diagnostics, do not skip delimiters on errors
2913 if (getLexer().isNot(AsmToken::RParen)) {
2917 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) {
2918 const AsmToken NextToken = getLexer().peekTok();
2919 if (NextToken.is(AsmToken::Identifier)) {
2928 OperandMatchResultTy
2929 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2930 AMDGPU::IsaInfo::IsaVersion ISA =
2931 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2932 int64_t Waitcnt = getWaitcntBitMask(ISA);
2933 SMLoc S = Parser.getTok().getLoc();
2935 switch(getLexer().getKind()) {
2936 default: return MatchOperand_ParseFail;
2937 case AsmToken::Integer:
2938 // The operand can be an integer value.
2939 if (getParser().parseAbsoluteExpression(Waitcnt))
2940 return MatchOperand_ParseFail;
2943 case AsmToken::Identifier:
2945 if (parseCnt(Waitcnt))
2946 return MatchOperand_ParseFail;
2947 } while(getLexer().isNot(AsmToken::EndOfStatement));
2950 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
2951 return MatchOperand_Success;
2954 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset,
2956 using namespace llvm::AMDGPU::Hwreg;
2958 if (Parser.getTok().getString() != "hwreg")
2962 if (getLexer().isNot(AsmToken::LParen))
2966 if (getLexer().is(AsmToken::Identifier)) {
2967 HwReg.IsSymbolic = true;
2968 HwReg.Id = ID_UNKNOWN_;
2969 const StringRef tok = Parser.getTok().getString();
2970 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
2971 if (tok == IdSymbolic[i]) {
2978 HwReg.IsSymbolic = false;
2979 if (getLexer().isNot(AsmToken::Integer))
2981 if (getParser().parseAbsoluteExpression(HwReg.Id))
2985 if (getLexer().is(AsmToken::RParen)) {
2991 if (getLexer().isNot(AsmToken::Comma))
2995 if (getLexer().isNot(AsmToken::Integer))
2997 if (getParser().parseAbsoluteExpression(Offset))
3000 if (getLexer().isNot(AsmToken::Comma))
3004 if (getLexer().isNot(AsmToken::Integer))
3006 if (getParser().parseAbsoluteExpression(Width))
3009 if (getLexer().isNot(AsmToken::RParen))
3016 OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
3017 using namespace llvm::AMDGPU::Hwreg;
3019 int64_t Imm16Val = 0;
3020 SMLoc S = Parser.getTok().getLoc();
3022 switch(getLexer().getKind()) {
3023 default: return MatchOperand_NoMatch;
3024 case AsmToken::Integer:
3025 // The operand can be an integer value.
3026 if (getParser().parseAbsoluteExpression(Imm16Val))
3027 return MatchOperand_NoMatch;
3028 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3029 Error(S, "invalid immediate: only 16-bit values are legal");
3030 // Do not return error code, but create an imm operand anyway and proceed
3031 // to the next operand, if any. That avoids unneccessary error messages.
3035 case AsmToken::Identifier: {
3036 OperandInfoTy HwReg(ID_UNKNOWN_);
3037 int64_t Offset = OFFSET_DEFAULT_;
3038 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
3039 if (parseHwregConstruct(HwReg, Offset, Width))
3040 return MatchOperand_ParseFail;
3041 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3042 if (HwReg.IsSymbolic)
3043 Error(S, "invalid symbolic name of hardware register");
3045 Error(S, "invalid code of hardware register: only 6-bit values are legal");
3047 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3048 Error(S, "invalid bit offset: only 5-bit values are legal");
3049 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3050 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
3051 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
3055 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3056 return MatchOperand_Success;
3059 bool AMDGPUOperand::isSWaitCnt() const {
3063 bool AMDGPUOperand::isHwreg() const {
3064 return isImmTy(ImmTyHwreg);
3067 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
3068 using namespace llvm::AMDGPU::SendMsg;
3070 if (Parser.getTok().getString() != "sendmsg")
3074 if (getLexer().isNot(AsmToken::LParen))
3078 if (getLexer().is(AsmToken::Identifier)) {
3079 Msg.IsSymbolic = true;
3080 Msg.Id = ID_UNKNOWN_;
3081 const std::string tok = Parser.getTok().getString();
3082 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
3084 default: continue; // Omit gaps.
3085 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
3087 if (tok == IdSymbolic[i]) {
3094 Msg.IsSymbolic = false;
3095 if (getLexer().isNot(AsmToken::Integer))
3097 if (getParser().parseAbsoluteExpression(Msg.Id))
3099 if (getLexer().is(AsmToken::Integer))
3100 if (getParser().parseAbsoluteExpression(Msg.Id))
3101 Msg.Id = ID_UNKNOWN_;
3103 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
3106 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
3107 if (getLexer().isNot(AsmToken::RParen))
3113 if (getLexer().isNot(AsmToken::Comma))
3117 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
3118 Operation.Id = ID_UNKNOWN_;
3119 if (getLexer().is(AsmToken::Identifier)) {
3120 Operation.IsSymbolic = true;
3121 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
3122 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
3123 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
3124 const StringRef Tok = Parser.getTok().getString();
3125 for (int i = F; i < L; ++i) {
3133 Operation.IsSymbolic = false;
3134 if (getLexer().isNot(AsmToken::Integer))
3136 if (getParser().parseAbsoluteExpression(Operation.Id))
3140 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3141 // Stream id is optional.
3142 if (getLexer().is(AsmToken::RParen)) {
3147 if (getLexer().isNot(AsmToken::Comma))
3151 if (getLexer().isNot(AsmToken::Integer))
3153 if (getParser().parseAbsoluteExpression(StreamId))
3157 if (getLexer().isNot(AsmToken::RParen))
3163 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
3164 if (getLexer().getKind() != AsmToken::Identifier)
3165 return MatchOperand_NoMatch;
3167 StringRef Str = Parser.getTok().getString();
3168 int Slot = StringSwitch<int>(Str)
3174 SMLoc S = Parser.getTok().getLoc();
3176 return MatchOperand_ParseFail;
3179 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
3180 AMDGPUOperand::ImmTyInterpSlot));
3181 return MatchOperand_Success;
3184 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
3185 if (getLexer().getKind() != AsmToken::Identifier)
3186 return MatchOperand_NoMatch;
3188 StringRef Str = Parser.getTok().getString();
3189 if (!Str.startswith("attr"))
3190 return MatchOperand_NoMatch;
3192 StringRef Chan = Str.take_back(2);
3193 int AttrChan = StringSwitch<int>(Chan)
3200 return MatchOperand_ParseFail;
3202 Str = Str.drop_back(2).drop_front(4);
3205 if (Str.getAsInteger(10, Attr))
3206 return MatchOperand_ParseFail;
3208 SMLoc S = Parser.getTok().getLoc();
3211 Error(S, "out of bounds attr");
3212 return MatchOperand_Success;
3215 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
3217 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
3218 AMDGPUOperand::ImmTyInterpAttr));
3219 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
3220 AMDGPUOperand::ImmTyAttrChan));
3221 return MatchOperand_Success;
3224 void AMDGPUAsmParser::errorExpTgt() {
3225 Error(Parser.getTok().getLoc(), "invalid exp target");
3228 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
3230 if (Str == "null") {
3232 return MatchOperand_Success;
3235 if (Str.startswith("mrt")) {
3236 Str = Str.drop_front(3);
3237 if (Str == "z") { // == mrtz
3239 return MatchOperand_Success;
3242 if (Str.getAsInteger(10, Val))
3243 return MatchOperand_ParseFail;
3248 return MatchOperand_Success;
3251 if (Str.startswith("pos")) {
3252 Str = Str.drop_front(3);
3253 if (Str.getAsInteger(10, Val))
3254 return MatchOperand_ParseFail;
3260 return MatchOperand_Success;
3263 if (Str.startswith("param")) {
3264 Str = Str.drop_front(5);
3265 if (Str.getAsInteger(10, Val))
3266 return MatchOperand_ParseFail;
3272 return MatchOperand_Success;
3275 if (Str.startswith("invalid_target_")) {
3276 Str = Str.drop_front(15);
3277 if (Str.getAsInteger(10, Val))
3278 return MatchOperand_ParseFail;
3281 return MatchOperand_Success;
3284 return MatchOperand_NoMatch;
3287 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
3289 StringRef Str = Parser.getTok().getString();
3291 auto Res = parseExpTgtImpl(Str, Val);
3292 if (Res != MatchOperand_Success)
3295 SMLoc S = Parser.getTok().getLoc();
3298 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
3299 AMDGPUOperand::ImmTyExpTgt));
3300 return MatchOperand_Success;
3303 OperandMatchResultTy
3304 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
3305 using namespace llvm::AMDGPU::SendMsg;
3307 int64_t Imm16Val = 0;
3308 SMLoc S = Parser.getTok().getLoc();
3310 switch(getLexer().getKind()) {
3312 return MatchOperand_NoMatch;
3313 case AsmToken::Integer:
3314 // The operand can be an integer value.
3315 if (getParser().parseAbsoluteExpression(Imm16Val))
3316 return MatchOperand_NoMatch;
3317 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3318 Error(S, "invalid immediate: only 16-bit values are legal");
3319 // Do not return error code, but create an imm operand anyway and proceed
3320 // to the next operand, if any. That avoids unneccessary error messages.
3323 case AsmToken::Identifier: {
3324 OperandInfoTy Msg(ID_UNKNOWN_);
3325 OperandInfoTy Operation(OP_UNKNOWN_);
3326 int64_t StreamId = STREAM_ID_DEFAULT_;
3327 if (parseSendMsgConstruct(Msg, Operation, StreamId))
3328 return MatchOperand_ParseFail;
3330 // Validate and encode message ID.
3331 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
3332 || Msg.Id == ID_SYSMSG)) {
3334 Error(S, "invalid/unsupported symbolic name of message");
3336 Error(S, "invalid/unsupported code of message");
3339 Imm16Val = (Msg.Id << ID_SHIFT_);
3340 // Validate and encode operation ID.
3341 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
3342 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
3343 if (Operation.IsSymbolic)
3344 Error(S, "invalid symbolic name of GS_OP");
3346 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
3349 if (Operation.Id == OP_GS_NOP
3350 && Msg.Id != ID_GS_DONE) {
3351 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
3354 Imm16Val |= (Operation.Id << OP_SHIFT_);
3356 if (Msg.Id == ID_SYSMSG) {
3357 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
3358 if (Operation.IsSymbolic)
3359 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
3361 Error(S, "invalid/unsupported code of SYSMSG_OP");
3364 Imm16Val |= (Operation.Id << OP_SHIFT_);
3366 // Validate and encode stream ID.
3367 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3368 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
3369 Error(S, "invalid stream id: only 2-bit values are legal");
3372 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
3378 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
3379 return MatchOperand_Success;
3382 bool AMDGPUOperand::isSendMsg() const {
3383 return isImmTy(ImmTySendMsg);
3386 //===----------------------------------------------------------------------===//
3387 // sopp branch targets
3388 //===----------------------------------------------------------------------===//
3390 OperandMatchResultTy
3391 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
3392 SMLoc S = Parser.getTok().getLoc();
3394 switch (getLexer().getKind()) {
3395 default: return MatchOperand_ParseFail;
3396 case AsmToken::Integer: {
3398 if (getParser().parseAbsoluteExpression(Imm))
3399 return MatchOperand_ParseFail;
3400 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
3401 return MatchOperand_Success;
3404 case AsmToken::Identifier:
3405 Operands.push_back(AMDGPUOperand::CreateExpr(this,
3406 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
3407 Parser.getTok().getString()), getContext()), S));
3409 return MatchOperand_Success;
3413 //===----------------------------------------------------------------------===//
3415 //===----------------------------------------------------------------------===//
3417 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
3418 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
3421 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
3422 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
3425 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
3426 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
3429 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
3430 const OperandVector &Operands,
3431 bool IsAtomic, bool IsAtomicReturn) {
3432 OptionalImmIndexMap OptionalIdx;
3433 assert(IsAtomicReturn ? IsAtomic : true);
3435 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3436 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3438 // Add the register arguments
3440 Op.addRegOperands(Inst, 1);
3444 // Handle the case where soffset is an immediate
3445 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3446 Op.addImmOperands(Inst, 1);
3450 // Handle tokens like 'offen' which are sometimes hard-coded into the
3451 // asm string. There are no MCInst operands for these.
3457 // Handle optional arguments
3458 OptionalIdx[Op.getImmTy()] = i;
3461 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
3462 if (IsAtomicReturn) {
3463 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
3467 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
3468 if (!IsAtomic) { // glc is hard-coded.
3469 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3471 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3472 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3475 //===----------------------------------------------------------------------===//
3477 //===----------------------------------------------------------------------===//
3479 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
3481 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3482 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3483 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3486 OptionalImmIndexMap OptionalIdx;
3488 for (unsigned E = Operands.size(); I != E; ++I) {
3489 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3491 // Add the register arguments
3492 if (Op.isRegOrImm()) {
3493 Op.addRegOrImmOperands(Inst, 1);
3495 } else if (Op.isImmModifier()) {
3496 OptionalIdx[Op.getImmTy()] = I;
3498 llvm_unreachable("unexpected operand type");
3502 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3503 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3504 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3505 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3506 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3507 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3508 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3509 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3512 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
3514 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3515 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3516 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3519 // Add src, same as dst
3520 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
3522 OptionalImmIndexMap OptionalIdx;
3524 for (unsigned E = Operands.size(); I != E; ++I) {
3525 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3527 // Add the register arguments
3528 if (Op.isRegOrImm()) {
3529 Op.addRegOrImmOperands(Inst, 1);
3531 } else if (Op.isImmModifier()) {
3532 OptionalIdx[Op.getImmTy()] = I;
3534 llvm_unreachable("unexpected operand type");
3538 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3539 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3540 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3541 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3542 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3543 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3544 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3545 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3548 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
3549 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
3552 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
3553 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
3556 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
3557 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
3560 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
3561 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3564 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3565 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3568 //===----------------------------------------------------------------------===//
3570 //===----------------------------------------------------------------------===//
3572 bool AMDGPUOperand::isSMRDOffset8() const {
3573 return isImm() && isUInt<8>(getImm());
3576 bool AMDGPUOperand::isSMRDOffset20() const {
3577 return isImm() && isUInt<20>(getImm());
3580 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3581 // 32-bit literals are only supported on CI and we only want to use them
3582 // when the offset is > 8-bits.
3583 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3586 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3587 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3590 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3591 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3594 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3595 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3598 //===----------------------------------------------------------------------===//
3600 //===----------------------------------------------------------------------===//
3602 static bool ConvertOmodMul(int64_t &Mul) {
3603 if (Mul != 1 && Mul != 2 && Mul != 4)
3610 static bool ConvertOmodDiv(int64_t &Div) {
3624 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
3625 if (BoundCtrl == 0) {
3630 if (BoundCtrl == -1) {
3638 // Note: the order in this table matches the order of operands in AsmString.
3639 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
3640 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
3641 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
3642 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
3643 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
3644 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
3645 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
3646 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
3647 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
3648 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
3649 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
3650 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
3651 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
3652 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
3653 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
3654 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
3655 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
3656 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
3657 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
3658 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
3659 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
3660 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
3661 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
3662 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
3663 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
3664 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
3665 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
3666 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
3667 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
3668 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
3669 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
3672 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
3673 OperandMatchResultTy res;
3674 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
3675 // try to parse any optional operand here
3677 res = parseNamedBit(Op.Name, Operands, Op.Type);
3678 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
3679 res = parseOModOperand(Operands);
3680 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
3681 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
3682 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
3683 res = parseSDWASel(Operands, Op.Name, Op.Type);
3684 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
3685 res = parseSDWADstUnused(Operands);
3686 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
3687 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
3688 Op.Type == AMDGPUOperand::ImmTyNegLo ||
3689 Op.Type == AMDGPUOperand::ImmTyNegHi) {
3690 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
3693 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
3695 if (res != MatchOperand_NoMatch) {
3699 return MatchOperand_NoMatch;
3702 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
3703 StringRef Name = Parser.getTok().getString();
3704 if (Name == "mul") {
3705 return parseIntWithPrefix("mul", Operands,
3706 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
3709 if (Name == "div") {
3710 return parseIntWithPrefix("div", Operands,
3711 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
3714 return MatchOperand_NoMatch;
3717 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
3719 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3720 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3721 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3723 for (unsigned E = Operands.size(); I != E; ++I)
3724 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
3727 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
3728 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3729 if (TSFlags & SIInstrFlags::VOP3) {
3730 cvtVOP3(Inst, Operands);
3732 cvtId(Inst, Operands);
3736 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
3737 // 1. This operand is input modifiers
3738 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
3739 // 2. This is not last operand
3740 && Desc.NumOperands > (OpNum + 1)
3741 // 3. Next operand is register class
3742 && Desc.OpInfo[OpNum + 1].RegClass != -1
3743 // 4. Next register is not tied to any other operand
3744 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
3747 void AMDGPUAsmParser::cvtVOP3Impl(MCInst &Inst, const OperandVector &Operands,
3748 OptionalImmIndexMap &OptionalIdx) {
3750 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3751 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3752 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3755 for (unsigned E = Operands.size(); I != E; ++I) {
3756 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3757 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
3758 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
3759 } else if (Op.isImmModifier()) {
3760 OptionalIdx[Op.getImmTy()] = I;
3761 } else if (Op.isRegOrImm()) {
3762 Op.addRegOrImmOperands(Inst, 1);
3764 llvm_unreachable("unhandled operand type");
3769 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
3770 OptionalImmIndexMap OptionalIdx;
3772 cvtVOP3Impl(Inst, Operands, OptionalIdx);
3774 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
3775 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
3777 // special case v_mac_{f16, f32}:
3778 // it has src2 register operand that is tied to dst operand
3779 // we don't allow modifiers for this operand in assembler so src2_modifiers
3781 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
3782 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
3783 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
3784 auto it = Inst.begin();
3787 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
3788 AMDGPU::V_MAC_F16_e64 :
3789 AMDGPU::V_MAC_F32_e64,
3790 AMDGPU::OpName::src2_modifiers));
3791 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
3793 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
3797 void AMDGPUAsmParser::cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands) {
3798 OptionalImmIndexMap OptionalIdx;
3801 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3802 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3803 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3806 for (unsigned E = Operands.size(); I != E; ++I) {
3807 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3809 OptionalIdx[Op.getImmTy()] = I;
3811 Op.addRegOrImmOperands(Inst, 1);
3815 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
3816 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
3819 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
3820 OptionalImmIndexMap OptIdx;
3822 cvtVOP3Impl(Inst, Operands, OptIdx);
3824 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
3825 // instruction, and then figure out where to actually put the modifiers
3826 int Opc = Inst.getOpcode();
3828 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
3829 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClampSI);
3832 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
3833 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, -1);
3835 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
3836 if (NegLoIdx != -1) {
3837 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
3838 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
3841 const int Ops[] = { AMDGPU::OpName::src0,
3842 AMDGPU::OpName::src1,
3843 AMDGPU::OpName::src2 };
3844 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
3845 AMDGPU::OpName::src1_modifiers,
3846 AMDGPU::OpName::src2_modifiers };
3848 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
3849 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
3851 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
3852 unsigned OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
3856 if (NegLoIdx != -1) {
3857 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
3858 NegLo = Inst.getOperand(NegLoIdx).getImm();
3859 NegHi = Inst.getOperand(NegHiIdx).getImm();
3862 for (int J = 0; J < 3; ++J) {
3863 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
3867 uint32_t ModVal = 0;
3869 if ((OpSel & (1 << J)) != 0)
3870 ModVal |= SISrcMods::OP_SEL_0;
3872 if ((OpSelHi & (1 << J)) != 0)
3873 ModVal |= SISrcMods::OP_SEL_1;
3875 if ((NegLo & (1 << J)) != 0)
3876 ModVal |= SISrcMods::NEG;
3878 if ((NegHi & (1 << J)) != 0)
3879 ModVal |= SISrcMods::NEG_HI;
3881 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
3883 Inst.getOperand(ModIdx).setImm(ModVal);
3887 //===----------------------------------------------------------------------===//
3889 //===----------------------------------------------------------------------===//
3891 bool AMDGPUOperand::isDPPCtrl() const {
3892 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
3894 int64_t Imm = getImm();
3895 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
3896 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
3897 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
3898 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
3911 bool AMDGPUOperand::isGPRIdxMode() const {
3912 return isImm() && isUInt<4>(getImm());
3915 bool AMDGPUOperand::isS16Imm() const {
3916 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
3919 bool AMDGPUOperand::isU16Imm() const {
3920 return isImm() && isUInt<16>(getImm());
3923 OperandMatchResultTy
3924 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
3925 SMLoc S = Parser.getTok().getLoc();
3929 if (getLexer().getKind() == AsmToken::Identifier) {
3930 Prefix = Parser.getTok().getString();
3932 return MatchOperand_NoMatch;
3935 if (Prefix == "row_mirror") {
3938 } else if (Prefix == "row_half_mirror") {
3942 // Check to prevent parseDPPCtrlOps from eating invalid tokens
3943 if (Prefix != "quad_perm"
3944 && Prefix != "row_shl"
3945 && Prefix != "row_shr"
3946 && Prefix != "row_ror"
3947 && Prefix != "wave_shl"
3948 && Prefix != "wave_rol"
3949 && Prefix != "wave_shr"
3950 && Prefix != "wave_ror"
3951 && Prefix != "row_bcast") {
3952 return MatchOperand_NoMatch;
3956 if (getLexer().isNot(AsmToken::Colon))
3957 return MatchOperand_ParseFail;
3959 if (Prefix == "quad_perm") {
3960 // quad_perm:[%d,%d,%d,%d]
3962 if (getLexer().isNot(AsmToken::LBrac))
3963 return MatchOperand_ParseFail;
3966 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
3967 return MatchOperand_ParseFail;
3969 for (int i = 0; i < 3; ++i) {
3970 if (getLexer().isNot(AsmToken::Comma))
3971 return MatchOperand_ParseFail;
3975 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
3976 return MatchOperand_ParseFail;
3977 const int shift = i*2 + 2;
3978 Int += (Temp << shift);
3981 if (getLexer().isNot(AsmToken::RBrac))
3982 return MatchOperand_ParseFail;
3988 if (getParser().parseAbsoluteExpression(Int))
3989 return MatchOperand_ParseFail;
3991 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
3993 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
3995 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
3997 } else if (Prefix == "wave_shl" && 1 == Int) {
3999 } else if (Prefix == "wave_rol" && 1 == Int) {
4001 } else if (Prefix == "wave_shr" && 1 == Int) {
4003 } else if (Prefix == "wave_ror" && 1 == Int) {
4005 } else if (Prefix == "row_bcast") {
4008 } else if (Int == 31) {
4011 return MatchOperand_ParseFail;
4014 return MatchOperand_ParseFail;
4019 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
4020 return MatchOperand_Success;
4023 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
4024 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
4027 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
4028 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
4031 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
4032 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
4035 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
4036 OptionalImmIndexMap OptionalIdx;
4039 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4040 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4041 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4044 for (unsigned E = Operands.size(); I != E; ++I) {
4045 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4046 // Add the register arguments
4047 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4048 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
4051 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4052 Op.addRegWithFPInputModsOperands(Inst, 2);
4053 } else if (Op.isDPPCtrl()) {
4054 Op.addImmOperands(Inst, 1);
4055 } else if (Op.isImm()) {
4056 // Handle optional arguments
4057 OptionalIdx[Op.getImmTy()] = I;
4059 llvm_unreachable("Invalid operand type");
4063 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
4064 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
4065 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
4067 // special case v_mac_{f16, f32}:
4068 // it has src2 register operand that is tied to dst operand
4069 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
4070 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
4071 auto it = Inst.begin();
4073 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4074 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4078 //===----------------------------------------------------------------------===//
4080 //===----------------------------------------------------------------------===//
4082 OperandMatchResultTy
4083 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
4084 AMDGPUOperand::ImmTy Type) {
4085 using namespace llvm::AMDGPU::SDWA;
4087 SMLoc S = Parser.getTok().getLoc();
4089 OperandMatchResultTy res;
4091 res = parseStringWithPrefix(Prefix, Value);
4092 if (res != MatchOperand_Success) {
4097 Int = StringSwitch<int64_t>(Value)
4098 .Case("BYTE_0", SdwaSel::BYTE_0)
4099 .Case("BYTE_1", SdwaSel::BYTE_1)
4100 .Case("BYTE_2", SdwaSel::BYTE_2)
4101 .Case("BYTE_3", SdwaSel::BYTE_3)
4102 .Case("WORD_0", SdwaSel::WORD_0)
4103 .Case("WORD_1", SdwaSel::WORD_1)
4104 .Case("DWORD", SdwaSel::DWORD)
4105 .Default(0xffffffff);
4106 Parser.Lex(); // eat last token
4108 if (Int == 0xffffffff) {
4109 return MatchOperand_ParseFail;
4112 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
4113 return MatchOperand_Success;
4116 OperandMatchResultTy
4117 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
4118 using namespace llvm::AMDGPU::SDWA;
4120 SMLoc S = Parser.getTok().getLoc();
4122 OperandMatchResultTy res;
4124 res = parseStringWithPrefix("dst_unused", Value);
4125 if (res != MatchOperand_Success) {
4130 Int = StringSwitch<int64_t>(Value)
4131 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
4132 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
4133 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
4134 .Default(0xffffffff);
4135 Parser.Lex(); // eat last token
4137 if (Int == 0xffffffff) {
4138 return MatchOperand_ParseFail;
4141 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
4142 return MatchOperand_Success;
4145 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
4146 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
4149 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
4150 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
4153 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
4154 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
4157 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
4158 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
4161 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
4162 uint64_t BasicInstType, bool skipVcc) {
4163 using namespace llvm::AMDGPU::SDWA;
4164 OptionalImmIndexMap OptionalIdx;
4165 bool skippedVcc = false;
4168 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4169 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4170 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4173 for (unsigned E = Operands.size(); I != E; ++I) {
4174 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4175 if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4176 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
4177 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
4178 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
4179 // Skip VCC only if we didn't skip it on previous iteration.
4180 if (BasicInstType == SIInstrFlags::VOP2 &&
4181 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
4184 } else if (BasicInstType == SIInstrFlags::VOPC &&
4185 Inst.getNumOperands() == 0) {
4190 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4191 Op.addRegWithInputModsOperands(Inst, 2);
4192 } else if (Op.isImm()) {
4193 // Handle optional arguments
4194 OptionalIdx[Op.getImmTy()] = I;
4196 llvm_unreachable("Invalid operand type");
4201 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
4202 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
4203 // V_NOP_sdwa_vi has no optional sdwa arguments
4204 switch (BasicInstType) {
4205 case SIInstrFlags::VOP1:
4206 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4208 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4209 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4211 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4212 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4213 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4216 case SIInstrFlags::VOP2:
4217 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4219 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4220 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4222 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4223 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4224 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4225 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4228 case SIInstrFlags::VOPC:
4230 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4232 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4233 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4237 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
4241 // special case v_mac_{f16, f32}:
4242 // it has src2 register operand that is tied to dst operand
4243 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
4244 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
4245 auto it = Inst.begin();
4247 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4248 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4252 /// Force static initialization.
4253 extern "C" void LLVMInitializeAMDGPUAsmParser() {
4254 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
4255 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
4258 #define GET_REGISTER_MATCHER
4259 #define GET_MATCHER_IMPLEMENTATION
4260 #include "AMDGPUGenAsmMatcher.inc"
4262 // This fuction should be defined after auto-generated include so that we have
4263 // MatchClassKind enum defined
4264 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
4266 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
4267 // But MatchInstructionImpl() expects to meet token and fails to validate
4268 // operand. This method checks if we are given immediate operand but expect to
4269 // get corresponding token.
4270 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
4273 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
4275 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
4277 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
4279 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
4281 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
4283 // When operands have expression values, they will return true for isToken,
4284 // because it is not possible to distinguish between a token and an
4285 // expression at parse time. MatchInstructionImpl() will always try to
4286 // match an operand as a token, when isToken returns true, and when the
4287 // name of the expression is not a valid token, the match will fail,
4288 // so we need to handle it here.
4289 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
4291 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
4292 case MCK_SoppBrTarget:
4293 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
4294 case MCK_VReg32OrOff:
4295 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
4296 case MCK_InterpSlot:
4297 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
4299 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
4301 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
4303 return Match_InvalidOperand;