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 //===----------------------------------------------------------------------===//
11 #include "AMDKernelCodeT.h"
12 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
13 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
14 #include "SIDefines.h"
15 #include "Utils/AMDGPUAsmUtils.h"
16 #include "Utils/AMDGPUBaseInfo.h"
17 #include "Utils/AMDKernelCodeTUtils.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/APInt.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/SmallBitVector.h"
23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/ADT/StringSwitch.h"
26 #include "llvm/ADT/Twine.h"
27 #include "llvm/BinaryFormat/ELF.h"
28 #include "llvm/CodeGen/MachineValueType.h"
29 #include "llvm/MC/MCAsmInfo.h"
30 #include "llvm/MC/MCContext.h"
31 #include "llvm/MC/MCExpr.h"
32 #include "llvm/MC/MCInst.h"
33 #include "llvm/MC/MCInstrDesc.h"
34 #include "llvm/MC/MCInstrInfo.h"
35 #include "llvm/MC/MCParser/MCAsmLexer.h"
36 #include "llvm/MC/MCParser/MCAsmParser.h"
37 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
38 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
39 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
40 #include "llvm/MC/MCRegisterInfo.h"
41 #include "llvm/MC/MCStreamer.h"
42 #include "llvm/MC/MCSubtargetInfo.h"
43 #include "llvm/MC/MCSymbol.h"
44 #include "llvm/Support/AMDGPUMetadata.h"
45 #include "llvm/Support/Casting.h"
46 #include "llvm/Support/Compiler.h"
47 #include "llvm/Support/ErrorHandling.h"
48 #include "llvm/Support/MathExtras.h"
49 #include "llvm/Support/SMLoc.h"
50 #include "llvm/Support/TargetRegistry.h"
51 #include "llvm/Support/raw_ostream.h"
62 using namespace llvm::AMDGPU;
66 class AMDGPUAsmParser;
68 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
70 //===----------------------------------------------------------------------===//
72 //===----------------------------------------------------------------------===//
74 class AMDGPUOperand : public MCParsedAsmOperand {
82 SMLoc StartLoc, EndLoc;
83 const AMDGPUAsmParser *AsmParser;
86 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
87 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
89 using Ptr = std::unique_ptr<AMDGPUOperand>;
96 bool hasFPModifiers() const { return Abs || Neg; }
97 bool hasIntModifiers() const { return Sext; }
98 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
100 int64_t getFPModifiersOperand() const {
102 Operand |= Abs ? SISrcMods::ABS : 0;
103 Operand |= Neg ? SISrcMods::NEG : 0;
107 int64_t getIntModifiersOperand() const {
109 Operand |= Sext ? SISrcMods::SEXT : 0;
113 int64_t getModifiersOperand() const {
114 assert(!(hasFPModifiers() && hasIntModifiers())
115 && "fp and int modifiers should not be used simultaneously");
116 if (hasFPModifiers()) {
117 return getFPModifiersOperand();
118 } else if (hasIntModifiers()) {
119 return getIntModifiersOperand();
125 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
200 bool isToken() const override {
204 if (Kind != Expression || !Expr)
207 // When parsing operands, we can't always tell if something was meant to be
208 // a token, like 'gds', or an expression that references a global variable.
209 // In this case, we assume the string is an expression, and if we need to
210 // interpret is a token, then we treat the symbol name as the token.
211 return isa<MCSymbolRefExpr>(Expr);
214 bool isImm() const override {
215 return Kind == Immediate;
218 bool isInlinableImm(MVT type) const;
219 bool isLiteralImm(MVT type) const;
221 bool isRegKind() const {
222 return Kind == Register;
225 bool isReg() const override {
226 return isRegKind() && !hasModifiers();
229 bool isRegOrImmWithInputMods(MVT type) const {
230 return isRegKind() || isInlinableImm(type);
233 bool isRegOrImmWithInt16InputMods() const {
234 return isRegOrImmWithInputMods(MVT::i16);
237 bool isRegOrImmWithInt32InputMods() const {
238 return isRegOrImmWithInputMods(MVT::i32);
241 bool isRegOrImmWithInt64InputMods() const {
242 return isRegOrImmWithInputMods(MVT::i64);
245 bool isRegOrImmWithFP16InputMods() const {
246 return isRegOrImmWithInputMods(MVT::f16);
249 bool isRegOrImmWithFP32InputMods() const {
250 return isRegOrImmWithInputMods(MVT::f32);
253 bool isRegOrImmWithFP64InputMods() const {
254 return isRegOrImmWithInputMods(MVT::f64);
257 bool isVReg() const {
258 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
259 isRegClass(AMDGPU::VReg_64RegClassID) ||
260 isRegClass(AMDGPU::VReg_96RegClassID) ||
261 isRegClass(AMDGPU::VReg_128RegClassID) ||
262 isRegClass(AMDGPU::VReg_256RegClassID) ||
263 isRegClass(AMDGPU::VReg_512RegClassID);
266 bool isVReg32OrOff() const {
267 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
270 bool isSDWARegKind() const;
272 bool isImmTy(ImmTy ImmT) const {
273 return isImm() && Imm.Type == ImmT;
276 bool isImmModifier() const {
277 return isImm() && Imm.Type != ImmTyNone;
280 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
281 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
282 bool isDMask() const { return isImmTy(ImmTyDMask); }
283 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
284 bool isDA() const { return isImmTy(ImmTyDA); }
285 bool isR128() const { return isImmTy(ImmTyUNorm); }
286 bool isLWE() const { return isImmTy(ImmTyLWE); }
287 bool isOff() const { return isImmTy(ImmTyOff); }
288 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
289 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
290 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
291 bool isOffen() const { return isImmTy(ImmTyOffen); }
292 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
293 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
294 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
295 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
296 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
298 bool isOffsetU12() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isUInt<12>(getImm()); }
299 bool isOffsetS13() const { return (isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset)) && isInt<13>(getImm()); }
300 bool isGDS() const { return isImmTy(ImmTyGDS); }
301 bool isGLC() const { return isImmTy(ImmTyGLC); }
302 bool isSLC() const { return isImmTy(ImmTySLC); }
303 bool isTFE() const { return isImmTy(ImmTyTFE); }
304 bool isDFMT() const { return isImmTy(ImmTyDFMT) && isUInt<8>(getImm()); }
305 bool isNFMT() const { return isImmTy(ImmTyNFMT) && isUInt<8>(getImm()); }
306 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
307 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
308 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
309 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
310 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
311 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
312 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
313 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
314 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
315 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
316 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
317 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
318 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
319 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
320 bool isHigh() const { return isImmTy(ImmTyHigh); }
323 return isClampSI() || isOModSI();
326 bool isRegOrImm() const {
327 return isReg() || isImm();
330 bool isRegClass(unsigned RCID) const;
332 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
333 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
336 bool isSCSrcB16() const {
337 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
340 bool isSCSrcV2B16() const {
344 bool isSCSrcB32() const {
345 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
348 bool isSCSrcB64() const {
349 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
352 bool isSCSrcF16() const {
353 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
356 bool isSCSrcV2F16() const {
360 bool isSCSrcF32() const {
361 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
364 bool isSCSrcF64() const {
365 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
368 bool isSSrcB32() const {
369 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
372 bool isSSrcB16() const {
373 return isSCSrcB16() || isLiteralImm(MVT::i16);
376 bool isSSrcV2B16() const {
377 llvm_unreachable("cannot happen");
381 bool isSSrcB64() const {
382 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
384 return isSCSrcB64() || isLiteralImm(MVT::i64);
387 bool isSSrcF32() const {
388 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
391 bool isSSrcF64() const {
392 return isSCSrcB64() || isLiteralImm(MVT::f64);
395 bool isSSrcF16() const {
396 return isSCSrcB16() || isLiteralImm(MVT::f16);
399 bool isSSrcV2F16() const {
400 llvm_unreachable("cannot happen");
404 bool isVCSrcB32() const {
405 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
408 bool isVCSrcB64() const {
409 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
412 bool isVCSrcB16() const {
413 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
416 bool isVCSrcV2B16() const {
420 bool isVCSrcF32() const {
421 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
424 bool isVCSrcF64() const {
425 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
428 bool isVCSrcF16() const {
429 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
432 bool isVCSrcV2F16() const {
436 bool isVSrcB32() const {
437 return isVCSrcF32() || isLiteralImm(MVT::i32);
440 bool isVSrcB64() const {
441 return isVCSrcF64() || isLiteralImm(MVT::i64);
444 bool isVSrcB16() const {
445 return isVCSrcF16() || isLiteralImm(MVT::i16);
448 bool isVSrcV2B16() const {
449 llvm_unreachable("cannot happen");
453 bool isVSrcF32() const {
454 return isVCSrcF32() || isLiteralImm(MVT::f32);
457 bool isVSrcF64() const {
458 return isVCSrcF64() || isLiteralImm(MVT::f64);
461 bool isVSrcF16() const {
462 return isVCSrcF16() || isLiteralImm(MVT::f16);
465 bool isVSrcV2F16() const {
466 llvm_unreachable("cannot happen");
470 bool isKImmFP32() const {
471 return isLiteralImm(MVT::f32);
474 bool isKImmFP16() const {
475 return isLiteralImm(MVT::f16);
478 bool isMem() const override {
482 bool isExpr() const {
483 return Kind == Expression;
486 bool isSoppBrTarget() const {
487 return isExpr() || isImm();
490 bool isSWaitCnt() const;
491 bool isHwreg() const;
492 bool isSendMsg() const;
493 bool isSwizzle() const;
494 bool isSMRDOffset8() const;
495 bool isSMRDOffset20() const;
496 bool isSMRDLiteralOffset() const;
497 bool isDPPCtrl() const;
498 bool isGPRIdxMode() const;
499 bool isS16Imm() const;
500 bool isU16Imm() const;
502 StringRef getExpressionAsToken() const {
504 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
505 return S->getSymbol().getName();
508 StringRef getToken() const {
511 if (Kind == Expression)
512 return getExpressionAsToken();
514 return StringRef(Tok.Data, Tok.Length);
517 int64_t getImm() const {
522 ImmTy getImmTy() const {
527 unsigned getReg() const override {
531 SMLoc getStartLoc() const override {
535 SMLoc getEndLoc() const override {
539 SMRange getLocRange() const {
540 return SMRange(StartLoc, EndLoc);
543 Modifiers getModifiers() const {
544 assert(isRegKind() || isImmTy(ImmTyNone));
545 return isRegKind() ? Reg.Mods : Imm.Mods;
548 void setModifiers(Modifiers Mods) {
549 assert(isRegKind() || isImmTy(ImmTyNone));
556 bool hasModifiers() const {
557 return getModifiers().hasModifiers();
560 bool hasFPModifiers() const {
561 return getModifiers().hasFPModifiers();
564 bool hasIntModifiers() const {
565 return getModifiers().hasIntModifiers();
568 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
570 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
572 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
574 template <unsigned Bitwidth>
575 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
577 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
578 addKImmFPOperands<16>(Inst, N);
581 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
582 addKImmFPOperands<32>(Inst, N);
585 void addRegOperands(MCInst &Inst, unsigned N) const;
587 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
589 addRegOperands(Inst, N);
591 Inst.addOperand(MCOperand::createExpr(Expr));
593 addImmOperands(Inst, N);
596 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
597 Modifiers Mods = getModifiers();
598 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
600 addRegOperands(Inst, N);
602 addImmOperands(Inst, N, false);
606 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
607 assert(!hasIntModifiers());
608 addRegOrImmWithInputModsOperands(Inst, N);
611 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
612 assert(!hasFPModifiers());
613 addRegOrImmWithInputModsOperands(Inst, N);
616 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
617 Modifiers Mods = getModifiers();
618 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
620 addRegOperands(Inst, N);
623 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
624 assert(!hasIntModifiers());
625 addRegWithInputModsOperands(Inst, N);
628 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
629 assert(!hasFPModifiers());
630 addRegWithInputModsOperands(Inst, N);
633 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
635 addImmOperands(Inst, N);
638 Inst.addOperand(MCOperand::createExpr(Expr));
642 static void printImmTy(raw_ostream& OS, ImmTy Type) {
644 case ImmTyNone: OS << "None"; break;
645 case ImmTyGDS: OS << "GDS"; break;
646 case ImmTyOffen: OS << "Offen"; break;
647 case ImmTyIdxen: OS << "Idxen"; break;
648 case ImmTyAddr64: OS << "Addr64"; break;
649 case ImmTyOffset: OS << "Offset"; break;
650 case ImmTyInstOffset: OS << "InstOffset"; break;
651 case ImmTyOffset0: OS << "Offset0"; break;
652 case ImmTyOffset1: OS << "Offset1"; break;
653 case ImmTyGLC: OS << "GLC"; break;
654 case ImmTySLC: OS << "SLC"; break;
655 case ImmTyTFE: OS << "TFE"; break;
656 case ImmTyDFMT: OS << "DFMT"; break;
657 case ImmTyNFMT: OS << "NFMT"; break;
658 case ImmTyClampSI: OS << "ClampSI"; break;
659 case ImmTyOModSI: OS << "OModSI"; break;
660 case ImmTyDppCtrl: OS << "DppCtrl"; break;
661 case ImmTyDppRowMask: OS << "DppRowMask"; break;
662 case ImmTyDppBankMask: OS << "DppBankMask"; break;
663 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
664 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
665 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
666 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
667 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
668 case ImmTyDMask: OS << "DMask"; break;
669 case ImmTyUNorm: OS << "UNorm"; break;
670 case ImmTyDA: OS << "DA"; break;
671 case ImmTyR128: OS << "R128"; break;
672 case ImmTyLWE: OS << "LWE"; break;
673 case ImmTyOff: OS << "Off"; break;
674 case ImmTyExpTgt: OS << "ExpTgt"; break;
675 case ImmTyExpCompr: OS << "ExpCompr"; break;
676 case ImmTyExpVM: OS << "ExpVM"; break;
677 case ImmTyHwreg: OS << "Hwreg"; break;
678 case ImmTySendMsg: OS << "SendMsg"; break;
679 case ImmTyInterpSlot: OS << "InterpSlot"; break;
680 case ImmTyInterpAttr: OS << "InterpAttr"; break;
681 case ImmTyAttrChan: OS << "AttrChan"; break;
682 case ImmTyOpSel: OS << "OpSel"; break;
683 case ImmTyOpSelHi: OS << "OpSelHi"; break;
684 case ImmTyNegLo: OS << "NegLo"; break;
685 case ImmTyNegHi: OS << "NegHi"; break;
686 case ImmTySwizzle: OS << "Swizzle"; break;
687 case ImmTyHigh: OS << "High"; break;
691 void print(raw_ostream &OS) const override {
694 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
697 OS << '<' << getImm();
698 if (getImmTy() != ImmTyNone) {
699 OS << " type: "; printImmTy(OS, getImmTy());
701 OS << " mods: " << Imm.Mods << '>';
704 OS << '\'' << getToken() << '\'';
707 OS << "<expr " << *Expr << '>';
712 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
713 int64_t Val, SMLoc Loc,
714 ImmTy Type = ImmTyNone,
715 bool IsFPImm = false) {
716 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
718 Op->Imm.IsFPImm = IsFPImm;
720 Op->Imm.Mods = Modifiers();
726 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
727 StringRef Str, SMLoc Loc,
728 bool HasExplicitEncodingSize = true) {
729 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
730 Res->Tok.Data = Str.data();
731 Res->Tok.Length = Str.size();
737 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
738 unsigned RegNo, SMLoc S,
741 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
742 Op->Reg.RegNo = RegNo;
743 Op->Reg.Mods = Modifiers();
744 Op->Reg.IsForcedVOP3 = ForceVOP3;
750 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
751 const class MCExpr *Expr, SMLoc S) {
752 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
760 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
761 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
765 //===----------------------------------------------------------------------===//
767 //===----------------------------------------------------------------------===//
769 // Holds info related to the current kernel, e.g. count of SGPRs used.
770 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
771 // .amdgpu_hsa_kernel or at EOF.
772 class KernelScopeInfo {
773 int SgprIndexUnusedMin = -1;
774 int VgprIndexUnusedMin = -1;
775 MCContext *Ctx = nullptr;
777 void usesSgprAt(int i) {
778 if (i >= SgprIndexUnusedMin) {
779 SgprIndexUnusedMin = ++i;
781 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
782 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
787 void usesVgprAt(int i) {
788 if (i >= VgprIndexUnusedMin) {
789 VgprIndexUnusedMin = ++i;
791 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
792 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
798 KernelScopeInfo() = default;
800 void initialize(MCContext &Context) {
802 usesSgprAt(SgprIndexUnusedMin = -1);
803 usesVgprAt(VgprIndexUnusedMin = -1);
806 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
808 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
809 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
815 class AMDGPUAsmParser : public MCTargetAsmParser {
818 // Number of extra operands parsed after the first optional operand.
819 // This may be necessary to skip hardcoded mandatory operands.
820 static const unsigned MAX_OPR_LOOKAHEAD = 1;
822 unsigned ForcedEncodingSize = 0;
823 bool ForcedDPP = false;
824 bool ForcedSDWA = false;
825 KernelScopeInfo KernelScope;
827 /// @name Auto-generated Match Functions
830 #define GET_ASSEMBLER_HEADER
831 #include "AMDGPUGenAsmMatcher.inc"
836 bool ParseAsAbsoluteExpression(uint32_t &Ret);
837 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
838 bool ParseDirectiveHSACodeObjectVersion();
839 bool ParseDirectiveHSACodeObjectISA();
840 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
841 bool ParseDirectiveAMDKernelCodeT();
842 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
843 bool ParseDirectiveAMDGPUHsaKernel();
845 bool ParseDirectiveISAVersion();
846 bool ParseDirectiveHSAMetadata();
847 bool ParseDirectivePALMetadata();
849 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
850 RegisterKind RegKind, unsigned Reg1,
852 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
853 unsigned& RegNum, unsigned& RegWidth,
854 unsigned *DwordRegIndex);
855 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
856 bool IsAtomic, bool IsAtomicReturn);
857 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
858 bool IsGdsHardcoded);
861 enum AMDGPUMatchResultTy {
862 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
865 using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
867 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
868 const MCInstrInfo &MII,
869 const MCTargetOptions &Options)
870 : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
871 MCAsmParserExtension::Initialize(Parser);
873 if (getFeatureBits().none()) {
874 // Set default features.
875 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
878 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
881 // TODO: make those pre-defined variables read-only.
882 // Currently there is none suitable machinery in the core llvm-mc for this.
883 // MCSymbol::isRedefinable is intended for another purpose, and
884 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
885 AMDGPU::IsaInfo::IsaVersion ISA =
886 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
887 MCContext &Ctx = getContext();
889 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
890 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
891 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
892 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
893 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
894 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
896 KernelScope.initialize(getContext());
900 return AMDGPU::isSI(getSTI());
904 return AMDGPU::isCI(getSTI());
908 return AMDGPU::isVI(getSTI());
911 bool isGFX9() const {
912 return AMDGPU::isGFX9(getSTI());
915 bool hasInv2PiInlineImm() const {
916 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
919 bool hasFlatOffsets() const {
920 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
923 bool hasSGPR102_SGPR103() const {
927 bool hasIntClamp() const {
928 return getFeatureBits()[AMDGPU::FeatureIntClamp];
931 AMDGPUTargetStreamer &getTargetStreamer() {
932 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
933 return static_cast<AMDGPUTargetStreamer &>(TS);
936 const MCRegisterInfo *getMRI() const {
937 // We need this const_cast because for some reason getContext() is not const
939 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
942 const MCInstrInfo *getMII() const {
946 const FeatureBitset &getFeatureBits() const {
947 return getSTI().getFeatureBits();
950 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
951 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
952 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
954 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
955 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
956 bool isForcedDPP() const { return ForcedDPP; }
957 bool isForcedSDWA() const { return ForcedSDWA; }
958 ArrayRef<unsigned> getMatchedVariants() const;
960 std::unique_ptr<AMDGPUOperand> parseRegister();
961 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
962 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
963 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
964 unsigned Kind) override;
965 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
966 OperandVector &Operands, MCStreamer &Out,
968 bool MatchingInlineAsm) override;
969 bool ParseDirective(AsmToken DirectiveID) override;
970 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
971 StringRef parseMnemonicSuffix(StringRef Name);
972 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
973 SMLoc NameLoc, OperandVector &Operands) override;
974 //bool ProcessInstruction(MCInst &Inst);
976 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
979 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
980 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
981 bool (*ConvertResult)(int64_t &) = nullptr);
983 OperandMatchResultTy parseOperandArrayWithPrefix(
985 OperandVector &Operands,
986 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
987 bool (*ConvertResult)(int64_t&) = nullptr);
990 parseNamedBit(const char *Name, OperandVector &Operands,
991 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
992 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
995 bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
996 OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
997 OperandMatchResultTy parseReg(OperandVector &Operands);
998 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
999 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1000 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1001 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1002 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
1003 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
1005 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
1006 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1007 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
1008 void cvtExp(MCInst &Inst, const OperandVector &Operands);
1010 bool parseCnt(int64_t &IntVal);
1011 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
1012 OperandMatchResultTy parseHwreg(OperandVector &Operands);
1015 struct OperandInfoTy {
1017 bool IsSymbolic = false;
1019 OperandInfoTy(int64_t Id_) : Id(Id_) {}
1022 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
1023 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1026 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1028 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
1029 bool validateConstantBusLimitations(const MCInst &Inst);
1030 bool validateEarlyClobberLimitations(const MCInst &Inst);
1031 bool validateIntClampSupported(const MCInst &Inst);
1032 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1033 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1034 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1036 bool trySkipId(const StringRef Id);
1037 bool trySkipToken(const AsmToken::TokenKind Kind);
1038 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1039 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1040 bool parseExpr(int64_t &Imm);
1043 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1044 OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
1046 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1047 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1048 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1049 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1050 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1052 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1053 const unsigned MinVal,
1054 const unsigned MaxVal,
1055 const StringRef ErrMsg);
1056 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1057 bool parseSwizzleOffset(int64_t &Imm);
1058 bool parseSwizzleMacro(int64_t &Imm);
1059 bool parseSwizzleQuadPerm(int64_t &Imm);
1060 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1061 bool parseSwizzleBroadcast(int64_t &Imm);
1062 bool parseSwizzleSwap(int64_t &Imm);
1063 bool parseSwizzleReverse(int64_t &Imm);
1065 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1066 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1067 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1068 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1070 AMDGPUOperand::Ptr defaultGLC() const;
1071 AMDGPUOperand::Ptr defaultSLC() const;
1072 AMDGPUOperand::Ptr defaultTFE() const;
1074 AMDGPUOperand::Ptr defaultDMask() const;
1075 AMDGPUOperand::Ptr defaultUNorm() const;
1076 AMDGPUOperand::Ptr defaultDA() const;
1077 AMDGPUOperand::Ptr defaultR128() const;
1078 AMDGPUOperand::Ptr defaultLWE() const;
1079 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1080 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1081 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1082 AMDGPUOperand::Ptr defaultOffsetU12() const;
1083 AMDGPUOperand::Ptr defaultOffsetS13() const;
1085 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1087 void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1088 OptionalImmIndexMap &OptionalIdx);
1089 void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1090 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1091 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1093 void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1095 void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1096 bool IsAtomic = false);
1097 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1099 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1100 AMDGPUOperand::Ptr defaultRowMask() const;
1101 AMDGPUOperand::Ptr defaultBankMask() const;
1102 AMDGPUOperand::Ptr defaultBoundCtrl() const;
1103 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1105 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1106 AMDGPUOperand::ImmTy Type);
1107 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1108 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1109 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1110 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1111 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1112 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1113 uint64_t BasicInstType, bool skipVcc = false);
1116 struct OptionalOperand {
1118 AMDGPUOperand::ImmTy Type;
1120 bool (*ConvertResult)(int64_t&);
1123 } // end anonymous namespace
1125 // May be called with integer type with equivalent bitwidth.
1126 static const fltSemantics *getFltSemantics(unsigned Size) {
1129 return &APFloat::IEEEsingle();
1131 return &APFloat::IEEEdouble();
1133 return &APFloat::IEEEhalf();
1135 llvm_unreachable("unsupported fp type");
1139 static const fltSemantics *getFltSemantics(MVT VT) {
1140 return getFltSemantics(VT.getSizeInBits() / 8);
1143 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1144 switch (OperandType) {
1145 case AMDGPU::OPERAND_REG_IMM_INT32:
1146 case AMDGPU::OPERAND_REG_IMM_FP32:
1147 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1148 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1149 return &APFloat::IEEEsingle();
1150 case AMDGPU::OPERAND_REG_IMM_INT64:
1151 case AMDGPU::OPERAND_REG_IMM_FP64:
1152 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1153 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1154 return &APFloat::IEEEdouble();
1155 case AMDGPU::OPERAND_REG_IMM_INT16:
1156 case AMDGPU::OPERAND_REG_IMM_FP16:
1157 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1158 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1159 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1160 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1161 return &APFloat::IEEEhalf();
1163 llvm_unreachable("unsupported fp type");
1167 //===----------------------------------------------------------------------===//
1169 //===----------------------------------------------------------------------===//
1171 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1174 // Convert literal to single precision
1175 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1176 APFloat::rmNearestTiesToEven,
1178 // We allow precision lost but not overflow or underflow
1179 if (Status != APFloat::opOK &&
1181 ((Status & APFloat::opOverflow) != 0 ||
1182 (Status & APFloat::opUnderflow) != 0)) {
1189 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1190 if (!isImmTy(ImmTyNone)) {
1191 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1194 // TODO: We should avoid using host float here. It would be better to
1195 // check the float bit values which is what a few other places do.
1196 // We've had bot failures before due to weird NaN support on mips hosts.
1198 APInt Literal(64, Imm.Val);
1200 if (Imm.IsFPImm) { // We got fp literal token
1201 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1202 return AMDGPU::isInlinableLiteral64(Imm.Val,
1203 AsmParser->hasInv2PiInlineImm());
1206 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1207 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1210 if (type.getScalarSizeInBits() == 16) {
1211 return AMDGPU::isInlinableLiteral16(
1212 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1213 AsmParser->hasInv2PiInlineImm());
1216 // Check if single precision literal is inlinable
1217 return AMDGPU::isInlinableLiteral32(
1218 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1219 AsmParser->hasInv2PiInlineImm());
1222 // We got int literal token.
1223 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1224 return AMDGPU::isInlinableLiteral64(Imm.Val,
1225 AsmParser->hasInv2PiInlineImm());
1228 if (type.getScalarSizeInBits() == 16) {
1229 return AMDGPU::isInlinableLiteral16(
1230 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1231 AsmParser->hasInv2PiInlineImm());
1234 return AMDGPU::isInlinableLiteral32(
1235 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1236 AsmParser->hasInv2PiInlineImm());
1239 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1240 // Check that this immediate can be added as literal
1241 if (!isImmTy(ImmTyNone)) {
1246 // We got int literal token.
1248 if (type == MVT::f64 && hasFPModifiers()) {
1249 // Cannot apply fp modifiers to int literals preserving the same semantics
1250 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1251 // disable these cases.
1255 unsigned Size = type.getSizeInBits();
1259 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1261 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1264 // We got fp literal token
1265 if (type == MVT::f64) { // Expected 64-bit fp operand
1266 // We would set low 64-bits of literal to zeroes but we accept this literals
1270 if (type == MVT::i64) { // Expected 64-bit int operand
1271 // We don't allow fp literals in 64-bit integer instructions. It is
1272 // unclear how we should encode them.
1276 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1277 return canLosslesslyConvertToFPType(FPLiteral, type);
1280 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1281 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1284 bool AMDGPUOperand::isSDWARegKind() const {
1285 if (AsmParser->isVI())
1287 else if (AsmParser->isGFX9())
1293 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1295 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1296 assert(Size == 2 || Size == 4 || Size == 8);
1298 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1310 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1311 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1312 Inst.getNumOperands())) {
1313 addLiteralImmOperand(Inst, Imm.Val,
1315 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1317 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1318 Inst.addOperand(MCOperand::createImm(Imm.Val));
1322 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1323 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1324 auto OpNum = Inst.getNumOperands();
1325 // Check that this operand accepts literals
1326 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1328 if (ApplyModifiers) {
1329 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1330 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1331 Val = applyInputFPModifiers(Val, Size);
1334 APInt Literal(64, Val);
1335 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1337 if (Imm.IsFPImm) { // We got fp literal token
1339 case AMDGPU::OPERAND_REG_IMM_INT64:
1340 case AMDGPU::OPERAND_REG_IMM_FP64:
1341 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1342 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1343 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1344 AsmParser->hasInv2PiInlineImm())) {
1345 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1350 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1351 // For fp operands we check if low 32 bits are zeros
1352 if (Literal.getLoBits(32) != 0) {
1353 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1354 "Can't encode literal as exact 64-bit floating-point operand. "
1355 "Low 32-bits will be set to zero");
1358 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1362 // We don't allow fp literals in 64-bit integer instructions. It is
1363 // unclear how we should encode them. This case should be checked earlier
1364 // in predicate methods (isLiteralImm())
1365 llvm_unreachable("fp literal in 64-bit integer instruction.");
1367 case AMDGPU::OPERAND_REG_IMM_INT32:
1368 case AMDGPU::OPERAND_REG_IMM_FP32:
1369 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1370 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1371 case AMDGPU::OPERAND_REG_IMM_INT16:
1372 case AMDGPU::OPERAND_REG_IMM_FP16:
1373 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1374 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1375 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1376 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1378 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1379 // Convert literal to single precision
1380 FPLiteral.convert(*getOpFltSemantics(OpTy),
1381 APFloat::rmNearestTiesToEven, &lost);
1382 // We allow precision lost but not overflow or underflow. This should be
1383 // checked earlier in isLiteralImm()
1385 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1386 if (OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
1387 OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
1388 ImmVal |= (ImmVal << 16);
1391 Inst.addOperand(MCOperand::createImm(ImmVal));
1395 llvm_unreachable("invalid operand size");
1401 // We got int literal token.
1402 // Only sign extend inline immediates.
1403 // FIXME: No errors on truncation
1405 case AMDGPU::OPERAND_REG_IMM_INT32:
1406 case AMDGPU::OPERAND_REG_IMM_FP32:
1407 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1408 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1409 if (isInt<32>(Val) &&
1410 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1411 AsmParser->hasInv2PiInlineImm())) {
1412 Inst.addOperand(MCOperand::createImm(Val));
1416 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1419 case AMDGPU::OPERAND_REG_IMM_INT64:
1420 case AMDGPU::OPERAND_REG_IMM_FP64:
1421 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1422 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1423 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1424 Inst.addOperand(MCOperand::createImm(Val));
1428 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1431 case AMDGPU::OPERAND_REG_IMM_INT16:
1432 case AMDGPU::OPERAND_REG_IMM_FP16:
1433 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1434 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1435 if (isInt<16>(Val) &&
1436 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1437 AsmParser->hasInv2PiInlineImm())) {
1438 Inst.addOperand(MCOperand::createImm(Val));
1442 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1445 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1446 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1447 auto LiteralVal = static_cast<uint16_t>(Literal.getLoBits(16).getZExtValue());
1448 assert(AMDGPU::isInlinableLiteral16(LiteralVal,
1449 AsmParser->hasInv2PiInlineImm()));
1451 uint32_t ImmVal = static_cast<uint32_t>(LiteralVal) << 16 |
1452 static_cast<uint32_t>(LiteralVal);
1453 Inst.addOperand(MCOperand::createImm(ImmVal));
1457 llvm_unreachable("invalid operand size");
1461 template <unsigned Bitwidth>
1462 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1463 APInt Literal(64, Imm.Val);
1466 // We got int literal token.
1467 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1472 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1473 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1474 APFloat::rmNearestTiesToEven, &Lost);
1475 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1478 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1479 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1482 //===----------------------------------------------------------------------===//
1484 //===----------------------------------------------------------------------===//
1486 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1487 if (Is == IS_VGPR) {
1490 case 1: return AMDGPU::VGPR_32RegClassID;
1491 case 2: return AMDGPU::VReg_64RegClassID;
1492 case 3: return AMDGPU::VReg_96RegClassID;
1493 case 4: return AMDGPU::VReg_128RegClassID;
1494 case 8: return AMDGPU::VReg_256RegClassID;
1495 case 16: return AMDGPU::VReg_512RegClassID;
1497 } else if (Is == IS_TTMP) {
1500 case 1: return AMDGPU::TTMP_32RegClassID;
1501 case 2: return AMDGPU::TTMP_64RegClassID;
1502 case 4: return AMDGPU::TTMP_128RegClassID;
1503 case 8: return AMDGPU::TTMP_256RegClassID;
1504 case 16: return AMDGPU::TTMP_512RegClassID;
1506 } else if (Is == IS_SGPR) {
1509 case 1: return AMDGPU::SGPR_32RegClassID;
1510 case 2: return AMDGPU::SGPR_64RegClassID;
1511 case 4: return AMDGPU::SGPR_128RegClassID;
1512 case 8: return AMDGPU::SGPR_256RegClassID;
1513 case 16: return AMDGPU::SGPR_512RegClassID;
1519 static unsigned getSpecialRegForName(StringRef RegName) {
1520 return StringSwitch<unsigned>(RegName)
1521 .Case("exec", AMDGPU::EXEC)
1522 .Case("vcc", AMDGPU::VCC)
1523 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1524 .Case("m0", AMDGPU::M0)
1525 .Case("scc", AMDGPU::SCC)
1526 .Case("tba", AMDGPU::TBA)
1527 .Case("tma", AMDGPU::TMA)
1528 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1529 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1530 .Case("vcc_lo", AMDGPU::VCC_LO)
1531 .Case("vcc_hi", AMDGPU::VCC_HI)
1532 .Case("exec_lo", AMDGPU::EXEC_LO)
1533 .Case("exec_hi", AMDGPU::EXEC_HI)
1534 .Case("tma_lo", AMDGPU::TMA_LO)
1535 .Case("tma_hi", AMDGPU::TMA_HI)
1536 .Case("tba_lo", AMDGPU::TBA_LO)
1537 .Case("tba_hi", AMDGPU::TBA_HI)
1541 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1543 auto R = parseRegister();
1544 if (!R) return true;
1546 RegNo = R->getReg();
1547 StartLoc = R->getStartLoc();
1548 EndLoc = R->getEndLoc();
1552 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1553 RegisterKind RegKind, unsigned Reg1,
1557 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1562 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1563 Reg = AMDGPU::FLAT_SCR;
1567 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1572 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1577 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1586 if (Reg1 != Reg + RegWidth) {
1592 llvm_unreachable("unexpected register kind");
1596 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1597 unsigned &RegNum, unsigned &RegWidth,
1598 unsigned *DwordRegIndex) {
1599 if (DwordRegIndex) { *DwordRegIndex = 0; }
1600 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1601 if (getLexer().is(AsmToken::Identifier)) {
1602 StringRef RegName = Parser.getTok().getString();
1603 if ((Reg = getSpecialRegForName(RegName))) {
1605 RegKind = IS_SPECIAL;
1607 unsigned RegNumIndex = 0;
1608 if (RegName[0] == 'v') {
1611 } else if (RegName[0] == 's') {
1614 } else if (RegName.startswith("ttmp")) {
1615 RegNumIndex = strlen("ttmp");
1620 if (RegName.size() > RegNumIndex) {
1621 // Single 32-bit register: vXX.
1622 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1627 // Range of registers: v[XX:YY]. ":YY" is optional.
1629 int64_t RegLo, RegHi;
1630 if (getLexer().isNot(AsmToken::LBrac))
1634 if (getParser().parseAbsoluteExpression(RegLo))
1637 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1638 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1645 if (getParser().parseAbsoluteExpression(RegHi))
1648 if (getLexer().isNot(AsmToken::RBrac))
1652 RegNum = (unsigned) RegLo;
1653 RegWidth = (RegHi - RegLo) + 1;
1656 } else if (getLexer().is(AsmToken::LBrac)) {
1657 // List of consecutive registers: [s0,s1,s2,s3]
1659 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1663 RegisterKind RegKind1;
1664 unsigned Reg1, RegNum1, RegWidth1;
1666 if (getLexer().is(AsmToken::Comma)) {
1668 } else if (getLexer().is(AsmToken::RBrac)) {
1671 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1672 if (RegWidth1 != 1) {
1675 if (RegKind1 != RegKind) {
1678 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1698 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1699 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1700 Size = std::min(RegWidth, 4u);
1702 if (RegNum % Size != 0)
1704 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1705 RegNum = RegNum / Size;
1706 int RCID = getRegClass(RegKind, RegWidth);
1709 const MCRegisterClass RC = TRI->getRegClass(RCID);
1710 if (RegNum >= RC.getNumRegs())
1712 Reg = RC.getRegister(RegNum);
1717 llvm_unreachable("unexpected register kind");
1720 if (!subtargetHasRegister(*TRI, Reg))
1725 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1726 const auto &Tok = Parser.getTok();
1727 SMLoc StartLoc = Tok.getLoc();
1728 SMLoc EndLoc = Tok.getEndLoc();
1729 RegisterKind RegKind;
1730 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1732 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1735 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1736 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1740 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) {
1741 if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) &&
1742 (getLexer().getKind() == AsmToken::Integer ||
1743 getLexer().getKind() == AsmToken::Real)) {
1744 // This is a workaround for handling operands like these:
1747 // This syntax is not compatible with syntax of standard
1748 // MC expressions (due to the trailing '|').
1753 if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1757 return !Expr->evaluateAsAbsolute(Val);
1760 return getParser().parseAbsoluteExpression(Val);
1763 OperandMatchResultTy
1764 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
1765 // TODO: add syntactic sugar for 1/(2*PI)
1767 if (getLexer().getKind() == AsmToken::Minus) {
1768 const AsmToken NextToken = getLexer().peekTok();
1769 if (!NextToken.is(AsmToken::Integer) &&
1770 !NextToken.is(AsmToken::Real)) {
1771 return MatchOperand_NoMatch;
1777 SMLoc S = Parser.getTok().getLoc();
1778 switch(getLexer().getKind()) {
1779 case AsmToken::Integer: {
1781 if (parseAbsoluteExpr(IntVal, AbsMod))
1782 return MatchOperand_ParseFail;
1785 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1786 return MatchOperand_Success;
1788 case AsmToken::Real: {
1790 if (parseAbsoluteExpr(IntVal, AbsMod))
1791 return MatchOperand_ParseFail;
1793 APFloat F(BitsToDouble(IntVal));
1797 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1798 AMDGPUOperand::ImmTyNone, true));
1799 return MatchOperand_Success;
1802 return MatchOperand_NoMatch;
1806 OperandMatchResultTy
1807 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1808 if (auto R = parseRegister()) {
1810 R->Reg.IsForcedVOP3 = isForcedVOP3();
1811 Operands.push_back(std::move(R));
1812 return MatchOperand_Success;
1814 return MatchOperand_NoMatch;
1817 OperandMatchResultTy
1818 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
1819 auto res = parseImm(Operands, AbsMod);
1820 if (res != MatchOperand_NoMatch) {
1824 return parseReg(Operands);
1827 OperandMatchResultTy
1828 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
1830 bool Negate = false, Negate2 = false, Abs = false, Abs2 = false;
1832 if (getLexer().getKind()== AsmToken::Minus) {
1833 const AsmToken NextToken = getLexer().peekTok();
1835 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
1836 if (NextToken.is(AsmToken::Minus)) {
1837 Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier");
1838 return MatchOperand_ParseFail;
1841 // '-' followed by an integer literal N should be interpreted as integer
1842 // negation rather than a floating-point NEG modifier applied to N.
1843 // Beside being contr-intuitive, such use of floating-point NEG modifier
1844 // results in different meaning of integer literals used with VOP1/2/C
1845 // and VOP3, for example:
1846 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
1847 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
1848 // Negative fp literals should be handled likewise for unifomtity
1849 if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) {
1855 if (getLexer().getKind() == AsmToken::Identifier &&
1856 Parser.getTok().getString() == "neg") {
1858 Error(Parser.getTok().getLoc(), "expected register or immediate");
1859 return MatchOperand_ParseFail;
1863 if (getLexer().isNot(AsmToken::LParen)) {
1864 Error(Parser.getTok().getLoc(), "expected left paren after neg");
1865 return MatchOperand_ParseFail;
1870 if (getLexer().getKind() == AsmToken::Identifier &&
1871 Parser.getTok().getString() == "abs") {
1874 if (getLexer().isNot(AsmToken::LParen)) {
1875 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1876 return MatchOperand_ParseFail;
1881 if (getLexer().getKind() == AsmToken::Pipe) {
1883 Error(Parser.getTok().getLoc(), "expected register or immediate");
1884 return MatchOperand_ParseFail;
1890 OperandMatchResultTy Res;
1892 Res = parseRegOrImm(Operands, Abs);
1894 Res = parseReg(Operands);
1896 if (Res != MatchOperand_Success) {
1900 AMDGPUOperand::Modifiers Mods;
1902 if (getLexer().getKind() != AsmToken::Pipe) {
1903 Error(Parser.getTok().getLoc(), "expected vertical bar");
1904 return MatchOperand_ParseFail;
1910 if (getLexer().isNot(AsmToken::RParen)) {
1911 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1912 return MatchOperand_ParseFail;
1920 } else if (Negate2) {
1921 if (getLexer().isNot(AsmToken::RParen)) {
1922 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1923 return MatchOperand_ParseFail;
1929 if (Mods.hasFPModifiers()) {
1930 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1931 Op.setModifiers(Mods);
1933 return MatchOperand_Success;
1936 OperandMatchResultTy
1937 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
1941 if (getLexer().getKind() == AsmToken::Identifier &&
1942 Parser.getTok().getString() == "sext") {
1945 if (getLexer().isNot(AsmToken::LParen)) {
1946 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1947 return MatchOperand_ParseFail;
1952 OperandMatchResultTy Res;
1954 Res = parseRegOrImm(Operands);
1956 Res = parseReg(Operands);
1958 if (Res != MatchOperand_Success) {
1962 AMDGPUOperand::Modifiers Mods;
1964 if (getLexer().isNot(AsmToken::RParen)) {
1965 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1966 return MatchOperand_ParseFail;
1972 if (Mods.hasIntModifiers()) {
1973 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1974 Op.setModifiers(Mods);
1977 return MatchOperand_Success;
1980 OperandMatchResultTy
1981 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1982 return parseRegOrImmWithFPInputMods(Operands, false);
1985 OperandMatchResultTy
1986 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1987 return parseRegOrImmWithIntInputMods(Operands, false);
1990 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1991 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1993 Operands.push_back(std::move(Reg));
1994 return MatchOperand_Success;
1997 const AsmToken &Tok = Parser.getTok();
1998 if (Tok.getString() == "off") {
1999 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
2000 AMDGPUOperand::ImmTyOff, false));
2002 return MatchOperand_Success;
2005 return MatchOperand_NoMatch;
2008 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2009 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2011 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
2012 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
2013 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
2014 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
2015 return Match_InvalidOperand;
2017 if ((TSFlags & SIInstrFlags::VOP3) &&
2018 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
2019 getForcedEncodingSize() != 64)
2020 return Match_PreferE32;
2022 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2023 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
2024 // v_mac_f32/16 allow only dst_sel == DWORD;
2026 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
2027 const auto &Op = Inst.getOperand(OpNum);
2028 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
2029 return Match_InvalidOperand;
2033 if ((TSFlags & SIInstrFlags::FLAT) && !hasFlatOffsets()) {
2034 // FIXME: Produces error without correct column reported.
2036 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::offset);
2037 const auto &Op = Inst.getOperand(OpNum);
2038 if (Op.getImm() != 0)
2039 return Match_InvalidOperand;
2042 return Match_Success;
2045 // What asm variants we should check
2046 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2047 if (getForcedEncodingSize() == 32) {
2048 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2049 return makeArrayRef(Variants);
2052 if (isForcedVOP3()) {
2053 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2054 return makeArrayRef(Variants);
2057 if (isForcedSDWA()) {
2058 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2059 AMDGPUAsmVariants::SDWA9};
2060 return makeArrayRef(Variants);
2063 if (isForcedDPP()) {
2064 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2065 return makeArrayRef(Variants);
2068 static const unsigned Variants[] = {
2069 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2070 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2073 return makeArrayRef(Variants);
2076 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2077 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2078 const unsigned Num = Desc.getNumImplicitUses();
2079 for (unsigned i = 0; i < Num; ++i) {
2080 unsigned Reg = Desc.ImplicitUses[i];
2082 case AMDGPU::FLAT_SCR:
2090 return AMDGPU::NoRegister;
2093 // NB: This code is correct only when used to check constant
2094 // bus limitations because GFX7 support no f16 inline constants.
2095 // Note that there are no cases when a GFX7 opcode violates
2096 // constant bus limitations due to the use of an f16 constant.
2097 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2098 unsigned OpIdx) const {
2099 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2101 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2105 const MCOperand &MO = Inst.getOperand(OpIdx);
2107 int64_t Val = MO.getImm();
2108 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2110 switch (OpSize) { // expected operand size
2112 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2114 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2116 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2117 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2118 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
2119 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2121 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2125 llvm_unreachable("invalid operand size");
2129 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2130 const MCOperand &MO = Inst.getOperand(OpIdx);
2132 return !isInlineConstant(Inst, OpIdx);
2134 return !MO.isReg() ||
2135 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
2138 bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
2139 const unsigned Opcode = Inst.getOpcode();
2140 const MCInstrDesc &Desc = MII.get(Opcode);
2141 unsigned ConstantBusUseCount = 0;
2144 (SIInstrFlags::VOPC |
2145 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
2146 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2147 SIInstrFlags::SDWA)) {
2148 // Check special imm operands (used by madmk, etc)
2149 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2150 ++ConstantBusUseCount;
2153 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2154 if (SGPRUsed != AMDGPU::NoRegister) {
2155 ++ConstantBusUseCount;
2158 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2159 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2160 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2162 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2164 for (int OpIdx : OpIndices) {
2165 if (OpIdx == -1) break;
2167 const MCOperand &MO = Inst.getOperand(OpIdx);
2168 if (usesConstantBus(Inst, OpIdx)) {
2170 const unsigned Reg = mc2PseudoReg(MO.getReg());
2171 // Pairs of registers with a partial intersections like these
2173 // flat_scratch_lo, flat_scratch
2174 // flat_scratch_lo, flat_scratch_hi
2175 // are theoretically valid but they are disabled anyway.
2176 // Note that this code mimics SIInstrInfo::verifyInstruction
2177 if (Reg != SGPRUsed) {
2178 ++ConstantBusUseCount;
2181 } else { // Expression or a literal
2182 ++ConstantBusUseCount;
2188 return ConstantBusUseCount <= 1;
2191 bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
2192 const unsigned Opcode = Inst.getOpcode();
2193 const MCInstrDesc &Desc = MII.get(Opcode);
2195 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2197 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2201 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2203 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2204 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2205 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2207 assert(DstIdx != -1);
2208 const MCOperand &Dst = Inst.getOperand(DstIdx);
2209 assert(Dst.isReg());
2210 const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2212 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2214 for (int SrcIdx : SrcIndices) {
2215 if (SrcIdx == -1) break;
2216 const MCOperand &Src = Inst.getOperand(SrcIdx);
2218 const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2219 if (isRegIntersect(DstReg, SrcReg, TRI)) {
2228 bool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
2230 const unsigned Opc = Inst.getOpcode();
2231 const MCInstrDesc &Desc = MII.get(Opc);
2233 if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) {
2234 int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
2235 assert(ClampIdx != -1);
2236 return Inst.getOperand(ClampIdx).getImm() == 0;
2242 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
2243 const SMLoc &IDLoc) {
2244 if (!validateConstantBusLimitations(Inst)) {
2246 "invalid operand (violates constant bus restrictions)");
2249 if (!validateEarlyClobberLimitations(Inst)) {
2251 "destination must be different than all sources");
2254 if (!validateIntClampSupported(Inst)) {
2256 "integer clamping is not supported on this GPU");
2263 static std::string AMDGPUMnemonicSpellCheck(StringRef S, uint64_t FBS,
2264 unsigned VariantID = 0);
2266 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2267 OperandVector &Operands,
2269 uint64_t &ErrorInfo,
2270 bool MatchingInlineAsm) {
2272 unsigned Result = Match_Success;
2273 for (auto Variant : getMatchedVariants()) {
2275 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2277 // We order match statuses from least to most specific. We use most specific
2278 // status as resulting
2279 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
2280 if ((R == Match_Success) ||
2281 (R == Match_PreferE32) ||
2282 (R == Match_MissingFeature && Result != Match_PreferE32) ||
2283 (R == Match_InvalidOperand && Result != Match_MissingFeature
2284 && Result != Match_PreferE32) ||
2285 (R == Match_MnemonicFail && Result != Match_InvalidOperand
2286 && Result != Match_MissingFeature
2287 && Result != Match_PreferE32)) {
2291 if (R == Match_Success)
2298 if (!validateInstruction(Inst, IDLoc)) {
2302 Out.EmitInstruction(Inst, getSTI());
2305 case Match_MissingFeature:
2306 return Error(IDLoc, "instruction not supported on this GPU");
2308 case Match_MnemonicFail: {
2309 uint64_t FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
2310 std::string Suggestion = AMDGPUMnemonicSpellCheck(
2311 ((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
2312 return Error(IDLoc, "invalid instruction" + Suggestion,
2313 ((AMDGPUOperand &)*Operands[0]).getLocRange());
2316 case Match_InvalidOperand: {
2317 SMLoc ErrorLoc = IDLoc;
2318 if (ErrorInfo != ~0ULL) {
2319 if (ErrorInfo >= Operands.size()) {
2320 return Error(IDLoc, "too few operands for instruction");
2322 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2323 if (ErrorLoc == SMLoc())
2326 return Error(ErrorLoc, "invalid operand for instruction");
2329 case Match_PreferE32:
2330 return Error(IDLoc, "internal error: instruction without _e64 suffix "
2331 "should be encoded as e32");
2333 llvm_unreachable("Implement any new match types added!");
2336 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
2338 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
2341 if (getParser().parseAbsoluteExpression(Tmp)) {
2344 Ret = static_cast<uint32_t>(Tmp);
2348 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
2350 if (ParseAsAbsoluteExpression(Major))
2351 return TokError("invalid major version");
2353 if (getLexer().isNot(AsmToken::Comma))
2354 return TokError("minor version number required, comma expected");
2357 if (ParseAsAbsoluteExpression(Minor))
2358 return TokError("invalid minor version");
2363 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2367 if (ParseDirectiveMajorMinor(Major, Minor))
2370 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2374 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2378 StringRef VendorName;
2381 // If this directive has no arguments, then use the ISA version for the
2383 if (getLexer().is(AsmToken::EndOfStatement)) {
2384 AMDGPU::IsaInfo::IsaVersion ISA =
2385 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2386 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2392 if (ParseDirectiveMajorMinor(Major, Minor))
2395 if (getLexer().isNot(AsmToken::Comma))
2396 return TokError("stepping version number required, comma expected");
2399 if (ParseAsAbsoluteExpression(Stepping))
2400 return TokError("invalid stepping version");
2402 if (getLexer().isNot(AsmToken::Comma))
2403 return TokError("vendor name required, comma expected");
2406 if (getLexer().isNot(AsmToken::String))
2407 return TokError("invalid vendor name");
2409 VendorName = getLexer().getTok().getStringContents();
2412 if (getLexer().isNot(AsmToken::Comma))
2413 return TokError("arch name required, comma expected");
2416 if (getLexer().isNot(AsmToken::String))
2417 return TokError("invalid arch name");
2419 ArchName = getLexer().getTok().getStringContents();
2422 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2423 VendorName, ArchName);
2427 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
2428 amd_kernel_code_t &Header) {
2429 SmallString<40> ErrStr;
2430 raw_svector_ostream Err(ErrStr);
2431 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
2432 return TokError(Err.str());
2438 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
2439 amd_kernel_code_t Header;
2440 AMDGPU::initDefaultAMDKernelCodeT(Header, getFeatureBits());
2443 // Lex EndOfStatement. This is in a while loop, because lexing a comment
2444 // will set the current token to EndOfStatement.
2445 while(getLexer().is(AsmToken::EndOfStatement))
2448 if (getLexer().isNot(AsmToken::Identifier))
2449 return TokError("expected value identifier or .end_amd_kernel_code_t");
2451 StringRef ID = getLexer().getTok().getIdentifier();
2454 if (ID == ".end_amd_kernel_code_t")
2457 if (ParseAMDKernelCodeTValue(ID, Header))
2461 getTargetStreamer().EmitAMDKernelCodeT(Header);
2466 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
2467 if (getLexer().isNot(AsmToken::Identifier))
2468 return TokError("expected symbol name");
2470 StringRef KernelName = Parser.getTok().getString();
2472 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
2473 ELF::STT_AMDGPU_HSA_KERNEL);
2475 KernelScope.initialize(getContext());
2479 bool AMDGPUAsmParser::ParseDirectiveISAVersion() {
2480 if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) {
2481 return Error(getParser().getTok().getLoc(),
2482 ".amd_amdgpu_isa directive is not available on non-amdgcn "
2486 auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
2488 std::string ISAVersionStringFromSTI;
2489 raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI);
2490 IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI);
2492 if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) {
2493 return Error(getParser().getTok().getLoc(),
2494 ".amd_amdgpu_isa directive does not match triple and/or mcpu "
2495 "arguments specified through the command line");
2498 getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str());
2504 bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
2505 if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) {
2506 return Error(getParser().getTok().getLoc(),
2507 (Twine(HSAMD::AssemblerDirectiveBegin) + Twine(" directive is "
2508 "not available on non-amdhsa OSes")).str());
2511 std::string HSAMetadataString;
2512 raw_string_ostream YamlStream(HSAMetadataString);
2514 getLexer().setSkipSpace(false);
2516 bool FoundEnd = false;
2517 while (!getLexer().is(AsmToken::Eof)) {
2518 while (getLexer().is(AsmToken::Space)) {
2519 YamlStream << getLexer().getTok().getString();
2523 if (getLexer().is(AsmToken::Identifier)) {
2524 StringRef ID = getLexer().getTok().getIdentifier();
2525 if (ID == AMDGPU::HSAMD::AssemblerDirectiveEnd) {
2532 YamlStream << Parser.parseStringToEndOfStatement()
2533 << getContext().getAsmInfo()->getSeparatorString();
2535 Parser.eatToEndOfStatement();
2538 getLexer().setSkipSpace(true);
2540 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
2541 return TokError(Twine("expected directive ") +
2542 Twine(HSAMD::AssemblerDirectiveEnd) + Twine(" not found"));
2547 if (!getTargetStreamer().EmitHSAMetadata(HSAMetadataString))
2548 return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
2553 bool AMDGPUAsmParser::ParseDirectivePALMetadata() {
2554 if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
2555 return Error(getParser().getTok().getLoc(),
2556 (Twine(PALMD::AssemblerDirective) + Twine(" directive is "
2557 "not available on non-amdpal OSes")).str());
2560 PALMD::Metadata PALMetadata;
2563 if (ParseAsAbsoluteExpression(Value)) {
2564 return TokError(Twine("invalid value in ") +
2565 Twine(PALMD::AssemblerDirective));
2567 PALMetadata.push_back(Value);
2568 if (getLexer().isNot(AsmToken::Comma))
2572 getTargetStreamer().EmitPALMetadata(PALMetadata);
2576 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2577 StringRef IDVal = DirectiveID.getString();
2579 if (IDVal == ".hsa_code_object_version")
2580 return ParseDirectiveHSACodeObjectVersion();
2582 if (IDVal == ".hsa_code_object_isa")
2583 return ParseDirectiveHSACodeObjectISA();
2585 if (IDVal == ".amd_kernel_code_t")
2586 return ParseDirectiveAMDKernelCodeT();
2588 if (IDVal == ".amdgpu_hsa_kernel")
2589 return ParseDirectiveAMDGPUHsaKernel();
2591 if (IDVal == ".amd_amdgpu_isa")
2592 return ParseDirectiveISAVersion();
2594 if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin)
2595 return ParseDirectiveHSAMetadata();
2597 if (IDVal == PALMD::AssemblerDirective)
2598 return ParseDirectivePALMetadata();
2603 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2604 unsigned RegNo) const {
2606 for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true);
2614 case AMDGPU::TBA_LO:
2615 case AMDGPU::TBA_HI:
2617 case AMDGPU::TMA_LO:
2618 case AMDGPU::TMA_HI:
2630 case AMDGPU::FLAT_SCR:
2631 case AMDGPU::FLAT_SCR_LO:
2632 case AMDGPU::FLAT_SCR_HI:
2639 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2641 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2650 OperandMatchResultTy
2651 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2652 // Try to parse with a custom parser
2653 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2655 // If we successfully parsed the operand or if there as an error parsing,
2658 // If we are parsing after we reach EndOfStatement then this means we
2659 // are appending default values to the Operands list. This is only done
2660 // by custom parser, so we shouldn't continue on to the generic parsing.
2661 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2662 getLexer().is(AsmToken::EndOfStatement))
2665 ResTy = parseRegOrImm(Operands);
2667 if (ResTy == MatchOperand_Success)
2670 const auto &Tok = Parser.getTok();
2671 SMLoc S = Tok.getLoc();
2673 const MCExpr *Expr = nullptr;
2674 if (!Parser.parseExpression(Expr)) {
2675 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2676 return MatchOperand_Success;
2679 // Possibly this is an instruction flag like 'gds'.
2680 if (Tok.getKind() == AsmToken::Identifier) {
2681 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), S));
2683 return MatchOperand_Success;
2686 return MatchOperand_NoMatch;
2689 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2690 // Clear any forced encodings from the previous instruction.
2691 setForcedEncodingSize(0);
2692 setForcedDPP(false);
2693 setForcedSDWA(false);
2695 if (Name.endswith("_e64")) {
2696 setForcedEncodingSize(64);
2697 return Name.substr(0, Name.size() - 4);
2698 } else if (Name.endswith("_e32")) {
2699 setForcedEncodingSize(32);
2700 return Name.substr(0, Name.size() - 4);
2701 } else if (Name.endswith("_dpp")) {
2703 return Name.substr(0, Name.size() - 4);
2704 } else if (Name.endswith("_sdwa")) {
2705 setForcedSDWA(true);
2706 return Name.substr(0, Name.size() - 5);
2711 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2713 SMLoc NameLoc, OperandVector &Operands) {
2714 // Add the instruction mnemonic
2715 Name = parseMnemonicSuffix(Name);
2716 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2718 while (!getLexer().is(AsmToken::EndOfStatement)) {
2719 OperandMatchResultTy Res = parseOperand(Operands, Name);
2721 // Eat the comma or space if there is one.
2722 if (getLexer().is(AsmToken::Comma))
2726 case MatchOperand_Success: break;
2727 case MatchOperand_ParseFail:
2728 Error(getLexer().getLoc(), "failed parsing operand.");
2729 while (!getLexer().is(AsmToken::EndOfStatement)) {
2733 case MatchOperand_NoMatch:
2734 Error(getLexer().getLoc(), "not a valid operand.");
2735 while (!getLexer().is(AsmToken::EndOfStatement)) {
2745 //===----------------------------------------------------------------------===//
2746 // Utility functions
2747 //===----------------------------------------------------------------------===//
2749 OperandMatchResultTy
2750 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2751 switch(getLexer().getKind()) {
2752 default: return MatchOperand_NoMatch;
2753 case AsmToken::Identifier: {
2754 StringRef Name = Parser.getTok().getString();
2755 if (!Name.equals(Prefix)) {
2756 return MatchOperand_NoMatch;
2760 if (getLexer().isNot(AsmToken::Colon))
2761 return MatchOperand_ParseFail;
2765 bool IsMinus = false;
2766 if (getLexer().getKind() == AsmToken::Minus) {
2771 if (getLexer().isNot(AsmToken::Integer))
2772 return MatchOperand_ParseFail;
2774 if (getParser().parseAbsoluteExpression(Int))
2775 return MatchOperand_ParseFail;
2782 return MatchOperand_Success;
2785 OperandMatchResultTy
2786 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2787 AMDGPUOperand::ImmTy ImmTy,
2788 bool (*ConvertResult)(int64_t&)) {
2789 SMLoc S = Parser.getTok().getLoc();
2792 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2793 if (Res != MatchOperand_Success)
2796 if (ConvertResult && !ConvertResult(Value)) {
2797 return MatchOperand_ParseFail;
2800 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2801 return MatchOperand_Success;
2804 OperandMatchResultTy AMDGPUAsmParser::parseOperandArrayWithPrefix(
2806 OperandVector &Operands,
2807 AMDGPUOperand::ImmTy ImmTy,
2808 bool (*ConvertResult)(int64_t&)) {
2809 StringRef Name = Parser.getTok().getString();
2810 if (!Name.equals(Prefix))
2811 return MatchOperand_NoMatch;
2814 if (getLexer().isNot(AsmToken::Colon))
2815 return MatchOperand_ParseFail;
2818 if (getLexer().isNot(AsmToken::LBrac))
2819 return MatchOperand_ParseFail;
2823 SMLoc S = Parser.getTok().getLoc();
2825 // FIXME: How to verify the number of elements matches the number of src
2827 for (int I = 0; I < 4; ++I) {
2829 if (getLexer().is(AsmToken::RBrac))
2832 if (getLexer().isNot(AsmToken::Comma))
2833 return MatchOperand_ParseFail;
2837 if (getLexer().isNot(AsmToken::Integer))
2838 return MatchOperand_ParseFail;
2841 if (getParser().parseAbsoluteExpression(Op))
2842 return MatchOperand_ParseFail;
2844 if (Op != 0 && Op != 1)
2845 return MatchOperand_ParseFail;
2850 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
2851 return MatchOperand_Success;
2854 OperandMatchResultTy
2855 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2856 AMDGPUOperand::ImmTy ImmTy) {
2858 SMLoc S = Parser.getTok().getLoc();
2860 // We are at the end of the statement, and this is a default argument, so
2861 // use a default value.
2862 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2863 switch(getLexer().getKind()) {
2864 case AsmToken::Identifier: {
2865 StringRef Tok = Parser.getTok().getString();
2869 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2873 return MatchOperand_NoMatch;
2878 return MatchOperand_NoMatch;
2882 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2883 return MatchOperand_Success;
2886 static void addOptionalImmOperand(
2887 MCInst& Inst, const OperandVector& Operands,
2888 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
2889 AMDGPUOperand::ImmTy ImmT,
2890 int64_t Default = 0) {
2891 auto i = OptionalIdx.find(ImmT);
2892 if (i != OptionalIdx.end()) {
2893 unsigned Idx = i->second;
2894 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2896 Inst.addOperand(MCOperand::createImm(Default));
2900 OperandMatchResultTy
2901 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2902 if (getLexer().isNot(AsmToken::Identifier)) {
2903 return MatchOperand_NoMatch;
2905 StringRef Tok = Parser.getTok().getString();
2906 if (Tok != Prefix) {
2907 return MatchOperand_NoMatch;
2911 if (getLexer().isNot(AsmToken::Colon)) {
2912 return MatchOperand_ParseFail;
2916 if (getLexer().isNot(AsmToken::Identifier)) {
2917 return MatchOperand_ParseFail;
2920 Value = Parser.getTok().getString();
2921 return MatchOperand_Success;
2924 //===----------------------------------------------------------------------===//
2926 //===----------------------------------------------------------------------===//
2928 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2929 const OperandVector &Operands) {
2930 OptionalImmIndexMap OptionalIdx;
2932 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2933 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2935 // Add the register arguments
2937 Op.addRegOperands(Inst, 1);
2941 // Handle optional arguments
2942 OptionalIdx[Op.getImmTy()] = i;
2945 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2946 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2947 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2949 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2952 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
2953 bool IsGdsHardcoded) {
2954 OptionalImmIndexMap OptionalIdx;
2956 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2957 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2959 // Add the register arguments
2961 Op.addRegOperands(Inst, 1);
2965 if (Op.isToken() && Op.getToken() == "gds") {
2966 IsGdsHardcoded = true;
2970 // Handle optional arguments
2971 OptionalIdx[Op.getImmTy()] = i;
2974 AMDGPUOperand::ImmTy OffsetType =
2975 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
2976 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
2977 AMDGPUOperand::ImmTyOffset;
2979 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
2981 if (!IsGdsHardcoded) {
2982 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2984 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2987 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2988 OptionalImmIndexMap OptionalIdx;
2990 unsigned OperandIdx[4];
2991 unsigned EnMask = 0;
2994 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2995 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2997 // Add the register arguments
3000 OperandIdx[SrcIdx] = Inst.size();
3001 Op.addRegOperands(Inst, 1);
3008 OperandIdx[SrcIdx] = Inst.size();
3009 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
3014 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
3015 Op.addImmOperands(Inst, 1);
3019 if (Op.isToken() && Op.getToken() == "done")
3022 // Handle optional arguments
3023 OptionalIdx[Op.getImmTy()] = i;
3026 assert(SrcIdx == 4);
3029 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
3031 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
3032 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
3033 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
3036 for (auto i = 0; i < SrcIdx; ++i) {
3037 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
3038 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
3042 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
3043 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
3045 Inst.addOperand(MCOperand::createImm(EnMask));
3048 //===----------------------------------------------------------------------===//
3050 //===----------------------------------------------------------------------===//
3054 const AMDGPU::IsaInfo::IsaVersion ISA,
3058 unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned),
3059 unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned))
3061 bool Failed = false;
3063 IntVal = encode(ISA, IntVal, CntVal);
3064 if (CntVal != decode(ISA, IntVal)) {
3066 IntVal = encode(ISA, IntVal, -1);
3074 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
3075 StringRef CntName = Parser.getTok().getString();
3079 if (getLexer().isNot(AsmToken::LParen))
3083 if (getLexer().isNot(AsmToken::Integer))
3086 SMLoc ValLoc = Parser.getTok().getLoc();
3087 if (getParser().parseAbsoluteExpression(CntVal))
3090 AMDGPU::IsaInfo::IsaVersion ISA =
3091 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
3094 bool Sat = CntName.endswith("_sat");
3096 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
3097 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
3098 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
3099 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
3100 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
3101 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
3105 Error(ValLoc, "too large value for " + CntName);
3109 if (getLexer().isNot(AsmToken::RParen)) {
3114 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) {
3115 const AsmToken NextToken = getLexer().peekTok();
3116 if (NextToken.is(AsmToken::Identifier)) {
3124 OperandMatchResultTy
3125 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
3126 AMDGPU::IsaInfo::IsaVersion ISA =
3127 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
3128 int64_t Waitcnt = getWaitcntBitMask(ISA);
3129 SMLoc S = Parser.getTok().getLoc();
3131 switch(getLexer().getKind()) {
3132 default: return MatchOperand_ParseFail;
3133 case AsmToken::Integer:
3134 // The operand can be an integer value.
3135 if (getParser().parseAbsoluteExpression(Waitcnt))
3136 return MatchOperand_ParseFail;
3139 case AsmToken::Identifier:
3141 if (parseCnt(Waitcnt))
3142 return MatchOperand_ParseFail;
3143 } while(getLexer().isNot(AsmToken::EndOfStatement));
3146 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
3147 return MatchOperand_Success;
3150 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset,
3152 using namespace llvm::AMDGPU::Hwreg;
3154 if (Parser.getTok().getString() != "hwreg")
3158 if (getLexer().isNot(AsmToken::LParen))
3162 if (getLexer().is(AsmToken::Identifier)) {
3163 HwReg.IsSymbolic = true;
3164 HwReg.Id = ID_UNKNOWN_;
3165 const StringRef tok = Parser.getTok().getString();
3166 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
3167 if (tok == IdSymbolic[i]) {
3174 HwReg.IsSymbolic = false;
3175 if (getLexer().isNot(AsmToken::Integer))
3177 if (getParser().parseAbsoluteExpression(HwReg.Id))
3181 if (getLexer().is(AsmToken::RParen)) {
3187 if (getLexer().isNot(AsmToken::Comma))
3191 if (getLexer().isNot(AsmToken::Integer))
3193 if (getParser().parseAbsoluteExpression(Offset))
3196 if (getLexer().isNot(AsmToken::Comma))
3200 if (getLexer().isNot(AsmToken::Integer))
3202 if (getParser().parseAbsoluteExpression(Width))
3205 if (getLexer().isNot(AsmToken::RParen))
3212 OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
3213 using namespace llvm::AMDGPU::Hwreg;
3215 int64_t Imm16Val = 0;
3216 SMLoc S = Parser.getTok().getLoc();
3218 switch(getLexer().getKind()) {
3219 default: return MatchOperand_NoMatch;
3220 case AsmToken::Integer:
3221 // The operand can be an integer value.
3222 if (getParser().parseAbsoluteExpression(Imm16Val))
3223 return MatchOperand_NoMatch;
3224 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3225 Error(S, "invalid immediate: only 16-bit values are legal");
3226 // Do not return error code, but create an imm operand anyway and proceed
3227 // to the next operand, if any. That avoids unneccessary error messages.
3231 case AsmToken::Identifier: {
3232 OperandInfoTy HwReg(ID_UNKNOWN_);
3233 int64_t Offset = OFFSET_DEFAULT_;
3234 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
3235 if (parseHwregConstruct(HwReg, Offset, Width))
3236 return MatchOperand_ParseFail;
3237 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3238 if (HwReg.IsSymbolic)
3239 Error(S, "invalid symbolic name of hardware register");
3241 Error(S, "invalid code of hardware register: only 6-bit values are legal");
3243 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3244 Error(S, "invalid bit offset: only 5-bit values are legal");
3245 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3246 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
3247 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
3251 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3252 return MatchOperand_Success;
3255 bool AMDGPUOperand::isSWaitCnt() const {
3259 bool AMDGPUOperand::isHwreg() const {
3260 return isImmTy(ImmTyHwreg);
3263 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
3264 using namespace llvm::AMDGPU::SendMsg;
3266 if (Parser.getTok().getString() != "sendmsg")
3270 if (getLexer().isNot(AsmToken::LParen))
3274 if (getLexer().is(AsmToken::Identifier)) {
3275 Msg.IsSymbolic = true;
3276 Msg.Id = ID_UNKNOWN_;
3277 const std::string tok = Parser.getTok().getString();
3278 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
3280 default: continue; // Omit gaps.
3281 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
3283 if (tok == IdSymbolic[i]) {
3290 Msg.IsSymbolic = false;
3291 if (getLexer().isNot(AsmToken::Integer))
3293 if (getParser().parseAbsoluteExpression(Msg.Id))
3295 if (getLexer().is(AsmToken::Integer))
3296 if (getParser().parseAbsoluteExpression(Msg.Id))
3297 Msg.Id = ID_UNKNOWN_;
3299 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
3302 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
3303 if (getLexer().isNot(AsmToken::RParen))
3309 if (getLexer().isNot(AsmToken::Comma))
3313 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
3314 Operation.Id = ID_UNKNOWN_;
3315 if (getLexer().is(AsmToken::Identifier)) {
3316 Operation.IsSymbolic = true;
3317 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
3318 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
3319 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
3320 const StringRef Tok = Parser.getTok().getString();
3321 for (int i = F; i < L; ++i) {
3329 Operation.IsSymbolic = false;
3330 if (getLexer().isNot(AsmToken::Integer))
3332 if (getParser().parseAbsoluteExpression(Operation.Id))
3336 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3337 // Stream id is optional.
3338 if (getLexer().is(AsmToken::RParen)) {
3343 if (getLexer().isNot(AsmToken::Comma))
3347 if (getLexer().isNot(AsmToken::Integer))
3349 if (getParser().parseAbsoluteExpression(StreamId))
3353 if (getLexer().isNot(AsmToken::RParen))
3359 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
3360 if (getLexer().getKind() != AsmToken::Identifier)
3361 return MatchOperand_NoMatch;
3363 StringRef Str = Parser.getTok().getString();
3364 int Slot = StringSwitch<int>(Str)
3370 SMLoc S = Parser.getTok().getLoc();
3372 return MatchOperand_ParseFail;
3375 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
3376 AMDGPUOperand::ImmTyInterpSlot));
3377 return MatchOperand_Success;
3380 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
3381 if (getLexer().getKind() != AsmToken::Identifier)
3382 return MatchOperand_NoMatch;
3384 StringRef Str = Parser.getTok().getString();
3385 if (!Str.startswith("attr"))
3386 return MatchOperand_NoMatch;
3388 StringRef Chan = Str.take_back(2);
3389 int AttrChan = StringSwitch<int>(Chan)
3396 return MatchOperand_ParseFail;
3398 Str = Str.drop_back(2).drop_front(4);
3401 if (Str.getAsInteger(10, Attr))
3402 return MatchOperand_ParseFail;
3404 SMLoc S = Parser.getTok().getLoc();
3407 Error(S, "out of bounds attr");
3408 return MatchOperand_Success;
3411 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
3413 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
3414 AMDGPUOperand::ImmTyInterpAttr));
3415 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
3416 AMDGPUOperand::ImmTyAttrChan));
3417 return MatchOperand_Success;
3420 void AMDGPUAsmParser::errorExpTgt() {
3421 Error(Parser.getTok().getLoc(), "invalid exp target");
3424 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
3426 if (Str == "null") {
3428 return MatchOperand_Success;
3431 if (Str.startswith("mrt")) {
3432 Str = Str.drop_front(3);
3433 if (Str == "z") { // == mrtz
3435 return MatchOperand_Success;
3438 if (Str.getAsInteger(10, Val))
3439 return MatchOperand_ParseFail;
3444 return MatchOperand_Success;
3447 if (Str.startswith("pos")) {
3448 Str = Str.drop_front(3);
3449 if (Str.getAsInteger(10, Val))
3450 return MatchOperand_ParseFail;
3456 return MatchOperand_Success;
3459 if (Str.startswith("param")) {
3460 Str = Str.drop_front(5);
3461 if (Str.getAsInteger(10, Val))
3462 return MatchOperand_ParseFail;
3468 return MatchOperand_Success;
3471 if (Str.startswith("invalid_target_")) {
3472 Str = Str.drop_front(15);
3473 if (Str.getAsInteger(10, Val))
3474 return MatchOperand_ParseFail;
3477 return MatchOperand_Success;
3480 return MatchOperand_NoMatch;
3483 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
3485 StringRef Str = Parser.getTok().getString();
3487 auto Res = parseExpTgtImpl(Str, Val);
3488 if (Res != MatchOperand_Success)
3491 SMLoc S = Parser.getTok().getLoc();
3494 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
3495 AMDGPUOperand::ImmTyExpTgt));
3496 return MatchOperand_Success;
3499 OperandMatchResultTy
3500 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
3501 using namespace llvm::AMDGPU::SendMsg;
3503 int64_t Imm16Val = 0;
3504 SMLoc S = Parser.getTok().getLoc();
3506 switch(getLexer().getKind()) {
3508 return MatchOperand_NoMatch;
3509 case AsmToken::Integer:
3510 // The operand can be an integer value.
3511 if (getParser().parseAbsoluteExpression(Imm16Val))
3512 return MatchOperand_NoMatch;
3513 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3514 Error(S, "invalid immediate: only 16-bit values are legal");
3515 // Do not return error code, but create an imm operand anyway and proceed
3516 // to the next operand, if any. That avoids unneccessary error messages.
3519 case AsmToken::Identifier: {
3520 OperandInfoTy Msg(ID_UNKNOWN_);
3521 OperandInfoTy Operation(OP_UNKNOWN_);
3522 int64_t StreamId = STREAM_ID_DEFAULT_;
3523 if (parseSendMsgConstruct(Msg, Operation, StreamId))
3524 return MatchOperand_ParseFail;
3526 // Validate and encode message ID.
3527 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
3528 || Msg.Id == ID_SYSMSG)) {
3530 Error(S, "invalid/unsupported symbolic name of message");
3532 Error(S, "invalid/unsupported code of message");
3535 Imm16Val = (Msg.Id << ID_SHIFT_);
3536 // Validate and encode operation ID.
3537 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
3538 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
3539 if (Operation.IsSymbolic)
3540 Error(S, "invalid symbolic name of GS_OP");
3542 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
3545 if (Operation.Id == OP_GS_NOP
3546 && Msg.Id != ID_GS_DONE) {
3547 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
3550 Imm16Val |= (Operation.Id << OP_SHIFT_);
3552 if (Msg.Id == ID_SYSMSG) {
3553 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
3554 if (Operation.IsSymbolic)
3555 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
3557 Error(S, "invalid/unsupported code of SYSMSG_OP");
3560 Imm16Val |= (Operation.Id << OP_SHIFT_);
3562 // Validate and encode stream ID.
3563 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3564 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
3565 Error(S, "invalid stream id: only 2-bit values are legal");
3568 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
3574 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
3575 return MatchOperand_Success;
3578 bool AMDGPUOperand::isSendMsg() const {
3579 return isImmTy(ImmTySendMsg);
3582 //===----------------------------------------------------------------------===//
3584 //===----------------------------------------------------------------------===//
3587 AMDGPUAsmParser::trySkipId(const StringRef Id) {
3588 if (getLexer().getKind() == AsmToken::Identifier &&
3589 Parser.getTok().getString() == Id) {
3597 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
3598 if (getLexer().getKind() == Kind) {
3606 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
3607 const StringRef ErrMsg) {
3608 if (!trySkipToken(Kind)) {
3609 Error(Parser.getTok().getLoc(), ErrMsg);
3616 AMDGPUAsmParser::parseExpr(int64_t &Imm) {
3617 return !getParser().parseAbsoluteExpression(Imm);
3621 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
3622 SMLoc S = Parser.getTok().getLoc();
3623 if (getLexer().getKind() == AsmToken::String) {
3624 Val = Parser.getTok().getStringContents();
3633 //===----------------------------------------------------------------------===//
3635 //===----------------------------------------------------------------------===//
3639 encodeBitmaskPerm(const unsigned AndMask,
3640 const unsigned OrMask,
3641 const unsigned XorMask) {
3642 using namespace llvm::AMDGPU::Swizzle;
3644 return BITMASK_PERM_ENC |
3645 (AndMask << BITMASK_AND_SHIFT) |
3646 (OrMask << BITMASK_OR_SHIFT) |
3647 (XorMask << BITMASK_XOR_SHIFT);
3651 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
3652 const unsigned MinVal,
3653 const unsigned MaxVal,
3654 const StringRef ErrMsg) {
3655 for (unsigned i = 0; i < OpNum; ++i) {
3656 if (!skipToken(AsmToken::Comma, "expected a comma")){
3659 SMLoc ExprLoc = Parser.getTok().getLoc();
3660 if (!parseExpr(Op[i])) {
3663 if (Op[i] < MinVal || Op[i] > MaxVal) {
3664 Error(ExprLoc, ErrMsg);
3673 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
3674 using namespace llvm::AMDGPU::Swizzle;
3676 int64_t Lane[LANE_NUM];
3677 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
3678 "expected a 2-bit lane id")) {
3679 Imm = QUAD_PERM_ENC;
3680 for (auto i = 0; i < LANE_NUM; ++i) {
3681 Imm |= Lane[i] << (LANE_SHIFT * i);
3689 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
3690 using namespace llvm::AMDGPU::Swizzle;
3692 SMLoc S = Parser.getTok().getLoc();
3696 if (!parseSwizzleOperands(1, &GroupSize,
3698 "group size must be in the interval [2,32]")) {
3701 if (!isPowerOf2_64(GroupSize)) {
3702 Error(S, "group size must be a power of two");
3705 if (parseSwizzleOperands(1, &LaneIdx,
3707 "lane id must be in the interval [0,group size - 1]")) {
3708 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
3715 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
3716 using namespace llvm::AMDGPU::Swizzle;
3718 SMLoc S = Parser.getTok().getLoc();
3721 if (!parseSwizzleOperands(1, &GroupSize,
3722 2, 32, "group size must be in the interval [2,32]")) {
3725 if (!isPowerOf2_64(GroupSize)) {
3726 Error(S, "group size must be a power of two");
3730 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
3735 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
3736 using namespace llvm::AMDGPU::Swizzle;
3738 SMLoc S = Parser.getTok().getLoc();
3741 if (!parseSwizzleOperands(1, &GroupSize,
3742 1, 16, "group size must be in the interval [1,16]")) {
3745 if (!isPowerOf2_64(GroupSize)) {
3746 Error(S, "group size must be a power of two");
3750 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
3755 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
3756 using namespace llvm::AMDGPU::Swizzle;
3758 if (!skipToken(AsmToken::Comma, "expected a comma")) {
3763 SMLoc StrLoc = Parser.getTok().getLoc();
3764 if (!parseString(Ctl)) {
3767 if (Ctl.size() != BITMASK_WIDTH) {
3768 Error(StrLoc, "expected a 5-character mask");
3772 unsigned AndMask = 0;
3773 unsigned OrMask = 0;
3774 unsigned XorMask = 0;
3776 for (size_t i = 0; i < Ctl.size(); ++i) {
3777 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
3780 Error(StrLoc, "invalid mask");
3797 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
3802 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
3804 SMLoc OffsetLoc = Parser.getTok().getLoc();
3806 if (!parseExpr(Imm)) {
3809 if (!isUInt<16>(Imm)) {
3810 Error(OffsetLoc, "expected a 16-bit offset");
3817 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
3818 using namespace llvm::AMDGPU::Swizzle;
3820 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
3822 SMLoc ModeLoc = Parser.getTok().getLoc();
3825 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
3826 Ok = parseSwizzleQuadPerm(Imm);
3827 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
3828 Ok = parseSwizzleBitmaskPerm(Imm);
3829 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
3830 Ok = parseSwizzleBroadcast(Imm);
3831 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
3832 Ok = parseSwizzleSwap(Imm);
3833 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
3834 Ok = parseSwizzleReverse(Imm);
3836 Error(ModeLoc, "expected a swizzle mode");
3839 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
3845 OperandMatchResultTy
3846 AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
3847 SMLoc S = Parser.getTok().getLoc();
3850 if (trySkipId("offset")) {
3853 if (skipToken(AsmToken::Colon, "expected a colon")) {
3854 if (trySkipId("swizzle")) {
3855 Ok = parseSwizzleMacro(Imm);
3857 Ok = parseSwizzleOffset(Imm);
3861 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
3863 return Ok? MatchOperand_Success : MatchOperand_ParseFail;
3865 // Swizzle "offset" operand is optional.
3866 // If it is omitted, try parsing other optional operands.
3867 return parseOptionalOpr(Operands);
3872 AMDGPUOperand::isSwizzle() const {
3873 return isImmTy(ImmTySwizzle);
3876 //===----------------------------------------------------------------------===//
3877 // sopp branch targets
3878 //===----------------------------------------------------------------------===//
3880 OperandMatchResultTy
3881 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
3882 SMLoc S = Parser.getTok().getLoc();
3884 switch (getLexer().getKind()) {
3885 default: return MatchOperand_ParseFail;
3886 case AsmToken::Integer: {
3888 if (getParser().parseAbsoluteExpression(Imm))
3889 return MatchOperand_ParseFail;
3890 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
3891 return MatchOperand_Success;
3894 case AsmToken::Identifier:
3895 Operands.push_back(AMDGPUOperand::CreateExpr(this,
3896 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
3897 Parser.getTok().getString()), getContext()), S));
3899 return MatchOperand_Success;
3903 //===----------------------------------------------------------------------===//
3905 //===----------------------------------------------------------------------===//
3907 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
3908 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
3911 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
3912 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
3915 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
3916 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
3919 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
3920 const OperandVector &Operands,
3921 bool IsAtomic, bool IsAtomicReturn) {
3922 OptionalImmIndexMap OptionalIdx;
3923 assert(IsAtomicReturn ? IsAtomic : true);
3925 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3926 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3928 // Add the register arguments
3930 Op.addRegOperands(Inst, 1);
3934 // Handle the case where soffset is an immediate
3935 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3936 Op.addImmOperands(Inst, 1);
3940 // Handle tokens like 'offen' which are sometimes hard-coded into the
3941 // asm string. There are no MCInst operands for these.
3947 // Handle optional arguments
3948 OptionalIdx[Op.getImmTy()] = i;
3951 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
3952 if (IsAtomicReturn) {
3953 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
3957 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
3958 if (!IsAtomic) { // glc is hard-coded.
3959 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3961 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3962 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3965 void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
3966 OptionalImmIndexMap OptionalIdx;
3968 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3969 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3971 // Add the register arguments
3973 Op.addRegOperands(Inst, 1);
3977 // Handle the case where soffset is an immediate
3978 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3979 Op.addImmOperands(Inst, 1);
3983 // Handle tokens like 'offen' which are sometimes hard-coded into the
3984 // asm string. There are no MCInst operands for these.
3990 // Handle optional arguments
3991 OptionalIdx[Op.getImmTy()] = i;
3994 addOptionalImmOperand(Inst, Operands, OptionalIdx,
3995 AMDGPUOperand::ImmTyOffset);
3996 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDFMT);
3997 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyNFMT);
3998 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3999 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
4000 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
4003 //===----------------------------------------------------------------------===//
4005 //===----------------------------------------------------------------------===//
4007 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands,
4010 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4011 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4012 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4016 // Add src, same as dst
4017 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
4020 OptionalImmIndexMap OptionalIdx;
4022 for (unsigned E = Operands.size(); I != E; ++I) {
4023 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4025 // Add the register arguments
4026 if (Op.isRegOrImm()) {
4027 Op.addRegOrImmOperands(Inst, 1);
4029 } else if (Op.isImmModifier()) {
4030 OptionalIdx[Op.getImmTy()] = I;
4032 llvm_unreachable("unexpected operand type");
4036 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
4037 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
4038 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
4039 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
4040 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
4041 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
4042 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
4043 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
4046 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
4047 cvtMIMG(Inst, Operands, true);
4050 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
4051 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
4054 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
4055 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
4058 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
4059 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
4062 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
4063 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
4066 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
4067 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
4070 //===----------------------------------------------------------------------===//
4072 //===----------------------------------------------------------------------===//
4074 bool AMDGPUOperand::isSMRDOffset8() const {
4075 return isImm() && isUInt<8>(getImm());
4078 bool AMDGPUOperand::isSMRDOffset20() const {
4079 return isImm() && isUInt<20>(getImm());
4082 bool AMDGPUOperand::isSMRDLiteralOffset() const {
4083 // 32-bit literals are only supported on CI and we only want to use them
4084 // when the offset is > 8-bits.
4085 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
4088 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
4089 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4092 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
4093 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4096 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
4097 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4100 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const {
4101 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4104 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetS13() const {
4105 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4108 //===----------------------------------------------------------------------===//
4110 //===----------------------------------------------------------------------===//
4112 static bool ConvertOmodMul(int64_t &Mul) {
4113 if (Mul != 1 && Mul != 2 && Mul != 4)
4120 static bool ConvertOmodDiv(int64_t &Div) {
4134 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
4135 if (BoundCtrl == 0) {
4140 if (BoundCtrl == -1) {
4148 // Note: the order in this table matches the order of operands in AsmString.
4149 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
4150 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
4151 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
4152 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
4153 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
4154 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
4155 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
4156 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
4157 {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
4158 {"dfmt", AMDGPUOperand::ImmTyDFMT, false, nullptr},
4159 {"nfmt", AMDGPUOperand::ImmTyNFMT, false, nullptr},
4160 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
4161 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
4162 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
4163 {"high", AMDGPUOperand::ImmTyHigh, true, nullptr},
4164 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
4165 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
4166 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
4167 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
4168 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
4169 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
4170 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
4171 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
4172 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
4173 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
4174 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
4175 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
4176 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
4177 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
4178 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
4179 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
4180 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
4181 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
4182 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
4183 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
4186 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
4187 unsigned size = Operands.size();
4190 OperandMatchResultTy res = parseOptionalOpr(Operands);
4192 // This is a hack to enable hardcoded mandatory operands which follow
4193 // optional operands.
4195 // Current design assumes that all operands after the first optional operand
4196 // are also optional. However implementation of some instructions violates
4197 // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands).
4199 // To alleviate this problem, we have to (implicitly) parse extra operands
4200 // to make sure autogenerated parser of custom operands never hit hardcoded
4201 // mandatory operands.
4203 if (size == 1 || ((AMDGPUOperand &)*Operands[size - 1]).isRegKind()) {
4205 // We have parsed the first optional operand.
4206 // Parse as many operands as necessary to skip all mandatory operands.
4208 for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
4209 if (res != MatchOperand_Success ||
4210 getLexer().is(AsmToken::EndOfStatement)) break;
4211 if (getLexer().is(AsmToken::Comma)) Parser.Lex();
4212 res = parseOptionalOpr(Operands);
4219 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) {
4220 OperandMatchResultTy res;
4221 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
4222 // try to parse any optional operand here
4224 res = parseNamedBit(Op.Name, Operands, Op.Type);
4225 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
4226 res = parseOModOperand(Operands);
4227 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
4228 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
4229 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
4230 res = parseSDWASel(Operands, Op.Name, Op.Type);
4231 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
4232 res = parseSDWADstUnused(Operands);
4233 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
4234 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
4235 Op.Type == AMDGPUOperand::ImmTyNegLo ||
4236 Op.Type == AMDGPUOperand::ImmTyNegHi) {
4237 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
4240 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
4242 if (res != MatchOperand_NoMatch) {
4246 return MatchOperand_NoMatch;
4249 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
4250 StringRef Name = Parser.getTok().getString();
4251 if (Name == "mul") {
4252 return parseIntWithPrefix("mul", Operands,
4253 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
4256 if (Name == "div") {
4257 return parseIntWithPrefix("div", Operands,
4258 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
4261 return MatchOperand_NoMatch;
4264 void AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) {
4265 cvtVOP3P(Inst, Operands);
4267 int Opc = Inst.getOpcode();
4270 const int Ops[] = { AMDGPU::OpName::src0,
4271 AMDGPU::OpName::src1,
4272 AMDGPU::OpName::src2 };
4274 SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1;
4278 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4279 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4281 if ((OpSel & (1 << SrcNum)) != 0) {
4282 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
4283 uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
4284 Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL);
4288 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
4289 // 1. This operand is input modifiers
4290 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
4291 // 2. This is not last operand
4292 && Desc.NumOperands > (OpNum + 1)
4293 // 3. Next operand is register class
4294 && Desc.OpInfo[OpNum + 1].RegClass != -1
4295 // 4. Next register is not tied to any other operand
4296 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
4299 void AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands)
4301 OptionalImmIndexMap OptionalIdx;
4302 unsigned Opc = Inst.getOpcode();
4305 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4306 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4307 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4310 for (unsigned E = Operands.size(); I != E; ++I) {
4311 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4312 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4313 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4314 } else if (Op.isInterpSlot() ||
4315 Op.isInterpAttr() ||
4317 Inst.addOperand(MCOperand::createImm(Op.Imm.Val));
4318 } else if (Op.isImmModifier()) {
4319 OptionalIdx[Op.getImmTy()] = I;
4321 llvm_unreachable("unhandled operand type");
4325 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) {
4326 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh);
4329 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4330 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4333 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
4334 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4338 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
4339 OptionalImmIndexMap &OptionalIdx) {
4340 unsigned Opc = Inst.getOpcode();
4343 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4344 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4345 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4348 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) {
4349 // This instruction has src modifiers
4350 for (unsigned E = Operands.size(); I != E; ++I) {
4351 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4352 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4353 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4354 } else if (Op.isImmModifier()) {
4355 OptionalIdx[Op.getImmTy()] = I;
4356 } else if (Op.isRegOrImm()) {
4357 Op.addRegOrImmOperands(Inst, 1);
4359 llvm_unreachable("unhandled operand type");
4364 for (unsigned E = Operands.size(); I != E; ++I) {
4365 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4367 OptionalIdx[Op.getImmTy()] = I;
4369 Op.addRegOrImmOperands(Inst, 1);
4374 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4375 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4378 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
4379 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4382 // special case v_mac_{f16, f32}:
4383 // it has src2 register operand that is tied to dst operand
4384 // we don't allow modifiers for this operand in assembler so src2_modifiers
4386 if (Opc == AMDGPU::V_MAC_F32_e64_si || Opc == AMDGPU::V_MAC_F32_e64_vi ||
4387 Opc == AMDGPU::V_MAC_F16_e64_vi) {
4388 auto it = Inst.begin();
4389 std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
4390 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
4392 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4396 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
4397 OptionalImmIndexMap OptionalIdx;
4398 cvtVOP3(Inst, Operands, OptionalIdx);
4401 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst,
4402 const OperandVector &Operands) {
4403 OptionalImmIndexMap OptIdx;
4404 const int Opc = Inst.getOpcode();
4405 const MCInstrDesc &Desc = MII.get(Opc);
4407 const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0;
4409 cvtVOP3(Inst, Operands, OptIdx);
4411 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) {
4413 Inst.addOperand(Inst.getOperand(0));
4416 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
4417 // instruction, and then figure out where to actually put the modifiers
4419 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
4421 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4422 if (OpSelHiIdx != -1) {
4423 int DefaultVal = IsPacked ? -1 : 0;
4424 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
4428 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
4429 if (NegLoIdx != -1) {
4431 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
4432 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
4435 const int Ops[] = { AMDGPU::OpName::src0,
4436 AMDGPU::OpName::src1,
4437 AMDGPU::OpName::src2 };
4438 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
4439 AMDGPU::OpName::src1_modifiers,
4440 AMDGPU::OpName::src2_modifiers };
4442 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4444 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4445 unsigned OpSelHi = 0;
4449 if (OpSelHiIdx != -1) {
4450 OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
4453 if (NegLoIdx != -1) {
4454 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
4455 NegLo = Inst.getOperand(NegLoIdx).getImm();
4456 NegHi = Inst.getOperand(NegHiIdx).getImm();
4459 for (int J = 0; J < 3; ++J) {
4460 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
4464 uint32_t ModVal = 0;
4466 if ((OpSel & (1 << J)) != 0)
4467 ModVal |= SISrcMods::OP_SEL_0;
4469 if ((OpSelHi & (1 << J)) != 0)
4470 ModVal |= SISrcMods::OP_SEL_1;
4472 if ((NegLo & (1 << J)) != 0)
4473 ModVal |= SISrcMods::NEG;
4475 if ((NegHi & (1 << J)) != 0)
4476 ModVal |= SISrcMods::NEG_HI;
4478 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
4480 Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
4484 //===----------------------------------------------------------------------===//
4486 //===----------------------------------------------------------------------===//
4488 bool AMDGPUOperand::isDPPCtrl() const {
4489 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
4491 int64_t Imm = getImm();
4492 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
4493 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
4494 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
4495 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
4508 bool AMDGPUOperand::isGPRIdxMode() const {
4509 return isImm() && isUInt<4>(getImm());
4512 bool AMDGPUOperand::isS16Imm() const {
4513 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
4516 bool AMDGPUOperand::isU16Imm() const {
4517 return isImm() && isUInt<16>(getImm());
4520 OperandMatchResultTy
4521 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
4522 SMLoc S = Parser.getTok().getLoc();
4526 if (getLexer().getKind() == AsmToken::Identifier) {
4527 Prefix = Parser.getTok().getString();
4529 return MatchOperand_NoMatch;
4532 if (Prefix == "row_mirror") {
4535 } else if (Prefix == "row_half_mirror") {
4539 // Check to prevent parseDPPCtrlOps from eating invalid tokens
4540 if (Prefix != "quad_perm"
4541 && Prefix != "row_shl"
4542 && Prefix != "row_shr"
4543 && Prefix != "row_ror"
4544 && Prefix != "wave_shl"
4545 && Prefix != "wave_rol"
4546 && Prefix != "wave_shr"
4547 && Prefix != "wave_ror"
4548 && Prefix != "row_bcast") {
4549 return MatchOperand_NoMatch;
4553 if (getLexer().isNot(AsmToken::Colon))
4554 return MatchOperand_ParseFail;
4556 if (Prefix == "quad_perm") {
4557 // quad_perm:[%d,%d,%d,%d]
4559 if (getLexer().isNot(AsmToken::LBrac))
4560 return MatchOperand_ParseFail;
4563 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
4564 return MatchOperand_ParseFail;
4566 for (int i = 0; i < 3; ++i) {
4567 if (getLexer().isNot(AsmToken::Comma))
4568 return MatchOperand_ParseFail;
4572 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
4573 return MatchOperand_ParseFail;
4574 const int shift = i*2 + 2;
4575 Int += (Temp << shift);
4578 if (getLexer().isNot(AsmToken::RBrac))
4579 return MatchOperand_ParseFail;
4584 if (getParser().parseAbsoluteExpression(Int))
4585 return MatchOperand_ParseFail;
4587 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
4589 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
4591 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
4593 } else if (Prefix == "wave_shl" && 1 == Int) {
4595 } else if (Prefix == "wave_rol" && 1 == Int) {
4597 } else if (Prefix == "wave_shr" && 1 == Int) {
4599 } else if (Prefix == "wave_ror" && 1 == Int) {
4601 } else if (Prefix == "row_bcast") {
4604 } else if (Int == 31) {
4607 return MatchOperand_ParseFail;
4610 return MatchOperand_ParseFail;
4615 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
4616 return MatchOperand_Success;
4619 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
4620 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
4623 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
4624 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
4627 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
4628 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
4631 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
4632 OptionalImmIndexMap OptionalIdx;
4635 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4636 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4637 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4640 // All DPP instructions with at least one source operand have a fake "old"
4641 // source at the beginning that's tied to the dst operand. Handle it here.
4642 if (Desc.getNumOperands() >= 2)
4643 Inst.addOperand(Inst.getOperand(0));
4645 for (unsigned E = Operands.size(); I != E; ++I) {
4646 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4647 // Add the register arguments
4648 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4649 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
4652 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4653 Op.addRegWithFPInputModsOperands(Inst, 2);
4654 } else if (Op.isDPPCtrl()) {
4655 Op.addImmOperands(Inst, 1);
4656 } else if (Op.isImm()) {
4657 // Handle optional arguments
4658 OptionalIdx[Op.getImmTy()] = I;
4660 llvm_unreachable("Invalid operand type");
4664 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
4665 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
4666 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
4669 //===----------------------------------------------------------------------===//
4671 //===----------------------------------------------------------------------===//
4673 OperandMatchResultTy
4674 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
4675 AMDGPUOperand::ImmTy Type) {
4676 using namespace llvm::AMDGPU::SDWA;
4678 SMLoc S = Parser.getTok().getLoc();
4680 OperandMatchResultTy res;
4682 res = parseStringWithPrefix(Prefix, Value);
4683 if (res != MatchOperand_Success) {
4688 Int = StringSwitch<int64_t>(Value)
4689 .Case("BYTE_0", SdwaSel::BYTE_0)
4690 .Case("BYTE_1", SdwaSel::BYTE_1)
4691 .Case("BYTE_2", SdwaSel::BYTE_2)
4692 .Case("BYTE_3", SdwaSel::BYTE_3)
4693 .Case("WORD_0", SdwaSel::WORD_0)
4694 .Case("WORD_1", SdwaSel::WORD_1)
4695 .Case("DWORD", SdwaSel::DWORD)
4696 .Default(0xffffffff);
4697 Parser.Lex(); // eat last token
4699 if (Int == 0xffffffff) {
4700 return MatchOperand_ParseFail;
4703 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
4704 return MatchOperand_Success;
4707 OperandMatchResultTy
4708 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
4709 using namespace llvm::AMDGPU::SDWA;
4711 SMLoc S = Parser.getTok().getLoc();
4713 OperandMatchResultTy res;
4715 res = parseStringWithPrefix("dst_unused", Value);
4716 if (res != MatchOperand_Success) {
4721 Int = StringSwitch<int64_t>(Value)
4722 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
4723 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
4724 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
4725 .Default(0xffffffff);
4726 Parser.Lex(); // eat last token
4728 if (Int == 0xffffffff) {
4729 return MatchOperand_ParseFail;
4732 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
4733 return MatchOperand_Success;
4736 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
4737 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
4740 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
4741 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
4744 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
4745 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
4748 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
4749 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
4752 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
4753 uint64_t BasicInstType, bool skipVcc) {
4754 using namespace llvm::AMDGPU::SDWA;
4756 OptionalImmIndexMap OptionalIdx;
4757 bool skippedVcc = false;
4760 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4761 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4762 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4765 for (unsigned E = Operands.size(); I != E; ++I) {
4766 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4767 if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4768 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
4769 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
4770 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
4771 // Skip VCC only if we didn't skip it on previous iteration.
4772 if (BasicInstType == SIInstrFlags::VOP2 &&
4773 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
4776 } else if (BasicInstType == SIInstrFlags::VOPC &&
4777 Inst.getNumOperands() == 0) {
4782 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4783 Op.addRegWithInputModsOperands(Inst, 2);
4784 } else if (Op.isImm()) {
4785 // Handle optional arguments
4786 OptionalIdx[Op.getImmTy()] = I;
4788 llvm_unreachable("Invalid operand type");
4793 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
4794 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
4795 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
4796 switch (BasicInstType) {
4797 case SIInstrFlags::VOP1:
4798 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4799 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4800 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4802 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4803 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4804 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4807 case SIInstrFlags::VOP2:
4808 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4809 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4810 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4812 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4813 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4814 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4815 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4818 case SIInstrFlags::VOPC:
4819 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4820 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4821 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4825 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
4829 // special case v_mac_{f16, f32}:
4830 // it has src2 register operand that is tied to dst operand
4831 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
4832 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
4833 auto it = Inst.begin();
4835 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4836 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4840 /// Force static initialization.
4841 extern "C" void LLVMInitializeAMDGPUAsmParser() {
4842 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
4843 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
4846 #define GET_REGISTER_MATCHER
4847 #define GET_MATCHER_IMPLEMENTATION
4848 #define GET_MNEMONIC_SPELL_CHECKER
4849 #include "AMDGPUGenAsmMatcher.inc"
4851 // This fuction should be defined after auto-generated include so that we have
4852 // MatchClassKind enum defined
4853 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
4855 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
4856 // But MatchInstructionImpl() expects to meet token and fails to validate
4857 // operand. This method checks if we are given immediate operand but expect to
4858 // get corresponding token.
4859 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
4862 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
4864 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
4866 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
4868 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
4870 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
4872 // When operands have expression values, they will return true for isToken,
4873 // because it is not possible to distinguish between a token and an
4874 // expression at parse time. MatchInstructionImpl() will always try to
4875 // match an operand as a token, when isToken returns true, and when the
4876 // name of the expression is not a valid token, the match will fail,
4877 // so we need to handle it here.
4878 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
4880 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
4881 case MCK_SoppBrTarget:
4882 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
4883 case MCK_VReg32OrOff:
4884 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
4885 case MCK_InterpSlot:
4886 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
4888 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
4890 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
4892 return Match_InvalidOperand;