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);
193 bool isToken() const override {
197 if (Kind != Expression || !Expr)
200 // When parsing operands, we can't always tell if something was meant to be
201 // a token, like 'gds', or an expression that references a global variable.
202 // In this case, we assume the string is an expression, and if we need to
203 // interpret is a token, then we treat the symbol name as the token.
204 return isa<MCSymbolRefExpr>(Expr);
207 bool isImm() const override {
208 return Kind == Immediate;
211 bool isInlinableImm(MVT type) const;
212 bool isLiteralImm(MVT type) const;
214 bool isRegKind() const {
215 return Kind == Register;
218 bool isReg() const override {
219 return isRegKind() && !hasModifiers();
222 bool isRegOrImmWithInputMods(MVT type) const {
223 return isRegKind() || isInlinableImm(type);
226 bool isRegOrImmWithInt16InputMods() const {
227 return isRegOrImmWithInputMods(MVT::i16);
230 bool isRegOrImmWithInt32InputMods() const {
231 return isRegOrImmWithInputMods(MVT::i32);
234 bool isRegOrImmWithInt64InputMods() const {
235 return isRegOrImmWithInputMods(MVT::i64);
238 bool isRegOrImmWithFP16InputMods() const {
239 return isRegOrImmWithInputMods(MVT::f16);
242 bool isRegOrImmWithFP32InputMods() const {
243 return isRegOrImmWithInputMods(MVT::f32);
246 bool isRegOrImmWithFP64InputMods() const {
247 return isRegOrImmWithInputMods(MVT::f64);
250 bool isVReg() const {
251 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
252 isRegClass(AMDGPU::VReg_64RegClassID) ||
253 isRegClass(AMDGPU::VReg_96RegClassID) ||
254 isRegClass(AMDGPU::VReg_128RegClassID) ||
255 isRegClass(AMDGPU::VReg_256RegClassID) ||
256 isRegClass(AMDGPU::VReg_512RegClassID);
259 bool isVReg32OrOff() const {
260 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
263 bool isImmTy(ImmTy ImmT) const {
264 return isImm() && Imm.Type == ImmT;
267 bool isImmModifier() const {
268 return isImm() && Imm.Type != ImmTyNone;
271 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
272 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
273 bool isDMask() const { return isImmTy(ImmTyDMask); }
274 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
275 bool isDA() const { return isImmTy(ImmTyDA); }
276 bool isR128() const { return isImmTy(ImmTyUNorm); }
277 bool isLWE() const { return isImmTy(ImmTyLWE); }
278 bool isOff() const { return isImmTy(ImmTyOff); }
279 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
280 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
281 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
282 bool isOffen() const { return isImmTy(ImmTyOffen); }
283 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
284 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
285 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
286 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
287 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
288 bool isGDS() const { return isImmTy(ImmTyGDS); }
289 bool isGLC() const { return isImmTy(ImmTyGLC); }
290 bool isSLC() const { return isImmTy(ImmTySLC); }
291 bool isTFE() const { return isImmTy(ImmTyTFE); }
292 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
293 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
294 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
295 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
296 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
297 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
298 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
299 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
300 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
301 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
302 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
303 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
304 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
305 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
308 return isClampSI() || isOModSI();
311 bool isRegOrImm() const {
312 return isReg() || isImm();
315 bool isRegClass(unsigned RCID) const;
317 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
318 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
321 bool isSCSrcB16() const {
322 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
325 bool isSCSrcV2B16() const {
329 bool isSCSrcB32() const {
330 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
333 bool isSCSrcB64() const {
334 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
337 bool isSCSrcF16() const {
338 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
341 bool isSCSrcV2F16() const {
345 bool isSCSrcF32() const {
346 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
349 bool isSCSrcF64() const {
350 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
353 bool isSSrcB32() const {
354 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
357 bool isSSrcB16() const {
358 return isSCSrcB16() || isLiteralImm(MVT::i16);
361 bool isSSrcV2B16() const {
362 llvm_unreachable("cannot happen");
366 bool isSSrcB64() const {
367 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
369 return isSCSrcB64() || isLiteralImm(MVT::i64);
372 bool isSSrcF32() const {
373 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
376 bool isSSrcF64() const {
377 return isSCSrcB64() || isLiteralImm(MVT::f64);
380 bool isSSrcF16() const {
381 return isSCSrcB16() || isLiteralImm(MVT::f16);
384 bool isSSrcV2F16() const {
385 llvm_unreachable("cannot happen");
389 bool isVCSrcB32() const {
390 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
393 bool isVCSrcB64() const {
394 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
397 bool isVCSrcB16() const {
398 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
401 bool isVCSrcV2B16() const {
405 bool isVCSrcF32() const {
406 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
409 bool isVCSrcF64() const {
410 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
413 bool isVCSrcF16() const {
414 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
417 bool isVCSrcV2F16() const {
421 bool isVSrcB32() const {
422 return isVCSrcF32() || isLiteralImm(MVT::i32);
425 bool isVSrcB64() const {
426 return isVCSrcF64() || isLiteralImm(MVT::i64);
429 bool isVSrcB16() const {
430 return isVCSrcF16() || isLiteralImm(MVT::i16);
433 bool isVSrcV2B16() const {
434 llvm_unreachable("cannot happen");
438 bool isVSrcF32() const {
439 return isVCSrcF32() || isLiteralImm(MVT::f32);
442 bool isVSrcF64() const {
443 return isVCSrcF64() || isLiteralImm(MVT::f64);
446 bool isVSrcF16() const {
447 return isVCSrcF16() || isLiteralImm(MVT::f16);
450 bool isVSrcV2F16() const {
451 llvm_unreachable("cannot happen");
455 bool isKImmFP32() const {
456 return isLiteralImm(MVT::f32);
459 bool isKImmFP16() const {
460 return isLiteralImm(MVT::f16);
463 bool isMem() const override {
467 bool isExpr() const {
468 return Kind == Expression;
471 bool isSoppBrTarget() const {
472 return isExpr() || isImm();
475 bool isSWaitCnt() const;
476 bool isHwreg() const;
477 bool isSendMsg() const;
478 bool isSwizzle() const;
479 bool isSMRDOffset8() const;
480 bool isSMRDOffset20() const;
481 bool isSMRDLiteralOffset() const;
482 bool isDPPCtrl() const;
483 bool isGPRIdxMode() const;
484 bool isS16Imm() const;
485 bool isU16Imm() const;
487 StringRef getExpressionAsToken() const {
489 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
490 return S->getSymbol().getName();
493 StringRef getToken() const {
496 if (Kind == Expression)
497 return getExpressionAsToken();
499 return StringRef(Tok.Data, Tok.Length);
502 int64_t getImm() const {
507 ImmTy getImmTy() const {
512 unsigned getReg() const override {
516 SMLoc getStartLoc() const override {
520 SMLoc getEndLoc() const override {
524 Modifiers getModifiers() const {
525 assert(isRegKind() || isImmTy(ImmTyNone));
526 return isRegKind() ? Reg.Mods : Imm.Mods;
529 void setModifiers(Modifiers Mods) {
530 assert(isRegKind() || isImmTy(ImmTyNone));
537 bool hasModifiers() const {
538 return getModifiers().hasModifiers();
541 bool hasFPModifiers() const {
542 return getModifiers().hasFPModifiers();
545 bool hasIntModifiers() const {
546 return getModifiers().hasIntModifiers();
549 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
551 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
553 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
555 template <unsigned Bitwidth>
556 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
558 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
559 addKImmFPOperands<16>(Inst, N);
562 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
563 addKImmFPOperands<32>(Inst, N);
566 void addRegOperands(MCInst &Inst, unsigned N) const;
568 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
570 addRegOperands(Inst, N);
572 Inst.addOperand(MCOperand::createExpr(Expr));
574 addImmOperands(Inst, N);
577 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
578 Modifiers Mods = getModifiers();
579 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
581 addRegOperands(Inst, N);
583 addImmOperands(Inst, N, false);
587 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
588 assert(!hasIntModifiers());
589 addRegOrImmWithInputModsOperands(Inst, N);
592 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
593 assert(!hasFPModifiers());
594 addRegOrImmWithInputModsOperands(Inst, N);
597 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
598 Modifiers Mods = getModifiers();
599 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
601 addRegOperands(Inst, N);
604 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
605 assert(!hasIntModifiers());
606 addRegWithInputModsOperands(Inst, N);
609 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
610 assert(!hasFPModifiers());
611 addRegWithInputModsOperands(Inst, N);
614 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
616 addImmOperands(Inst, N);
619 Inst.addOperand(MCOperand::createExpr(Expr));
623 static void printImmTy(raw_ostream& OS, ImmTy Type) {
625 case ImmTyNone: OS << "None"; break;
626 case ImmTyGDS: OS << "GDS"; break;
627 case ImmTyOffen: OS << "Offen"; break;
628 case ImmTyIdxen: OS << "Idxen"; break;
629 case ImmTyAddr64: OS << "Addr64"; break;
630 case ImmTyOffset: OS << "Offset"; break;
631 case ImmTyOffset0: OS << "Offset0"; break;
632 case ImmTyOffset1: OS << "Offset1"; break;
633 case ImmTyGLC: OS << "GLC"; break;
634 case ImmTySLC: OS << "SLC"; break;
635 case ImmTyTFE: OS << "TFE"; break;
636 case ImmTyClampSI: OS << "ClampSI"; break;
637 case ImmTyOModSI: OS << "OModSI"; break;
638 case ImmTyDppCtrl: OS << "DppCtrl"; break;
639 case ImmTyDppRowMask: OS << "DppRowMask"; break;
640 case ImmTyDppBankMask: OS << "DppBankMask"; break;
641 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
642 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
643 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
644 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
645 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
646 case ImmTyDMask: OS << "DMask"; break;
647 case ImmTyUNorm: OS << "UNorm"; break;
648 case ImmTyDA: OS << "DA"; break;
649 case ImmTyR128: OS << "R128"; break;
650 case ImmTyLWE: OS << "LWE"; break;
651 case ImmTyOff: OS << "Off"; break;
652 case ImmTyExpTgt: OS << "ExpTgt"; break;
653 case ImmTyExpCompr: OS << "ExpCompr"; break;
654 case ImmTyExpVM: OS << "ExpVM"; break;
655 case ImmTyHwreg: OS << "Hwreg"; break;
656 case ImmTySendMsg: OS << "SendMsg"; break;
657 case ImmTyInterpSlot: OS << "InterpSlot"; break;
658 case ImmTyInterpAttr: OS << "InterpAttr"; break;
659 case ImmTyAttrChan: OS << "AttrChan"; break;
660 case ImmTyOpSel: OS << "OpSel"; break;
661 case ImmTyOpSelHi: OS << "OpSelHi"; break;
662 case ImmTyNegLo: OS << "NegLo"; break;
663 case ImmTyNegHi: OS << "NegHi"; break;
664 case ImmTySwizzle: OS << "Swizzle"; break;
668 void print(raw_ostream &OS) const override {
671 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
674 OS << '<' << getImm();
675 if (getImmTy() != ImmTyNone) {
676 OS << " type: "; printImmTy(OS, getImmTy());
678 OS << " mods: " << Imm.Mods << '>';
681 OS << '\'' << getToken() << '\'';
684 OS << "<expr " << *Expr << '>';
689 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
690 int64_t Val, SMLoc Loc,
691 ImmTy Type = ImmTyNone,
692 bool IsFPImm = false) {
693 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
695 Op->Imm.IsFPImm = IsFPImm;
697 Op->Imm.Mods = Modifiers();
703 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
704 StringRef Str, SMLoc Loc,
705 bool HasExplicitEncodingSize = true) {
706 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
707 Res->Tok.Data = Str.data();
708 Res->Tok.Length = Str.size();
714 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
715 unsigned RegNo, SMLoc S,
718 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
719 Op->Reg.RegNo = RegNo;
720 Op->Reg.Mods = Modifiers();
721 Op->Reg.IsForcedVOP3 = ForceVOP3;
727 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
728 const class MCExpr *Expr, SMLoc S) {
729 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
737 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
738 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
742 //===----------------------------------------------------------------------===//
744 //===----------------------------------------------------------------------===//
746 // Holds info related to the current kernel, e.g. count of SGPRs used.
747 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
748 // .amdgpu_hsa_kernel or at EOF.
749 class KernelScopeInfo {
750 int SgprIndexUnusedMin = -1;
751 int VgprIndexUnusedMin = -1;
752 MCContext *Ctx = nullptr;
754 void usesSgprAt(int i) {
755 if (i >= SgprIndexUnusedMin) {
756 SgprIndexUnusedMin = ++i;
758 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
759 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
764 void usesVgprAt(int i) {
765 if (i >= VgprIndexUnusedMin) {
766 VgprIndexUnusedMin = ++i;
768 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
769 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
775 KernelScopeInfo() = default;
777 void initialize(MCContext &Context) {
779 usesSgprAt(SgprIndexUnusedMin = -1);
780 usesVgprAt(VgprIndexUnusedMin = -1);
783 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
785 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
786 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
792 class AMDGPUAsmParser : public MCTargetAsmParser {
793 const MCInstrInfo &MII;
796 unsigned ForcedEncodingSize = 0;
797 bool ForcedDPP = false;
798 bool ForcedSDWA = false;
799 KernelScopeInfo KernelScope;
801 /// @name Auto-generated Match Functions
804 #define GET_ASSEMBLER_HEADER
805 #include "AMDGPUGenAsmMatcher.inc"
810 bool ParseAsAbsoluteExpression(uint32_t &Ret);
811 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
812 bool ParseDirectiveHSACodeObjectVersion();
813 bool ParseDirectiveHSACodeObjectISA();
814 bool ParseDirectiveCodeObjectMetadata();
815 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
816 bool ParseDirectiveAMDKernelCodeT();
817 bool ParseSectionDirectiveHSAText();
818 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
819 bool ParseDirectiveAMDGPUHsaKernel();
820 bool ParseDirectiveAMDGPUHsaModuleGlobal();
821 bool ParseDirectiveAMDGPUHsaProgramGlobal();
822 bool ParseSectionDirectiveHSADataGlobalAgent();
823 bool ParseSectionDirectiveHSADataGlobalProgram();
824 bool ParseSectionDirectiveHSARodataReadonlyAgent();
825 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
826 RegisterKind RegKind, unsigned Reg1,
828 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
829 unsigned& RegNum, unsigned& RegWidth,
830 unsigned *DwordRegIndex);
831 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
832 bool IsAtomic, bool IsAtomicReturn);
833 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
834 bool IsGdsHardcoded);
837 enum AMDGPUMatchResultTy {
838 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
841 typedef std::map<AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
843 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
844 const MCInstrInfo &MII,
845 const MCTargetOptions &Options)
846 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser) {
847 MCAsmParserExtension::Initialize(Parser);
849 if (getFeatureBits().none()) {
850 // Set default features.
851 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
854 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
857 // TODO: make those pre-defined variables read-only.
858 // Currently there is none suitable machinery in the core llvm-mc for this.
859 // MCSymbol::isRedefinable is intended for another purpose, and
860 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
861 AMDGPU::IsaInfo::IsaVersion ISA =
862 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
863 MCContext &Ctx = getContext();
865 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
866 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
867 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
868 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
869 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
870 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
872 KernelScope.initialize(getContext());
876 return AMDGPU::isSI(getSTI());
880 return AMDGPU::isCI(getSTI());
884 return AMDGPU::isVI(getSTI());
887 bool isGFX9() const {
888 return AMDGPU::isGFX9(getSTI());
891 bool hasInv2PiInlineImm() const {
892 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
895 bool hasSGPR102_SGPR103() const {
899 AMDGPUTargetStreamer &getTargetStreamer() {
900 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
901 return static_cast<AMDGPUTargetStreamer &>(TS);
904 const MCRegisterInfo *getMRI() const {
905 // We need this const_cast because for some reason getContext() is not const
907 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
910 const MCInstrInfo *getMII() const {
914 const FeatureBitset &getFeatureBits() const {
915 return getSTI().getFeatureBits();
918 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
919 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
920 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
922 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
923 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
924 bool isForcedDPP() const { return ForcedDPP; }
925 bool isForcedSDWA() const { return ForcedSDWA; }
926 ArrayRef<unsigned> getMatchedVariants() const;
928 std::unique_ptr<AMDGPUOperand> parseRegister();
929 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
930 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
931 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
932 unsigned Kind) override;
933 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
934 OperandVector &Operands, MCStreamer &Out,
936 bool MatchingInlineAsm) override;
937 bool ParseDirective(AsmToken DirectiveID) override;
938 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
939 StringRef parseMnemonicSuffix(StringRef Name);
940 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
941 SMLoc NameLoc, OperandVector &Operands) override;
942 //bool ProcessInstruction(MCInst &Inst);
944 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
947 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
948 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
949 bool (*ConvertResult)(int64_t &) = nullptr);
951 OperandMatchResultTy parseOperandArrayWithPrefix(
953 OperandVector &Operands,
954 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
955 bool (*ConvertResult)(int64_t&) = nullptr);
958 parseNamedBit(const char *Name, OperandVector &Operands,
959 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
960 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
963 bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
964 OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
965 OperandMatchResultTy parseReg(OperandVector &Operands);
966 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
967 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
968 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
969 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
970 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
971 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
973 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
974 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
975 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
976 void cvtExp(MCInst &Inst, const OperandVector &Operands);
978 bool parseCnt(int64_t &IntVal);
979 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
980 OperandMatchResultTy parseHwreg(OperandVector &Operands);
983 struct OperandInfoTy {
986 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
989 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
990 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
993 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
995 bool validateOperandLimitations(const MCInst &Inst);
996 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
997 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
998 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1000 bool trySkipId(const StringRef Id);
1001 bool trySkipToken(const AsmToken::TokenKind Kind);
1002 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1003 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1004 bool parseExpr(int64_t &Imm);
1007 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1009 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1010 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1011 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1012 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1013 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1015 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1016 const unsigned MinVal,
1017 const unsigned MaxVal,
1018 const StringRef ErrMsg);
1019 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1020 bool parseSwizzleOffset(int64_t &Imm);
1021 bool parseSwizzleMacro(int64_t &Imm);
1022 bool parseSwizzleQuadPerm(int64_t &Imm);
1023 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1024 bool parseSwizzleBroadcast(int64_t &Imm);
1025 bool parseSwizzleSwap(int64_t &Imm);
1026 bool parseSwizzleReverse(int64_t &Imm);
1028 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1029 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1030 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1031 AMDGPUOperand::Ptr defaultGLC() const;
1032 AMDGPUOperand::Ptr defaultSLC() const;
1033 AMDGPUOperand::Ptr defaultTFE() const;
1035 AMDGPUOperand::Ptr defaultDMask() const;
1036 AMDGPUOperand::Ptr defaultUNorm() const;
1037 AMDGPUOperand::Ptr defaultDA() const;
1038 AMDGPUOperand::Ptr defaultR128() const;
1039 AMDGPUOperand::Ptr defaultLWE() const;
1040 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1041 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1042 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1044 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1046 void cvtId(MCInst &Inst, const OperandVector &Operands);
1047 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
1049 void cvtVOP3Impl(MCInst &Inst,
1050 const OperandVector &Operands,
1051 OptionalImmIndexMap &OptionalIdx);
1052 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1053 void cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands);
1054 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1056 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
1057 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1059 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1060 AMDGPUOperand::Ptr defaultRowMask() const;
1061 AMDGPUOperand::Ptr defaultBankMask() const;
1062 AMDGPUOperand::Ptr defaultBoundCtrl() const;
1063 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1065 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1066 AMDGPUOperand::ImmTy Type);
1067 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1068 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1069 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1070 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1071 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1072 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1073 uint64_t BasicInstType, bool skipVcc = false);
1076 struct OptionalOperand {
1078 AMDGPUOperand::ImmTy Type;
1080 bool (*ConvertResult)(int64_t&);
1083 } // end anonymous namespace
1085 // May be called with integer type with equivalent bitwidth.
1086 static const fltSemantics *getFltSemantics(unsigned Size) {
1089 return &APFloat::IEEEsingle();
1091 return &APFloat::IEEEdouble();
1093 return &APFloat::IEEEhalf();
1095 llvm_unreachable("unsupported fp type");
1099 static const fltSemantics *getFltSemantics(MVT VT) {
1100 return getFltSemantics(VT.getSizeInBits() / 8);
1103 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1104 switch (OperandType) {
1105 case AMDGPU::OPERAND_REG_IMM_INT32:
1106 case AMDGPU::OPERAND_REG_IMM_FP32:
1107 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1108 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1109 return &APFloat::IEEEsingle();
1110 case AMDGPU::OPERAND_REG_IMM_INT64:
1111 case AMDGPU::OPERAND_REG_IMM_FP64:
1112 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1113 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1114 return &APFloat::IEEEdouble();
1115 case AMDGPU::OPERAND_REG_IMM_INT16:
1116 case AMDGPU::OPERAND_REG_IMM_FP16:
1117 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1118 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1119 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1120 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1121 return &APFloat::IEEEhalf();
1123 llvm_unreachable("unsupported fp type");
1127 //===----------------------------------------------------------------------===//
1129 //===----------------------------------------------------------------------===//
1131 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1134 // Convert literal to single precision
1135 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1136 APFloat::rmNearestTiesToEven,
1138 // We allow precision lost but not overflow or underflow
1139 if (Status != APFloat::opOK &&
1141 ((Status & APFloat::opOverflow) != 0 ||
1142 (Status & APFloat::opUnderflow) != 0)) {
1149 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1150 if (!isImmTy(ImmTyNone)) {
1151 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1154 // TODO: We should avoid using host float here. It would be better to
1155 // check the float bit values which is what a few other places do.
1156 // We've had bot failures before due to weird NaN support on mips hosts.
1158 APInt Literal(64, Imm.Val);
1160 if (Imm.IsFPImm) { // We got fp literal token
1161 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1162 return AMDGPU::isInlinableLiteral64(Imm.Val,
1163 AsmParser->hasInv2PiInlineImm());
1166 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1167 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1170 if (type.getScalarSizeInBits() == 16) {
1171 return AMDGPU::isInlinableLiteral16(
1172 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1173 AsmParser->hasInv2PiInlineImm());
1176 // Check if single precision literal is inlinable
1177 return AMDGPU::isInlinableLiteral32(
1178 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1179 AsmParser->hasInv2PiInlineImm());
1182 // We got int literal token.
1183 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1184 return AMDGPU::isInlinableLiteral64(Imm.Val,
1185 AsmParser->hasInv2PiInlineImm());
1188 if (type.getScalarSizeInBits() == 16) {
1189 return AMDGPU::isInlinableLiteral16(
1190 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1191 AsmParser->hasInv2PiInlineImm());
1194 return AMDGPU::isInlinableLiteral32(
1195 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1196 AsmParser->hasInv2PiInlineImm());
1199 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1200 // Check that this imediate can be added as literal
1201 if (!isImmTy(ImmTyNone)) {
1206 // We got int literal token.
1208 if (type == MVT::f64 && hasFPModifiers()) {
1209 // Cannot apply fp modifiers to int literals preserving the same semantics
1210 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1211 // disable these cases.
1215 unsigned Size = type.getSizeInBits();
1219 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1221 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1224 // We got fp literal token
1225 if (type == MVT::f64) { // Expected 64-bit fp operand
1226 // We would set low 64-bits of literal to zeroes but we accept this literals
1230 if (type == MVT::i64) { // Expected 64-bit int operand
1231 // We don't allow fp literals in 64-bit integer instructions. It is
1232 // unclear how we should encode them.
1236 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1237 return canLosslesslyConvertToFPType(FPLiteral, type);
1240 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1241 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1244 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1246 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1247 assert(Size == 2 || Size == 4 || Size == 8);
1249 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1261 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1263 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1264 Inst.getNumOperands())) {
1265 addLiteralImmOperand(Inst, Imm.Val,
1267 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1269 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1270 Inst.addOperand(MCOperand::createImm(Imm.Val));
1274 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1275 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1276 auto OpNum = Inst.getNumOperands();
1277 // Check that this operand accepts literals
1278 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1280 if (ApplyModifiers) {
1281 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1282 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1283 Val = applyInputFPModifiers(Val, Size);
1286 APInt Literal(64, Val);
1287 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1289 if (Imm.IsFPImm) { // We got fp literal token
1291 case AMDGPU::OPERAND_REG_IMM_INT64:
1292 case AMDGPU::OPERAND_REG_IMM_FP64:
1293 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1294 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1295 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1296 AsmParser->hasInv2PiInlineImm())) {
1297 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1302 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1303 // For fp operands we check if low 32 bits are zeros
1304 if (Literal.getLoBits(32) != 0) {
1305 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1306 "Can't encode literal as exact 64-bit floating-point operand. "
1307 "Low 32-bits will be set to zero");
1310 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1314 // We don't allow fp literals in 64-bit integer instructions. It is
1315 // unclear how we should encode them. This case should be checked earlier
1316 // in predicate methods (isLiteralImm())
1317 llvm_unreachable("fp literal in 64-bit integer instruction.");
1319 case AMDGPU::OPERAND_REG_IMM_INT32:
1320 case AMDGPU::OPERAND_REG_IMM_FP32:
1321 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1322 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1323 case AMDGPU::OPERAND_REG_IMM_INT16:
1324 case AMDGPU::OPERAND_REG_IMM_FP16:
1325 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1326 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1327 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1328 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1330 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1331 // Convert literal to single precision
1332 FPLiteral.convert(*getOpFltSemantics(OpTy),
1333 APFloat::rmNearestTiesToEven, &lost);
1334 // We allow precision lost but not overflow or underflow. This should be
1335 // checked earlier in isLiteralImm()
1337 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1338 if (OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
1339 OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
1340 ImmVal |= (ImmVal << 16);
1343 Inst.addOperand(MCOperand::createImm(ImmVal));
1347 llvm_unreachable("invalid operand size");
1353 // We got int literal token.
1354 // Only sign extend inline immediates.
1355 // FIXME: No errors on truncation
1357 case AMDGPU::OPERAND_REG_IMM_INT32:
1358 case AMDGPU::OPERAND_REG_IMM_FP32:
1359 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1360 case AMDGPU::OPERAND_REG_INLINE_C_FP32: {
1361 if (isInt<32>(Val) &&
1362 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1363 AsmParser->hasInv2PiInlineImm())) {
1364 Inst.addOperand(MCOperand::createImm(Val));
1368 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1371 case AMDGPU::OPERAND_REG_IMM_INT64:
1372 case AMDGPU::OPERAND_REG_IMM_FP64:
1373 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1374 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1375 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1376 Inst.addOperand(MCOperand::createImm(Val));
1380 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1383 case AMDGPU::OPERAND_REG_IMM_INT16:
1384 case AMDGPU::OPERAND_REG_IMM_FP16:
1385 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1386 case AMDGPU::OPERAND_REG_INLINE_C_FP16: {
1387 if (isInt<16>(Val) &&
1388 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1389 AsmParser->hasInv2PiInlineImm())) {
1390 Inst.addOperand(MCOperand::createImm(Val));
1394 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1397 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1398 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1399 auto LiteralVal = static_cast<uint16_t>(Literal.getLoBits(16).getZExtValue());
1400 assert(AMDGPU::isInlinableLiteral16(LiteralVal,
1401 AsmParser->hasInv2PiInlineImm()));
1403 uint32_t ImmVal = static_cast<uint32_t>(LiteralVal) << 16 |
1404 static_cast<uint32_t>(LiteralVal);
1405 Inst.addOperand(MCOperand::createImm(ImmVal));
1409 llvm_unreachable("invalid operand size");
1413 template <unsigned Bitwidth>
1414 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1415 APInt Literal(64, Imm.Val);
1418 // We got int literal token.
1419 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1424 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1425 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1426 APFloat::rmNearestTiesToEven, &Lost);
1427 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1430 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1431 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1434 //===----------------------------------------------------------------------===//
1436 //===----------------------------------------------------------------------===//
1438 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1439 if (Is == IS_VGPR) {
1442 case 1: return AMDGPU::VGPR_32RegClassID;
1443 case 2: return AMDGPU::VReg_64RegClassID;
1444 case 3: return AMDGPU::VReg_96RegClassID;
1445 case 4: return AMDGPU::VReg_128RegClassID;
1446 case 8: return AMDGPU::VReg_256RegClassID;
1447 case 16: return AMDGPU::VReg_512RegClassID;
1449 } else if (Is == IS_TTMP) {
1452 case 1: return AMDGPU::TTMP_32RegClassID;
1453 case 2: return AMDGPU::TTMP_64RegClassID;
1454 case 4: return AMDGPU::TTMP_128RegClassID;
1456 } else if (Is == IS_SGPR) {
1459 case 1: return AMDGPU::SGPR_32RegClassID;
1460 case 2: return AMDGPU::SGPR_64RegClassID;
1461 case 4: return AMDGPU::SGPR_128RegClassID;
1462 case 8: return AMDGPU::SReg_256RegClassID;
1463 case 16: return AMDGPU::SReg_512RegClassID;
1469 static unsigned getSpecialRegForName(StringRef RegName) {
1470 return StringSwitch<unsigned>(RegName)
1471 .Case("exec", AMDGPU::EXEC)
1472 .Case("vcc", AMDGPU::VCC)
1473 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1474 .Case("m0", AMDGPU::M0)
1475 .Case("scc", AMDGPU::SCC)
1476 .Case("tba", AMDGPU::TBA)
1477 .Case("tma", AMDGPU::TMA)
1478 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1479 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1480 .Case("vcc_lo", AMDGPU::VCC_LO)
1481 .Case("vcc_hi", AMDGPU::VCC_HI)
1482 .Case("exec_lo", AMDGPU::EXEC_LO)
1483 .Case("exec_hi", AMDGPU::EXEC_HI)
1484 .Case("tma_lo", AMDGPU::TMA_LO)
1485 .Case("tma_hi", AMDGPU::TMA_HI)
1486 .Case("tba_lo", AMDGPU::TBA_LO)
1487 .Case("tba_hi", AMDGPU::TBA_HI)
1491 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1493 auto R = parseRegister();
1494 if (!R) return true;
1496 RegNo = R->getReg();
1497 StartLoc = R->getStartLoc();
1498 EndLoc = R->getEndLoc();
1502 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1503 RegisterKind RegKind, unsigned Reg1,
1507 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1512 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1513 Reg = AMDGPU::FLAT_SCR;
1517 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1522 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1527 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1536 if (Reg1 != Reg + RegWidth) {
1542 llvm_unreachable("unexpected register kind");
1546 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1547 unsigned &RegNum, unsigned &RegWidth,
1548 unsigned *DwordRegIndex) {
1549 if (DwordRegIndex) { *DwordRegIndex = 0; }
1550 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1551 if (getLexer().is(AsmToken::Identifier)) {
1552 StringRef RegName = Parser.getTok().getString();
1553 if ((Reg = getSpecialRegForName(RegName))) {
1555 RegKind = IS_SPECIAL;
1557 unsigned RegNumIndex = 0;
1558 if (RegName[0] == 'v') {
1561 } else if (RegName[0] == 's') {
1564 } else if (RegName.startswith("ttmp")) {
1565 RegNumIndex = strlen("ttmp");
1570 if (RegName.size() > RegNumIndex) {
1571 // Single 32-bit register: vXX.
1572 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1577 // Range of registers: v[XX:YY]. ":YY" is optional.
1579 int64_t RegLo, RegHi;
1580 if (getLexer().isNot(AsmToken::LBrac))
1584 if (getParser().parseAbsoluteExpression(RegLo))
1587 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1588 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1595 if (getParser().parseAbsoluteExpression(RegHi))
1598 if (getLexer().isNot(AsmToken::RBrac))
1602 RegNum = (unsigned) RegLo;
1603 RegWidth = (RegHi - RegLo) + 1;
1606 } else if (getLexer().is(AsmToken::LBrac)) {
1607 // List of consecutive registers: [s0,s1,s2,s3]
1609 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1613 RegisterKind RegKind1;
1614 unsigned Reg1, RegNum1, RegWidth1;
1616 if (getLexer().is(AsmToken::Comma)) {
1618 } else if (getLexer().is(AsmToken::RBrac)) {
1621 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1622 if (RegWidth1 != 1) {
1625 if (RegKind1 != RegKind) {
1628 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1648 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1649 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1650 Size = std::min(RegWidth, 4u);
1652 if (RegNum % Size != 0)
1654 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1655 RegNum = RegNum / Size;
1656 int RCID = getRegClass(RegKind, RegWidth);
1659 const MCRegisterClass RC = TRI->getRegClass(RCID);
1660 if (RegNum >= RC.getNumRegs())
1662 Reg = RC.getRegister(RegNum);
1667 llvm_unreachable("unexpected register kind");
1670 if (!subtargetHasRegister(*TRI, Reg))
1675 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1676 const auto &Tok = Parser.getTok();
1677 SMLoc StartLoc = Tok.getLoc();
1678 SMLoc EndLoc = Tok.getEndLoc();
1679 RegisterKind RegKind;
1680 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1682 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1685 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1686 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1690 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) {
1691 if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) &&
1692 (getLexer().getKind() == AsmToken::Integer ||
1693 getLexer().getKind() == AsmToken::Real)) {
1695 // This is a workaround for handling operands like these:
1698 // This syntax is not compatible with syntax of standard
1699 // MC expressions (due to the trailing '|').
1704 if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1708 return !Expr->evaluateAsAbsolute(Val);
1711 return getParser().parseAbsoluteExpression(Val);
1714 OperandMatchResultTy
1715 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
1716 // TODO: add syntactic sugar for 1/(2*PI)
1718 if (getLexer().getKind() == AsmToken::Minus) {
1723 SMLoc S = Parser.getTok().getLoc();
1724 switch(getLexer().getKind()) {
1725 case AsmToken::Integer: {
1727 if (parseAbsoluteExpr(IntVal, AbsMod))
1728 return MatchOperand_ParseFail;
1731 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1732 return MatchOperand_Success;
1734 case AsmToken::Real: {
1736 if (parseAbsoluteExpr(IntVal, AbsMod))
1737 return MatchOperand_ParseFail;
1739 APFloat F(BitsToDouble(IntVal));
1743 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1744 AMDGPUOperand::ImmTyNone, true));
1745 return MatchOperand_Success;
1748 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1752 OperandMatchResultTy
1753 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1754 if (auto R = parseRegister()) {
1756 R->Reg.IsForcedVOP3 = isForcedVOP3();
1757 Operands.push_back(std::move(R));
1758 return MatchOperand_Success;
1760 return MatchOperand_NoMatch;
1763 OperandMatchResultTy
1764 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
1765 auto res = parseImm(Operands, AbsMod);
1766 if (res != MatchOperand_NoMatch) {
1770 return parseReg(Operands);
1773 OperandMatchResultTy
1774 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
1776 bool Negate = false, Negate2 = false, Abs = false, Abs2 = false;
1778 if (getLexer().getKind()== AsmToken::Minus) {
1779 const AsmToken NextToken = getLexer().peekTok();
1781 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
1782 if (NextToken.is(AsmToken::Minus)) {
1783 Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier");
1784 return MatchOperand_ParseFail;
1787 // '-' followed by an integer literal N should be interpreted as integer
1788 // negation rather than a floating-point NEG modifier applied to N.
1789 // Beside being contr-intuitive, such use of floating-point NEG modifier
1790 // results in different meaning of integer literals used with VOP1/2/C
1791 // and VOP3, for example:
1792 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
1793 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
1794 // Negative fp literals should be handled likewise for unifomtity
1795 if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) {
1801 if (getLexer().getKind() == AsmToken::Identifier &&
1802 Parser.getTok().getString() == "neg") {
1804 Error(Parser.getTok().getLoc(), "expected register or immediate");
1805 return MatchOperand_ParseFail;
1809 if (getLexer().isNot(AsmToken::LParen)) {
1810 Error(Parser.getTok().getLoc(), "expected left paren after neg");
1811 return MatchOperand_ParseFail;
1816 if (getLexer().getKind() == AsmToken::Identifier &&
1817 Parser.getTok().getString() == "abs") {
1820 if (getLexer().isNot(AsmToken::LParen)) {
1821 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1822 return MatchOperand_ParseFail;
1827 if (getLexer().getKind() == AsmToken::Pipe) {
1829 Error(Parser.getTok().getLoc(), "expected register or immediate");
1830 return MatchOperand_ParseFail;
1836 OperandMatchResultTy Res;
1838 Res = parseRegOrImm(Operands, Abs);
1840 Res = parseReg(Operands);
1842 if (Res != MatchOperand_Success) {
1846 AMDGPUOperand::Modifiers Mods;
1848 if (getLexer().getKind() != AsmToken::Pipe) {
1849 Error(Parser.getTok().getLoc(), "expected vertical bar");
1850 return MatchOperand_ParseFail;
1856 if (getLexer().isNot(AsmToken::RParen)) {
1857 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1858 return MatchOperand_ParseFail;
1866 } else if (Negate2) {
1867 if (getLexer().isNot(AsmToken::RParen)) {
1868 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1869 return MatchOperand_ParseFail;
1875 if (Mods.hasFPModifiers()) {
1876 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1877 Op.setModifiers(Mods);
1879 return MatchOperand_Success;
1882 OperandMatchResultTy
1883 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
1887 if (getLexer().getKind() == AsmToken::Identifier &&
1888 Parser.getTok().getString() == "sext") {
1891 if (getLexer().isNot(AsmToken::LParen)) {
1892 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1893 return MatchOperand_ParseFail;
1898 OperandMatchResultTy Res;
1900 Res = parseRegOrImm(Operands);
1902 Res = parseReg(Operands);
1904 if (Res != MatchOperand_Success) {
1908 AMDGPUOperand::Modifiers Mods;
1910 if (getLexer().isNot(AsmToken::RParen)) {
1911 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1912 return MatchOperand_ParseFail;
1918 if (Mods.hasIntModifiers()) {
1919 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1920 Op.setModifiers(Mods);
1923 return MatchOperand_Success;
1926 OperandMatchResultTy
1927 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1928 return parseRegOrImmWithFPInputMods(Operands, false);
1931 OperandMatchResultTy
1932 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1933 return parseRegOrImmWithIntInputMods(Operands, false);
1936 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1937 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1939 Operands.push_back(std::move(Reg));
1940 return MatchOperand_Success;
1943 const AsmToken &Tok = Parser.getTok();
1944 if (Tok.getString() == "off") {
1945 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1946 AMDGPUOperand::ImmTyOff, false));
1948 return MatchOperand_Success;
1951 return MatchOperand_NoMatch;
1954 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1955 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1957 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1958 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1959 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1960 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1961 return Match_InvalidOperand;
1963 if ((TSFlags & SIInstrFlags::VOP3) &&
1964 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1965 getForcedEncodingSize() != 64)
1966 return Match_PreferE32;
1968 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1969 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1970 // v_mac_f32/16 allow only dst_sel == DWORD;
1972 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1973 const auto &Op = Inst.getOperand(OpNum);
1974 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1975 return Match_InvalidOperand;
1979 return Match_Success;
1982 // What asm variants we should check
1983 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
1984 if (getForcedEncodingSize() == 32) {
1985 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
1986 return makeArrayRef(Variants);
1989 if (isForcedVOP3()) {
1990 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
1991 return makeArrayRef(Variants);
1994 if (isForcedSDWA()) {
1995 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
1996 AMDGPUAsmVariants::SDWA9};
1997 return makeArrayRef(Variants);
2000 if (isForcedDPP()) {
2001 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2002 return makeArrayRef(Variants);
2005 static const unsigned Variants[] = {
2006 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2007 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2010 return makeArrayRef(Variants);
2013 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2014 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2015 const unsigned Num = Desc.getNumImplicitUses();
2016 for (unsigned i = 0; i < Num; ++i) {
2017 unsigned Reg = Desc.ImplicitUses[i];
2019 case AMDGPU::FLAT_SCR:
2027 return AMDGPU::NoRegister;
2030 // NB: This code is correct only when used to check constant
2031 // bus limitations because GFX7 support no f16 inline constants.
2032 // Note that there are no cases when a GFX7 opcode violates
2033 // constant bus limitations due to the use of an f16 constant.
2034 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2035 unsigned OpIdx) const {
2036 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2038 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2042 const MCOperand &MO = Inst.getOperand(OpIdx);
2044 int64_t Val = MO.getImm();
2045 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2047 switch (OpSize) { // expected operand size
2049 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2051 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2053 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2054 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2055 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
2056 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2058 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2062 llvm_unreachable("invalid operand size");
2066 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2067 const MCOperand &MO = Inst.getOperand(OpIdx);
2069 return !isInlineConstant(Inst, OpIdx);
2071 return !MO.isReg() ||
2072 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
2075 bool AMDGPUAsmParser::validateOperandLimitations(const MCInst &Inst) {
2076 const unsigned Opcode = Inst.getOpcode();
2077 const MCInstrDesc &Desc = MII.get(Opcode);
2078 unsigned ConstantBusUseCount = 0;
2081 (SIInstrFlags::VOPC |
2082 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
2083 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2084 SIInstrFlags::SDWA)) {
2086 // Check special imm operands (used by madmk, etc)
2087 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2088 ++ConstantBusUseCount;
2091 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2092 if (SGPRUsed != AMDGPU::NoRegister) {
2093 ++ConstantBusUseCount;
2096 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2097 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2098 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2100 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2102 for (int OpIdx : OpIndices) {
2103 if (OpIdx == -1) break;
2105 const MCOperand &MO = Inst.getOperand(OpIdx);
2106 if (usesConstantBus(Inst, OpIdx)) {
2108 const unsigned Reg = mc2PseudoReg(MO.getReg());
2109 // Pairs of registers with a partial intersections like these
2111 // flat_scratch_lo, flat_scratch
2112 // flat_scratch_lo, flat_scratch_hi
2113 // are theoretically valid but they are disabled anyway.
2114 // Note that this code mimics SIInstrInfo::verifyInstruction
2115 if (Reg != SGPRUsed) {
2116 ++ConstantBusUseCount;
2119 } else { // Expression or a literal
2120 ++ConstantBusUseCount;
2126 return ConstantBusUseCount <= 1;
2129 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2130 OperandVector &Operands,
2132 uint64_t &ErrorInfo,
2133 bool MatchingInlineAsm) {
2135 unsigned Result = Match_Success;
2136 for (auto Variant : getMatchedVariants()) {
2138 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2140 // We order match statuses from least to most specific. We use most specific
2141 // status as resulting
2142 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
2143 if ((R == Match_Success) ||
2144 (R == Match_PreferE32) ||
2145 (R == Match_MissingFeature && Result != Match_PreferE32) ||
2146 (R == Match_InvalidOperand && Result != Match_MissingFeature
2147 && Result != Match_PreferE32) ||
2148 (R == Match_MnemonicFail && Result != Match_InvalidOperand
2149 && Result != Match_MissingFeature
2150 && Result != Match_PreferE32)) {
2154 if (R == Match_Success)
2161 if (!validateOperandLimitations(Inst)) {
2163 "invalid operand (violates constant bus restrictions)");
2166 Out.EmitInstruction(Inst, getSTI());
2169 case Match_MissingFeature:
2170 return Error(IDLoc, "instruction not supported on this GPU");
2172 case Match_MnemonicFail:
2173 return Error(IDLoc, "unrecognized instruction mnemonic");
2175 case Match_InvalidOperand: {
2176 SMLoc ErrorLoc = IDLoc;
2177 if (ErrorInfo != ~0ULL) {
2178 if (ErrorInfo >= Operands.size()) {
2179 return Error(IDLoc, "too few operands for instruction");
2181 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2182 if (ErrorLoc == SMLoc())
2185 return Error(ErrorLoc, "invalid operand for instruction");
2188 case Match_PreferE32:
2189 return Error(IDLoc, "internal error: instruction without _e64 suffix "
2190 "should be encoded as e32");
2192 llvm_unreachable("Implement any new match types added!");
2195 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
2197 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
2200 if (getParser().parseAbsoluteExpression(Tmp)) {
2203 Ret = static_cast<uint32_t>(Tmp);
2207 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
2209 if (ParseAsAbsoluteExpression(Major))
2210 return TokError("invalid major version");
2212 if (getLexer().isNot(AsmToken::Comma))
2213 return TokError("minor version number required, comma expected");
2216 if (ParseAsAbsoluteExpression(Minor))
2217 return TokError("invalid minor version");
2222 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2226 if (ParseDirectiveMajorMinor(Major, Minor))
2229 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2233 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2237 StringRef VendorName;
2240 // If this directive has no arguments, then use the ISA version for the
2242 if (getLexer().is(AsmToken::EndOfStatement)) {
2243 AMDGPU::IsaInfo::IsaVersion ISA =
2244 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2245 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2251 if (ParseDirectiveMajorMinor(Major, Minor))
2254 if (getLexer().isNot(AsmToken::Comma))
2255 return TokError("stepping version number required, comma expected");
2258 if (ParseAsAbsoluteExpression(Stepping))
2259 return TokError("invalid stepping version");
2261 if (getLexer().isNot(AsmToken::Comma))
2262 return TokError("vendor name required, comma expected");
2265 if (getLexer().isNot(AsmToken::String))
2266 return TokError("invalid vendor name");
2268 VendorName = getLexer().getTok().getStringContents();
2271 if (getLexer().isNot(AsmToken::Comma))
2272 return TokError("arch name required, comma expected");
2275 if (getLexer().isNot(AsmToken::String))
2276 return TokError("invalid arch name");
2278 ArchName = getLexer().getTok().getStringContents();
2281 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2282 VendorName, ArchName);
2286 bool AMDGPUAsmParser::ParseDirectiveCodeObjectMetadata() {
2287 std::string YamlString;
2288 raw_string_ostream YamlStream(YamlString);
2290 getLexer().setSkipSpace(false);
2292 bool FoundEnd = false;
2293 while (!getLexer().is(AsmToken::Eof)) {
2294 while (getLexer().is(AsmToken::Space)) {
2295 YamlStream << getLexer().getTok().getString();
2299 if (getLexer().is(AsmToken::Identifier)) {
2300 StringRef ID = getLexer().getTok().getIdentifier();
2301 if (ID == AMDGPU::CodeObject::MetadataAssemblerDirectiveEnd) {
2308 YamlStream << Parser.parseStringToEndOfStatement()
2309 << getContext().getAsmInfo()->getSeparatorString();
2311 Parser.eatToEndOfStatement();
2314 getLexer().setSkipSpace(true);
2316 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
2318 "expected directive .end_amdgpu_code_object_metadata not found");
2323 if (!getTargetStreamer().EmitCodeObjectMetadata(YamlString))
2324 return Error(getParser().getTok().getLoc(), "invalid code object metadata");
2329 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
2330 amd_kernel_code_t &Header) {
2331 SmallString<40> ErrStr;
2332 raw_svector_ostream Err(ErrStr);
2333 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
2334 return TokError(Err.str());
2340 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
2341 amd_kernel_code_t Header;
2342 AMDGPU::initDefaultAMDKernelCodeT(Header, getFeatureBits());
2345 // Lex EndOfStatement. This is in a while loop, because lexing a comment
2346 // will set the current token to EndOfStatement.
2347 while(getLexer().is(AsmToken::EndOfStatement))
2350 if (getLexer().isNot(AsmToken::Identifier))
2351 return TokError("expected value identifier or .end_amd_kernel_code_t");
2353 StringRef ID = getLexer().getTok().getIdentifier();
2356 if (ID == ".end_amd_kernel_code_t")
2359 if (ParseAMDKernelCodeTValue(ID, Header))
2363 getTargetStreamer().EmitAMDKernelCodeT(Header);
2368 bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
2369 getParser().getStreamer().SwitchSection(
2370 AMDGPU::getHSATextSection(getContext()));
2374 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
2375 if (getLexer().isNot(AsmToken::Identifier))
2376 return TokError("expected symbol name");
2378 StringRef KernelName = Parser.getTok().getString();
2380 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
2381 ELF::STT_AMDGPU_HSA_KERNEL);
2383 KernelScope.initialize(getContext());
2387 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
2388 if (getLexer().isNot(AsmToken::Identifier))
2389 return TokError("expected symbol name");
2391 StringRef GlobalName = Parser.getTok().getIdentifier();
2393 getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
2398 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
2399 if (getLexer().isNot(AsmToken::Identifier))
2400 return TokError("expected symbol name");
2402 StringRef GlobalName = Parser.getTok().getIdentifier();
2404 getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
2409 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
2410 getParser().getStreamer().SwitchSection(
2411 AMDGPU::getHSADataGlobalAgentSection(getContext()));
2415 bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
2416 getParser().getStreamer().SwitchSection(
2417 AMDGPU::getHSADataGlobalProgramSection(getContext()));
2421 bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
2422 getParser().getStreamer().SwitchSection(
2423 AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
2427 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2428 StringRef IDVal = DirectiveID.getString();
2430 if (IDVal == ".hsa_code_object_version")
2431 return ParseDirectiveHSACodeObjectVersion();
2433 if (IDVal == ".hsa_code_object_isa")
2434 return ParseDirectiveHSACodeObjectISA();
2436 if (IDVal == AMDGPU::CodeObject::MetadataAssemblerDirectiveBegin)
2437 return ParseDirectiveCodeObjectMetadata();
2439 if (IDVal == ".amd_kernel_code_t")
2440 return ParseDirectiveAMDKernelCodeT();
2442 if (IDVal == ".hsatext")
2443 return ParseSectionDirectiveHSAText();
2445 if (IDVal == ".amdgpu_hsa_kernel")
2446 return ParseDirectiveAMDGPUHsaKernel();
2448 if (IDVal == ".amdgpu_hsa_module_global")
2449 return ParseDirectiveAMDGPUHsaModuleGlobal();
2451 if (IDVal == ".amdgpu_hsa_program_global")
2452 return ParseDirectiveAMDGPUHsaProgramGlobal();
2454 if (IDVal == ".hsadata_global_agent")
2455 return ParseSectionDirectiveHSADataGlobalAgent();
2457 if (IDVal == ".hsadata_global_program")
2458 return ParseSectionDirectiveHSADataGlobalProgram();
2460 if (IDVal == ".hsarodata_readonly_agent")
2461 return ParseSectionDirectiveHSARodataReadonlyAgent();
2466 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2467 unsigned RegNo) const {
2474 case AMDGPU::FLAT_SCR:
2475 case AMDGPU::FLAT_SCR_LO:
2476 case AMDGPU::FLAT_SCR_HI:
2483 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2485 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2494 OperandMatchResultTy
2495 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2496 // Try to parse with a custom parser
2497 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2499 // If we successfully parsed the operand or if there as an error parsing,
2502 // If we are parsing after we reach EndOfStatement then this means we
2503 // are appending default values to the Operands list. This is only done
2504 // by custom parser, so we shouldn't continue on to the generic parsing.
2505 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2506 getLexer().is(AsmToken::EndOfStatement))
2509 ResTy = parseRegOrImm(Operands);
2511 if (ResTy == MatchOperand_Success)
2514 if (getLexer().getKind() == AsmToken::Identifier) {
2515 // If this identifier is a symbol, we want to create an expression for it.
2516 // It is a little difficult to distinguish between a symbol name, and
2517 // an instruction flag like 'gds'. In order to do this, we parse
2518 // all tokens as expressions and then treate the symbol name as the token
2519 // string when we want to interpret the operand as a token.
2520 const auto &Tok = Parser.getTok();
2521 SMLoc S = Tok.getLoc();
2522 const MCExpr *Expr = nullptr;
2523 if (!Parser.parseExpression(Expr)) {
2524 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2525 return MatchOperand_Success;
2528 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2530 return MatchOperand_Success;
2532 return MatchOperand_NoMatch;
2535 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2536 // Clear any forced encodings from the previous instruction.
2537 setForcedEncodingSize(0);
2538 setForcedDPP(false);
2539 setForcedSDWA(false);
2541 if (Name.endswith("_e64")) {
2542 setForcedEncodingSize(64);
2543 return Name.substr(0, Name.size() - 4);
2544 } else if (Name.endswith("_e32")) {
2545 setForcedEncodingSize(32);
2546 return Name.substr(0, Name.size() - 4);
2547 } else if (Name.endswith("_dpp")) {
2549 return Name.substr(0, Name.size() - 4);
2550 } else if (Name.endswith("_sdwa")) {
2551 setForcedSDWA(true);
2552 return Name.substr(0, Name.size() - 5);
2557 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2559 SMLoc NameLoc, OperandVector &Operands) {
2560 // Add the instruction mnemonic
2561 Name = parseMnemonicSuffix(Name);
2562 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2564 while (!getLexer().is(AsmToken::EndOfStatement)) {
2565 OperandMatchResultTy Res = parseOperand(Operands, Name);
2567 // Eat the comma or space if there is one.
2568 if (getLexer().is(AsmToken::Comma))
2572 case MatchOperand_Success: break;
2573 case MatchOperand_ParseFail:
2574 Error(getLexer().getLoc(), "failed parsing operand.");
2575 while (!getLexer().is(AsmToken::EndOfStatement)) {
2579 case MatchOperand_NoMatch:
2580 Error(getLexer().getLoc(), "not a valid operand.");
2581 while (!getLexer().is(AsmToken::EndOfStatement)) {
2591 //===----------------------------------------------------------------------===//
2592 // Utility functions
2593 //===----------------------------------------------------------------------===//
2595 OperandMatchResultTy
2596 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2597 switch(getLexer().getKind()) {
2598 default: return MatchOperand_NoMatch;
2599 case AsmToken::Identifier: {
2600 StringRef Name = Parser.getTok().getString();
2601 if (!Name.equals(Prefix)) {
2602 return MatchOperand_NoMatch;
2606 if (getLexer().isNot(AsmToken::Colon))
2607 return MatchOperand_ParseFail;
2610 if (getLexer().isNot(AsmToken::Integer))
2611 return MatchOperand_ParseFail;
2613 if (getParser().parseAbsoluteExpression(Int))
2614 return MatchOperand_ParseFail;
2618 return MatchOperand_Success;
2621 OperandMatchResultTy
2622 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2623 AMDGPUOperand::ImmTy ImmTy,
2624 bool (*ConvertResult)(int64_t&)) {
2625 SMLoc S = Parser.getTok().getLoc();
2628 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2629 if (Res != MatchOperand_Success)
2632 if (ConvertResult && !ConvertResult(Value)) {
2633 return MatchOperand_ParseFail;
2636 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2637 return MatchOperand_Success;
2640 OperandMatchResultTy AMDGPUAsmParser::parseOperandArrayWithPrefix(
2642 OperandVector &Operands,
2643 AMDGPUOperand::ImmTy ImmTy,
2644 bool (*ConvertResult)(int64_t&)) {
2645 StringRef Name = Parser.getTok().getString();
2646 if (!Name.equals(Prefix))
2647 return MatchOperand_NoMatch;
2650 if (getLexer().isNot(AsmToken::Colon))
2651 return MatchOperand_ParseFail;
2654 if (getLexer().isNot(AsmToken::LBrac))
2655 return MatchOperand_ParseFail;
2659 SMLoc S = Parser.getTok().getLoc();
2661 // FIXME: How to verify the number of elements matches the number of src
2663 for (int I = 0; I < 3; ++I) {
2665 if (getLexer().is(AsmToken::RBrac))
2668 if (getLexer().isNot(AsmToken::Comma))
2669 return MatchOperand_ParseFail;
2673 if (getLexer().isNot(AsmToken::Integer))
2674 return MatchOperand_ParseFail;
2677 if (getParser().parseAbsoluteExpression(Op))
2678 return MatchOperand_ParseFail;
2680 if (Op != 0 && Op != 1)
2681 return MatchOperand_ParseFail;
2686 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
2687 return MatchOperand_Success;
2690 OperandMatchResultTy
2691 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2692 AMDGPUOperand::ImmTy ImmTy) {
2694 SMLoc S = Parser.getTok().getLoc();
2696 // We are at the end of the statement, and this is a default argument, so
2697 // use a default value.
2698 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2699 switch(getLexer().getKind()) {
2700 case AsmToken::Identifier: {
2701 StringRef Tok = Parser.getTok().getString();
2705 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2709 return MatchOperand_NoMatch;
2714 return MatchOperand_NoMatch;
2718 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2719 return MatchOperand_Success;
2722 static void addOptionalImmOperand(
2723 MCInst& Inst, const OperandVector& Operands,
2724 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
2725 AMDGPUOperand::ImmTy ImmT,
2726 int64_t Default = 0) {
2727 auto i = OptionalIdx.find(ImmT);
2728 if (i != OptionalIdx.end()) {
2729 unsigned Idx = i->second;
2730 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2732 Inst.addOperand(MCOperand::createImm(Default));
2736 OperandMatchResultTy
2737 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2738 if (getLexer().isNot(AsmToken::Identifier)) {
2739 return MatchOperand_NoMatch;
2741 StringRef Tok = Parser.getTok().getString();
2742 if (Tok != Prefix) {
2743 return MatchOperand_NoMatch;
2747 if (getLexer().isNot(AsmToken::Colon)) {
2748 return MatchOperand_ParseFail;
2752 if (getLexer().isNot(AsmToken::Identifier)) {
2753 return MatchOperand_ParseFail;
2756 Value = Parser.getTok().getString();
2757 return MatchOperand_Success;
2760 //===----------------------------------------------------------------------===//
2762 //===----------------------------------------------------------------------===//
2764 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2765 const OperandVector &Operands) {
2766 OptionalImmIndexMap OptionalIdx;
2768 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2769 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2771 // Add the register arguments
2773 Op.addRegOperands(Inst, 1);
2777 // Handle optional arguments
2778 OptionalIdx[Op.getImmTy()] = i;
2781 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2782 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2783 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2785 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2788 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
2789 bool IsGdsHardcoded) {
2790 OptionalImmIndexMap OptionalIdx;
2792 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2793 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2795 // Add the register arguments
2797 Op.addRegOperands(Inst, 1);
2801 if (Op.isToken() && Op.getToken() == "gds") {
2802 IsGdsHardcoded = true;
2806 // Handle optional arguments
2807 OptionalIdx[Op.getImmTy()] = i;
2810 AMDGPUOperand::ImmTy OffsetType =
2811 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
2812 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
2813 AMDGPUOperand::ImmTyOffset;
2815 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
2817 if (!IsGdsHardcoded) {
2818 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2820 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2823 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2824 OptionalImmIndexMap OptionalIdx;
2826 unsigned OperandIdx[4];
2827 unsigned EnMask = 0;
2830 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2831 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2833 // Add the register arguments
2836 OperandIdx[SrcIdx] = Inst.size();
2837 Op.addRegOperands(Inst, 1);
2844 OperandIdx[SrcIdx] = Inst.size();
2845 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2850 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2851 Op.addImmOperands(Inst, 1);
2855 if (Op.isToken() && Op.getToken() == "done")
2858 // Handle optional arguments
2859 OptionalIdx[Op.getImmTy()] = i;
2862 assert(SrcIdx == 4);
2865 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
2867 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
2868 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
2869 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
2872 for (auto i = 0; i < SrcIdx; ++i) {
2873 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
2874 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
2878 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2879 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2881 Inst.addOperand(MCOperand::createImm(EnMask));
2884 //===----------------------------------------------------------------------===//
2886 //===----------------------------------------------------------------------===//
2890 const AMDGPU::IsaInfo::IsaVersion ISA,
2894 unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned),
2895 unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned))
2897 bool Failed = false;
2899 IntVal = encode(ISA, IntVal, CntVal);
2900 if (CntVal != decode(ISA, IntVal)) {
2902 IntVal = encode(ISA, IntVal, -1);
2910 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2911 StringRef CntName = Parser.getTok().getString();
2915 if (getLexer().isNot(AsmToken::LParen))
2919 if (getLexer().isNot(AsmToken::Integer))
2922 if (getParser().parseAbsoluteExpression(CntVal))
2925 AMDGPU::IsaInfo::IsaVersion ISA =
2926 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2929 bool Sat = CntName.endswith("_sat");
2931 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
2932 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
2933 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
2934 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
2935 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
2936 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
2939 // To improve diagnostics, do not skip delimiters on errors
2941 if (getLexer().isNot(AsmToken::RParen)) {
2945 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) {
2946 const AsmToken NextToken = getLexer().peekTok();
2947 if (NextToken.is(AsmToken::Identifier)) {
2956 OperandMatchResultTy
2957 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2958 AMDGPU::IsaInfo::IsaVersion ISA =
2959 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2960 int64_t Waitcnt = getWaitcntBitMask(ISA);
2961 SMLoc S = Parser.getTok().getLoc();
2963 switch(getLexer().getKind()) {
2964 default: return MatchOperand_ParseFail;
2965 case AsmToken::Integer:
2966 // The operand can be an integer value.
2967 if (getParser().parseAbsoluteExpression(Waitcnt))
2968 return MatchOperand_ParseFail;
2971 case AsmToken::Identifier:
2973 if (parseCnt(Waitcnt))
2974 return MatchOperand_ParseFail;
2975 } while(getLexer().isNot(AsmToken::EndOfStatement));
2978 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
2979 return MatchOperand_Success;
2982 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset,
2984 using namespace llvm::AMDGPU::Hwreg;
2986 if (Parser.getTok().getString() != "hwreg")
2990 if (getLexer().isNot(AsmToken::LParen))
2994 if (getLexer().is(AsmToken::Identifier)) {
2995 HwReg.IsSymbolic = true;
2996 HwReg.Id = ID_UNKNOWN_;
2997 const StringRef tok = Parser.getTok().getString();
2998 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
2999 if (tok == IdSymbolic[i]) {
3006 HwReg.IsSymbolic = false;
3007 if (getLexer().isNot(AsmToken::Integer))
3009 if (getParser().parseAbsoluteExpression(HwReg.Id))
3013 if (getLexer().is(AsmToken::RParen)) {
3019 if (getLexer().isNot(AsmToken::Comma))
3023 if (getLexer().isNot(AsmToken::Integer))
3025 if (getParser().parseAbsoluteExpression(Offset))
3028 if (getLexer().isNot(AsmToken::Comma))
3032 if (getLexer().isNot(AsmToken::Integer))
3034 if (getParser().parseAbsoluteExpression(Width))
3037 if (getLexer().isNot(AsmToken::RParen))
3044 OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
3045 using namespace llvm::AMDGPU::Hwreg;
3047 int64_t Imm16Val = 0;
3048 SMLoc S = Parser.getTok().getLoc();
3050 switch(getLexer().getKind()) {
3051 default: return MatchOperand_NoMatch;
3052 case AsmToken::Integer:
3053 // The operand can be an integer value.
3054 if (getParser().parseAbsoluteExpression(Imm16Val))
3055 return MatchOperand_NoMatch;
3056 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3057 Error(S, "invalid immediate: only 16-bit values are legal");
3058 // Do not return error code, but create an imm operand anyway and proceed
3059 // to the next operand, if any. That avoids unneccessary error messages.
3063 case AsmToken::Identifier: {
3064 OperandInfoTy HwReg(ID_UNKNOWN_);
3065 int64_t Offset = OFFSET_DEFAULT_;
3066 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
3067 if (parseHwregConstruct(HwReg, Offset, Width))
3068 return MatchOperand_ParseFail;
3069 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3070 if (HwReg.IsSymbolic)
3071 Error(S, "invalid symbolic name of hardware register");
3073 Error(S, "invalid code of hardware register: only 6-bit values are legal");
3075 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3076 Error(S, "invalid bit offset: only 5-bit values are legal");
3077 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3078 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
3079 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
3083 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3084 return MatchOperand_Success;
3087 bool AMDGPUOperand::isSWaitCnt() const {
3091 bool AMDGPUOperand::isHwreg() const {
3092 return isImmTy(ImmTyHwreg);
3095 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
3096 using namespace llvm::AMDGPU::SendMsg;
3098 if (Parser.getTok().getString() != "sendmsg")
3102 if (getLexer().isNot(AsmToken::LParen))
3106 if (getLexer().is(AsmToken::Identifier)) {
3107 Msg.IsSymbolic = true;
3108 Msg.Id = ID_UNKNOWN_;
3109 const std::string tok = Parser.getTok().getString();
3110 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
3112 default: continue; // Omit gaps.
3113 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
3115 if (tok == IdSymbolic[i]) {
3122 Msg.IsSymbolic = false;
3123 if (getLexer().isNot(AsmToken::Integer))
3125 if (getParser().parseAbsoluteExpression(Msg.Id))
3127 if (getLexer().is(AsmToken::Integer))
3128 if (getParser().parseAbsoluteExpression(Msg.Id))
3129 Msg.Id = ID_UNKNOWN_;
3131 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
3134 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
3135 if (getLexer().isNot(AsmToken::RParen))
3141 if (getLexer().isNot(AsmToken::Comma))
3145 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
3146 Operation.Id = ID_UNKNOWN_;
3147 if (getLexer().is(AsmToken::Identifier)) {
3148 Operation.IsSymbolic = true;
3149 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
3150 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
3151 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
3152 const StringRef Tok = Parser.getTok().getString();
3153 for (int i = F; i < L; ++i) {
3161 Operation.IsSymbolic = false;
3162 if (getLexer().isNot(AsmToken::Integer))
3164 if (getParser().parseAbsoluteExpression(Operation.Id))
3168 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3169 // Stream id is optional.
3170 if (getLexer().is(AsmToken::RParen)) {
3175 if (getLexer().isNot(AsmToken::Comma))
3179 if (getLexer().isNot(AsmToken::Integer))
3181 if (getParser().parseAbsoluteExpression(StreamId))
3185 if (getLexer().isNot(AsmToken::RParen))
3191 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
3192 if (getLexer().getKind() != AsmToken::Identifier)
3193 return MatchOperand_NoMatch;
3195 StringRef Str = Parser.getTok().getString();
3196 int Slot = StringSwitch<int>(Str)
3202 SMLoc S = Parser.getTok().getLoc();
3204 return MatchOperand_ParseFail;
3207 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
3208 AMDGPUOperand::ImmTyInterpSlot));
3209 return MatchOperand_Success;
3212 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
3213 if (getLexer().getKind() != AsmToken::Identifier)
3214 return MatchOperand_NoMatch;
3216 StringRef Str = Parser.getTok().getString();
3217 if (!Str.startswith("attr"))
3218 return MatchOperand_NoMatch;
3220 StringRef Chan = Str.take_back(2);
3221 int AttrChan = StringSwitch<int>(Chan)
3228 return MatchOperand_ParseFail;
3230 Str = Str.drop_back(2).drop_front(4);
3233 if (Str.getAsInteger(10, Attr))
3234 return MatchOperand_ParseFail;
3236 SMLoc S = Parser.getTok().getLoc();
3239 Error(S, "out of bounds attr");
3240 return MatchOperand_Success;
3243 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
3245 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
3246 AMDGPUOperand::ImmTyInterpAttr));
3247 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
3248 AMDGPUOperand::ImmTyAttrChan));
3249 return MatchOperand_Success;
3252 void AMDGPUAsmParser::errorExpTgt() {
3253 Error(Parser.getTok().getLoc(), "invalid exp target");
3256 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
3258 if (Str == "null") {
3260 return MatchOperand_Success;
3263 if (Str.startswith("mrt")) {
3264 Str = Str.drop_front(3);
3265 if (Str == "z") { // == mrtz
3267 return MatchOperand_Success;
3270 if (Str.getAsInteger(10, Val))
3271 return MatchOperand_ParseFail;
3276 return MatchOperand_Success;
3279 if (Str.startswith("pos")) {
3280 Str = Str.drop_front(3);
3281 if (Str.getAsInteger(10, Val))
3282 return MatchOperand_ParseFail;
3288 return MatchOperand_Success;
3291 if (Str.startswith("param")) {
3292 Str = Str.drop_front(5);
3293 if (Str.getAsInteger(10, Val))
3294 return MatchOperand_ParseFail;
3300 return MatchOperand_Success;
3303 if (Str.startswith("invalid_target_")) {
3304 Str = Str.drop_front(15);
3305 if (Str.getAsInteger(10, Val))
3306 return MatchOperand_ParseFail;
3309 return MatchOperand_Success;
3312 return MatchOperand_NoMatch;
3315 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
3317 StringRef Str = Parser.getTok().getString();
3319 auto Res = parseExpTgtImpl(Str, Val);
3320 if (Res != MatchOperand_Success)
3323 SMLoc S = Parser.getTok().getLoc();
3326 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
3327 AMDGPUOperand::ImmTyExpTgt));
3328 return MatchOperand_Success;
3331 OperandMatchResultTy
3332 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
3333 using namespace llvm::AMDGPU::SendMsg;
3335 int64_t Imm16Val = 0;
3336 SMLoc S = Parser.getTok().getLoc();
3338 switch(getLexer().getKind()) {
3340 return MatchOperand_NoMatch;
3341 case AsmToken::Integer:
3342 // The operand can be an integer value.
3343 if (getParser().parseAbsoluteExpression(Imm16Val))
3344 return MatchOperand_NoMatch;
3345 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3346 Error(S, "invalid immediate: only 16-bit values are legal");
3347 // Do not return error code, but create an imm operand anyway and proceed
3348 // to the next operand, if any. That avoids unneccessary error messages.
3351 case AsmToken::Identifier: {
3352 OperandInfoTy Msg(ID_UNKNOWN_);
3353 OperandInfoTy Operation(OP_UNKNOWN_);
3354 int64_t StreamId = STREAM_ID_DEFAULT_;
3355 if (parseSendMsgConstruct(Msg, Operation, StreamId))
3356 return MatchOperand_ParseFail;
3358 // Validate and encode message ID.
3359 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
3360 || Msg.Id == ID_SYSMSG)) {
3362 Error(S, "invalid/unsupported symbolic name of message");
3364 Error(S, "invalid/unsupported code of message");
3367 Imm16Val = (Msg.Id << ID_SHIFT_);
3368 // Validate and encode operation ID.
3369 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
3370 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
3371 if (Operation.IsSymbolic)
3372 Error(S, "invalid symbolic name of GS_OP");
3374 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
3377 if (Operation.Id == OP_GS_NOP
3378 && Msg.Id != ID_GS_DONE) {
3379 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
3382 Imm16Val |= (Operation.Id << OP_SHIFT_);
3384 if (Msg.Id == ID_SYSMSG) {
3385 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
3386 if (Operation.IsSymbolic)
3387 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
3389 Error(S, "invalid/unsupported code of SYSMSG_OP");
3392 Imm16Val |= (Operation.Id << OP_SHIFT_);
3394 // Validate and encode stream ID.
3395 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3396 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
3397 Error(S, "invalid stream id: only 2-bit values are legal");
3400 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
3406 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
3407 return MatchOperand_Success;
3410 bool AMDGPUOperand::isSendMsg() const {
3411 return isImmTy(ImmTySendMsg);
3414 //===----------------------------------------------------------------------===//
3416 //===----------------------------------------------------------------------===//
3419 AMDGPUAsmParser::trySkipId(const StringRef Id) {
3420 if (getLexer().getKind() == AsmToken::Identifier &&
3421 Parser.getTok().getString() == Id) {
3429 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
3430 if (getLexer().getKind() == Kind) {
3438 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
3439 const StringRef ErrMsg) {
3440 if (!trySkipToken(Kind)) {
3441 Error(Parser.getTok().getLoc(), ErrMsg);
3448 AMDGPUAsmParser::parseExpr(int64_t &Imm) {
3449 return !getParser().parseAbsoluteExpression(Imm);
3453 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
3454 SMLoc S = Parser.getTok().getLoc();
3455 if (getLexer().getKind() == AsmToken::String) {
3456 Val = Parser.getTok().getStringContents();
3465 //===----------------------------------------------------------------------===//
3467 //===----------------------------------------------------------------------===//
3471 encodeBitmaskPerm(const unsigned AndMask,
3472 const unsigned OrMask,
3473 const unsigned XorMask) {
3474 using namespace llvm::AMDGPU::Swizzle;
3476 return BITMASK_PERM_ENC |
3477 (AndMask << BITMASK_AND_SHIFT) |
3478 (OrMask << BITMASK_OR_SHIFT) |
3479 (XorMask << BITMASK_XOR_SHIFT);
3483 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
3484 const unsigned MinVal,
3485 const unsigned MaxVal,
3486 const StringRef ErrMsg) {
3487 for (unsigned i = 0; i < OpNum; ++i) {
3488 if (!skipToken(AsmToken::Comma, "expected a comma")){
3491 SMLoc ExprLoc = Parser.getTok().getLoc();
3492 if (!parseExpr(Op[i])) {
3495 if (Op[i] < MinVal || Op[i] > MaxVal) {
3496 Error(ExprLoc, ErrMsg);
3505 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
3506 using namespace llvm::AMDGPU::Swizzle;
3508 int64_t Lane[LANE_NUM];
3509 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
3510 "expected a 2-bit lane id")) {
3511 Imm = QUAD_PERM_ENC;
3512 for (auto i = 0; i < LANE_NUM; ++i) {
3513 Imm |= Lane[i] << (LANE_SHIFT * i);
3521 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
3522 using namespace llvm::AMDGPU::Swizzle;
3524 SMLoc S = Parser.getTok().getLoc();
3528 if (!parseSwizzleOperands(1, &GroupSize,
3530 "group size must be in the interval [2,32]")) {
3533 if (!isPowerOf2_64(GroupSize)) {
3534 Error(S, "group size must be a power of two");
3537 if (parseSwizzleOperands(1, &LaneIdx,
3539 "lane id must be in the interval [0,group size - 1]")) {
3540 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
3547 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
3548 using namespace llvm::AMDGPU::Swizzle;
3550 SMLoc S = Parser.getTok().getLoc();
3553 if (!parseSwizzleOperands(1, &GroupSize,
3554 2, 32, "group size must be in the interval [2,32]")) {
3557 if (!isPowerOf2_64(GroupSize)) {
3558 Error(S, "group size must be a power of two");
3562 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
3567 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
3568 using namespace llvm::AMDGPU::Swizzle;
3570 SMLoc S = Parser.getTok().getLoc();
3573 if (!parseSwizzleOperands(1, &GroupSize,
3574 1, 16, "group size must be in the interval [1,16]")) {
3577 if (!isPowerOf2_64(GroupSize)) {
3578 Error(S, "group size must be a power of two");
3582 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
3587 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
3588 using namespace llvm::AMDGPU::Swizzle;
3590 if (!skipToken(AsmToken::Comma, "expected a comma")) {
3595 SMLoc StrLoc = Parser.getTok().getLoc();
3596 if (!parseString(Ctl)) {
3599 if (Ctl.size() != BITMASK_WIDTH) {
3600 Error(StrLoc, "expected a 5-character mask");
3604 unsigned AndMask = 0;
3605 unsigned OrMask = 0;
3606 unsigned XorMask = 0;
3608 for (size_t i = 0; i < Ctl.size(); ++i) {
3609 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
3612 Error(StrLoc, "invalid mask");
3629 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
3634 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
3636 SMLoc OffsetLoc = Parser.getTok().getLoc();
3638 if (!parseExpr(Imm)) {
3641 if (!isUInt<16>(Imm)) {
3642 Error(OffsetLoc, "expected a 16-bit offset");
3649 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
3650 using namespace llvm::AMDGPU::Swizzle;
3652 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
3654 SMLoc ModeLoc = Parser.getTok().getLoc();
3657 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
3658 Ok = parseSwizzleQuadPerm(Imm);
3659 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
3660 Ok = parseSwizzleBitmaskPerm(Imm);
3661 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
3662 Ok = parseSwizzleBroadcast(Imm);
3663 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
3664 Ok = parseSwizzleSwap(Imm);
3665 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
3666 Ok = parseSwizzleReverse(Imm);
3668 Error(ModeLoc, "expected a swizzle mode");
3671 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
3677 OperandMatchResultTy
3678 AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
3679 SMLoc S = Parser.getTok().getLoc();
3682 if (trySkipId("offset")) {
3685 if (skipToken(AsmToken::Colon, "expected a colon")) {
3686 if (trySkipId("swizzle")) {
3687 Ok = parseSwizzleMacro(Imm);
3689 Ok = parseSwizzleOffset(Imm);
3693 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
3695 return Ok? MatchOperand_Success : MatchOperand_ParseFail;
3697 return MatchOperand_NoMatch;
3702 AMDGPUOperand::isSwizzle() const {
3703 return isImmTy(ImmTySwizzle);
3706 //===----------------------------------------------------------------------===//
3707 // sopp branch targets
3708 //===----------------------------------------------------------------------===//
3710 OperandMatchResultTy
3711 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
3712 SMLoc S = Parser.getTok().getLoc();
3714 switch (getLexer().getKind()) {
3715 default: return MatchOperand_ParseFail;
3716 case AsmToken::Integer: {
3718 if (getParser().parseAbsoluteExpression(Imm))
3719 return MatchOperand_ParseFail;
3720 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
3721 return MatchOperand_Success;
3724 case AsmToken::Identifier:
3725 Operands.push_back(AMDGPUOperand::CreateExpr(this,
3726 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
3727 Parser.getTok().getString()), getContext()), S));
3729 return MatchOperand_Success;
3733 //===----------------------------------------------------------------------===//
3735 //===----------------------------------------------------------------------===//
3737 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
3738 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
3741 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
3742 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
3745 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
3746 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
3749 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
3750 const OperandVector &Operands,
3751 bool IsAtomic, bool IsAtomicReturn) {
3752 OptionalImmIndexMap OptionalIdx;
3753 assert(IsAtomicReturn ? IsAtomic : true);
3755 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3756 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3758 // Add the register arguments
3760 Op.addRegOperands(Inst, 1);
3764 // Handle the case where soffset is an immediate
3765 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3766 Op.addImmOperands(Inst, 1);
3770 // Handle tokens like 'offen' which are sometimes hard-coded into the
3771 // asm string. There are no MCInst operands for these.
3777 // Handle optional arguments
3778 OptionalIdx[Op.getImmTy()] = i;
3781 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
3782 if (IsAtomicReturn) {
3783 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
3787 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
3788 if (!IsAtomic) { // glc is hard-coded.
3789 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3791 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3792 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3795 //===----------------------------------------------------------------------===//
3797 //===----------------------------------------------------------------------===//
3799 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
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 OptionalImmIndexMap OptionalIdx;
3808 for (unsigned E = Operands.size(); I != E; ++I) {
3809 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3811 // Add the register arguments
3812 if (Op.isRegOrImm()) {
3813 Op.addRegOrImmOperands(Inst, 1);
3815 } else if (Op.isImmModifier()) {
3816 OptionalIdx[Op.getImmTy()] = I;
3818 llvm_unreachable("unexpected operand type");
3822 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3823 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3824 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3825 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3826 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3827 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3828 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3829 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3832 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
3834 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3835 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3836 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3839 // Add src, same as dst
3840 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
3842 OptionalImmIndexMap OptionalIdx;
3844 for (unsigned E = Operands.size(); I != E; ++I) {
3845 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3847 // Add the register arguments
3848 if (Op.isRegOrImm()) {
3849 Op.addRegOrImmOperands(Inst, 1);
3851 } else if (Op.isImmModifier()) {
3852 OptionalIdx[Op.getImmTy()] = I;
3854 llvm_unreachable("unexpected operand type");
3858 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3859 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3860 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3861 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3862 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3863 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3864 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3865 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3868 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
3869 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
3872 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
3873 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
3876 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
3877 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
3880 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
3881 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3884 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3885 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3888 //===----------------------------------------------------------------------===//
3890 //===----------------------------------------------------------------------===//
3892 bool AMDGPUOperand::isSMRDOffset8() const {
3893 return isImm() && isUInt<8>(getImm());
3896 bool AMDGPUOperand::isSMRDOffset20() const {
3897 return isImm() && isUInt<20>(getImm());
3900 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3901 // 32-bit literals are only supported on CI and we only want to use them
3902 // when the offset is > 8-bits.
3903 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3906 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3907 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3910 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3911 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3914 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3915 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3918 //===----------------------------------------------------------------------===//
3920 //===----------------------------------------------------------------------===//
3922 static bool ConvertOmodMul(int64_t &Mul) {
3923 if (Mul != 1 && Mul != 2 && Mul != 4)
3930 static bool ConvertOmodDiv(int64_t &Div) {
3944 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
3945 if (BoundCtrl == 0) {
3950 if (BoundCtrl == -1) {
3958 // Note: the order in this table matches the order of operands in AsmString.
3959 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
3960 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
3961 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
3962 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
3963 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
3964 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
3965 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
3966 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
3967 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
3968 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
3969 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
3970 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
3971 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
3972 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
3973 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
3974 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
3975 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
3976 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
3977 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
3978 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
3979 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
3980 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
3981 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
3982 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
3983 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
3984 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
3985 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
3986 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
3987 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
3988 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
3989 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
3992 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
3993 OperandMatchResultTy res;
3994 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
3995 // try to parse any optional operand here
3997 res = parseNamedBit(Op.Name, Operands, Op.Type);
3998 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
3999 res = parseOModOperand(Operands);
4000 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
4001 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
4002 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
4003 res = parseSDWASel(Operands, Op.Name, Op.Type);
4004 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
4005 res = parseSDWADstUnused(Operands);
4006 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
4007 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
4008 Op.Type == AMDGPUOperand::ImmTyNegLo ||
4009 Op.Type == AMDGPUOperand::ImmTyNegHi) {
4010 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
4013 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
4015 if (res != MatchOperand_NoMatch) {
4019 return MatchOperand_NoMatch;
4022 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
4023 StringRef Name = Parser.getTok().getString();
4024 if (Name == "mul") {
4025 return parseIntWithPrefix("mul", Operands,
4026 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
4029 if (Name == "div") {
4030 return parseIntWithPrefix("div", Operands,
4031 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
4034 return MatchOperand_NoMatch;
4037 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
4039 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4040 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4041 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4043 for (unsigned E = Operands.size(); I != E; ++I)
4044 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
4047 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
4048 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
4049 if (TSFlags & SIInstrFlags::VOP3) {
4050 cvtVOP3(Inst, Operands);
4052 cvtId(Inst, Operands);
4056 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
4057 // 1. This operand is input modifiers
4058 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
4059 // 2. This is not last operand
4060 && Desc.NumOperands > (OpNum + 1)
4061 // 3. Next operand is register class
4062 && Desc.OpInfo[OpNum + 1].RegClass != -1
4063 // 4. Next register is not tied to any other operand
4064 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
4067 void AMDGPUAsmParser::cvtVOP3Impl(MCInst &Inst, const OperandVector &Operands,
4068 OptionalImmIndexMap &OptionalIdx) {
4070 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4071 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4072 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4075 for (unsigned E = Operands.size(); I != E; ++I) {
4076 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4077 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4078 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4079 } else if (Op.isImmModifier()) {
4080 OptionalIdx[Op.getImmTy()] = I;
4081 } else if (Op.isRegOrImm()) {
4082 Op.addRegOrImmOperands(Inst, 1);
4084 llvm_unreachable("unhandled operand type");
4089 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
4090 OptionalImmIndexMap OptionalIdx;
4092 cvtVOP3Impl(Inst, Operands, OptionalIdx);
4094 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4095 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4097 // special case v_mac_{f16, f32}:
4098 // it has src2 register operand that is tied to dst operand
4099 // we don't allow modifiers for this operand in assembler so src2_modifiers
4101 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
4102 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
4103 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
4104 auto it = Inst.begin();
4107 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
4108 AMDGPU::V_MAC_F16_e64 :
4109 AMDGPU::V_MAC_F32_e64,
4110 AMDGPU::OpName::src2_modifiers));
4111 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
4113 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4117 void AMDGPUAsmParser::cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands) {
4118 OptionalImmIndexMap OptionalIdx;
4121 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4122 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4123 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4126 for (unsigned E = Operands.size(); I != E; ++I) {
4127 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4129 OptionalIdx[Op.getImmTy()] = I;
4131 Op.addRegOrImmOperands(Inst, 1);
4135 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4136 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4139 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
4140 OptionalImmIndexMap OptIdx;
4142 cvtVOP3Impl(Inst, Operands, OptIdx);
4144 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
4145 // instruction, and then figure out where to actually put the modifiers
4146 int Opc = Inst.getOpcode();
4148 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4149 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClampSI);
4152 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
4153 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, -1);
4155 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
4156 if (NegLoIdx != -1) {
4157 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
4158 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
4161 const int Ops[] = { AMDGPU::OpName::src0,
4162 AMDGPU::OpName::src1,
4163 AMDGPU::OpName::src2 };
4164 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
4165 AMDGPU::OpName::src1_modifiers,
4166 AMDGPU::OpName::src2_modifiers };
4168 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4169 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4171 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4172 unsigned OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
4176 if (NegLoIdx != -1) {
4177 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
4178 NegLo = Inst.getOperand(NegLoIdx).getImm();
4179 NegHi = Inst.getOperand(NegHiIdx).getImm();
4182 for (int J = 0; J < 3; ++J) {
4183 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
4187 uint32_t ModVal = 0;
4189 if ((OpSel & (1 << J)) != 0)
4190 ModVal |= SISrcMods::OP_SEL_0;
4192 if ((OpSelHi & (1 << J)) != 0)
4193 ModVal |= SISrcMods::OP_SEL_1;
4195 if ((NegLo & (1 << J)) != 0)
4196 ModVal |= SISrcMods::NEG;
4198 if ((NegHi & (1 << J)) != 0)
4199 ModVal |= SISrcMods::NEG_HI;
4201 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
4203 Inst.getOperand(ModIdx).setImm(ModVal);
4207 //===----------------------------------------------------------------------===//
4209 //===----------------------------------------------------------------------===//
4211 bool AMDGPUOperand::isDPPCtrl() const {
4212 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
4214 int64_t Imm = getImm();
4215 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
4216 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
4217 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
4218 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
4231 bool AMDGPUOperand::isGPRIdxMode() const {
4232 return isImm() && isUInt<4>(getImm());
4235 bool AMDGPUOperand::isS16Imm() const {
4236 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
4239 bool AMDGPUOperand::isU16Imm() const {
4240 return isImm() && isUInt<16>(getImm());
4243 OperandMatchResultTy
4244 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
4245 SMLoc S = Parser.getTok().getLoc();
4249 if (getLexer().getKind() == AsmToken::Identifier) {
4250 Prefix = Parser.getTok().getString();
4252 return MatchOperand_NoMatch;
4255 if (Prefix == "row_mirror") {
4258 } else if (Prefix == "row_half_mirror") {
4262 // Check to prevent parseDPPCtrlOps from eating invalid tokens
4263 if (Prefix != "quad_perm"
4264 && Prefix != "row_shl"
4265 && Prefix != "row_shr"
4266 && Prefix != "row_ror"
4267 && Prefix != "wave_shl"
4268 && Prefix != "wave_rol"
4269 && Prefix != "wave_shr"
4270 && Prefix != "wave_ror"
4271 && Prefix != "row_bcast") {
4272 return MatchOperand_NoMatch;
4276 if (getLexer().isNot(AsmToken::Colon))
4277 return MatchOperand_ParseFail;
4279 if (Prefix == "quad_perm") {
4280 // quad_perm:[%d,%d,%d,%d]
4282 if (getLexer().isNot(AsmToken::LBrac))
4283 return MatchOperand_ParseFail;
4286 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
4287 return MatchOperand_ParseFail;
4289 for (int i = 0; i < 3; ++i) {
4290 if (getLexer().isNot(AsmToken::Comma))
4291 return MatchOperand_ParseFail;
4295 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
4296 return MatchOperand_ParseFail;
4297 const int shift = i*2 + 2;
4298 Int += (Temp << shift);
4301 if (getLexer().isNot(AsmToken::RBrac))
4302 return MatchOperand_ParseFail;
4308 if (getParser().parseAbsoluteExpression(Int))
4309 return MatchOperand_ParseFail;
4311 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
4313 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
4315 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
4317 } else if (Prefix == "wave_shl" && 1 == Int) {
4319 } else if (Prefix == "wave_rol" && 1 == Int) {
4321 } else if (Prefix == "wave_shr" && 1 == Int) {
4323 } else if (Prefix == "wave_ror" && 1 == Int) {
4325 } else if (Prefix == "row_bcast") {
4328 } else if (Int == 31) {
4331 return MatchOperand_ParseFail;
4334 return MatchOperand_ParseFail;
4339 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
4340 return MatchOperand_Success;
4343 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
4344 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
4347 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
4348 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
4351 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
4352 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
4355 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
4356 OptionalImmIndexMap OptionalIdx;
4359 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4360 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4361 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4364 for (unsigned E = Operands.size(); I != E; ++I) {
4365 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4366 // Add the register arguments
4367 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4368 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
4371 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4372 Op.addRegWithFPInputModsOperands(Inst, 2);
4373 } else if (Op.isDPPCtrl()) {
4374 Op.addImmOperands(Inst, 1);
4375 } else if (Op.isImm()) {
4376 // Handle optional arguments
4377 OptionalIdx[Op.getImmTy()] = I;
4379 llvm_unreachable("Invalid operand type");
4383 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
4384 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
4385 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
4387 // special case v_mac_{f16, f32}:
4388 // it has src2 register operand that is tied to dst operand
4389 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
4390 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
4391 auto it = Inst.begin();
4393 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4394 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4398 //===----------------------------------------------------------------------===//
4400 //===----------------------------------------------------------------------===//
4402 OperandMatchResultTy
4403 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
4404 AMDGPUOperand::ImmTy Type) {
4405 using namespace llvm::AMDGPU::SDWA;
4407 SMLoc S = Parser.getTok().getLoc();
4409 OperandMatchResultTy res;
4411 res = parseStringWithPrefix(Prefix, Value);
4412 if (res != MatchOperand_Success) {
4417 Int = StringSwitch<int64_t>(Value)
4418 .Case("BYTE_0", SdwaSel::BYTE_0)
4419 .Case("BYTE_1", SdwaSel::BYTE_1)
4420 .Case("BYTE_2", SdwaSel::BYTE_2)
4421 .Case("BYTE_3", SdwaSel::BYTE_3)
4422 .Case("WORD_0", SdwaSel::WORD_0)
4423 .Case("WORD_1", SdwaSel::WORD_1)
4424 .Case("DWORD", SdwaSel::DWORD)
4425 .Default(0xffffffff);
4426 Parser.Lex(); // eat last token
4428 if (Int == 0xffffffff) {
4429 return MatchOperand_ParseFail;
4432 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
4433 return MatchOperand_Success;
4436 OperandMatchResultTy
4437 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
4438 using namespace llvm::AMDGPU::SDWA;
4440 SMLoc S = Parser.getTok().getLoc();
4442 OperandMatchResultTy res;
4444 res = parseStringWithPrefix("dst_unused", Value);
4445 if (res != MatchOperand_Success) {
4450 Int = StringSwitch<int64_t>(Value)
4451 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
4452 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
4453 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
4454 .Default(0xffffffff);
4455 Parser.Lex(); // eat last token
4457 if (Int == 0xffffffff) {
4458 return MatchOperand_ParseFail;
4461 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
4462 return MatchOperand_Success;
4465 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
4466 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
4469 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
4470 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
4473 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
4474 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
4477 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
4478 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
4481 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
4482 uint64_t BasicInstType, bool skipVcc) {
4483 using namespace llvm::AMDGPU::SDWA;
4484 OptionalImmIndexMap OptionalIdx;
4485 bool skippedVcc = false;
4488 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4489 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4490 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4493 for (unsigned E = Operands.size(); I != E; ++I) {
4494 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4495 if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4496 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
4497 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
4498 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
4499 // Skip VCC only if we didn't skip it on previous iteration.
4500 if (BasicInstType == SIInstrFlags::VOP2 &&
4501 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
4504 } else if (BasicInstType == SIInstrFlags::VOPC &&
4505 Inst.getNumOperands() == 0) {
4510 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4511 Op.addRegWithInputModsOperands(Inst, 2);
4512 } else if (Op.isImm()) {
4513 // Handle optional arguments
4514 OptionalIdx[Op.getImmTy()] = I;
4516 llvm_unreachable("Invalid operand type");
4521 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
4522 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
4523 // V_NOP_sdwa_vi has no optional sdwa arguments
4524 switch (BasicInstType) {
4525 case SIInstrFlags::VOP1:
4526 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4528 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4529 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4531 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4532 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4533 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4536 case SIInstrFlags::VOP2:
4537 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4539 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4540 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4542 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4543 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4544 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4545 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4548 case SIInstrFlags::VOPC:
4550 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4552 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4553 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4557 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
4561 // special case v_mac_{f16, f32}:
4562 // it has src2 register operand that is tied to dst operand
4563 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
4564 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
4565 auto it = Inst.begin();
4567 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4568 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4572 /// Force static initialization.
4573 extern "C" void LLVMInitializeAMDGPUAsmParser() {
4574 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
4575 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
4578 #define GET_REGISTER_MATCHER
4579 #define GET_MATCHER_IMPLEMENTATION
4580 #include "AMDGPUGenAsmMatcher.inc"
4582 // This fuction should be defined after auto-generated include so that we have
4583 // MatchClassKind enum defined
4584 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
4586 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
4587 // But MatchInstructionImpl() expects to meet token and fails to validate
4588 // operand. This method checks if we are given immediate operand but expect to
4589 // get corresponding token.
4590 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
4593 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
4595 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
4597 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
4599 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
4601 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
4603 // When operands have expression values, they will return true for isToken,
4604 // because it is not possible to distinguish between a token and an
4605 // expression at parse time. MatchInstructionImpl() will always try to
4606 // match an operand as a token, when isToken returns true, and when the
4607 // name of the expression is not a valid token, the match will fail,
4608 // so we need to handle it here.
4609 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
4611 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
4612 case MCK_SoppBrTarget:
4613 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
4614 case MCK_VReg32OrOff:
4615 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
4616 case MCK_InterpSlot:
4617 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
4619 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
4621 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
4623 return Match_InvalidOperand;