1 //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "AMDKernelCodeT.h"
11 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
13 #include "SIDefines.h"
14 #include "Utils/AMDGPUAsmUtils.h"
15 #include "Utils/AMDGPUBaseInfo.h"
16 #include "Utils/AMDKernelCodeTUtils.h"
17 #include "llvm/ADT/APFloat.h"
18 #include "llvm/ADT/APInt.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/SmallBitVector.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 #include "llvm/ADT/Twine.h"
26 #include "llvm/BinaryFormat/ELF.h"
27 #include "llvm/CodeGen/MachineValueType.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCContext.h"
30 #include "llvm/MC/MCExpr.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCInstrDesc.h"
33 #include "llvm/MC/MCInstrInfo.h"
34 #include "llvm/MC/MCParser/MCAsmLexer.h"
35 #include "llvm/MC/MCParser/MCAsmParser.h"
36 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
37 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
38 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
39 #include "llvm/MC/MCRegisterInfo.h"
40 #include "llvm/MC/MCStreamer.h"
41 #include "llvm/MC/MCSubtargetInfo.h"
42 #include "llvm/MC/MCSymbol.h"
43 #include "llvm/Support/Casting.h"
44 #include "llvm/Support/ErrorHandling.h"
45 #include "llvm/Support/MathExtras.h"
46 #include "llvm/Support/SMLoc.h"
47 #include "llvm/Support/TargetRegistry.h"
48 #include "llvm/Support/raw_ostream.h"
59 using namespace llvm::AMDGPU;
63 class AMDGPUAsmParser;
65 enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
67 //===----------------------------------------------------------------------===//
69 //===----------------------------------------------------------------------===//
71 class AMDGPUOperand : public MCParsedAsmOperand {
79 SMLoc StartLoc, EndLoc;
80 const AMDGPUAsmParser *AsmParser;
83 AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
84 : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
86 typedef std::unique_ptr<AMDGPUOperand> Ptr;
93 bool hasFPModifiers() const { return Abs || Neg; }
94 bool hasIntModifiers() const { return Sext; }
95 bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
97 int64_t getFPModifiersOperand() const {
99 Operand |= Abs ? SISrcMods::ABS : 0;
100 Operand |= Neg ? SISrcMods::NEG : 0;
104 int64_t getIntModifiersOperand() const {
106 Operand |= Sext ? SISrcMods::SEXT : 0;
110 int64_t getModifiersOperand() const {
111 assert(!(hasFPModifiers() && hasIntModifiers())
112 && "fp and int modifiers should not be used simultaneously");
113 if (hasFPModifiers()) {
114 return getFPModifiersOperand();
115 } else if (hasIntModifiers()) {
116 return getIntModifiersOperand();
122 friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
195 bool isToken() const override {
199 if (Kind != Expression || !Expr)
202 // When parsing operands, we can't always tell if something was meant to be
203 // a token, like 'gds', or an expression that references a global variable.
204 // In this case, we assume the string is an expression, and if we need to
205 // interpret is a token, then we treat the symbol name as the token.
206 return isa<MCSymbolRefExpr>(Expr);
209 bool isImm() const override {
210 return Kind == Immediate;
213 bool isInlinableImm(MVT type) const;
214 bool isLiteralImm(MVT type) const;
216 bool isRegKind() const {
217 return Kind == Register;
220 bool isReg() const override {
221 return isRegKind() && !hasModifiers();
224 bool isRegOrImmWithInputMods(MVT type) const {
225 return isRegKind() || isInlinableImm(type);
228 bool isRegOrImmWithInt16InputMods() const {
229 return isRegOrImmWithInputMods(MVT::i16);
232 bool isRegOrImmWithInt32InputMods() const {
233 return isRegOrImmWithInputMods(MVT::i32);
236 bool isRegOrImmWithInt64InputMods() const {
237 return isRegOrImmWithInputMods(MVT::i64);
240 bool isRegOrImmWithFP16InputMods() const {
241 return isRegOrImmWithInputMods(MVT::f16);
244 bool isRegOrImmWithFP32InputMods() const {
245 return isRegOrImmWithInputMods(MVT::f32);
248 bool isRegOrImmWithFP64InputMods() const {
249 return isRegOrImmWithInputMods(MVT::f64);
252 bool isVReg() const {
253 return isRegClass(AMDGPU::VGPR_32RegClassID) ||
254 isRegClass(AMDGPU::VReg_64RegClassID) ||
255 isRegClass(AMDGPU::VReg_96RegClassID) ||
256 isRegClass(AMDGPU::VReg_128RegClassID) ||
257 isRegClass(AMDGPU::VReg_256RegClassID) ||
258 isRegClass(AMDGPU::VReg_512RegClassID);
261 bool isVReg32OrOff() const {
262 return isOff() || isRegClass(AMDGPU::VGPR_32RegClassID);
265 bool isSDWARegKind() const;
267 bool isImmTy(ImmTy ImmT) const {
268 return isImm() && Imm.Type == ImmT;
271 bool isImmModifier() const {
272 return isImm() && Imm.Type != ImmTyNone;
275 bool isClampSI() const { return isImmTy(ImmTyClampSI); }
276 bool isOModSI() const { return isImmTy(ImmTyOModSI); }
277 bool isDMask() const { return isImmTy(ImmTyDMask); }
278 bool isUNorm() const { return isImmTy(ImmTyUNorm); }
279 bool isDA() const { return isImmTy(ImmTyDA); }
280 bool isR128() const { return isImmTy(ImmTyUNorm); }
281 bool isLWE() const { return isImmTy(ImmTyLWE); }
282 bool isOff() const { return isImmTy(ImmTyOff); }
283 bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
284 bool isExpVM() const { return isImmTy(ImmTyExpVM); }
285 bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
286 bool isOffen() const { return isImmTy(ImmTyOffen); }
287 bool isIdxen() const { return isImmTy(ImmTyIdxen); }
288 bool isAddr64() const { return isImmTy(ImmTyAddr64); }
289 bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
290 bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
291 bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
293 bool isOffsetU12() const { return isImmTy(ImmTyOffset) && isUInt<12>(getImm()); }
294 bool isOffsetS13() const { return isImmTy(ImmTyOffset) && isInt<13>(getImm()); }
295 bool isGDS() const { return isImmTy(ImmTyGDS); }
296 bool isGLC() const { return isImmTy(ImmTyGLC); }
297 bool isSLC() const { return isImmTy(ImmTySLC); }
298 bool isTFE() const { return isImmTy(ImmTyTFE); }
299 bool isDFMT() const { return isImmTy(ImmTyDFMT) && isUInt<8>(getImm()); }
300 bool isNFMT() const { return isImmTy(ImmTyNFMT) && isUInt<8>(getImm()); }
301 bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
302 bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
303 bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
304 bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
305 bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
306 bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
307 bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
308 bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
309 bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
310 bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
311 bool isOpSel() const { return isImmTy(ImmTyOpSel); }
312 bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
313 bool isNegLo() const { return isImmTy(ImmTyNegLo); }
314 bool isNegHi() const { return isImmTy(ImmTyNegHi); }
317 return isClampSI() || isOModSI();
320 bool isRegOrImm() const {
321 return isReg() || isImm();
324 bool isRegClass(unsigned RCID) const;
326 bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
327 return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
330 bool isSCSrcB16() const {
331 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
334 bool isSCSrcV2B16() const {
338 bool isSCSrcB32() const {
339 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
342 bool isSCSrcB64() const {
343 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
346 bool isSCSrcF16() const {
347 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
350 bool isSCSrcV2F16() const {
354 bool isSCSrcF32() const {
355 return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
358 bool isSCSrcF64() const {
359 return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
362 bool isSSrcB32() const {
363 return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
366 bool isSSrcB16() const {
367 return isSCSrcB16() || isLiteralImm(MVT::i16);
370 bool isSSrcV2B16() const {
371 llvm_unreachable("cannot happen");
375 bool isSSrcB64() const {
376 // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
378 return isSCSrcB64() || isLiteralImm(MVT::i64);
381 bool isSSrcF32() const {
382 return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
385 bool isSSrcF64() const {
386 return isSCSrcB64() || isLiteralImm(MVT::f64);
389 bool isSSrcF16() const {
390 return isSCSrcB16() || isLiteralImm(MVT::f16);
393 bool isSSrcV2F16() const {
394 llvm_unreachable("cannot happen");
398 bool isVCSrcB32() const {
399 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
402 bool isVCSrcB64() const {
403 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
406 bool isVCSrcB16() const {
407 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
410 bool isVCSrcV2B16() const {
414 bool isVCSrcF32() const {
415 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
418 bool isVCSrcF64() const {
419 return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
422 bool isVCSrcF16() const {
423 return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
426 bool isVCSrcV2F16() const {
430 bool isVSrcB32() const {
431 return isVCSrcF32() || isLiteralImm(MVT::i32);
434 bool isVSrcB64() const {
435 return isVCSrcF64() || isLiteralImm(MVT::i64);
438 bool isVSrcB16() const {
439 return isVCSrcF16() || isLiteralImm(MVT::i16);
442 bool isVSrcV2B16() const {
443 llvm_unreachable("cannot happen");
447 bool isVSrcF32() const {
448 return isVCSrcF32() || isLiteralImm(MVT::f32);
451 bool isVSrcF64() const {
452 return isVCSrcF64() || isLiteralImm(MVT::f64);
455 bool isVSrcF16() const {
456 return isVCSrcF16() || isLiteralImm(MVT::f16);
459 bool isVSrcV2F16() const {
460 llvm_unreachable("cannot happen");
464 bool isKImmFP32() const {
465 return isLiteralImm(MVT::f32);
468 bool isKImmFP16() const {
469 return isLiteralImm(MVT::f16);
472 bool isMem() const override {
476 bool isExpr() const {
477 return Kind == Expression;
480 bool isSoppBrTarget() const {
481 return isExpr() || isImm();
484 bool isSWaitCnt() const;
485 bool isHwreg() const;
486 bool isSendMsg() const;
487 bool isSwizzle() const;
488 bool isSMRDOffset8() const;
489 bool isSMRDOffset20() const;
490 bool isSMRDLiteralOffset() const;
491 bool isDPPCtrl() const;
492 bool isGPRIdxMode() const;
493 bool isS16Imm() const;
494 bool isU16Imm() const;
496 StringRef getExpressionAsToken() const {
498 const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
499 return S->getSymbol().getName();
502 StringRef getToken() const {
505 if (Kind == Expression)
506 return getExpressionAsToken();
508 return StringRef(Tok.Data, Tok.Length);
511 int64_t getImm() const {
516 ImmTy getImmTy() const {
521 unsigned getReg() const override {
525 SMLoc getStartLoc() const override {
529 SMLoc getEndLoc() const override {
533 Modifiers getModifiers() const {
534 assert(isRegKind() || isImmTy(ImmTyNone));
535 return isRegKind() ? Reg.Mods : Imm.Mods;
538 void setModifiers(Modifiers Mods) {
539 assert(isRegKind() || isImmTy(ImmTyNone));
546 bool hasModifiers() const {
547 return getModifiers().hasModifiers();
550 bool hasFPModifiers() const {
551 return getModifiers().hasFPModifiers();
554 bool hasIntModifiers() const {
555 return getModifiers().hasIntModifiers();
558 uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
560 void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
562 void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
564 template <unsigned Bitwidth>
565 void addKImmFPOperands(MCInst &Inst, unsigned N) const;
567 void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
568 addKImmFPOperands<16>(Inst, N);
571 void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
572 addKImmFPOperands<32>(Inst, N);
575 void addRegOperands(MCInst &Inst, unsigned N) const;
577 void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
579 addRegOperands(Inst, N);
581 Inst.addOperand(MCOperand::createExpr(Expr));
583 addImmOperands(Inst, N);
586 void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
587 Modifiers Mods = getModifiers();
588 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
590 addRegOperands(Inst, N);
592 addImmOperands(Inst, N, false);
596 void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
597 assert(!hasIntModifiers());
598 addRegOrImmWithInputModsOperands(Inst, N);
601 void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
602 assert(!hasFPModifiers());
603 addRegOrImmWithInputModsOperands(Inst, N);
606 void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
607 Modifiers Mods = getModifiers();
608 Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
610 addRegOperands(Inst, N);
613 void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
614 assert(!hasIntModifiers());
615 addRegWithInputModsOperands(Inst, N);
618 void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
619 assert(!hasFPModifiers());
620 addRegWithInputModsOperands(Inst, N);
623 void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
625 addImmOperands(Inst, N);
628 Inst.addOperand(MCOperand::createExpr(Expr));
632 static void printImmTy(raw_ostream& OS, ImmTy Type) {
634 case ImmTyNone: OS << "None"; break;
635 case ImmTyGDS: OS << "GDS"; break;
636 case ImmTyOffen: OS << "Offen"; break;
637 case ImmTyIdxen: OS << "Idxen"; break;
638 case ImmTyAddr64: OS << "Addr64"; break;
639 case ImmTyOffset: OS << "Offset"; break;
640 case ImmTyOffset0: OS << "Offset0"; break;
641 case ImmTyOffset1: OS << "Offset1"; break;
642 case ImmTyGLC: OS << "GLC"; break;
643 case ImmTySLC: OS << "SLC"; break;
644 case ImmTyTFE: OS << "TFE"; break;
645 case ImmTyDFMT: OS << "DFMT"; break;
646 case ImmTyNFMT: OS << "NFMT"; break;
647 case ImmTyClampSI: OS << "ClampSI"; break;
648 case ImmTyOModSI: OS << "OModSI"; break;
649 case ImmTyDppCtrl: OS << "DppCtrl"; break;
650 case ImmTyDppRowMask: OS << "DppRowMask"; break;
651 case ImmTyDppBankMask: OS << "DppBankMask"; break;
652 case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
653 case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
654 case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
655 case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
656 case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
657 case ImmTyDMask: OS << "DMask"; break;
658 case ImmTyUNorm: OS << "UNorm"; break;
659 case ImmTyDA: OS << "DA"; break;
660 case ImmTyR128: OS << "R128"; break;
661 case ImmTyLWE: OS << "LWE"; break;
662 case ImmTyOff: OS << "Off"; break;
663 case ImmTyExpTgt: OS << "ExpTgt"; break;
664 case ImmTyExpCompr: OS << "ExpCompr"; break;
665 case ImmTyExpVM: OS << "ExpVM"; break;
666 case ImmTyHwreg: OS << "Hwreg"; break;
667 case ImmTySendMsg: OS << "SendMsg"; break;
668 case ImmTyInterpSlot: OS << "InterpSlot"; break;
669 case ImmTyInterpAttr: OS << "InterpAttr"; break;
670 case ImmTyAttrChan: OS << "AttrChan"; break;
671 case ImmTyOpSel: OS << "OpSel"; break;
672 case ImmTyOpSelHi: OS << "OpSelHi"; break;
673 case ImmTyNegLo: OS << "NegLo"; break;
674 case ImmTyNegHi: OS << "NegHi"; break;
675 case ImmTySwizzle: OS << "Swizzle"; break;
679 void print(raw_ostream &OS) const override {
682 OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
685 OS << '<' << getImm();
686 if (getImmTy() != ImmTyNone) {
687 OS << " type: "; printImmTy(OS, getImmTy());
689 OS << " mods: " << Imm.Mods << '>';
692 OS << '\'' << getToken() << '\'';
695 OS << "<expr " << *Expr << '>';
700 static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
701 int64_t Val, SMLoc Loc,
702 ImmTy Type = ImmTyNone,
703 bool IsFPImm = false) {
704 auto Op = llvm::make_unique<AMDGPUOperand>(Immediate, AsmParser);
706 Op->Imm.IsFPImm = IsFPImm;
708 Op->Imm.Mods = Modifiers();
714 static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
715 StringRef Str, SMLoc Loc,
716 bool HasExplicitEncodingSize = true) {
717 auto Res = llvm::make_unique<AMDGPUOperand>(Token, AsmParser);
718 Res->Tok.Data = Str.data();
719 Res->Tok.Length = Str.size();
725 static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
726 unsigned RegNo, SMLoc S,
729 auto Op = llvm::make_unique<AMDGPUOperand>(Register, AsmParser);
730 Op->Reg.RegNo = RegNo;
731 Op->Reg.Mods = Modifiers();
732 Op->Reg.IsForcedVOP3 = ForceVOP3;
738 static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
739 const class MCExpr *Expr, SMLoc S) {
740 auto Op = llvm::make_unique<AMDGPUOperand>(Expression, AsmParser);
748 raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
749 OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
753 //===----------------------------------------------------------------------===//
755 //===----------------------------------------------------------------------===//
757 // Holds info related to the current kernel, e.g. count of SGPRs used.
758 // Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
759 // .amdgpu_hsa_kernel or at EOF.
760 class KernelScopeInfo {
761 int SgprIndexUnusedMin = -1;
762 int VgprIndexUnusedMin = -1;
763 MCContext *Ctx = nullptr;
765 void usesSgprAt(int i) {
766 if (i >= SgprIndexUnusedMin) {
767 SgprIndexUnusedMin = ++i;
769 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
770 Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
775 void usesVgprAt(int i) {
776 if (i >= VgprIndexUnusedMin) {
777 VgprIndexUnusedMin = ++i;
779 MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
780 Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
786 KernelScopeInfo() = default;
788 void initialize(MCContext &Context) {
790 usesSgprAt(SgprIndexUnusedMin = -1);
791 usesVgprAt(VgprIndexUnusedMin = -1);
794 void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
796 case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
797 case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
803 class AMDGPUAsmParser : public MCTargetAsmParser {
804 const MCInstrInfo &MII;
807 unsigned ForcedEncodingSize = 0;
808 bool ForcedDPP = false;
809 bool ForcedSDWA = false;
810 KernelScopeInfo KernelScope;
812 /// @name Auto-generated Match Functions
815 #define GET_ASSEMBLER_HEADER
816 #include "AMDGPUGenAsmMatcher.inc"
821 bool ParseAsAbsoluteExpression(uint32_t &Ret);
822 bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
823 bool ParseDirectiveHSACodeObjectVersion();
824 bool ParseDirectiveHSACodeObjectISA();
825 bool ParseDirectiveCodeObjectMetadata();
826 bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
827 bool ParseDirectiveAMDKernelCodeT();
828 bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
829 bool ParseDirectiveAMDGPUHsaKernel();
830 bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
831 RegisterKind RegKind, unsigned Reg1,
833 bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
834 unsigned& RegNum, unsigned& RegWidth,
835 unsigned *DwordRegIndex);
836 void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
837 bool IsAtomic, bool IsAtomicReturn);
838 void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
839 bool IsGdsHardcoded);
842 enum AMDGPUMatchResultTy {
843 Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
846 typedef std::map<AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
848 AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
849 const MCInstrInfo &MII,
850 const MCTargetOptions &Options)
851 : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser) {
852 MCAsmParserExtension::Initialize(Parser);
854 if (getFeatureBits().none()) {
855 // Set default features.
856 copySTI().ToggleFeature("SOUTHERN_ISLANDS");
859 setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
862 // TODO: make those pre-defined variables read-only.
863 // Currently there is none suitable machinery in the core llvm-mc for this.
864 // MCSymbol::isRedefinable is intended for another purpose, and
865 // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
866 AMDGPU::IsaInfo::IsaVersion ISA =
867 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
868 MCContext &Ctx = getContext();
870 Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
871 Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
872 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
873 Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
874 Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
875 Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
877 KernelScope.initialize(getContext());
881 return AMDGPU::isSI(getSTI());
885 return AMDGPU::isCI(getSTI());
889 return AMDGPU::isVI(getSTI());
892 bool isGFX9() const {
893 return AMDGPU::isGFX9(getSTI());
896 bool hasInv2PiInlineImm() const {
897 return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
900 bool hasFlatOffsets() const {
901 return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
904 bool hasSGPR102_SGPR103() const {
908 AMDGPUTargetStreamer &getTargetStreamer() {
909 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
910 return static_cast<AMDGPUTargetStreamer &>(TS);
913 const MCRegisterInfo *getMRI() const {
914 // We need this const_cast because for some reason getContext() is not const
916 return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
919 const MCInstrInfo *getMII() const {
923 const FeatureBitset &getFeatureBits() const {
924 return getSTI().getFeatureBits();
927 void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
928 void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
929 void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
931 unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
932 bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
933 bool isForcedDPP() const { return ForcedDPP; }
934 bool isForcedSDWA() const { return ForcedSDWA; }
935 ArrayRef<unsigned> getMatchedVariants() const;
937 std::unique_ptr<AMDGPUOperand> parseRegister();
938 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
939 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
940 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
941 unsigned Kind) override;
942 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
943 OperandVector &Operands, MCStreamer &Out,
945 bool MatchingInlineAsm) override;
946 bool ParseDirective(AsmToken DirectiveID) override;
947 OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
948 StringRef parseMnemonicSuffix(StringRef Name);
949 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
950 SMLoc NameLoc, OperandVector &Operands) override;
951 //bool ProcessInstruction(MCInst &Inst);
953 OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
956 parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
957 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
958 bool (*ConvertResult)(int64_t &) = nullptr);
960 OperandMatchResultTy parseOperandArrayWithPrefix(
962 OperandVector &Operands,
963 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
964 bool (*ConvertResult)(int64_t&) = nullptr);
967 parseNamedBit(const char *Name, OperandVector &Operands,
968 AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
969 OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
972 bool parseAbsoluteExpr(int64_t &Val, bool AbsMod = false);
973 OperandMatchResultTy parseImm(OperandVector &Operands, bool AbsMod = false);
974 OperandMatchResultTy parseReg(OperandVector &Operands);
975 OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool AbsMod = false);
976 OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
977 OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
978 OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
979 OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
980 OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
982 void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
983 void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
984 void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
985 void cvtExp(MCInst &Inst, const OperandVector &Operands);
987 bool parseCnt(int64_t &IntVal);
988 OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
989 OperandMatchResultTy parseHwreg(OperandVector &Operands);
992 struct OperandInfoTy {
995 OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
998 bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
999 bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1002 OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1004 bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc);
1005 bool validateConstantBusLimitations(const MCInst &Inst);
1006 bool validateEarlyClobberLimitations(const MCInst &Inst);
1007 bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1008 bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1009 unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1011 bool trySkipId(const StringRef Id);
1012 bool trySkipToken(const AsmToken::TokenKind Kind);
1013 bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1014 bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1015 bool parseExpr(int64_t &Imm);
1018 OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1020 OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1021 OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1022 OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1023 OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1024 OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1026 bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1027 const unsigned MinVal,
1028 const unsigned MaxVal,
1029 const StringRef ErrMsg);
1030 OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1031 bool parseSwizzleOffset(int64_t &Imm);
1032 bool parseSwizzleMacro(int64_t &Imm);
1033 bool parseSwizzleQuadPerm(int64_t &Imm);
1034 bool parseSwizzleBitmaskPerm(int64_t &Imm);
1035 bool parseSwizzleBroadcast(int64_t &Imm);
1036 bool parseSwizzleSwap(int64_t &Imm);
1037 bool parseSwizzleReverse(int64_t &Imm);
1039 void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1040 void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1041 void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1042 void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1044 AMDGPUOperand::Ptr defaultGLC() const;
1045 AMDGPUOperand::Ptr defaultSLC() const;
1046 AMDGPUOperand::Ptr defaultTFE() const;
1048 AMDGPUOperand::Ptr defaultDMask() const;
1049 AMDGPUOperand::Ptr defaultUNorm() const;
1050 AMDGPUOperand::Ptr defaultDA() const;
1051 AMDGPUOperand::Ptr defaultR128() const;
1052 AMDGPUOperand::Ptr defaultLWE() const;
1053 AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1054 AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1055 AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1056 AMDGPUOperand::Ptr defaultOffsetU12() const;
1057 AMDGPUOperand::Ptr defaultOffsetS13() const;
1059 OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1061 void cvtId(MCInst &Inst, const OperandVector &Operands);
1062 void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
1064 void cvtVOP3Impl(MCInst &Inst,
1065 const OperandVector &Operands,
1066 OptionalImmIndexMap &OptionalIdx);
1067 void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1068 void cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands);
1069 void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1071 void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
1072 void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1074 OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1075 AMDGPUOperand::Ptr defaultRowMask() const;
1076 AMDGPUOperand::Ptr defaultBankMask() const;
1077 AMDGPUOperand::Ptr defaultBoundCtrl() const;
1078 void cvtDPP(MCInst &Inst, const OperandVector &Operands);
1080 OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1081 AMDGPUOperand::ImmTy Type);
1082 OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1083 void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1084 void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1085 void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1086 void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1087 void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1088 uint64_t BasicInstType, bool skipVcc = false);
1091 struct OptionalOperand {
1093 AMDGPUOperand::ImmTy Type;
1095 bool (*ConvertResult)(int64_t&);
1098 } // end anonymous namespace
1100 // May be called with integer type with equivalent bitwidth.
1101 static const fltSemantics *getFltSemantics(unsigned Size) {
1104 return &APFloat::IEEEsingle();
1106 return &APFloat::IEEEdouble();
1108 return &APFloat::IEEEhalf();
1110 llvm_unreachable("unsupported fp type");
1114 static const fltSemantics *getFltSemantics(MVT VT) {
1115 return getFltSemantics(VT.getSizeInBits() / 8);
1118 static const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1119 switch (OperandType) {
1120 case AMDGPU::OPERAND_REG_IMM_INT32:
1121 case AMDGPU::OPERAND_REG_IMM_FP32:
1122 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1123 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1124 return &APFloat::IEEEsingle();
1125 case AMDGPU::OPERAND_REG_IMM_INT64:
1126 case AMDGPU::OPERAND_REG_IMM_FP64:
1127 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1128 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1129 return &APFloat::IEEEdouble();
1130 case AMDGPU::OPERAND_REG_IMM_INT16:
1131 case AMDGPU::OPERAND_REG_IMM_FP16:
1132 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1133 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1134 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1135 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1136 return &APFloat::IEEEhalf();
1138 llvm_unreachable("unsupported fp type");
1142 //===----------------------------------------------------------------------===//
1144 //===----------------------------------------------------------------------===//
1146 static bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1149 // Convert literal to single precision
1150 APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1151 APFloat::rmNearestTiesToEven,
1153 // We allow precision lost but not overflow or underflow
1154 if (Status != APFloat::opOK &&
1156 ((Status & APFloat::opOverflow) != 0 ||
1157 (Status & APFloat::opUnderflow) != 0)) {
1164 bool AMDGPUOperand::isInlinableImm(MVT type) const {
1165 if (!isImmTy(ImmTyNone)) {
1166 // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1169 // TODO: We should avoid using host float here. It would be better to
1170 // check the float bit values which is what a few other places do.
1171 // We've had bot failures before due to weird NaN support on mips hosts.
1173 APInt Literal(64, Imm.Val);
1175 if (Imm.IsFPImm) { // We got fp literal token
1176 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1177 return AMDGPU::isInlinableLiteral64(Imm.Val,
1178 AsmParser->hasInv2PiInlineImm());
1181 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1182 if (!canLosslesslyConvertToFPType(FPLiteral, type))
1185 if (type.getScalarSizeInBits() == 16) {
1186 return AMDGPU::isInlinableLiteral16(
1187 static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1188 AsmParser->hasInv2PiInlineImm());
1191 // Check if single precision literal is inlinable
1192 return AMDGPU::isInlinableLiteral32(
1193 static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1194 AsmParser->hasInv2PiInlineImm());
1197 // We got int literal token.
1198 if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1199 return AMDGPU::isInlinableLiteral64(Imm.Val,
1200 AsmParser->hasInv2PiInlineImm());
1203 if (type.getScalarSizeInBits() == 16) {
1204 return AMDGPU::isInlinableLiteral16(
1205 static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1206 AsmParser->hasInv2PiInlineImm());
1209 return AMDGPU::isInlinableLiteral32(
1210 static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1211 AsmParser->hasInv2PiInlineImm());
1214 bool AMDGPUOperand::isLiteralImm(MVT type) const {
1215 // Check that this imediate can be added as literal
1216 if (!isImmTy(ImmTyNone)) {
1221 // We got int literal token.
1223 if (type == MVT::f64 && hasFPModifiers()) {
1224 // Cannot apply fp modifiers to int literals preserving the same semantics
1225 // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1226 // disable these cases.
1230 unsigned Size = type.getSizeInBits();
1234 // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1236 return isUIntN(Size, Imm.Val) || isIntN(Size, Imm.Val);
1239 // We got fp literal token
1240 if (type == MVT::f64) { // Expected 64-bit fp operand
1241 // We would set low 64-bits of literal to zeroes but we accept this literals
1245 if (type == MVT::i64) { // Expected 64-bit int operand
1246 // We don't allow fp literals in 64-bit integer instructions. It is
1247 // unclear how we should encode them.
1251 APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1252 return canLosslesslyConvertToFPType(FPLiteral, type);
1255 bool AMDGPUOperand::isRegClass(unsigned RCID) const {
1256 return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1259 bool AMDGPUOperand::isSDWARegKind() const {
1260 if (AsmParser->isVI())
1262 else if (AsmParser->isGFX9())
1268 uint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1270 assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1271 assert(Size == 2 || Size == 4 || Size == 8);
1273 const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1285 void AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1287 if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1288 Inst.getNumOperands())) {
1289 addLiteralImmOperand(Inst, Imm.Val,
1291 isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1293 assert(!isImmTy(ImmTyNone) || !hasModifiers());
1294 Inst.addOperand(MCOperand::createImm(Imm.Val));
1298 void AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1299 const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1300 auto OpNum = Inst.getNumOperands();
1301 // Check that this operand accepts literals
1302 assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1304 if (ApplyModifiers) {
1305 assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1306 const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1307 Val = applyInputFPModifiers(Val, Size);
1310 APInt Literal(64, Val);
1311 uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1313 if (Imm.IsFPImm) { // We got fp literal token
1315 case AMDGPU::OPERAND_REG_IMM_INT64:
1316 case AMDGPU::OPERAND_REG_IMM_FP64:
1317 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1318 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1319 if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1320 AsmParser->hasInv2PiInlineImm())) {
1321 Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1326 if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1327 // For fp operands we check if low 32 bits are zeros
1328 if (Literal.getLoBits(32) != 0) {
1329 const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1330 "Can't encode literal as exact 64-bit floating-point operand. "
1331 "Low 32-bits will be set to zero");
1334 Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1338 // We don't allow fp literals in 64-bit integer instructions. It is
1339 // unclear how we should encode them. This case should be checked earlier
1340 // in predicate methods (isLiteralImm())
1341 llvm_unreachable("fp literal in 64-bit integer instruction.");
1343 case AMDGPU::OPERAND_REG_IMM_INT32:
1344 case AMDGPU::OPERAND_REG_IMM_FP32:
1345 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1346 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1347 case AMDGPU::OPERAND_REG_IMM_INT16:
1348 case AMDGPU::OPERAND_REG_IMM_FP16:
1349 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1350 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1351 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1352 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1354 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1355 // Convert literal to single precision
1356 FPLiteral.convert(*getOpFltSemantics(OpTy),
1357 APFloat::rmNearestTiesToEven, &lost);
1358 // We allow precision lost but not overflow or underflow. This should be
1359 // checked earlier in isLiteralImm()
1361 uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1362 if (OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
1363 OpTy == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
1364 ImmVal |= (ImmVal << 16);
1367 Inst.addOperand(MCOperand::createImm(ImmVal));
1371 llvm_unreachable("invalid operand size");
1377 // We got int literal token.
1378 // Only sign extend inline immediates.
1379 // FIXME: No errors on truncation
1381 case AMDGPU::OPERAND_REG_IMM_INT32:
1382 case AMDGPU::OPERAND_REG_IMM_FP32:
1383 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1384 case AMDGPU::OPERAND_REG_INLINE_C_FP32: {
1385 if (isInt<32>(Val) &&
1386 AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1387 AsmParser->hasInv2PiInlineImm())) {
1388 Inst.addOperand(MCOperand::createImm(Val));
1392 Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1395 case AMDGPU::OPERAND_REG_IMM_INT64:
1396 case AMDGPU::OPERAND_REG_IMM_FP64:
1397 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1398 case AMDGPU::OPERAND_REG_INLINE_C_FP64: {
1399 if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1400 Inst.addOperand(MCOperand::createImm(Val));
1404 Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1407 case AMDGPU::OPERAND_REG_IMM_INT16:
1408 case AMDGPU::OPERAND_REG_IMM_FP16:
1409 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1410 case AMDGPU::OPERAND_REG_INLINE_C_FP16: {
1411 if (isInt<16>(Val) &&
1412 AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1413 AsmParser->hasInv2PiInlineImm())) {
1414 Inst.addOperand(MCOperand::createImm(Val));
1418 Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1421 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1422 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16: {
1423 auto LiteralVal = static_cast<uint16_t>(Literal.getLoBits(16).getZExtValue());
1424 assert(AMDGPU::isInlinableLiteral16(LiteralVal,
1425 AsmParser->hasInv2PiInlineImm()));
1427 uint32_t ImmVal = static_cast<uint32_t>(LiteralVal) << 16 |
1428 static_cast<uint32_t>(LiteralVal);
1429 Inst.addOperand(MCOperand::createImm(ImmVal));
1433 llvm_unreachable("invalid operand size");
1437 template <unsigned Bitwidth>
1438 void AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1439 APInt Literal(64, Imm.Val);
1442 // We got int literal token.
1443 Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1448 APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1449 FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1450 APFloat::rmNearestTiesToEven, &Lost);
1451 Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1454 void AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1455 Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1458 //===----------------------------------------------------------------------===//
1460 //===----------------------------------------------------------------------===//
1462 static int getRegClass(RegisterKind Is, unsigned RegWidth) {
1463 if (Is == IS_VGPR) {
1466 case 1: return AMDGPU::VGPR_32RegClassID;
1467 case 2: return AMDGPU::VReg_64RegClassID;
1468 case 3: return AMDGPU::VReg_96RegClassID;
1469 case 4: return AMDGPU::VReg_128RegClassID;
1470 case 8: return AMDGPU::VReg_256RegClassID;
1471 case 16: return AMDGPU::VReg_512RegClassID;
1473 } else if (Is == IS_TTMP) {
1476 case 1: return AMDGPU::TTMP_32RegClassID;
1477 case 2: return AMDGPU::TTMP_64RegClassID;
1478 case 4: return AMDGPU::TTMP_128RegClassID;
1480 } else if (Is == IS_SGPR) {
1483 case 1: return AMDGPU::SGPR_32RegClassID;
1484 case 2: return AMDGPU::SGPR_64RegClassID;
1485 case 4: return AMDGPU::SGPR_128RegClassID;
1486 case 8: return AMDGPU::SReg_256RegClassID;
1487 case 16: return AMDGPU::SReg_512RegClassID;
1493 static unsigned getSpecialRegForName(StringRef RegName) {
1494 return StringSwitch<unsigned>(RegName)
1495 .Case("exec", AMDGPU::EXEC)
1496 .Case("vcc", AMDGPU::VCC)
1497 .Case("flat_scratch", AMDGPU::FLAT_SCR)
1498 .Case("m0", AMDGPU::M0)
1499 .Case("scc", AMDGPU::SCC)
1500 .Case("tba", AMDGPU::TBA)
1501 .Case("tma", AMDGPU::TMA)
1502 .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1503 .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1504 .Case("vcc_lo", AMDGPU::VCC_LO)
1505 .Case("vcc_hi", AMDGPU::VCC_HI)
1506 .Case("exec_lo", AMDGPU::EXEC_LO)
1507 .Case("exec_hi", AMDGPU::EXEC_HI)
1508 .Case("tma_lo", AMDGPU::TMA_LO)
1509 .Case("tma_hi", AMDGPU::TMA_HI)
1510 .Case("tba_lo", AMDGPU::TBA_LO)
1511 .Case("tba_hi", AMDGPU::TBA_HI)
1515 bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1517 auto R = parseRegister();
1518 if (!R) return true;
1520 RegNo = R->getReg();
1521 StartLoc = R->getStartLoc();
1522 EndLoc = R->getEndLoc();
1526 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1527 RegisterKind RegKind, unsigned Reg1,
1531 if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1536 if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
1537 Reg = AMDGPU::FLAT_SCR;
1541 if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
1546 if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
1551 if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
1560 if (Reg1 != Reg + RegWidth) {
1566 llvm_unreachable("unexpected register kind");
1570 bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind, unsigned &Reg,
1571 unsigned &RegNum, unsigned &RegWidth,
1572 unsigned *DwordRegIndex) {
1573 if (DwordRegIndex) { *DwordRegIndex = 0; }
1574 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
1575 if (getLexer().is(AsmToken::Identifier)) {
1576 StringRef RegName = Parser.getTok().getString();
1577 if ((Reg = getSpecialRegForName(RegName))) {
1579 RegKind = IS_SPECIAL;
1581 unsigned RegNumIndex = 0;
1582 if (RegName[0] == 'v') {
1585 } else if (RegName[0] == 's') {
1588 } else if (RegName.startswith("ttmp")) {
1589 RegNumIndex = strlen("ttmp");
1594 if (RegName.size() > RegNumIndex) {
1595 // Single 32-bit register: vXX.
1596 if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
1601 // Range of registers: v[XX:YY]. ":YY" is optional.
1603 int64_t RegLo, RegHi;
1604 if (getLexer().isNot(AsmToken::LBrac))
1608 if (getParser().parseAbsoluteExpression(RegLo))
1611 const bool isRBrace = getLexer().is(AsmToken::RBrac);
1612 if (!isRBrace && getLexer().isNot(AsmToken::Colon))
1619 if (getParser().parseAbsoluteExpression(RegHi))
1622 if (getLexer().isNot(AsmToken::RBrac))
1626 RegNum = (unsigned) RegLo;
1627 RegWidth = (RegHi - RegLo) + 1;
1630 } else if (getLexer().is(AsmToken::LBrac)) {
1631 // List of consecutive registers: [s0,s1,s2,s3]
1633 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, nullptr))
1637 RegisterKind RegKind1;
1638 unsigned Reg1, RegNum1, RegWidth1;
1640 if (getLexer().is(AsmToken::Comma)) {
1642 } else if (getLexer().is(AsmToken::RBrac)) {
1645 } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1, nullptr)) {
1646 if (RegWidth1 != 1) {
1649 if (RegKind1 != RegKind) {
1652 if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
1672 if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
1673 // SGPR and TTMP registers must be aligned. Max required alignment is 4 dwords.
1674 Size = std::min(RegWidth, 4u);
1676 if (RegNum % Size != 0)
1678 if (DwordRegIndex) { *DwordRegIndex = RegNum; }
1679 RegNum = RegNum / Size;
1680 int RCID = getRegClass(RegKind, RegWidth);
1683 const MCRegisterClass RC = TRI->getRegClass(RCID);
1684 if (RegNum >= RC.getNumRegs())
1686 Reg = RC.getRegister(RegNum);
1691 llvm_unreachable("unexpected register kind");
1694 if (!subtargetHasRegister(*TRI, Reg))
1699 std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
1700 const auto &Tok = Parser.getTok();
1701 SMLoc StartLoc = Tok.getLoc();
1702 SMLoc EndLoc = Tok.getEndLoc();
1703 RegisterKind RegKind;
1704 unsigned Reg, RegNum, RegWidth, DwordRegIndex;
1706 if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth, &DwordRegIndex)) {
1709 KernelScope.usesRegister(RegKind, DwordRegIndex, RegWidth);
1710 return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc, false);
1714 AMDGPUAsmParser::parseAbsoluteExpr(int64_t &Val, bool AbsMod) {
1715 if (AbsMod && getLexer().peekTok().is(AsmToken::Pipe) &&
1716 (getLexer().getKind() == AsmToken::Integer ||
1717 getLexer().getKind() == AsmToken::Real)) {
1719 // This is a workaround for handling operands like these:
1722 // This syntax is not compatible with syntax of standard
1723 // MC expressions (due to the trailing '|').
1728 if (getParser().parsePrimaryExpr(Expr, EndLoc)) {
1732 return !Expr->evaluateAsAbsolute(Val);
1735 return getParser().parseAbsoluteExpression(Val);
1738 OperandMatchResultTy
1739 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool AbsMod) {
1740 // TODO: add syntactic sugar for 1/(2*PI)
1742 if (getLexer().getKind() == AsmToken::Minus) {
1747 SMLoc S = Parser.getTok().getLoc();
1748 switch(getLexer().getKind()) {
1749 case AsmToken::Integer: {
1751 if (parseAbsoluteExpr(IntVal, AbsMod))
1752 return MatchOperand_ParseFail;
1755 Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
1756 return MatchOperand_Success;
1758 case AsmToken::Real: {
1760 if (parseAbsoluteExpr(IntVal, AbsMod))
1761 return MatchOperand_ParseFail;
1763 APFloat F(BitsToDouble(IntVal));
1767 AMDGPUOperand::CreateImm(this, F.bitcastToAPInt().getZExtValue(), S,
1768 AMDGPUOperand::ImmTyNone, true));
1769 return MatchOperand_Success;
1772 return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1776 OperandMatchResultTy
1777 AMDGPUAsmParser::parseReg(OperandVector &Operands) {
1778 if (auto R = parseRegister()) {
1780 R->Reg.IsForcedVOP3 = isForcedVOP3();
1781 Operands.push_back(std::move(R));
1782 return MatchOperand_Success;
1784 return MatchOperand_NoMatch;
1787 OperandMatchResultTy
1788 AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool AbsMod) {
1789 auto res = parseImm(Operands, AbsMod);
1790 if (res != MatchOperand_NoMatch) {
1794 return parseReg(Operands);
1797 OperandMatchResultTy
1798 AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
1800 bool Negate = false, Negate2 = false, Abs = false, Abs2 = false;
1802 if (getLexer().getKind()== AsmToken::Minus) {
1803 const AsmToken NextToken = getLexer().peekTok();
1805 // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
1806 if (NextToken.is(AsmToken::Minus)) {
1807 Error(Parser.getTok().getLoc(), "invalid syntax, expected 'neg' modifier");
1808 return MatchOperand_ParseFail;
1811 // '-' followed by an integer literal N should be interpreted as integer
1812 // negation rather than a floating-point NEG modifier applied to N.
1813 // Beside being contr-intuitive, such use of floating-point NEG modifier
1814 // results in different meaning of integer literals used with VOP1/2/C
1815 // and VOP3, for example:
1816 // v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
1817 // v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
1818 // Negative fp literals should be handled likewise for unifomtity
1819 if (!NextToken.is(AsmToken::Integer) && !NextToken.is(AsmToken::Real)) {
1825 if (getLexer().getKind() == AsmToken::Identifier &&
1826 Parser.getTok().getString() == "neg") {
1828 Error(Parser.getTok().getLoc(), "expected register or immediate");
1829 return MatchOperand_ParseFail;
1833 if (getLexer().isNot(AsmToken::LParen)) {
1834 Error(Parser.getTok().getLoc(), "expected left paren after neg");
1835 return MatchOperand_ParseFail;
1840 if (getLexer().getKind() == AsmToken::Identifier &&
1841 Parser.getTok().getString() == "abs") {
1844 if (getLexer().isNot(AsmToken::LParen)) {
1845 Error(Parser.getTok().getLoc(), "expected left paren after abs");
1846 return MatchOperand_ParseFail;
1851 if (getLexer().getKind() == AsmToken::Pipe) {
1853 Error(Parser.getTok().getLoc(), "expected register or immediate");
1854 return MatchOperand_ParseFail;
1860 OperandMatchResultTy Res;
1862 Res = parseRegOrImm(Operands, Abs);
1864 Res = parseReg(Operands);
1866 if (Res != MatchOperand_Success) {
1870 AMDGPUOperand::Modifiers Mods;
1872 if (getLexer().getKind() != AsmToken::Pipe) {
1873 Error(Parser.getTok().getLoc(), "expected vertical bar");
1874 return MatchOperand_ParseFail;
1880 if (getLexer().isNot(AsmToken::RParen)) {
1881 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1882 return MatchOperand_ParseFail;
1890 } else if (Negate2) {
1891 if (getLexer().isNot(AsmToken::RParen)) {
1892 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1893 return MatchOperand_ParseFail;
1899 if (Mods.hasFPModifiers()) {
1900 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1901 Op.setModifiers(Mods);
1903 return MatchOperand_Success;
1906 OperandMatchResultTy
1907 AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
1911 if (getLexer().getKind() == AsmToken::Identifier &&
1912 Parser.getTok().getString() == "sext") {
1915 if (getLexer().isNot(AsmToken::LParen)) {
1916 Error(Parser.getTok().getLoc(), "expected left paren after sext");
1917 return MatchOperand_ParseFail;
1922 OperandMatchResultTy Res;
1924 Res = parseRegOrImm(Operands);
1926 Res = parseReg(Operands);
1928 if (Res != MatchOperand_Success) {
1932 AMDGPUOperand::Modifiers Mods;
1934 if (getLexer().isNot(AsmToken::RParen)) {
1935 Error(Parser.getTok().getLoc(), "expected closing parentheses");
1936 return MatchOperand_ParseFail;
1942 if (Mods.hasIntModifiers()) {
1943 AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1944 Op.setModifiers(Mods);
1947 return MatchOperand_Success;
1950 OperandMatchResultTy
1951 AMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
1952 return parseRegOrImmWithFPInputMods(Operands, false);
1955 OperandMatchResultTy
1956 AMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
1957 return parseRegOrImmWithIntInputMods(Operands, false);
1960 OperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
1961 std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
1963 Operands.push_back(std::move(Reg));
1964 return MatchOperand_Success;
1967 const AsmToken &Tok = Parser.getTok();
1968 if (Tok.getString() == "off") {
1969 Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Tok.getLoc(),
1970 AMDGPUOperand::ImmTyOff, false));
1972 return MatchOperand_Success;
1975 return MatchOperand_NoMatch;
1978 unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1979 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1981 if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1982 (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1983 (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1984 (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1985 return Match_InvalidOperand;
1987 if ((TSFlags & SIInstrFlags::VOP3) &&
1988 (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1989 getForcedEncodingSize() != 64)
1990 return Match_PreferE32;
1992 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
1993 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
1994 // v_mac_f32/16 allow only dst_sel == DWORD;
1996 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
1997 const auto &Op = Inst.getOperand(OpNum);
1998 if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
1999 return Match_InvalidOperand;
2003 if ((TSFlags & SIInstrFlags::FLAT) && !hasFlatOffsets()) {
2004 // FIXME: Produces error without correct column reported.
2006 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::offset);
2007 const auto &Op = Inst.getOperand(OpNum);
2008 if (Op.getImm() != 0)
2009 return Match_InvalidOperand;
2012 return Match_Success;
2015 // What asm variants we should check
2016 ArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2017 if (getForcedEncodingSize() == 32) {
2018 static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2019 return makeArrayRef(Variants);
2022 if (isForcedVOP3()) {
2023 static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2024 return makeArrayRef(Variants);
2027 if (isForcedSDWA()) {
2028 static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2029 AMDGPUAsmVariants::SDWA9};
2030 return makeArrayRef(Variants);
2033 if (isForcedDPP()) {
2034 static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2035 return makeArrayRef(Variants);
2038 static const unsigned Variants[] = {
2039 AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2040 AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2043 return makeArrayRef(Variants);
2046 unsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2047 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2048 const unsigned Num = Desc.getNumImplicitUses();
2049 for (unsigned i = 0; i < Num; ++i) {
2050 unsigned Reg = Desc.ImplicitUses[i];
2052 case AMDGPU::FLAT_SCR:
2060 return AMDGPU::NoRegister;
2063 // NB: This code is correct only when used to check constant
2064 // bus limitations because GFX7 support no f16 inline constants.
2065 // Note that there are no cases when a GFX7 opcode violates
2066 // constant bus limitations due to the use of an f16 constant.
2067 bool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2068 unsigned OpIdx) const {
2069 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2071 if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2075 const MCOperand &MO = Inst.getOperand(OpIdx);
2077 int64_t Val = MO.getImm();
2078 auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2080 switch (OpSize) { // expected operand size
2082 return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2084 return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2086 const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2087 if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2088 OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16) {
2089 return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2091 return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2095 llvm_unreachable("invalid operand size");
2099 bool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2100 const MCOperand &MO = Inst.getOperand(OpIdx);
2102 return !isInlineConstant(Inst, OpIdx);
2104 return !MO.isReg() ||
2105 isSGPR(mc2PseudoReg(MO.getReg()), getContext().getRegisterInfo());
2108 bool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
2109 const unsigned Opcode = Inst.getOpcode();
2110 const MCInstrDesc &Desc = MII.get(Opcode);
2111 unsigned ConstantBusUseCount = 0;
2114 (SIInstrFlags::VOPC |
2115 SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
2116 SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2117 SIInstrFlags::SDWA)) {
2119 // Check special imm operands (used by madmk, etc)
2120 if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2121 ++ConstantBusUseCount;
2124 unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2125 if (SGPRUsed != AMDGPU::NoRegister) {
2126 ++ConstantBusUseCount;
2129 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2130 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2131 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2133 const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2135 for (int OpIdx : OpIndices) {
2136 if (OpIdx == -1) break;
2138 const MCOperand &MO = Inst.getOperand(OpIdx);
2139 if (usesConstantBus(Inst, OpIdx)) {
2141 const unsigned Reg = mc2PseudoReg(MO.getReg());
2142 // Pairs of registers with a partial intersections like these
2144 // flat_scratch_lo, flat_scratch
2145 // flat_scratch_lo, flat_scratch_hi
2146 // are theoretically valid but they are disabled anyway.
2147 // Note that this code mimics SIInstrInfo::verifyInstruction
2148 if (Reg != SGPRUsed) {
2149 ++ConstantBusUseCount;
2152 } else { // Expression or a literal
2153 ++ConstantBusUseCount;
2159 return ConstantBusUseCount <= 1;
2162 bool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
2164 const unsigned Opcode = Inst.getOpcode();
2165 const MCInstrDesc &Desc = MII.get(Opcode);
2167 const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2169 Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2173 const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2175 const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2176 const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2177 const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2179 assert(DstIdx != -1);
2180 const MCOperand &Dst = Inst.getOperand(DstIdx);
2181 assert(Dst.isReg());
2182 const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2184 const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2186 for (int SrcIdx : SrcIndices) {
2187 if (SrcIdx == -1) break;
2188 const MCOperand &Src = Inst.getOperand(SrcIdx);
2190 const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2191 if (isRegIntersect(DstReg, SrcReg, TRI)) {
2200 bool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
2201 const SMLoc &IDLoc) {
2202 if (!validateConstantBusLimitations(Inst)) {
2204 "invalid operand (violates constant bus restrictions)");
2207 if (!validateEarlyClobberLimitations(Inst)) {
2209 "destination must be different than all sources");
2216 bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
2217 OperandVector &Operands,
2219 uint64_t &ErrorInfo,
2220 bool MatchingInlineAsm) {
2222 unsigned Result = Match_Success;
2223 for (auto Variant : getMatchedVariants()) {
2225 auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
2227 // We order match statuses from least to most specific. We use most specific
2228 // status as resulting
2229 // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
2230 if ((R == Match_Success) ||
2231 (R == Match_PreferE32) ||
2232 (R == Match_MissingFeature && Result != Match_PreferE32) ||
2233 (R == Match_InvalidOperand && Result != Match_MissingFeature
2234 && Result != Match_PreferE32) ||
2235 (R == Match_MnemonicFail && Result != Match_InvalidOperand
2236 && Result != Match_MissingFeature
2237 && Result != Match_PreferE32)) {
2241 if (R == Match_Success)
2248 if (!validateInstruction(Inst, IDLoc)) {
2252 Out.EmitInstruction(Inst, getSTI());
2255 case Match_MissingFeature:
2256 return Error(IDLoc, "instruction not supported on this GPU");
2258 case Match_MnemonicFail:
2259 return Error(IDLoc, "unrecognized instruction mnemonic");
2261 case Match_InvalidOperand: {
2262 SMLoc ErrorLoc = IDLoc;
2263 if (ErrorInfo != ~0ULL) {
2264 if (ErrorInfo >= Operands.size()) {
2265 return Error(IDLoc, "too few operands for instruction");
2267 ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
2268 if (ErrorLoc == SMLoc())
2271 return Error(ErrorLoc, "invalid operand for instruction");
2274 case Match_PreferE32:
2275 return Error(IDLoc, "internal error: instruction without _e64 suffix "
2276 "should be encoded as e32");
2278 llvm_unreachable("Implement any new match types added!");
2281 bool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
2283 if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
2286 if (getParser().parseAbsoluteExpression(Tmp)) {
2289 Ret = static_cast<uint32_t>(Tmp);
2293 bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
2295 if (ParseAsAbsoluteExpression(Major))
2296 return TokError("invalid major version");
2298 if (getLexer().isNot(AsmToken::Comma))
2299 return TokError("minor version number required, comma expected");
2302 if (ParseAsAbsoluteExpression(Minor))
2303 return TokError("invalid minor version");
2308 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
2312 if (ParseDirectiveMajorMinor(Major, Minor))
2315 getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
2319 bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
2323 StringRef VendorName;
2326 // If this directive has no arguments, then use the ISA version for the
2328 if (getLexer().is(AsmToken::EndOfStatement)) {
2329 AMDGPU::IsaInfo::IsaVersion ISA =
2330 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2331 getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
2337 if (ParseDirectiveMajorMinor(Major, Minor))
2340 if (getLexer().isNot(AsmToken::Comma))
2341 return TokError("stepping version number required, comma expected");
2344 if (ParseAsAbsoluteExpression(Stepping))
2345 return TokError("invalid stepping version");
2347 if (getLexer().isNot(AsmToken::Comma))
2348 return TokError("vendor name required, comma expected");
2351 if (getLexer().isNot(AsmToken::String))
2352 return TokError("invalid vendor name");
2354 VendorName = getLexer().getTok().getStringContents();
2357 if (getLexer().isNot(AsmToken::Comma))
2358 return TokError("arch name required, comma expected");
2361 if (getLexer().isNot(AsmToken::String))
2362 return TokError("invalid arch name");
2364 ArchName = getLexer().getTok().getStringContents();
2367 getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
2368 VendorName, ArchName);
2372 bool AMDGPUAsmParser::ParseDirectiveCodeObjectMetadata() {
2373 std::string YamlString;
2374 raw_string_ostream YamlStream(YamlString);
2376 getLexer().setSkipSpace(false);
2378 bool FoundEnd = false;
2379 while (!getLexer().is(AsmToken::Eof)) {
2380 while (getLexer().is(AsmToken::Space)) {
2381 YamlStream << getLexer().getTok().getString();
2385 if (getLexer().is(AsmToken::Identifier)) {
2386 StringRef ID = getLexer().getTok().getIdentifier();
2387 if (ID == AMDGPU::CodeObject::MetadataAssemblerDirectiveEnd) {
2394 YamlStream << Parser.parseStringToEndOfStatement()
2395 << getContext().getAsmInfo()->getSeparatorString();
2397 Parser.eatToEndOfStatement();
2400 getLexer().setSkipSpace(true);
2402 if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
2404 "expected directive .end_amdgpu_code_object_metadata not found");
2409 if (!getTargetStreamer().EmitCodeObjectMetadata(YamlString))
2410 return Error(getParser().getTok().getLoc(), "invalid code object metadata");
2415 bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
2416 amd_kernel_code_t &Header) {
2417 SmallString<40> ErrStr;
2418 raw_svector_ostream Err(ErrStr);
2419 if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
2420 return TokError(Err.str());
2426 bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
2427 amd_kernel_code_t Header;
2428 AMDGPU::initDefaultAMDKernelCodeT(Header, getFeatureBits());
2431 // Lex EndOfStatement. This is in a while loop, because lexing a comment
2432 // will set the current token to EndOfStatement.
2433 while(getLexer().is(AsmToken::EndOfStatement))
2436 if (getLexer().isNot(AsmToken::Identifier))
2437 return TokError("expected value identifier or .end_amd_kernel_code_t");
2439 StringRef ID = getLexer().getTok().getIdentifier();
2442 if (ID == ".end_amd_kernel_code_t")
2445 if (ParseAMDKernelCodeTValue(ID, Header))
2449 getTargetStreamer().EmitAMDKernelCodeT(Header);
2454 bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
2455 if (getLexer().isNot(AsmToken::Identifier))
2456 return TokError("expected symbol name");
2458 StringRef KernelName = Parser.getTok().getString();
2460 getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
2461 ELF::STT_AMDGPU_HSA_KERNEL);
2463 KernelScope.initialize(getContext());
2467 bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
2468 StringRef IDVal = DirectiveID.getString();
2470 if (IDVal == ".hsa_code_object_version")
2471 return ParseDirectiveHSACodeObjectVersion();
2473 if (IDVal == ".hsa_code_object_isa")
2474 return ParseDirectiveHSACodeObjectISA();
2476 if (IDVal == AMDGPU::CodeObject::MetadataAssemblerDirectiveBegin)
2477 return ParseDirectiveCodeObjectMetadata();
2479 if (IDVal == ".amd_kernel_code_t")
2480 return ParseDirectiveAMDKernelCodeT();
2482 if (IDVal == ".amdgpu_hsa_kernel")
2483 return ParseDirectiveAMDGPUHsaKernel();
2488 bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
2489 unsigned RegNo) const {
2496 case AMDGPU::FLAT_SCR:
2497 case AMDGPU::FLAT_SCR_LO:
2498 case AMDGPU::FLAT_SCR_HI:
2505 // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
2507 for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
2516 OperandMatchResultTy
2517 AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
2518 // Try to parse with a custom parser
2519 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
2521 // If we successfully parsed the operand or if there as an error parsing,
2524 // If we are parsing after we reach EndOfStatement then this means we
2525 // are appending default values to the Operands list. This is only done
2526 // by custom parser, so we shouldn't continue on to the generic parsing.
2527 if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
2528 getLexer().is(AsmToken::EndOfStatement))
2531 ResTy = parseRegOrImm(Operands);
2533 if (ResTy == MatchOperand_Success)
2536 if (getLexer().getKind() == AsmToken::Identifier) {
2537 // If this identifier is a symbol, we want to create an expression for it.
2538 // It is a little difficult to distinguish between a symbol name, and
2539 // an instruction flag like 'gds'. In order to do this, we parse
2540 // all tokens as expressions and then treate the symbol name as the token
2541 // string when we want to interpret the operand as a token.
2542 const auto &Tok = Parser.getTok();
2543 SMLoc S = Tok.getLoc();
2544 const MCExpr *Expr = nullptr;
2545 if (!Parser.parseExpression(Expr)) {
2546 Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2547 return MatchOperand_Success;
2550 Operands.push_back(AMDGPUOperand::CreateToken(this, Tok.getString(), Tok.getLoc()));
2552 return MatchOperand_Success;
2554 return MatchOperand_NoMatch;
2557 StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
2558 // Clear any forced encodings from the previous instruction.
2559 setForcedEncodingSize(0);
2560 setForcedDPP(false);
2561 setForcedSDWA(false);
2563 if (Name.endswith("_e64")) {
2564 setForcedEncodingSize(64);
2565 return Name.substr(0, Name.size() - 4);
2566 } else if (Name.endswith("_e32")) {
2567 setForcedEncodingSize(32);
2568 return Name.substr(0, Name.size() - 4);
2569 } else if (Name.endswith("_dpp")) {
2571 return Name.substr(0, Name.size() - 4);
2572 } else if (Name.endswith("_sdwa")) {
2573 setForcedSDWA(true);
2574 return Name.substr(0, Name.size() - 5);
2579 bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
2581 SMLoc NameLoc, OperandVector &Operands) {
2582 // Add the instruction mnemonic
2583 Name = parseMnemonicSuffix(Name);
2584 Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
2586 while (!getLexer().is(AsmToken::EndOfStatement)) {
2587 OperandMatchResultTy Res = parseOperand(Operands, Name);
2589 // Eat the comma or space if there is one.
2590 if (getLexer().is(AsmToken::Comma))
2594 case MatchOperand_Success: break;
2595 case MatchOperand_ParseFail:
2596 Error(getLexer().getLoc(), "failed parsing operand.");
2597 while (!getLexer().is(AsmToken::EndOfStatement)) {
2601 case MatchOperand_NoMatch:
2602 Error(getLexer().getLoc(), "not a valid operand.");
2603 while (!getLexer().is(AsmToken::EndOfStatement)) {
2613 //===----------------------------------------------------------------------===//
2614 // Utility functions
2615 //===----------------------------------------------------------------------===//
2617 OperandMatchResultTy
2618 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
2619 switch(getLexer().getKind()) {
2620 default: return MatchOperand_NoMatch;
2621 case AsmToken::Identifier: {
2622 StringRef Name = Parser.getTok().getString();
2623 if (!Name.equals(Prefix)) {
2624 return MatchOperand_NoMatch;
2628 if (getLexer().isNot(AsmToken::Colon))
2629 return MatchOperand_ParseFail;
2633 bool IsMinus = false;
2634 if (getLexer().getKind() == AsmToken::Minus) {
2639 if (getLexer().isNot(AsmToken::Integer))
2640 return MatchOperand_ParseFail;
2642 if (getParser().parseAbsoluteExpression(Int))
2643 return MatchOperand_ParseFail;
2650 return MatchOperand_Success;
2653 OperandMatchResultTy
2654 AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
2655 AMDGPUOperand::ImmTy ImmTy,
2656 bool (*ConvertResult)(int64_t&)) {
2657 SMLoc S = Parser.getTok().getLoc();
2660 OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
2661 if (Res != MatchOperand_Success)
2664 if (ConvertResult && !ConvertResult(Value)) {
2665 return MatchOperand_ParseFail;
2668 Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
2669 return MatchOperand_Success;
2672 OperandMatchResultTy AMDGPUAsmParser::parseOperandArrayWithPrefix(
2674 OperandVector &Operands,
2675 AMDGPUOperand::ImmTy ImmTy,
2676 bool (*ConvertResult)(int64_t&)) {
2677 StringRef Name = Parser.getTok().getString();
2678 if (!Name.equals(Prefix))
2679 return MatchOperand_NoMatch;
2682 if (getLexer().isNot(AsmToken::Colon))
2683 return MatchOperand_ParseFail;
2686 if (getLexer().isNot(AsmToken::LBrac))
2687 return MatchOperand_ParseFail;
2691 SMLoc S = Parser.getTok().getLoc();
2693 // FIXME: How to verify the number of elements matches the number of src
2695 for (int I = 0; I < 3; ++I) {
2697 if (getLexer().is(AsmToken::RBrac))
2700 if (getLexer().isNot(AsmToken::Comma))
2701 return MatchOperand_ParseFail;
2705 if (getLexer().isNot(AsmToken::Integer))
2706 return MatchOperand_ParseFail;
2709 if (getParser().parseAbsoluteExpression(Op))
2710 return MatchOperand_ParseFail;
2712 if (Op != 0 && Op != 1)
2713 return MatchOperand_ParseFail;
2718 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
2719 return MatchOperand_Success;
2722 OperandMatchResultTy
2723 AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
2724 AMDGPUOperand::ImmTy ImmTy) {
2726 SMLoc S = Parser.getTok().getLoc();
2728 // We are at the end of the statement, and this is a default argument, so
2729 // use a default value.
2730 if (getLexer().isNot(AsmToken::EndOfStatement)) {
2731 switch(getLexer().getKind()) {
2732 case AsmToken::Identifier: {
2733 StringRef Tok = Parser.getTok().getString();
2737 } else if (Tok.startswith("no") && Tok.endswith(Name)) {
2741 return MatchOperand_NoMatch;
2746 return MatchOperand_NoMatch;
2750 Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
2751 return MatchOperand_Success;
2754 static void addOptionalImmOperand(
2755 MCInst& Inst, const OperandVector& Operands,
2756 AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
2757 AMDGPUOperand::ImmTy ImmT,
2758 int64_t Default = 0) {
2759 auto i = OptionalIdx.find(ImmT);
2760 if (i != OptionalIdx.end()) {
2761 unsigned Idx = i->second;
2762 ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
2764 Inst.addOperand(MCOperand::createImm(Default));
2768 OperandMatchResultTy
2769 AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
2770 if (getLexer().isNot(AsmToken::Identifier)) {
2771 return MatchOperand_NoMatch;
2773 StringRef Tok = Parser.getTok().getString();
2774 if (Tok != Prefix) {
2775 return MatchOperand_NoMatch;
2779 if (getLexer().isNot(AsmToken::Colon)) {
2780 return MatchOperand_ParseFail;
2784 if (getLexer().isNot(AsmToken::Identifier)) {
2785 return MatchOperand_ParseFail;
2788 Value = Parser.getTok().getString();
2789 return MatchOperand_Success;
2792 //===----------------------------------------------------------------------===//
2794 //===----------------------------------------------------------------------===//
2796 void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
2797 const OperandVector &Operands) {
2798 OptionalImmIndexMap OptionalIdx;
2800 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2801 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2803 // Add the register arguments
2805 Op.addRegOperands(Inst, 1);
2809 // Handle optional arguments
2810 OptionalIdx[Op.getImmTy()] = i;
2813 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
2814 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
2815 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2817 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2820 void AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
2821 bool IsGdsHardcoded) {
2822 OptionalImmIndexMap OptionalIdx;
2824 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2825 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2827 // Add the register arguments
2829 Op.addRegOperands(Inst, 1);
2833 if (Op.isToken() && Op.getToken() == "gds") {
2834 IsGdsHardcoded = true;
2838 // Handle optional arguments
2839 OptionalIdx[Op.getImmTy()] = i;
2842 AMDGPUOperand::ImmTy OffsetType =
2843 (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_si ||
2844 Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
2845 AMDGPUOperand::ImmTyOffset;
2847 addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
2849 if (!IsGdsHardcoded) {
2850 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
2852 Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
2855 void AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
2856 OptionalImmIndexMap OptionalIdx;
2858 unsigned OperandIdx[4];
2859 unsigned EnMask = 0;
2862 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2863 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2865 // Add the register arguments
2868 OperandIdx[SrcIdx] = Inst.size();
2869 Op.addRegOperands(Inst, 1);
2876 OperandIdx[SrcIdx] = Inst.size();
2877 Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
2882 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
2883 Op.addImmOperands(Inst, 1);
2887 if (Op.isToken() && Op.getToken() == "done")
2890 // Handle optional arguments
2891 OptionalIdx[Op.getImmTy()] = i;
2894 assert(SrcIdx == 4);
2897 if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
2899 Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
2900 Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
2901 Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
2904 for (auto i = 0; i < SrcIdx; ++i) {
2905 if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
2906 EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
2910 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
2911 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
2913 Inst.addOperand(MCOperand::createImm(EnMask));
2916 //===----------------------------------------------------------------------===//
2918 //===----------------------------------------------------------------------===//
2922 const AMDGPU::IsaInfo::IsaVersion ISA,
2926 unsigned (*encode)(const IsaInfo::IsaVersion &Version, unsigned, unsigned),
2927 unsigned (*decode)(const IsaInfo::IsaVersion &Version, unsigned))
2929 bool Failed = false;
2931 IntVal = encode(ISA, IntVal, CntVal);
2932 if (CntVal != decode(ISA, IntVal)) {
2934 IntVal = encode(ISA, IntVal, -1);
2942 bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
2943 StringRef CntName = Parser.getTok().getString();
2947 if (getLexer().isNot(AsmToken::LParen))
2951 if (getLexer().isNot(AsmToken::Integer))
2954 SMLoc ValLoc = Parser.getTok().getLoc();
2955 if (getParser().parseAbsoluteExpression(CntVal))
2958 AMDGPU::IsaInfo::IsaVersion ISA =
2959 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2962 bool Sat = CntName.endswith("_sat");
2964 if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
2965 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
2966 } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
2967 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
2968 } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
2969 Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
2973 Error(ValLoc, "too large value for " + CntName);
2977 if (getLexer().isNot(AsmToken::RParen)) {
2982 if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma)) {
2983 const AsmToken NextToken = getLexer().peekTok();
2984 if (NextToken.is(AsmToken::Identifier)) {
2992 OperandMatchResultTy
2993 AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
2994 AMDGPU::IsaInfo::IsaVersion ISA =
2995 AMDGPU::IsaInfo::getIsaVersion(getFeatureBits());
2996 int64_t Waitcnt = getWaitcntBitMask(ISA);
2997 SMLoc S = Parser.getTok().getLoc();
2999 switch(getLexer().getKind()) {
3000 default: return MatchOperand_ParseFail;
3001 case AsmToken::Integer:
3002 // The operand can be an integer value.
3003 if (getParser().parseAbsoluteExpression(Waitcnt))
3004 return MatchOperand_ParseFail;
3007 case AsmToken::Identifier:
3009 if (parseCnt(Waitcnt))
3010 return MatchOperand_ParseFail;
3011 } while(getLexer().isNot(AsmToken::EndOfStatement));
3014 Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
3015 return MatchOperand_Success;
3018 bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset,
3020 using namespace llvm::AMDGPU::Hwreg;
3022 if (Parser.getTok().getString() != "hwreg")
3026 if (getLexer().isNot(AsmToken::LParen))
3030 if (getLexer().is(AsmToken::Identifier)) {
3031 HwReg.IsSymbolic = true;
3032 HwReg.Id = ID_UNKNOWN_;
3033 const StringRef tok = Parser.getTok().getString();
3034 for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
3035 if (tok == IdSymbolic[i]) {
3042 HwReg.IsSymbolic = false;
3043 if (getLexer().isNot(AsmToken::Integer))
3045 if (getParser().parseAbsoluteExpression(HwReg.Id))
3049 if (getLexer().is(AsmToken::RParen)) {
3055 if (getLexer().isNot(AsmToken::Comma))
3059 if (getLexer().isNot(AsmToken::Integer))
3061 if (getParser().parseAbsoluteExpression(Offset))
3064 if (getLexer().isNot(AsmToken::Comma))
3068 if (getLexer().isNot(AsmToken::Integer))
3070 if (getParser().parseAbsoluteExpression(Width))
3073 if (getLexer().isNot(AsmToken::RParen))
3080 OperandMatchResultTy AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
3081 using namespace llvm::AMDGPU::Hwreg;
3083 int64_t Imm16Val = 0;
3084 SMLoc S = Parser.getTok().getLoc();
3086 switch(getLexer().getKind()) {
3087 default: return MatchOperand_NoMatch;
3088 case AsmToken::Integer:
3089 // The operand can be an integer value.
3090 if (getParser().parseAbsoluteExpression(Imm16Val))
3091 return MatchOperand_NoMatch;
3092 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3093 Error(S, "invalid immediate: only 16-bit values are legal");
3094 // Do not return error code, but create an imm operand anyway and proceed
3095 // to the next operand, if any. That avoids unneccessary error messages.
3099 case AsmToken::Identifier: {
3100 OperandInfoTy HwReg(ID_UNKNOWN_);
3101 int64_t Offset = OFFSET_DEFAULT_;
3102 int64_t Width = WIDTH_M1_DEFAULT_ + 1;
3103 if (parseHwregConstruct(HwReg, Offset, Width))
3104 return MatchOperand_ParseFail;
3105 if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
3106 if (HwReg.IsSymbolic)
3107 Error(S, "invalid symbolic name of hardware register");
3109 Error(S, "invalid code of hardware register: only 6-bit values are legal");
3111 if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
3112 Error(S, "invalid bit offset: only 5-bit values are legal");
3113 if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
3114 Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
3115 Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
3119 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
3120 return MatchOperand_Success;
3123 bool AMDGPUOperand::isSWaitCnt() const {
3127 bool AMDGPUOperand::isHwreg() const {
3128 return isImmTy(ImmTyHwreg);
3131 bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
3132 using namespace llvm::AMDGPU::SendMsg;
3134 if (Parser.getTok().getString() != "sendmsg")
3138 if (getLexer().isNot(AsmToken::LParen))
3142 if (getLexer().is(AsmToken::Identifier)) {
3143 Msg.IsSymbolic = true;
3144 Msg.Id = ID_UNKNOWN_;
3145 const std::string tok = Parser.getTok().getString();
3146 for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
3148 default: continue; // Omit gaps.
3149 case ID_INTERRUPT: case ID_GS: case ID_GS_DONE: case ID_SYSMSG: break;
3151 if (tok == IdSymbolic[i]) {
3158 Msg.IsSymbolic = false;
3159 if (getLexer().isNot(AsmToken::Integer))
3161 if (getParser().parseAbsoluteExpression(Msg.Id))
3163 if (getLexer().is(AsmToken::Integer))
3164 if (getParser().parseAbsoluteExpression(Msg.Id))
3165 Msg.Id = ID_UNKNOWN_;
3167 if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
3170 if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
3171 if (getLexer().isNot(AsmToken::RParen))
3177 if (getLexer().isNot(AsmToken::Comma))
3181 assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
3182 Operation.Id = ID_UNKNOWN_;
3183 if (getLexer().is(AsmToken::Identifier)) {
3184 Operation.IsSymbolic = true;
3185 const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
3186 const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
3187 const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
3188 const StringRef Tok = Parser.getTok().getString();
3189 for (int i = F; i < L; ++i) {
3197 Operation.IsSymbolic = false;
3198 if (getLexer().isNot(AsmToken::Integer))
3200 if (getParser().parseAbsoluteExpression(Operation.Id))
3204 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3205 // Stream id is optional.
3206 if (getLexer().is(AsmToken::RParen)) {
3211 if (getLexer().isNot(AsmToken::Comma))
3215 if (getLexer().isNot(AsmToken::Integer))
3217 if (getParser().parseAbsoluteExpression(StreamId))
3221 if (getLexer().isNot(AsmToken::RParen))
3227 OperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
3228 if (getLexer().getKind() != AsmToken::Identifier)
3229 return MatchOperand_NoMatch;
3231 StringRef Str = Parser.getTok().getString();
3232 int Slot = StringSwitch<int>(Str)
3238 SMLoc S = Parser.getTok().getLoc();
3240 return MatchOperand_ParseFail;
3243 Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
3244 AMDGPUOperand::ImmTyInterpSlot));
3245 return MatchOperand_Success;
3248 OperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
3249 if (getLexer().getKind() != AsmToken::Identifier)
3250 return MatchOperand_NoMatch;
3252 StringRef Str = Parser.getTok().getString();
3253 if (!Str.startswith("attr"))
3254 return MatchOperand_NoMatch;
3256 StringRef Chan = Str.take_back(2);
3257 int AttrChan = StringSwitch<int>(Chan)
3264 return MatchOperand_ParseFail;
3266 Str = Str.drop_back(2).drop_front(4);
3269 if (Str.getAsInteger(10, Attr))
3270 return MatchOperand_ParseFail;
3272 SMLoc S = Parser.getTok().getLoc();
3275 Error(S, "out of bounds attr");
3276 return MatchOperand_Success;
3279 SMLoc SChan = SMLoc::getFromPointer(Chan.data());
3281 Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
3282 AMDGPUOperand::ImmTyInterpAttr));
3283 Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
3284 AMDGPUOperand::ImmTyAttrChan));
3285 return MatchOperand_Success;
3288 void AMDGPUAsmParser::errorExpTgt() {
3289 Error(Parser.getTok().getLoc(), "invalid exp target");
3292 OperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
3294 if (Str == "null") {
3296 return MatchOperand_Success;
3299 if (Str.startswith("mrt")) {
3300 Str = Str.drop_front(3);
3301 if (Str == "z") { // == mrtz
3303 return MatchOperand_Success;
3306 if (Str.getAsInteger(10, Val))
3307 return MatchOperand_ParseFail;
3312 return MatchOperand_Success;
3315 if (Str.startswith("pos")) {
3316 Str = Str.drop_front(3);
3317 if (Str.getAsInteger(10, Val))
3318 return MatchOperand_ParseFail;
3324 return MatchOperand_Success;
3327 if (Str.startswith("param")) {
3328 Str = Str.drop_front(5);
3329 if (Str.getAsInteger(10, Val))
3330 return MatchOperand_ParseFail;
3336 return MatchOperand_Success;
3339 if (Str.startswith("invalid_target_")) {
3340 Str = Str.drop_front(15);
3341 if (Str.getAsInteger(10, Val))
3342 return MatchOperand_ParseFail;
3345 return MatchOperand_Success;
3348 return MatchOperand_NoMatch;
3351 OperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
3353 StringRef Str = Parser.getTok().getString();
3355 auto Res = parseExpTgtImpl(Str, Val);
3356 if (Res != MatchOperand_Success)
3359 SMLoc S = Parser.getTok().getLoc();
3362 Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
3363 AMDGPUOperand::ImmTyExpTgt));
3364 return MatchOperand_Success;
3367 OperandMatchResultTy
3368 AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
3369 using namespace llvm::AMDGPU::SendMsg;
3371 int64_t Imm16Val = 0;
3372 SMLoc S = Parser.getTok().getLoc();
3374 switch(getLexer().getKind()) {
3376 return MatchOperand_NoMatch;
3377 case AsmToken::Integer:
3378 // The operand can be an integer value.
3379 if (getParser().parseAbsoluteExpression(Imm16Val))
3380 return MatchOperand_NoMatch;
3381 if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
3382 Error(S, "invalid immediate: only 16-bit values are legal");
3383 // Do not return error code, but create an imm operand anyway and proceed
3384 // to the next operand, if any. That avoids unneccessary error messages.
3387 case AsmToken::Identifier: {
3388 OperandInfoTy Msg(ID_UNKNOWN_);
3389 OperandInfoTy Operation(OP_UNKNOWN_);
3390 int64_t StreamId = STREAM_ID_DEFAULT_;
3391 if (parseSendMsgConstruct(Msg, Operation, StreamId))
3392 return MatchOperand_ParseFail;
3394 // Validate and encode message ID.
3395 if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
3396 || Msg.Id == ID_SYSMSG)) {
3398 Error(S, "invalid/unsupported symbolic name of message");
3400 Error(S, "invalid/unsupported code of message");
3403 Imm16Val = (Msg.Id << ID_SHIFT_);
3404 // Validate and encode operation ID.
3405 if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
3406 if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
3407 if (Operation.IsSymbolic)
3408 Error(S, "invalid symbolic name of GS_OP");
3410 Error(S, "invalid code of GS_OP: only 2-bit values are legal");
3413 if (Operation.Id == OP_GS_NOP
3414 && Msg.Id != ID_GS_DONE) {
3415 Error(S, "invalid GS_OP: NOP is for GS_DONE only");
3418 Imm16Val |= (Operation.Id << OP_SHIFT_);
3420 if (Msg.Id == ID_SYSMSG) {
3421 if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
3422 if (Operation.IsSymbolic)
3423 Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
3425 Error(S, "invalid/unsupported code of SYSMSG_OP");
3428 Imm16Val |= (Operation.Id << OP_SHIFT_);
3430 // Validate and encode stream ID.
3431 if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
3432 if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
3433 Error(S, "invalid stream id: only 2-bit values are legal");
3436 Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
3442 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
3443 return MatchOperand_Success;
3446 bool AMDGPUOperand::isSendMsg() const {
3447 return isImmTy(ImmTySendMsg);
3450 //===----------------------------------------------------------------------===//
3452 //===----------------------------------------------------------------------===//
3455 AMDGPUAsmParser::trySkipId(const StringRef Id) {
3456 if (getLexer().getKind() == AsmToken::Identifier &&
3457 Parser.getTok().getString() == Id) {
3465 AMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
3466 if (getLexer().getKind() == Kind) {
3474 AMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
3475 const StringRef ErrMsg) {
3476 if (!trySkipToken(Kind)) {
3477 Error(Parser.getTok().getLoc(), ErrMsg);
3484 AMDGPUAsmParser::parseExpr(int64_t &Imm) {
3485 return !getParser().parseAbsoluteExpression(Imm);
3489 AMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
3490 SMLoc S = Parser.getTok().getLoc();
3491 if (getLexer().getKind() == AsmToken::String) {
3492 Val = Parser.getTok().getStringContents();
3501 //===----------------------------------------------------------------------===//
3503 //===----------------------------------------------------------------------===//
3507 encodeBitmaskPerm(const unsigned AndMask,
3508 const unsigned OrMask,
3509 const unsigned XorMask) {
3510 using namespace llvm::AMDGPU::Swizzle;
3512 return BITMASK_PERM_ENC |
3513 (AndMask << BITMASK_AND_SHIFT) |
3514 (OrMask << BITMASK_OR_SHIFT) |
3515 (XorMask << BITMASK_XOR_SHIFT);
3519 AMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
3520 const unsigned MinVal,
3521 const unsigned MaxVal,
3522 const StringRef ErrMsg) {
3523 for (unsigned i = 0; i < OpNum; ++i) {
3524 if (!skipToken(AsmToken::Comma, "expected a comma")){
3527 SMLoc ExprLoc = Parser.getTok().getLoc();
3528 if (!parseExpr(Op[i])) {
3531 if (Op[i] < MinVal || Op[i] > MaxVal) {
3532 Error(ExprLoc, ErrMsg);
3541 AMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
3542 using namespace llvm::AMDGPU::Swizzle;
3544 int64_t Lane[LANE_NUM];
3545 if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
3546 "expected a 2-bit lane id")) {
3547 Imm = QUAD_PERM_ENC;
3548 for (auto i = 0; i < LANE_NUM; ++i) {
3549 Imm |= Lane[i] << (LANE_SHIFT * i);
3557 AMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
3558 using namespace llvm::AMDGPU::Swizzle;
3560 SMLoc S = Parser.getTok().getLoc();
3564 if (!parseSwizzleOperands(1, &GroupSize,
3566 "group size must be in the interval [2,32]")) {
3569 if (!isPowerOf2_64(GroupSize)) {
3570 Error(S, "group size must be a power of two");
3573 if (parseSwizzleOperands(1, &LaneIdx,
3575 "lane id must be in the interval [0,group size - 1]")) {
3576 Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
3583 AMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
3584 using namespace llvm::AMDGPU::Swizzle;
3586 SMLoc S = Parser.getTok().getLoc();
3589 if (!parseSwizzleOperands(1, &GroupSize,
3590 2, 32, "group size must be in the interval [2,32]")) {
3593 if (!isPowerOf2_64(GroupSize)) {
3594 Error(S, "group size must be a power of two");
3598 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
3603 AMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
3604 using namespace llvm::AMDGPU::Swizzle;
3606 SMLoc S = Parser.getTok().getLoc();
3609 if (!parseSwizzleOperands(1, &GroupSize,
3610 1, 16, "group size must be in the interval [1,16]")) {
3613 if (!isPowerOf2_64(GroupSize)) {
3614 Error(S, "group size must be a power of two");
3618 Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
3623 AMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
3624 using namespace llvm::AMDGPU::Swizzle;
3626 if (!skipToken(AsmToken::Comma, "expected a comma")) {
3631 SMLoc StrLoc = Parser.getTok().getLoc();
3632 if (!parseString(Ctl)) {
3635 if (Ctl.size() != BITMASK_WIDTH) {
3636 Error(StrLoc, "expected a 5-character mask");
3640 unsigned AndMask = 0;
3641 unsigned OrMask = 0;
3642 unsigned XorMask = 0;
3644 for (size_t i = 0; i < Ctl.size(); ++i) {
3645 unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
3648 Error(StrLoc, "invalid mask");
3665 Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
3670 AMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
3672 SMLoc OffsetLoc = Parser.getTok().getLoc();
3674 if (!parseExpr(Imm)) {
3677 if (!isUInt<16>(Imm)) {
3678 Error(OffsetLoc, "expected a 16-bit offset");
3685 AMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
3686 using namespace llvm::AMDGPU::Swizzle;
3688 if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
3690 SMLoc ModeLoc = Parser.getTok().getLoc();
3693 if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
3694 Ok = parseSwizzleQuadPerm(Imm);
3695 } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
3696 Ok = parseSwizzleBitmaskPerm(Imm);
3697 } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
3698 Ok = parseSwizzleBroadcast(Imm);
3699 } else if (trySkipId(IdSymbolic[ID_SWAP])) {
3700 Ok = parseSwizzleSwap(Imm);
3701 } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
3702 Ok = parseSwizzleReverse(Imm);
3704 Error(ModeLoc, "expected a swizzle mode");
3707 return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
3713 OperandMatchResultTy
3714 AMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
3715 SMLoc S = Parser.getTok().getLoc();
3718 if (trySkipId("offset")) {
3721 if (skipToken(AsmToken::Colon, "expected a colon")) {
3722 if (trySkipId("swizzle")) {
3723 Ok = parseSwizzleMacro(Imm);
3725 Ok = parseSwizzleOffset(Imm);
3729 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
3731 return Ok? MatchOperand_Success : MatchOperand_ParseFail;
3733 return MatchOperand_NoMatch;
3738 AMDGPUOperand::isSwizzle() const {
3739 return isImmTy(ImmTySwizzle);
3742 //===----------------------------------------------------------------------===//
3743 // sopp branch targets
3744 //===----------------------------------------------------------------------===//
3746 OperandMatchResultTy
3747 AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
3748 SMLoc S = Parser.getTok().getLoc();
3750 switch (getLexer().getKind()) {
3751 default: return MatchOperand_ParseFail;
3752 case AsmToken::Integer: {
3754 if (getParser().parseAbsoluteExpression(Imm))
3755 return MatchOperand_ParseFail;
3756 Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S));
3757 return MatchOperand_Success;
3760 case AsmToken::Identifier:
3761 Operands.push_back(AMDGPUOperand::CreateExpr(this,
3762 MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
3763 Parser.getTok().getString()), getContext()), S));
3765 return MatchOperand_Success;
3769 //===----------------------------------------------------------------------===//
3771 //===----------------------------------------------------------------------===//
3773 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
3774 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
3777 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
3778 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
3781 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
3782 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyTFE);
3785 void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
3786 const OperandVector &Operands,
3787 bool IsAtomic, bool IsAtomicReturn) {
3788 OptionalImmIndexMap OptionalIdx;
3789 assert(IsAtomicReturn ? IsAtomic : true);
3791 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3792 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3794 // Add the register arguments
3796 Op.addRegOperands(Inst, 1);
3800 // Handle the case where soffset is an immediate
3801 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3802 Op.addImmOperands(Inst, 1);
3806 // Handle tokens like 'offen' which are sometimes hard-coded into the
3807 // asm string. There are no MCInst operands for these.
3813 // Handle optional arguments
3814 OptionalIdx[Op.getImmTy()] = i;
3817 // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
3818 if (IsAtomicReturn) {
3819 MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
3823 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
3824 if (!IsAtomic) { // glc is hard-coded.
3825 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3827 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3828 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3831 void AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
3832 OptionalImmIndexMap OptionalIdx;
3834 for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3835 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3837 // Add the register arguments
3839 Op.addRegOperands(Inst, 1);
3843 // Handle the case where soffset is an immediate
3844 if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
3845 Op.addImmOperands(Inst, 1);
3849 // Handle tokens like 'offen' which are sometimes hard-coded into the
3850 // asm string. There are no MCInst operands for these.
3856 // Handle optional arguments
3857 OptionalIdx[Op.getImmTy()] = i;
3860 addOptionalImmOperand(Inst, Operands, OptionalIdx,
3861 AMDGPUOperand::ImmTyOffset);
3862 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDFMT);
3863 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyNFMT);
3864 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3865 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3866 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3869 //===----------------------------------------------------------------------===//
3871 //===----------------------------------------------------------------------===//
3873 void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
3875 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3876 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3877 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3880 OptionalImmIndexMap OptionalIdx;
3882 for (unsigned E = Operands.size(); I != E; ++I) {
3883 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3885 // Add the register arguments
3886 if (Op.isRegOrImm()) {
3887 Op.addRegOrImmOperands(Inst, 1);
3889 } else if (Op.isImmModifier()) {
3890 OptionalIdx[Op.getImmTy()] = I;
3892 llvm_unreachable("unexpected operand type");
3896 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3897 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3898 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3899 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3900 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3901 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3902 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3903 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3906 void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
3908 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
3909 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
3910 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
3913 // Add src, same as dst
3914 ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
3916 OptionalImmIndexMap OptionalIdx;
3918 for (unsigned E = Operands.size(); I != E; ++I) {
3919 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
3921 // Add the register arguments
3922 if (Op.isRegOrImm()) {
3923 Op.addRegOrImmOperands(Inst, 1);
3925 } else if (Op.isImmModifier()) {
3926 OptionalIdx[Op.getImmTy()] = I;
3928 llvm_unreachable("unexpected operand type");
3932 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
3933 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
3934 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
3935 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
3936 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
3937 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
3938 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
3939 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
3942 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
3943 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDMask);
3946 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
3947 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
3950 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
3951 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDA);
3954 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
3955 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyR128);
3958 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
3959 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyLWE);
3962 //===----------------------------------------------------------------------===//
3964 //===----------------------------------------------------------------------===//
3966 bool AMDGPUOperand::isSMRDOffset8() const {
3967 return isImm() && isUInt<8>(getImm());
3970 bool AMDGPUOperand::isSMRDOffset20() const {
3971 return isImm() && isUInt<20>(getImm());
3974 bool AMDGPUOperand::isSMRDLiteralOffset() const {
3975 // 32-bit literals are only supported on CI and we only want to use them
3976 // when the offset is > 8-bits.
3977 return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
3980 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
3981 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3984 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
3985 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3988 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
3989 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3992 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetU12() const {
3993 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
3996 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultOffsetS13() const {
3997 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
4000 //===----------------------------------------------------------------------===//
4002 //===----------------------------------------------------------------------===//
4004 static bool ConvertOmodMul(int64_t &Mul) {
4005 if (Mul != 1 && Mul != 2 && Mul != 4)
4012 static bool ConvertOmodDiv(int64_t &Div) {
4026 static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
4027 if (BoundCtrl == 0) {
4032 if (BoundCtrl == -1) {
4040 // Note: the order in this table matches the order of operands in AsmString.
4041 static const OptionalOperand AMDGPUOptionalOperandTable[] = {
4042 {"offen", AMDGPUOperand::ImmTyOffen, true, nullptr},
4043 {"idxen", AMDGPUOperand::ImmTyIdxen, true, nullptr},
4044 {"addr64", AMDGPUOperand::ImmTyAddr64, true, nullptr},
4045 {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
4046 {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
4047 {"gds", AMDGPUOperand::ImmTyGDS, true, nullptr},
4048 {"offset", AMDGPUOperand::ImmTyOffset, false, nullptr},
4049 {"dfmt", AMDGPUOperand::ImmTyDFMT, false, nullptr},
4050 {"nfmt", AMDGPUOperand::ImmTyNFMT, false, nullptr},
4051 {"glc", AMDGPUOperand::ImmTyGLC, true, nullptr},
4052 {"slc", AMDGPUOperand::ImmTySLC, true, nullptr},
4053 {"tfe", AMDGPUOperand::ImmTyTFE, true, nullptr},
4054 {"clamp", AMDGPUOperand::ImmTyClampSI, true, nullptr},
4055 {"omod", AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
4056 {"unorm", AMDGPUOperand::ImmTyUNorm, true, nullptr},
4057 {"da", AMDGPUOperand::ImmTyDA, true, nullptr},
4058 {"r128", AMDGPUOperand::ImmTyR128, true, nullptr},
4059 {"lwe", AMDGPUOperand::ImmTyLWE, true, nullptr},
4060 {"dmask", AMDGPUOperand::ImmTyDMask, false, nullptr},
4061 {"row_mask", AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
4062 {"bank_mask", AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
4063 {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
4064 {"dst_sel", AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
4065 {"src0_sel", AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
4066 {"src1_sel", AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
4067 {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
4068 {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
4069 {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
4070 {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
4071 {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
4072 {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
4073 {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr}
4076 OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
4077 OperandMatchResultTy res;
4078 for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
4079 // try to parse any optional operand here
4081 res = parseNamedBit(Op.Name, Operands, Op.Type);
4082 } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
4083 res = parseOModOperand(Operands);
4084 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
4085 Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
4086 Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
4087 res = parseSDWASel(Operands, Op.Name, Op.Type);
4088 } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
4089 res = parseSDWADstUnused(Operands);
4090 } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
4091 Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
4092 Op.Type == AMDGPUOperand::ImmTyNegLo ||
4093 Op.Type == AMDGPUOperand::ImmTyNegHi) {
4094 res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
4097 res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
4099 if (res != MatchOperand_NoMatch) {
4103 return MatchOperand_NoMatch;
4106 OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
4107 StringRef Name = Parser.getTok().getString();
4108 if (Name == "mul") {
4109 return parseIntWithPrefix("mul", Operands,
4110 AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
4113 if (Name == "div") {
4114 return parseIntWithPrefix("div", Operands,
4115 AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
4118 return MatchOperand_NoMatch;
4121 void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
4123 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4124 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4125 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4127 for (unsigned E = Operands.size(); I != E; ++I)
4128 ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
4131 void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
4132 uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
4133 if (TSFlags & SIInstrFlags::VOP3) {
4134 cvtVOP3(Inst, Operands);
4136 cvtId(Inst, Operands);
4140 static bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
4141 // 1. This operand is input modifiers
4142 return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
4143 // 2. This is not last operand
4144 && Desc.NumOperands > (OpNum + 1)
4145 // 3. Next operand is register class
4146 && Desc.OpInfo[OpNum + 1].RegClass != -1
4147 // 4. Next register is not tied to any other operand
4148 && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
4151 void AMDGPUAsmParser::cvtVOP3Impl(MCInst &Inst, const OperandVector &Operands,
4152 OptionalImmIndexMap &OptionalIdx) {
4154 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4155 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4156 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4159 for (unsigned E = Operands.size(); I != E; ++I) {
4160 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4161 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4162 Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
4163 } else if (Op.isImmModifier()) {
4164 OptionalIdx[Op.getImmTy()] = I;
4165 } else if (Op.isRegOrImm()) {
4166 Op.addRegOrImmOperands(Inst, 1);
4168 llvm_unreachable("unhandled operand type");
4173 void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
4174 OptionalImmIndexMap OptionalIdx;
4176 cvtVOP3Impl(Inst, Operands, OptionalIdx);
4178 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4179 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4181 // special case v_mac_{f16, f32}:
4182 // it has src2 register operand that is tied to dst operand
4183 // we don't allow modifiers for this operand in assembler so src2_modifiers
4185 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_si ||
4186 Inst.getOpcode() == AMDGPU::V_MAC_F32_e64_vi ||
4187 Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi) {
4188 auto it = Inst.begin();
4191 AMDGPU::getNamedOperandIdx(Inst.getOpcode() == AMDGPU::V_MAC_F16_e64_vi ?
4192 AMDGPU::V_MAC_F16_e64 :
4193 AMDGPU::V_MAC_F32_e64,
4194 AMDGPU::OpName::src2_modifiers));
4195 it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
4197 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4201 void AMDGPUAsmParser::cvtVOP3OMod(MCInst &Inst, const OperandVector &Operands) {
4202 OptionalImmIndexMap OptionalIdx;
4205 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4206 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4207 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4210 for (unsigned E = Operands.size(); I != E; ++I) {
4211 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4213 OptionalIdx[Op.getImmTy()] = I;
4215 Op.addRegOrImmOperands(Inst, 1);
4219 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
4220 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
4223 void AMDGPUAsmParser::cvtVOP3P(MCInst &Inst, const OperandVector &Operands) {
4224 OptionalImmIndexMap OptIdx;
4226 cvtVOP3Impl(Inst, Operands, OptIdx);
4228 // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
4229 // instruction, and then figure out where to actually put the modifiers
4230 int Opc = Inst.getOpcode();
4232 if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
4233 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyClampSI);
4236 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
4237 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi, -1);
4239 int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
4240 if (NegLoIdx != -1) {
4241 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
4242 addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
4245 const int Ops[] = { AMDGPU::OpName::src0,
4246 AMDGPU::OpName::src1,
4247 AMDGPU::OpName::src2 };
4248 const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
4249 AMDGPU::OpName::src1_modifiers,
4250 AMDGPU::OpName::src2_modifiers };
4252 int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
4253 int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
4255 unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
4256 unsigned OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
4260 if (NegLoIdx != -1) {
4261 int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
4262 NegLo = Inst.getOperand(NegLoIdx).getImm();
4263 NegHi = Inst.getOperand(NegHiIdx).getImm();
4266 for (int J = 0; J < 3; ++J) {
4267 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
4271 uint32_t ModVal = 0;
4273 if ((OpSel & (1 << J)) != 0)
4274 ModVal |= SISrcMods::OP_SEL_0;
4276 if ((OpSelHi & (1 << J)) != 0)
4277 ModVal |= SISrcMods::OP_SEL_1;
4279 if ((NegLo & (1 << J)) != 0)
4280 ModVal |= SISrcMods::NEG;
4282 if ((NegHi & (1 << J)) != 0)
4283 ModVal |= SISrcMods::NEG_HI;
4285 int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
4287 Inst.getOperand(ModIdx).setImm(ModVal);
4291 //===----------------------------------------------------------------------===//
4293 //===----------------------------------------------------------------------===//
4295 bool AMDGPUOperand::isDPPCtrl() const {
4296 bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
4298 int64_t Imm = getImm();
4299 return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
4300 ((Imm >= 0x101) && (Imm <= 0x10f)) ||
4301 ((Imm >= 0x111) && (Imm <= 0x11f)) ||
4302 ((Imm >= 0x121) && (Imm <= 0x12f)) ||
4315 bool AMDGPUOperand::isGPRIdxMode() const {
4316 return isImm() && isUInt<4>(getImm());
4319 bool AMDGPUOperand::isS16Imm() const {
4320 return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
4323 bool AMDGPUOperand::isU16Imm() const {
4324 return isImm() && isUInt<16>(getImm());
4327 OperandMatchResultTy
4328 AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
4329 SMLoc S = Parser.getTok().getLoc();
4333 if (getLexer().getKind() == AsmToken::Identifier) {
4334 Prefix = Parser.getTok().getString();
4336 return MatchOperand_NoMatch;
4339 if (Prefix == "row_mirror") {
4342 } else if (Prefix == "row_half_mirror") {
4346 // Check to prevent parseDPPCtrlOps from eating invalid tokens
4347 if (Prefix != "quad_perm"
4348 && Prefix != "row_shl"
4349 && Prefix != "row_shr"
4350 && Prefix != "row_ror"
4351 && Prefix != "wave_shl"
4352 && Prefix != "wave_rol"
4353 && Prefix != "wave_shr"
4354 && Prefix != "wave_ror"
4355 && Prefix != "row_bcast") {
4356 return MatchOperand_NoMatch;
4360 if (getLexer().isNot(AsmToken::Colon))
4361 return MatchOperand_ParseFail;
4363 if (Prefix == "quad_perm") {
4364 // quad_perm:[%d,%d,%d,%d]
4366 if (getLexer().isNot(AsmToken::LBrac))
4367 return MatchOperand_ParseFail;
4370 if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
4371 return MatchOperand_ParseFail;
4373 for (int i = 0; i < 3; ++i) {
4374 if (getLexer().isNot(AsmToken::Comma))
4375 return MatchOperand_ParseFail;
4379 if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
4380 return MatchOperand_ParseFail;
4381 const int shift = i*2 + 2;
4382 Int += (Temp << shift);
4385 if (getLexer().isNot(AsmToken::RBrac))
4386 return MatchOperand_ParseFail;
4392 if (getParser().parseAbsoluteExpression(Int))
4393 return MatchOperand_ParseFail;
4395 if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
4397 } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
4399 } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
4401 } else if (Prefix == "wave_shl" && 1 == Int) {
4403 } else if (Prefix == "wave_rol" && 1 == Int) {
4405 } else if (Prefix == "wave_shr" && 1 == Int) {
4407 } else if (Prefix == "wave_ror" && 1 == Int) {
4409 } else if (Prefix == "row_bcast") {
4412 } else if (Int == 31) {
4415 return MatchOperand_ParseFail;
4418 return MatchOperand_ParseFail;
4423 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
4424 return MatchOperand_Success;
4427 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
4428 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
4431 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
4432 return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
4435 AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
4436 return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
4439 void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
4440 OptionalImmIndexMap OptionalIdx;
4443 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4444 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4445 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4448 for (unsigned E = Operands.size(); I != E; ++I) {
4449 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4450 // Add the register arguments
4451 if (Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4452 // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
4455 } if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4456 Op.addRegWithFPInputModsOperands(Inst, 2);
4457 } else if (Op.isDPPCtrl()) {
4458 Op.addImmOperands(Inst, 1);
4459 } else if (Op.isImm()) {
4460 // Handle optional arguments
4461 OptionalIdx[Op.getImmTy()] = I;
4463 llvm_unreachable("Invalid operand type");
4467 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
4468 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
4469 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
4471 // special case v_mac_{f16, f32}:
4472 // it has src2 register operand that is tied to dst operand
4473 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_dpp ||
4474 Inst.getOpcode() == AMDGPU::V_MAC_F16_dpp) {
4475 auto it = Inst.begin();
4477 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4478 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4482 //===----------------------------------------------------------------------===//
4484 //===----------------------------------------------------------------------===//
4486 OperandMatchResultTy
4487 AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
4488 AMDGPUOperand::ImmTy Type) {
4489 using namespace llvm::AMDGPU::SDWA;
4491 SMLoc S = Parser.getTok().getLoc();
4493 OperandMatchResultTy res;
4495 res = parseStringWithPrefix(Prefix, Value);
4496 if (res != MatchOperand_Success) {
4501 Int = StringSwitch<int64_t>(Value)
4502 .Case("BYTE_0", SdwaSel::BYTE_0)
4503 .Case("BYTE_1", SdwaSel::BYTE_1)
4504 .Case("BYTE_2", SdwaSel::BYTE_2)
4505 .Case("BYTE_3", SdwaSel::BYTE_3)
4506 .Case("WORD_0", SdwaSel::WORD_0)
4507 .Case("WORD_1", SdwaSel::WORD_1)
4508 .Case("DWORD", SdwaSel::DWORD)
4509 .Default(0xffffffff);
4510 Parser.Lex(); // eat last token
4512 if (Int == 0xffffffff) {
4513 return MatchOperand_ParseFail;
4516 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
4517 return MatchOperand_Success;
4520 OperandMatchResultTy
4521 AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
4522 using namespace llvm::AMDGPU::SDWA;
4524 SMLoc S = Parser.getTok().getLoc();
4526 OperandMatchResultTy res;
4528 res = parseStringWithPrefix("dst_unused", Value);
4529 if (res != MatchOperand_Success) {
4534 Int = StringSwitch<int64_t>(Value)
4535 .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
4536 .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
4537 .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
4538 .Default(0xffffffff);
4539 Parser.Lex(); // eat last token
4541 if (Int == 0xffffffff) {
4542 return MatchOperand_ParseFail;
4545 Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
4546 return MatchOperand_Success;
4549 void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
4550 cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
4553 void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
4554 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
4557 void AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
4558 cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true);
4561 void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
4562 cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
4565 void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
4566 uint64_t BasicInstType, bool skipVcc) {
4567 using namespace llvm::AMDGPU::SDWA;
4568 OptionalImmIndexMap OptionalIdx;
4569 bool skippedVcc = false;
4572 const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
4573 for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
4574 ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
4577 for (unsigned E = Operands.size(); I != E; ++I) {
4578 AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
4579 if (skipVcc && !skippedVcc && Op.isReg() && Op.Reg.RegNo == AMDGPU::VCC) {
4580 // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
4581 // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
4582 // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
4583 // Skip VCC only if we didn't skip it on previous iteration.
4584 if (BasicInstType == SIInstrFlags::VOP2 &&
4585 (Inst.getNumOperands() == 1 || Inst.getNumOperands() == 5)) {
4588 } else if (BasicInstType == SIInstrFlags::VOPC &&
4589 Inst.getNumOperands() == 0) {
4594 if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
4595 Op.addRegWithInputModsOperands(Inst, 2);
4596 } else if (Op.isImm()) {
4597 // Handle optional arguments
4598 OptionalIdx[Op.getImmTy()] = I;
4600 llvm_unreachable("Invalid operand type");
4605 if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
4606 Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
4607 // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
4608 switch (BasicInstType) {
4609 case SIInstrFlags::VOP1:
4610 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4611 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4612 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4614 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4615 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4616 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4619 case SIInstrFlags::VOP2:
4620 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4621 if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
4622 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
4624 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
4625 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
4626 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4627 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4630 case SIInstrFlags::VOPC:
4631 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
4632 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
4633 addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
4637 llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
4641 // special case v_mac_{f16, f32}:
4642 // it has src2 register operand that is tied to dst operand
4643 if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
4644 Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
4645 auto it = Inst.begin();
4647 it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
4648 Inst.insert(it, Inst.getOperand(0)); // src2 = dst
4652 /// Force static initialization.
4653 extern "C" void LLVMInitializeAMDGPUAsmParser() {
4654 RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
4655 RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
4658 #define GET_REGISTER_MATCHER
4659 #define GET_MATCHER_IMPLEMENTATION
4660 #include "AMDGPUGenAsmMatcher.inc"
4662 // This fuction should be defined after auto-generated include so that we have
4663 // MatchClassKind enum defined
4664 unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
4666 // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
4667 // But MatchInstructionImpl() expects to meet token and fails to validate
4668 // operand. This method checks if we are given immediate operand but expect to
4669 // get corresponding token.
4670 AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
4673 return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
4675 return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
4677 return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
4679 return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
4681 return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
4683 // When operands have expression values, they will return true for isToken,
4684 // because it is not possible to distinguish between a token and an
4685 // expression at parse time. MatchInstructionImpl() will always try to
4686 // match an operand as a token, when isToken returns true, and when the
4687 // name of the expression is not a valid token, the match will fail,
4688 // so we need to handle it here.
4689 return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
4691 return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
4692 case MCK_SoppBrTarget:
4693 return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
4694 case MCK_VReg32OrOff:
4695 return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
4696 case MCK_InterpSlot:
4697 return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
4699 return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
4701 return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
4703 return Match_InvalidOperand;