xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ---------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "AMDKernelCodeT.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/AMDGPUTargetStreamer.h"
13*9880d681SAndroid Build Coastguard Worker #include "SIDefines.h"
14*9880d681SAndroid Build Coastguard Worker #include "Utils/AMDGPUBaseInfo.h"
15*9880d681SAndroid Build Coastguard Worker #include "Utils/AMDKernelCodeTUtils.h"
16*9880d681SAndroid Build Coastguard Worker #include "Utils/AMDGPUAsmUtils.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/APFloat.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallBitVector.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallString.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/StringSwitch.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Twine.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCExpr.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInst.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrInfo.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmLexer.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCAsmParser.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCParser/MCTargetAsmParser.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCRegisterInfo.h"
32*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCStreamer.h"
33*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
34*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbolELF.h"
35*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
36*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ELF.h"
37*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/SourceMgr.h"
38*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/TargetRegistry.h"
39*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
40*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
41*9880d681SAndroid Build Coastguard Worker 
42*9880d681SAndroid Build Coastguard Worker using namespace llvm;
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker namespace {
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker struct OptionalOperand;
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker enum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_TTMP, IS_SPECIAL };
49*9880d681SAndroid Build Coastguard Worker 
50*9880d681SAndroid Build Coastguard Worker class AMDGPUOperand : public MCParsedAsmOperand {
51*9880d681SAndroid Build Coastguard Worker   enum KindTy {
52*9880d681SAndroid Build Coastguard Worker     Token,
53*9880d681SAndroid Build Coastguard Worker     Immediate,
54*9880d681SAndroid Build Coastguard Worker     Register,
55*9880d681SAndroid Build Coastguard Worker     Expression
56*9880d681SAndroid Build Coastguard Worker   } Kind;
57*9880d681SAndroid Build Coastguard Worker 
58*9880d681SAndroid Build Coastguard Worker   SMLoc StartLoc, EndLoc;
59*9880d681SAndroid Build Coastguard Worker 
60*9880d681SAndroid Build Coastguard Worker public:
AMDGPUOperand(enum KindTy K)61*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand(enum KindTy K) : MCParsedAsmOperand(), Kind(K) {}
62*9880d681SAndroid Build Coastguard Worker 
63*9880d681SAndroid Build Coastguard Worker   typedef std::unique_ptr<AMDGPUOperand> Ptr;
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   struct Modifiers {
66*9880d681SAndroid Build Coastguard Worker     bool Abs;
67*9880d681SAndroid Build Coastguard Worker     bool Neg;
68*9880d681SAndroid Build Coastguard Worker     bool Sext;
69*9880d681SAndroid Build Coastguard Worker 
hasFPModifiers__anon66474c340111::AMDGPUOperand::Modifiers70*9880d681SAndroid Build Coastguard Worker     bool hasFPModifiers() const { return Abs || Neg; }
hasIntModifiers__anon66474c340111::AMDGPUOperand::Modifiers71*9880d681SAndroid Build Coastguard Worker     bool hasIntModifiers() const { return Sext; }
hasModifiers__anon66474c340111::AMDGPUOperand::Modifiers72*9880d681SAndroid Build Coastguard Worker     bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
73*9880d681SAndroid Build Coastguard Worker 
getFPModifiersOperand__anon66474c340111::AMDGPUOperand::Modifiers74*9880d681SAndroid Build Coastguard Worker     int64_t getFPModifiersOperand() const {
75*9880d681SAndroid Build Coastguard Worker       int64_t Operand = 0;
76*9880d681SAndroid Build Coastguard Worker       Operand |= Abs ? SISrcMods::ABS : 0;
77*9880d681SAndroid Build Coastguard Worker       Operand |= Neg ? SISrcMods::NEG : 0;
78*9880d681SAndroid Build Coastguard Worker       return Operand;
79*9880d681SAndroid Build Coastguard Worker     }
80*9880d681SAndroid Build Coastguard Worker 
getIntModifiersOperand__anon66474c340111::AMDGPUOperand::Modifiers81*9880d681SAndroid Build Coastguard Worker     int64_t getIntModifiersOperand() const {
82*9880d681SAndroid Build Coastguard Worker       int64_t Operand = 0;
83*9880d681SAndroid Build Coastguard Worker       Operand |= Sext ? SISrcMods::SEXT : 0;
84*9880d681SAndroid Build Coastguard Worker       return Operand;
85*9880d681SAndroid Build Coastguard Worker     }
86*9880d681SAndroid Build Coastguard Worker 
getModifiersOperand__anon66474c340111::AMDGPUOperand::Modifiers87*9880d681SAndroid Build Coastguard Worker     int64_t getModifiersOperand() const {
88*9880d681SAndroid Build Coastguard Worker       assert(!(hasFPModifiers() && hasIntModifiers())
89*9880d681SAndroid Build Coastguard Worker            && "fp and int modifiers should not be used simultaneously");
90*9880d681SAndroid Build Coastguard Worker       if (hasFPModifiers()) {
91*9880d681SAndroid Build Coastguard Worker         return getFPModifiersOperand();
92*9880d681SAndroid Build Coastguard Worker       } else if (hasIntModifiers()) {
93*9880d681SAndroid Build Coastguard Worker         return getIntModifiersOperand();
94*9880d681SAndroid Build Coastguard Worker       } else {
95*9880d681SAndroid Build Coastguard Worker         return 0;
96*9880d681SAndroid Build Coastguard Worker       }
97*9880d681SAndroid Build Coastguard Worker     }
98*9880d681SAndroid Build Coastguard Worker 
99*9880d681SAndroid Build Coastguard Worker     friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
100*9880d681SAndroid Build Coastguard Worker   };
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker   enum ImmTy {
103*9880d681SAndroid Build Coastguard Worker     ImmTyNone,
104*9880d681SAndroid Build Coastguard Worker     ImmTyGDS,
105*9880d681SAndroid Build Coastguard Worker     ImmTyOffen,
106*9880d681SAndroid Build Coastguard Worker     ImmTyIdxen,
107*9880d681SAndroid Build Coastguard Worker     ImmTyAddr64,
108*9880d681SAndroid Build Coastguard Worker     ImmTyOffset,
109*9880d681SAndroid Build Coastguard Worker     ImmTyOffset0,
110*9880d681SAndroid Build Coastguard Worker     ImmTyOffset1,
111*9880d681SAndroid Build Coastguard Worker     ImmTyGLC,
112*9880d681SAndroid Build Coastguard Worker     ImmTySLC,
113*9880d681SAndroid Build Coastguard Worker     ImmTyTFE,
114*9880d681SAndroid Build Coastguard Worker     ImmTyClampSI,
115*9880d681SAndroid Build Coastguard Worker     ImmTyOModSI,
116*9880d681SAndroid Build Coastguard Worker     ImmTyDppCtrl,
117*9880d681SAndroid Build Coastguard Worker     ImmTyDppRowMask,
118*9880d681SAndroid Build Coastguard Worker     ImmTyDppBankMask,
119*9880d681SAndroid Build Coastguard Worker     ImmTyDppBoundCtrl,
120*9880d681SAndroid Build Coastguard Worker     ImmTySdwaDstSel,
121*9880d681SAndroid Build Coastguard Worker     ImmTySdwaSrc0Sel,
122*9880d681SAndroid Build Coastguard Worker     ImmTySdwaSrc1Sel,
123*9880d681SAndroid Build Coastguard Worker     ImmTySdwaDstUnused,
124*9880d681SAndroid Build Coastguard Worker     ImmTyDMask,
125*9880d681SAndroid Build Coastguard Worker     ImmTyUNorm,
126*9880d681SAndroid Build Coastguard Worker     ImmTyDA,
127*9880d681SAndroid Build Coastguard Worker     ImmTyR128,
128*9880d681SAndroid Build Coastguard Worker     ImmTyLWE,
129*9880d681SAndroid Build Coastguard Worker     ImmTyHwreg,
130*9880d681SAndroid Build Coastguard Worker     ImmTySendMsg,
131*9880d681SAndroid Build Coastguard Worker   };
132*9880d681SAndroid Build Coastguard Worker 
133*9880d681SAndroid Build Coastguard Worker   struct TokOp {
134*9880d681SAndroid Build Coastguard Worker     const char *Data;
135*9880d681SAndroid Build Coastguard Worker     unsigned Length;
136*9880d681SAndroid Build Coastguard Worker   };
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker   struct ImmOp {
139*9880d681SAndroid Build Coastguard Worker     bool IsFPImm;
140*9880d681SAndroid Build Coastguard Worker     ImmTy Type;
141*9880d681SAndroid Build Coastguard Worker     int64_t Val;
142*9880d681SAndroid Build Coastguard Worker     Modifiers Mods;
143*9880d681SAndroid Build Coastguard Worker   };
144*9880d681SAndroid Build Coastguard Worker 
145*9880d681SAndroid Build Coastguard Worker   struct RegOp {
146*9880d681SAndroid Build Coastguard Worker     unsigned RegNo;
147*9880d681SAndroid Build Coastguard Worker     Modifiers Mods;
148*9880d681SAndroid Build Coastguard Worker     const MCRegisterInfo *TRI;
149*9880d681SAndroid Build Coastguard Worker     const MCSubtargetInfo *STI;
150*9880d681SAndroid Build Coastguard Worker     bool IsForcedVOP3;
151*9880d681SAndroid Build Coastguard Worker   };
152*9880d681SAndroid Build Coastguard Worker 
153*9880d681SAndroid Build Coastguard Worker   union {
154*9880d681SAndroid Build Coastguard Worker     TokOp Tok;
155*9880d681SAndroid Build Coastguard Worker     ImmOp Imm;
156*9880d681SAndroid Build Coastguard Worker     RegOp Reg;
157*9880d681SAndroid Build Coastguard Worker     const MCExpr *Expr;
158*9880d681SAndroid Build Coastguard Worker   };
159*9880d681SAndroid Build Coastguard Worker 
isToken() const160*9880d681SAndroid Build Coastguard Worker   bool isToken() const override {
161*9880d681SAndroid Build Coastguard Worker     if (Kind == Token)
162*9880d681SAndroid Build Coastguard Worker       return true;
163*9880d681SAndroid Build Coastguard Worker 
164*9880d681SAndroid Build Coastguard Worker     if (Kind != Expression || !Expr)
165*9880d681SAndroid Build Coastguard Worker       return false;
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker     // When parsing operands, we can't always tell if something was meant to be
168*9880d681SAndroid Build Coastguard Worker     // a token, like 'gds', or an expression that references a global variable.
169*9880d681SAndroid Build Coastguard Worker     // In this case, we assume the string is an expression, and if we need to
170*9880d681SAndroid Build Coastguard Worker     // interpret is a token, then we treat the symbol name as the token.
171*9880d681SAndroid Build Coastguard Worker     return isa<MCSymbolRefExpr>(Expr);
172*9880d681SAndroid Build Coastguard Worker   }
173*9880d681SAndroid Build Coastguard Worker 
isImm() const174*9880d681SAndroid Build Coastguard Worker   bool isImm() const override {
175*9880d681SAndroid Build Coastguard Worker     return Kind == Immediate;
176*9880d681SAndroid Build Coastguard Worker   }
177*9880d681SAndroid Build Coastguard Worker 
isInlinableImm() const178*9880d681SAndroid Build Coastguard Worker   bool isInlinableImm() const {
179*9880d681SAndroid Build Coastguard Worker     if (!isImmTy(ImmTyNone)) {
180*9880d681SAndroid Build Coastguard Worker       // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
181*9880d681SAndroid Build Coastguard Worker       return false;
182*9880d681SAndroid Build Coastguard Worker     }
183*9880d681SAndroid Build Coastguard Worker     // TODO: We should avoid using host float here. It would be better to
184*9880d681SAndroid Build Coastguard Worker     // check the float bit values which is what a few other places do.
185*9880d681SAndroid Build Coastguard Worker     // We've had bot failures before due to weird NaN support on mips hosts.
186*9880d681SAndroid Build Coastguard Worker     const float F = BitsToFloat(Imm.Val);
187*9880d681SAndroid Build Coastguard Worker     // TODO: Add 1/(2*pi) for VI
188*9880d681SAndroid Build Coastguard Worker     return (Imm.Val <= 64 && Imm.Val >= -16) ||
189*9880d681SAndroid Build Coastguard Worker            (F == 0.0 || F == 0.5 || F == -0.5 || F == 1.0 || F == -1.0 ||
190*9880d681SAndroid Build Coastguard Worker            F == 2.0 || F == -2.0 || F == 4.0 || F == -4.0);
191*9880d681SAndroid Build Coastguard Worker   }
192*9880d681SAndroid Build Coastguard Worker 
isRegKind() const193*9880d681SAndroid Build Coastguard Worker   bool isRegKind() const {
194*9880d681SAndroid Build Coastguard Worker     return Kind == Register;
195*9880d681SAndroid Build Coastguard Worker   }
196*9880d681SAndroid Build Coastguard Worker 
isReg() const197*9880d681SAndroid Build Coastguard Worker   bool isReg() const override {
198*9880d681SAndroid Build Coastguard Worker     return isRegKind() && !Reg.Mods.hasModifiers();
199*9880d681SAndroid Build Coastguard Worker   }
200*9880d681SAndroid Build Coastguard Worker 
isRegOrImmWithInputMods() const201*9880d681SAndroid Build Coastguard Worker   bool isRegOrImmWithInputMods() const {
202*9880d681SAndroid Build Coastguard Worker     return isRegKind() || isInlinableImm();
203*9880d681SAndroid Build Coastguard Worker   }
204*9880d681SAndroid Build Coastguard Worker 
isImmTy(ImmTy ImmT) const205*9880d681SAndroid Build Coastguard Worker   bool isImmTy(ImmTy ImmT) const {
206*9880d681SAndroid Build Coastguard Worker     return isImm() && Imm.Type == ImmT;
207*9880d681SAndroid Build Coastguard Worker   }
208*9880d681SAndroid Build Coastguard Worker 
isImmModifier() const209*9880d681SAndroid Build Coastguard Worker   bool isImmModifier() const {
210*9880d681SAndroid Build Coastguard Worker     return isImm() && Imm.Type != ImmTyNone;
211*9880d681SAndroid Build Coastguard Worker   }
212*9880d681SAndroid Build Coastguard Worker 
isClampSI() const213*9880d681SAndroid Build Coastguard Worker   bool isClampSI() const { return isImmTy(ImmTyClampSI); }
isOModSI() const214*9880d681SAndroid Build Coastguard Worker   bool isOModSI() const { return isImmTy(ImmTyOModSI); }
isDMask() const215*9880d681SAndroid Build Coastguard Worker   bool isDMask() const { return isImmTy(ImmTyDMask); }
isUNorm() const216*9880d681SAndroid Build Coastguard Worker   bool isUNorm() const { return isImmTy(ImmTyUNorm); }
isDA() const217*9880d681SAndroid Build Coastguard Worker   bool isDA() const { return isImmTy(ImmTyDA); }
isR128() const218*9880d681SAndroid Build Coastguard Worker   bool isR128() const { return isImmTy(ImmTyUNorm); }
isLWE() const219*9880d681SAndroid Build Coastguard Worker   bool isLWE() const { return isImmTy(ImmTyLWE); }
isOffen() const220*9880d681SAndroid Build Coastguard Worker   bool isOffen() const { return isImmTy(ImmTyOffen); }
isIdxen() const221*9880d681SAndroid Build Coastguard Worker   bool isIdxen() const { return isImmTy(ImmTyIdxen); }
isAddr64() const222*9880d681SAndroid Build Coastguard Worker   bool isAddr64() const { return isImmTy(ImmTyAddr64); }
isOffset() const223*9880d681SAndroid Build Coastguard Worker   bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
isOffset0() const224*9880d681SAndroid Build Coastguard Worker   bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<16>(getImm()); }
isOffset1() const225*9880d681SAndroid Build Coastguard Worker   bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
isGDS() const226*9880d681SAndroid Build Coastguard Worker   bool isGDS() const { return isImmTy(ImmTyGDS); }
isGLC() const227*9880d681SAndroid Build Coastguard Worker   bool isGLC() const { return isImmTy(ImmTyGLC); }
isSLC() const228*9880d681SAndroid Build Coastguard Worker   bool isSLC() const { return isImmTy(ImmTySLC); }
isTFE() const229*9880d681SAndroid Build Coastguard Worker   bool isTFE() const { return isImmTy(ImmTyTFE); }
isBankMask() const230*9880d681SAndroid Build Coastguard Worker   bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
isRowMask() const231*9880d681SAndroid Build Coastguard Worker   bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
isBoundCtrl() const232*9880d681SAndroid Build Coastguard Worker   bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
isSDWADstSel() const233*9880d681SAndroid Build Coastguard Worker   bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
isSDWASrc0Sel() const234*9880d681SAndroid Build Coastguard Worker   bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
isSDWASrc1Sel() const235*9880d681SAndroid Build Coastguard Worker   bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
isSDWADstUnused() const236*9880d681SAndroid Build Coastguard Worker   bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
237*9880d681SAndroid Build Coastguard Worker 
isMod() const238*9880d681SAndroid Build Coastguard Worker   bool isMod() const {
239*9880d681SAndroid Build Coastguard Worker     return isClampSI() || isOModSI();
240*9880d681SAndroid Build Coastguard Worker   }
241*9880d681SAndroid Build Coastguard Worker 
isRegOrImm() const242*9880d681SAndroid Build Coastguard Worker   bool isRegOrImm() const {
243*9880d681SAndroid Build Coastguard Worker     return isReg() || isImm();
244*9880d681SAndroid Build Coastguard Worker   }
245*9880d681SAndroid Build Coastguard Worker 
isRegClass(unsigned RCID) const246*9880d681SAndroid Build Coastguard Worker   bool isRegClass(unsigned RCID) const {
247*9880d681SAndroid Build Coastguard Worker     return isReg() && Reg.TRI->getRegClass(RCID).contains(getReg());
248*9880d681SAndroid Build Coastguard Worker   }
249*9880d681SAndroid Build Coastguard Worker 
isSCSrc32() const250*9880d681SAndroid Build Coastguard Worker   bool isSCSrc32() const {
251*9880d681SAndroid Build Coastguard Worker     return isInlinableImm() || isRegClass(AMDGPU::SReg_32RegClassID);
252*9880d681SAndroid Build Coastguard Worker   }
253*9880d681SAndroid Build Coastguard Worker 
isSCSrc64() const254*9880d681SAndroid Build Coastguard Worker   bool isSCSrc64() const {
255*9880d681SAndroid Build Coastguard Worker     return isInlinableImm() || isRegClass(AMDGPU::SReg_64RegClassID);
256*9880d681SAndroid Build Coastguard Worker   }
257*9880d681SAndroid Build Coastguard Worker 
isSSrc32() const258*9880d681SAndroid Build Coastguard Worker   bool isSSrc32() const {
259*9880d681SAndroid Build Coastguard Worker     return isImm() || isSCSrc32() || isExpr();
260*9880d681SAndroid Build Coastguard Worker   }
261*9880d681SAndroid Build Coastguard Worker 
isSSrc64() const262*9880d681SAndroid Build Coastguard Worker   bool isSSrc64() const {
263*9880d681SAndroid Build Coastguard Worker     // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
264*9880d681SAndroid Build Coastguard Worker     // See isVSrc64().
265*9880d681SAndroid Build Coastguard Worker     return isImm() || isSCSrc64();
266*9880d681SAndroid Build Coastguard Worker   }
267*9880d681SAndroid Build Coastguard Worker 
isVCSrc32() const268*9880d681SAndroid Build Coastguard Worker   bool isVCSrc32() const {
269*9880d681SAndroid Build Coastguard Worker     return isInlinableImm() || isRegClass(AMDGPU::VS_32RegClassID);
270*9880d681SAndroid Build Coastguard Worker   }
271*9880d681SAndroid Build Coastguard Worker 
isVCSrc64() const272*9880d681SAndroid Build Coastguard Worker   bool isVCSrc64() const {
273*9880d681SAndroid Build Coastguard Worker     return isInlinableImm() || isRegClass(AMDGPU::VS_64RegClassID);
274*9880d681SAndroid Build Coastguard Worker   }
275*9880d681SAndroid Build Coastguard Worker 
isVSrc32() const276*9880d681SAndroid Build Coastguard Worker   bool isVSrc32() const {
277*9880d681SAndroid Build Coastguard Worker     return isImm() || isVCSrc32();
278*9880d681SAndroid Build Coastguard Worker   }
279*9880d681SAndroid Build Coastguard Worker 
isVSrc64() const280*9880d681SAndroid Build Coastguard Worker   bool isVSrc64() const {
281*9880d681SAndroid Build Coastguard Worker     // TODO: Check if the 64-bit value (coming from assembly source) can be
282*9880d681SAndroid Build Coastguard Worker     // narrowed to 32 bits (in the instruction stream). That require knowledge
283*9880d681SAndroid Build Coastguard Worker     // of instruction type (unsigned/signed, floating or "untyped"/B64),
284*9880d681SAndroid Build Coastguard Worker     // see [AMD GCN3 ISA 6.3.1].
285*9880d681SAndroid Build Coastguard Worker     // TODO: How 64-bit values are formed from 32-bit literals in _B64 insns?
286*9880d681SAndroid Build Coastguard Worker     return isImm() || isVCSrc64();
287*9880d681SAndroid Build Coastguard Worker   }
288*9880d681SAndroid Build Coastguard Worker 
isMem() const289*9880d681SAndroid Build Coastguard Worker   bool isMem() const override {
290*9880d681SAndroid Build Coastguard Worker     return false;
291*9880d681SAndroid Build Coastguard Worker   }
292*9880d681SAndroid Build Coastguard Worker 
isExpr() const293*9880d681SAndroid Build Coastguard Worker   bool isExpr() const {
294*9880d681SAndroid Build Coastguard Worker     return Kind == Expression;
295*9880d681SAndroid Build Coastguard Worker   }
296*9880d681SAndroid Build Coastguard Worker 
isSoppBrTarget() const297*9880d681SAndroid Build Coastguard Worker   bool isSoppBrTarget() const {
298*9880d681SAndroid Build Coastguard Worker     return isExpr() || isImm();
299*9880d681SAndroid Build Coastguard Worker   }
300*9880d681SAndroid Build Coastguard Worker 
301*9880d681SAndroid Build Coastguard Worker   bool isSWaitCnt() const;
302*9880d681SAndroid Build Coastguard Worker   bool isHwreg() const;
303*9880d681SAndroid Build Coastguard Worker   bool isSendMsg() const;
304*9880d681SAndroid Build Coastguard Worker   bool isSMRDOffset() const;
305*9880d681SAndroid Build Coastguard Worker   bool isSMRDLiteralOffset() const;
306*9880d681SAndroid Build Coastguard Worker   bool isDPPCtrl() const;
307*9880d681SAndroid Build Coastguard Worker 
getExpressionAsToken() const308*9880d681SAndroid Build Coastguard Worker   StringRef getExpressionAsToken() const {
309*9880d681SAndroid Build Coastguard Worker     assert(isExpr());
310*9880d681SAndroid Build Coastguard Worker     const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
311*9880d681SAndroid Build Coastguard Worker     return S->getSymbol().getName();
312*9880d681SAndroid Build Coastguard Worker   }
313*9880d681SAndroid Build Coastguard Worker 
314*9880d681SAndroid Build Coastguard Worker 
getToken() const315*9880d681SAndroid Build Coastguard Worker   StringRef getToken() const {
316*9880d681SAndroid Build Coastguard Worker     assert(isToken());
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker     if (Kind == Expression)
319*9880d681SAndroid Build Coastguard Worker       return getExpressionAsToken();
320*9880d681SAndroid Build Coastguard Worker 
321*9880d681SAndroid Build Coastguard Worker     return StringRef(Tok.Data, Tok.Length);
322*9880d681SAndroid Build Coastguard Worker   }
323*9880d681SAndroid Build Coastguard Worker 
getImm() const324*9880d681SAndroid Build Coastguard Worker   int64_t getImm() const {
325*9880d681SAndroid Build Coastguard Worker     assert(isImm());
326*9880d681SAndroid Build Coastguard Worker     return Imm.Val;
327*9880d681SAndroid Build Coastguard Worker   }
328*9880d681SAndroid Build Coastguard Worker 
getImmTy() const329*9880d681SAndroid Build Coastguard Worker   enum ImmTy getImmTy() const {
330*9880d681SAndroid Build Coastguard Worker     assert(isImm());
331*9880d681SAndroid Build Coastguard Worker     return Imm.Type;
332*9880d681SAndroid Build Coastguard Worker   }
333*9880d681SAndroid Build Coastguard Worker 
getReg() const334*9880d681SAndroid Build Coastguard Worker   unsigned getReg() const override {
335*9880d681SAndroid Build Coastguard Worker     return Reg.RegNo;
336*9880d681SAndroid Build Coastguard Worker   }
337*9880d681SAndroid Build Coastguard Worker 
getStartLoc() const338*9880d681SAndroid Build Coastguard Worker   SMLoc getStartLoc() const override {
339*9880d681SAndroid Build Coastguard Worker     return StartLoc;
340*9880d681SAndroid Build Coastguard Worker   }
341*9880d681SAndroid Build Coastguard Worker 
getEndLoc() const342*9880d681SAndroid Build Coastguard Worker   SMLoc getEndLoc() const override {
343*9880d681SAndroid Build Coastguard Worker     return EndLoc;
344*9880d681SAndroid Build Coastguard Worker   }
345*9880d681SAndroid Build Coastguard Worker 
getModifiers() const346*9880d681SAndroid Build Coastguard Worker   Modifiers getModifiers() const {
347*9880d681SAndroid Build Coastguard Worker     assert(isRegKind() || isImmTy(ImmTyNone));
348*9880d681SAndroid Build Coastguard Worker     return isRegKind() ? Reg.Mods : Imm.Mods;
349*9880d681SAndroid Build Coastguard Worker   }
350*9880d681SAndroid Build Coastguard Worker 
setModifiers(Modifiers Mods)351*9880d681SAndroid Build Coastguard Worker   void setModifiers(Modifiers Mods) {
352*9880d681SAndroid Build Coastguard Worker     assert(isRegKind() || isImmTy(ImmTyNone));
353*9880d681SAndroid Build Coastguard Worker     if (isRegKind())
354*9880d681SAndroid Build Coastguard Worker       Reg.Mods = Mods;
355*9880d681SAndroid Build Coastguard Worker     else
356*9880d681SAndroid Build Coastguard Worker       Imm.Mods = Mods;
357*9880d681SAndroid Build Coastguard Worker   }
358*9880d681SAndroid Build Coastguard Worker 
hasModifiers() const359*9880d681SAndroid Build Coastguard Worker   bool hasModifiers() const {
360*9880d681SAndroid Build Coastguard Worker     return getModifiers().hasModifiers();
361*9880d681SAndroid Build Coastguard Worker   }
362*9880d681SAndroid Build Coastguard Worker 
hasFPModifiers() const363*9880d681SAndroid Build Coastguard Worker   bool hasFPModifiers() const {
364*9880d681SAndroid Build Coastguard Worker     return getModifiers().hasFPModifiers();
365*9880d681SAndroid Build Coastguard Worker   }
366*9880d681SAndroid Build Coastguard Worker 
hasIntModifiers() const367*9880d681SAndroid Build Coastguard Worker   bool hasIntModifiers() const {
368*9880d681SAndroid Build Coastguard Worker     return getModifiers().hasIntModifiers();
369*9880d681SAndroid Build Coastguard Worker   }
370*9880d681SAndroid Build Coastguard Worker 
addImmOperands(MCInst & Inst,unsigned N,bool ApplyModifiers=true) const371*9880d681SAndroid Build Coastguard Worker   void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const {
372*9880d681SAndroid Build Coastguard Worker     if (isImmTy(ImmTyNone) && ApplyModifiers && Imm.Mods.hasFPModifiers()) {
373*9880d681SAndroid Build Coastguard Worker       // Apply modifiers to immediate value
374*9880d681SAndroid Build Coastguard Worker       int64_t Val = Imm.Val;
375*9880d681SAndroid Build Coastguard Worker       bool Negate = Imm.Mods.Neg; // Only negate can get here
376*9880d681SAndroid Build Coastguard Worker       if (Imm.IsFPImm) {
377*9880d681SAndroid Build Coastguard Worker         APFloat F(BitsToFloat(Val));
378*9880d681SAndroid Build Coastguard Worker         if (Negate) {
379*9880d681SAndroid Build Coastguard Worker           F.changeSign();
380*9880d681SAndroid Build Coastguard Worker         }
381*9880d681SAndroid Build Coastguard Worker         Val = F.bitcastToAPInt().getZExtValue();
382*9880d681SAndroid Build Coastguard Worker       } else {
383*9880d681SAndroid Build Coastguard Worker         Val = Negate ? -Val : Val;
384*9880d681SAndroid Build Coastguard Worker       }
385*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(Val));
386*9880d681SAndroid Build Coastguard Worker     } else {
387*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createImm(getImm()));
388*9880d681SAndroid Build Coastguard Worker     }
389*9880d681SAndroid Build Coastguard Worker   }
390*9880d681SAndroid Build Coastguard Worker 
addRegOperands(MCInst & Inst,unsigned N) const391*9880d681SAndroid Build Coastguard Worker   void addRegOperands(MCInst &Inst, unsigned N) const {
392*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), *Reg.STI)));
393*9880d681SAndroid Build Coastguard Worker   }
394*9880d681SAndroid Build Coastguard Worker 
addRegOrImmOperands(MCInst & Inst,unsigned N) const395*9880d681SAndroid Build Coastguard Worker   void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
396*9880d681SAndroid Build Coastguard Worker     if (isRegKind())
397*9880d681SAndroid Build Coastguard Worker       addRegOperands(Inst, N);
398*9880d681SAndroid Build Coastguard Worker     else if (isExpr())
399*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(Expr));
400*9880d681SAndroid Build Coastguard Worker     else
401*9880d681SAndroid Build Coastguard Worker       addImmOperands(Inst, N);
402*9880d681SAndroid Build Coastguard Worker   }
403*9880d681SAndroid Build Coastguard Worker 
addRegOrImmWithInputModsOperands(MCInst & Inst,unsigned N) const404*9880d681SAndroid Build Coastguard Worker   void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
405*9880d681SAndroid Build Coastguard Worker     Modifiers Mods = getModifiers();
406*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
407*9880d681SAndroid Build Coastguard Worker     if (isRegKind()) {
408*9880d681SAndroid Build Coastguard Worker       addRegOperands(Inst, N);
409*9880d681SAndroid Build Coastguard Worker     } else {
410*9880d681SAndroid Build Coastguard Worker       addImmOperands(Inst, N, false);
411*9880d681SAndroid Build Coastguard Worker     }
412*9880d681SAndroid Build Coastguard Worker   }
413*9880d681SAndroid Build Coastguard Worker 
addRegOrImmWithFPInputModsOperands(MCInst & Inst,unsigned N) const414*9880d681SAndroid Build Coastguard Worker   void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
415*9880d681SAndroid Build Coastguard Worker     assert(!hasIntModifiers());
416*9880d681SAndroid Build Coastguard Worker     addRegOrImmWithInputModsOperands(Inst, N);
417*9880d681SAndroid Build Coastguard Worker   }
418*9880d681SAndroid Build Coastguard Worker 
addRegOrImmWithIntInputModsOperands(MCInst & Inst,unsigned N) const419*9880d681SAndroid Build Coastguard Worker   void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
420*9880d681SAndroid Build Coastguard Worker     assert(!hasFPModifiers());
421*9880d681SAndroid Build Coastguard Worker     addRegOrImmWithInputModsOperands(Inst, N);
422*9880d681SAndroid Build Coastguard Worker   }
423*9880d681SAndroid Build Coastguard Worker 
addSoppBrTargetOperands(MCInst & Inst,unsigned N) const424*9880d681SAndroid Build Coastguard Worker   void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
425*9880d681SAndroid Build Coastguard Worker     if (isImm())
426*9880d681SAndroid Build Coastguard Worker       addImmOperands(Inst, N);
427*9880d681SAndroid Build Coastguard Worker     else {
428*9880d681SAndroid Build Coastguard Worker       assert(isExpr());
429*9880d681SAndroid Build Coastguard Worker       Inst.addOperand(MCOperand::createExpr(Expr));
430*9880d681SAndroid Build Coastguard Worker     }
431*9880d681SAndroid Build Coastguard Worker   }
432*9880d681SAndroid Build Coastguard Worker 
printImmTy(raw_ostream & OS,ImmTy Type) const433*9880d681SAndroid Build Coastguard Worker   void printImmTy(raw_ostream& OS, ImmTy Type) const {
434*9880d681SAndroid Build Coastguard Worker     switch (Type) {
435*9880d681SAndroid Build Coastguard Worker     case ImmTyNone: OS << "None"; break;
436*9880d681SAndroid Build Coastguard Worker     case ImmTyGDS: OS << "GDS"; break;
437*9880d681SAndroid Build Coastguard Worker     case ImmTyOffen: OS << "Offen"; break;
438*9880d681SAndroid Build Coastguard Worker     case ImmTyIdxen: OS << "Idxen"; break;
439*9880d681SAndroid Build Coastguard Worker     case ImmTyAddr64: OS << "Addr64"; break;
440*9880d681SAndroid Build Coastguard Worker     case ImmTyOffset: OS << "Offset"; break;
441*9880d681SAndroid Build Coastguard Worker     case ImmTyOffset0: OS << "Offset0"; break;
442*9880d681SAndroid Build Coastguard Worker     case ImmTyOffset1: OS << "Offset1"; break;
443*9880d681SAndroid Build Coastguard Worker     case ImmTyGLC: OS << "GLC"; break;
444*9880d681SAndroid Build Coastguard Worker     case ImmTySLC: OS << "SLC"; break;
445*9880d681SAndroid Build Coastguard Worker     case ImmTyTFE: OS << "TFE"; break;
446*9880d681SAndroid Build Coastguard Worker     case ImmTyClampSI: OS << "ClampSI"; break;
447*9880d681SAndroid Build Coastguard Worker     case ImmTyOModSI: OS << "OModSI"; break;
448*9880d681SAndroid Build Coastguard Worker     case ImmTyDppCtrl: OS << "DppCtrl"; break;
449*9880d681SAndroid Build Coastguard Worker     case ImmTyDppRowMask: OS << "DppRowMask"; break;
450*9880d681SAndroid Build Coastguard Worker     case ImmTyDppBankMask: OS << "DppBankMask"; break;
451*9880d681SAndroid Build Coastguard Worker     case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
452*9880d681SAndroid Build Coastguard Worker     case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
453*9880d681SAndroid Build Coastguard Worker     case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
454*9880d681SAndroid Build Coastguard Worker     case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
455*9880d681SAndroid Build Coastguard Worker     case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
456*9880d681SAndroid Build Coastguard Worker     case ImmTyDMask: OS << "DMask"; break;
457*9880d681SAndroid Build Coastguard Worker     case ImmTyUNorm: OS << "UNorm"; break;
458*9880d681SAndroid Build Coastguard Worker     case ImmTyDA: OS << "DA"; break;
459*9880d681SAndroid Build Coastguard Worker     case ImmTyR128: OS << "R128"; break;
460*9880d681SAndroid Build Coastguard Worker     case ImmTyLWE: OS << "LWE"; break;
461*9880d681SAndroid Build Coastguard Worker     case ImmTyHwreg: OS << "Hwreg"; break;
462*9880d681SAndroid Build Coastguard Worker     case ImmTySendMsg: OS << "SendMsg"; break;
463*9880d681SAndroid Build Coastguard Worker     }
464*9880d681SAndroid Build Coastguard Worker   }
465*9880d681SAndroid Build Coastguard Worker 
print(raw_ostream & OS) const466*9880d681SAndroid Build Coastguard Worker   void print(raw_ostream &OS) const override {
467*9880d681SAndroid Build Coastguard Worker     switch (Kind) {
468*9880d681SAndroid Build Coastguard Worker     case Register:
469*9880d681SAndroid Build Coastguard Worker       OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
470*9880d681SAndroid Build Coastguard Worker       break;
471*9880d681SAndroid Build Coastguard Worker     case Immediate:
472*9880d681SAndroid Build Coastguard Worker       OS << '<' << getImm();
473*9880d681SAndroid Build Coastguard Worker       if (getImmTy() != ImmTyNone) {
474*9880d681SAndroid Build Coastguard Worker         OS << " type: "; printImmTy(OS, getImmTy());
475*9880d681SAndroid Build Coastguard Worker       }
476*9880d681SAndroid Build Coastguard Worker       OS << " mods: " << Imm.Mods << '>';
477*9880d681SAndroid Build Coastguard Worker       break;
478*9880d681SAndroid Build Coastguard Worker     case Token:
479*9880d681SAndroid Build Coastguard Worker       OS << '\'' << getToken() << '\'';
480*9880d681SAndroid Build Coastguard Worker       break;
481*9880d681SAndroid Build Coastguard Worker     case Expression:
482*9880d681SAndroid Build Coastguard Worker       OS << "<expr " << *Expr << '>';
483*9880d681SAndroid Build Coastguard Worker       break;
484*9880d681SAndroid Build Coastguard Worker     }
485*9880d681SAndroid Build Coastguard Worker   }
486*9880d681SAndroid Build Coastguard Worker 
CreateImm(int64_t Val,SMLoc Loc,enum ImmTy Type=ImmTyNone,bool IsFPImm=false)487*9880d681SAndroid Build Coastguard Worker   static AMDGPUOperand::Ptr CreateImm(int64_t Val, SMLoc Loc,
488*9880d681SAndroid Build Coastguard Worker                                       enum ImmTy Type = ImmTyNone,
489*9880d681SAndroid Build Coastguard Worker                                       bool IsFPImm = false) {
490*9880d681SAndroid Build Coastguard Worker     auto Op = llvm::make_unique<AMDGPUOperand>(Immediate);
491*9880d681SAndroid Build Coastguard Worker     Op->Imm.Val = Val;
492*9880d681SAndroid Build Coastguard Worker     Op->Imm.IsFPImm = IsFPImm;
493*9880d681SAndroid Build Coastguard Worker     Op->Imm.Type = Type;
494*9880d681SAndroid Build Coastguard Worker     Op->Imm.Mods = {false, false, false};
495*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = Loc;
496*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = Loc;
497*9880d681SAndroid Build Coastguard Worker     return Op;
498*9880d681SAndroid Build Coastguard Worker   }
499*9880d681SAndroid Build Coastguard Worker 
CreateToken(StringRef Str,SMLoc Loc,bool HasExplicitEncodingSize=true)500*9880d681SAndroid Build Coastguard Worker   static AMDGPUOperand::Ptr CreateToken(StringRef Str, SMLoc Loc,
501*9880d681SAndroid Build Coastguard Worker                                         bool HasExplicitEncodingSize = true) {
502*9880d681SAndroid Build Coastguard Worker     auto Res = llvm::make_unique<AMDGPUOperand>(Token);
503*9880d681SAndroid Build Coastguard Worker     Res->Tok.Data = Str.data();
504*9880d681SAndroid Build Coastguard Worker     Res->Tok.Length = Str.size();
505*9880d681SAndroid Build Coastguard Worker     Res->StartLoc = Loc;
506*9880d681SAndroid Build Coastguard Worker     Res->EndLoc = Loc;
507*9880d681SAndroid Build Coastguard Worker     return Res;
508*9880d681SAndroid Build Coastguard Worker   }
509*9880d681SAndroid Build Coastguard Worker 
CreateReg(unsigned RegNo,SMLoc S,SMLoc E,const MCRegisterInfo * TRI,const MCSubtargetInfo * STI,bool ForceVOP3)510*9880d681SAndroid Build Coastguard Worker   static AMDGPUOperand::Ptr CreateReg(unsigned RegNo, SMLoc S,
511*9880d681SAndroid Build Coastguard Worker                                       SMLoc E,
512*9880d681SAndroid Build Coastguard Worker                                       const MCRegisterInfo *TRI,
513*9880d681SAndroid Build Coastguard Worker                                       const MCSubtargetInfo *STI,
514*9880d681SAndroid Build Coastguard Worker                                       bool ForceVOP3) {
515*9880d681SAndroid Build Coastguard Worker     auto Op = llvm::make_unique<AMDGPUOperand>(Register);
516*9880d681SAndroid Build Coastguard Worker     Op->Reg.RegNo = RegNo;
517*9880d681SAndroid Build Coastguard Worker     Op->Reg.TRI = TRI;
518*9880d681SAndroid Build Coastguard Worker     Op->Reg.STI = STI;
519*9880d681SAndroid Build Coastguard Worker     Op->Reg.Mods = {false, false, false};
520*9880d681SAndroid Build Coastguard Worker     Op->Reg.IsForcedVOP3 = ForceVOP3;
521*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = S;
522*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = E;
523*9880d681SAndroid Build Coastguard Worker     return Op;
524*9880d681SAndroid Build Coastguard Worker   }
525*9880d681SAndroid Build Coastguard Worker 
CreateExpr(const class MCExpr * Expr,SMLoc S)526*9880d681SAndroid Build Coastguard Worker   static AMDGPUOperand::Ptr CreateExpr(const class MCExpr *Expr, SMLoc S) {
527*9880d681SAndroid Build Coastguard Worker     auto Op = llvm::make_unique<AMDGPUOperand>(Expression);
528*9880d681SAndroid Build Coastguard Worker     Op->Expr = Expr;
529*9880d681SAndroid Build Coastguard Worker     Op->StartLoc = S;
530*9880d681SAndroid Build Coastguard Worker     Op->EndLoc = S;
531*9880d681SAndroid Build Coastguard Worker     return Op;
532*9880d681SAndroid Build Coastguard Worker   }
533*9880d681SAndroid Build Coastguard Worker };
534*9880d681SAndroid Build Coastguard Worker 
operator <<(raw_ostream & OS,AMDGPUOperand::Modifiers Mods)535*9880d681SAndroid Build Coastguard Worker raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
536*9880d681SAndroid Build Coastguard Worker   OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
537*9880d681SAndroid Build Coastguard Worker   return OS;
538*9880d681SAndroid Build Coastguard Worker }
539*9880d681SAndroid Build Coastguard Worker 
540*9880d681SAndroid Build Coastguard Worker class AMDGPUAsmParser : public MCTargetAsmParser {
541*9880d681SAndroid Build Coastguard Worker   const MCInstrInfo &MII;
542*9880d681SAndroid Build Coastguard Worker   MCAsmParser &Parser;
543*9880d681SAndroid Build Coastguard Worker 
544*9880d681SAndroid Build Coastguard Worker   unsigned ForcedEncodingSize;
545*9880d681SAndroid Build Coastguard Worker   bool ForcedDPP;
546*9880d681SAndroid Build Coastguard Worker   bool ForcedSDWA;
547*9880d681SAndroid Build Coastguard Worker 
isSI() const548*9880d681SAndroid Build Coastguard Worker   bool isSI() const {
549*9880d681SAndroid Build Coastguard Worker     return AMDGPU::isSI(getSTI());
550*9880d681SAndroid Build Coastguard Worker   }
551*9880d681SAndroid Build Coastguard Worker 
isCI() const552*9880d681SAndroid Build Coastguard Worker   bool isCI() const {
553*9880d681SAndroid Build Coastguard Worker     return AMDGPU::isCI(getSTI());
554*9880d681SAndroid Build Coastguard Worker   }
555*9880d681SAndroid Build Coastguard Worker 
isVI() const556*9880d681SAndroid Build Coastguard Worker   bool isVI() const {
557*9880d681SAndroid Build Coastguard Worker     return AMDGPU::isVI(getSTI());
558*9880d681SAndroid Build Coastguard Worker   }
559*9880d681SAndroid Build Coastguard Worker 
hasSGPR102_SGPR103() const560*9880d681SAndroid Build Coastguard Worker   bool hasSGPR102_SGPR103() const {
561*9880d681SAndroid Build Coastguard Worker     return !isVI();
562*9880d681SAndroid Build Coastguard Worker   }
563*9880d681SAndroid Build Coastguard Worker 
564*9880d681SAndroid Build Coastguard Worker   /// @name Auto-generated Match Functions
565*9880d681SAndroid Build Coastguard Worker   /// {
566*9880d681SAndroid Build Coastguard Worker 
567*9880d681SAndroid Build Coastguard Worker #define GET_ASSEMBLER_HEADER
568*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenAsmMatcher.inc"
569*9880d681SAndroid Build Coastguard Worker 
570*9880d681SAndroid Build Coastguard Worker   /// }
571*9880d681SAndroid Build Coastguard Worker 
572*9880d681SAndroid Build Coastguard Worker private:
573*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
574*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveHSACodeObjectVersion();
575*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveHSACodeObjectISA();
576*9880d681SAndroid Build Coastguard Worker   bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
577*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveAMDKernelCodeT();
578*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveHSAText();
579*9880d681SAndroid Build Coastguard Worker   bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
580*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveAMDGPUHsaKernel();
581*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveAMDGPUHsaModuleGlobal();
582*9880d681SAndroid Build Coastguard Worker   bool ParseDirectiveAMDGPUHsaProgramGlobal();
583*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveHSADataGlobalAgent();
584*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveHSADataGlobalProgram();
585*9880d681SAndroid Build Coastguard Worker   bool ParseSectionDirectiveHSARodataReadonlyAgent();
586*9880d681SAndroid Build Coastguard Worker   bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum);
587*9880d681SAndroid Build Coastguard Worker   bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth);
588*9880d681SAndroid Build Coastguard Worker   void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands, bool IsAtomic, bool IsAtomicReturn);
589*9880d681SAndroid Build Coastguard Worker 
590*9880d681SAndroid Build Coastguard Worker public:
591*9880d681SAndroid Build Coastguard Worker   enum AMDGPUMatchResultTy {
592*9880d681SAndroid Build Coastguard Worker     Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
593*9880d681SAndroid Build Coastguard Worker   };
594*9880d681SAndroid Build Coastguard Worker 
AMDGPUAsmParser(const MCSubtargetInfo & STI,MCAsmParser & _Parser,const MCInstrInfo & MII,const MCTargetOptions & Options)595*9880d681SAndroid Build Coastguard Worker   AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
596*9880d681SAndroid Build Coastguard Worker                const MCInstrInfo &MII,
597*9880d681SAndroid Build Coastguard Worker                const MCTargetOptions &Options)
598*9880d681SAndroid Build Coastguard Worker       : MCTargetAsmParser(Options, STI), MII(MII), Parser(_Parser),
599*9880d681SAndroid Build Coastguard Worker         ForcedEncodingSize(0),
600*9880d681SAndroid Build Coastguard Worker         ForcedDPP(false),
601*9880d681SAndroid Build Coastguard Worker         ForcedSDWA(false) {
602*9880d681SAndroid Build Coastguard Worker     MCAsmParserExtension::Initialize(Parser);
603*9880d681SAndroid Build Coastguard Worker 
604*9880d681SAndroid Build Coastguard Worker     if (getSTI().getFeatureBits().none()) {
605*9880d681SAndroid Build Coastguard Worker       // Set default features.
606*9880d681SAndroid Build Coastguard Worker       copySTI().ToggleFeature("SOUTHERN_ISLANDS");
607*9880d681SAndroid Build Coastguard Worker     }
608*9880d681SAndroid Build Coastguard Worker 
609*9880d681SAndroid Build Coastguard Worker     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
610*9880d681SAndroid Build Coastguard Worker 
611*9880d681SAndroid Build Coastguard Worker     {
612*9880d681SAndroid Build Coastguard Worker       // TODO: make those pre-defined variables read-only.
613*9880d681SAndroid Build Coastguard Worker       // Currently there is none suitable machinery in the core llvm-mc for this.
614*9880d681SAndroid Build Coastguard Worker       // MCSymbol::isRedefinable is intended for another purpose, and
615*9880d681SAndroid Build Coastguard Worker       // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
616*9880d681SAndroid Build Coastguard Worker       AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
617*9880d681SAndroid Build Coastguard Worker       MCContext &Ctx = getContext();
618*9880d681SAndroid Build Coastguard Worker       MCSymbol *Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
619*9880d681SAndroid Build Coastguard Worker       Sym->setVariableValue(MCConstantExpr::create(Isa.Major, Ctx));
620*9880d681SAndroid Build Coastguard Worker       Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
621*9880d681SAndroid Build Coastguard Worker       Sym->setVariableValue(MCConstantExpr::create(Isa.Minor, Ctx));
622*9880d681SAndroid Build Coastguard Worker       Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
623*9880d681SAndroid Build Coastguard Worker       Sym->setVariableValue(MCConstantExpr::create(Isa.Stepping, Ctx));
624*9880d681SAndroid Build Coastguard Worker     }
625*9880d681SAndroid Build Coastguard Worker   }
626*9880d681SAndroid Build Coastguard Worker 
getTargetStreamer()627*9880d681SAndroid Build Coastguard Worker   AMDGPUTargetStreamer &getTargetStreamer() {
628*9880d681SAndroid Build Coastguard Worker     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
629*9880d681SAndroid Build Coastguard Worker     return static_cast<AMDGPUTargetStreamer &>(TS);
630*9880d681SAndroid Build Coastguard Worker   }
631*9880d681SAndroid Build Coastguard Worker 
setForcedEncodingSize(unsigned Size)632*9880d681SAndroid Build Coastguard Worker   void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
setForcedDPP(bool ForceDPP_)633*9880d681SAndroid Build Coastguard Worker   void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
setForcedSDWA(bool ForceSDWA_)634*9880d681SAndroid Build Coastguard Worker   void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
635*9880d681SAndroid Build Coastguard Worker 
getForcedEncodingSize() const636*9880d681SAndroid Build Coastguard Worker   unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
isForcedVOP3() const637*9880d681SAndroid Build Coastguard Worker   bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
isForcedDPP() const638*9880d681SAndroid Build Coastguard Worker   bool isForcedDPP() const { return ForcedDPP; }
isForcedSDWA() const639*9880d681SAndroid Build Coastguard Worker   bool isForcedSDWA() const { return ForcedSDWA; }
640*9880d681SAndroid Build Coastguard Worker 
641*9880d681SAndroid Build Coastguard Worker   std::unique_ptr<AMDGPUOperand> parseRegister();
642*9880d681SAndroid Build Coastguard Worker   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
643*9880d681SAndroid Build Coastguard Worker   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
644*9880d681SAndroid Build Coastguard Worker   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
645*9880d681SAndroid Build Coastguard Worker                                       unsigned Kind) override;
646*9880d681SAndroid Build Coastguard Worker   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
647*9880d681SAndroid Build Coastguard Worker                                OperandVector &Operands, MCStreamer &Out,
648*9880d681SAndroid Build Coastguard Worker                                uint64_t &ErrorInfo,
649*9880d681SAndroid Build Coastguard Worker                                bool MatchingInlineAsm) override;
650*9880d681SAndroid Build Coastguard Worker   bool ParseDirective(AsmToken DirectiveID) override;
651*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic);
652*9880d681SAndroid Build Coastguard Worker   StringRef parseMnemonicSuffix(StringRef Name);
653*9880d681SAndroid Build Coastguard Worker   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
654*9880d681SAndroid Build Coastguard Worker                         SMLoc NameLoc, OperandVector &Operands) override;
655*9880d681SAndroid Build Coastguard Worker 
656*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
657*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseIntWithPrefix(const char *Prefix,
658*9880d681SAndroid Build Coastguard Worker                                           OperandVector &Operands,
659*9880d681SAndroid Build Coastguard Worker                                           enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
660*9880d681SAndroid Build Coastguard Worker                                           bool (*ConvertResult)(int64_t&) = 0);
661*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseNamedBit(const char *Name, OperandVector &Operands,
662*9880d681SAndroid Build Coastguard Worker                                      enum AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
663*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseStringWithPrefix(StringRef Prefix, StringRef &Value);
664*9880d681SAndroid Build Coastguard Worker 
665*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseImm(OperandVector &Operands);
666*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseRegOrImm(OperandVector &Operands);
667*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands);
668*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands);
669*9880d681SAndroid Build Coastguard Worker 
670*9880d681SAndroid Build Coastguard Worker   void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
671*9880d681SAndroid Build Coastguard Worker   void cvtDS(MCInst &Inst, const OperandVector &Operands);
672*9880d681SAndroid Build Coastguard Worker 
673*9880d681SAndroid Build Coastguard Worker   bool parseCnt(int64_t &IntVal);
674*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
675*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseHwreg(OperandVector &Operands);
676*9880d681SAndroid Build Coastguard Worker 
677*9880d681SAndroid Build Coastguard Worker private:
678*9880d681SAndroid Build Coastguard Worker   struct OperandInfoTy {
679*9880d681SAndroid Build Coastguard Worker     int64_t Id;
680*9880d681SAndroid Build Coastguard Worker     bool IsSymbolic;
OperandInfoTy__anon66474c340111::AMDGPUAsmParser::OperandInfoTy681*9880d681SAndroid Build Coastguard Worker     OperandInfoTy(int64_t Id_) : Id(Id_), IsSymbolic(false) { }
682*9880d681SAndroid Build Coastguard Worker   };
683*9880d681SAndroid Build Coastguard Worker 
684*9880d681SAndroid Build Coastguard Worker   bool parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId);
685*9880d681SAndroid Build Coastguard Worker   bool parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
686*9880d681SAndroid Build Coastguard Worker public:
687*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
688*9880d681SAndroid Build Coastguard Worker 
689*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
690*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
691*9880d681SAndroid Build Coastguard Worker 
cvtMubuf(MCInst & Inst,const OperandVector & Operands)692*9880d681SAndroid Build Coastguard Worker   void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
cvtMubufAtomic(MCInst & Inst,const OperandVector & Operands)693*9880d681SAndroid Build Coastguard Worker   void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
cvtMubufAtomicReturn(MCInst & Inst,const OperandVector & Operands)694*9880d681SAndroid Build Coastguard Worker   void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
695*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultGLC() const;
696*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultSLC() const;
697*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultTFE() const;
698*9880d681SAndroid Build Coastguard Worker 
699*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultDMask() const;
700*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultUNorm() const;
701*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultDA() const;
702*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultR128() const;
703*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultLWE() const;
704*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultSMRDOffset() const;
705*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
706*9880d681SAndroid Build Coastguard Worker 
707*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseOModOperand(OperandVector &Operands);
708*9880d681SAndroid Build Coastguard Worker 
709*9880d681SAndroid Build Coastguard Worker   void cvtId(MCInst &Inst, const OperandVector &Operands);
710*9880d681SAndroid Build Coastguard Worker   void cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands);
711*9880d681SAndroid Build Coastguard Worker   void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
712*9880d681SAndroid Build Coastguard Worker 
713*9880d681SAndroid Build Coastguard Worker   void cvtMIMG(MCInst &Inst, const OperandVector &Operands);
714*9880d681SAndroid Build Coastguard Worker   void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
715*9880d681SAndroid Build Coastguard Worker 
716*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
717*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultRowMask() const;
718*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultBankMask() const;
719*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Ptr defaultBoundCtrl() const;
720*9880d681SAndroid Build Coastguard Worker   void cvtDPP(MCInst &Inst, const OperandVector &Operands);
721*9880d681SAndroid Build Coastguard Worker 
722*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
723*9880d681SAndroid Build Coastguard Worker                                     AMDGPUOperand::ImmTy Type);
724*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
725*9880d681SAndroid Build Coastguard Worker   void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
726*9880d681SAndroid Build Coastguard Worker   void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
727*9880d681SAndroid Build Coastguard Worker   void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
728*9880d681SAndroid Build Coastguard Worker   void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
729*9880d681SAndroid Build Coastguard Worker                uint64_t BasicInstType);
730*9880d681SAndroid Build Coastguard Worker };
731*9880d681SAndroid Build Coastguard Worker 
732*9880d681SAndroid Build Coastguard Worker struct OptionalOperand {
733*9880d681SAndroid Build Coastguard Worker   const char *Name;
734*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::ImmTy Type;
735*9880d681SAndroid Build Coastguard Worker   bool IsBit;
736*9880d681SAndroid Build Coastguard Worker   bool (*ConvertResult)(int64_t&);
737*9880d681SAndroid Build Coastguard Worker };
738*9880d681SAndroid Build Coastguard Worker 
739*9880d681SAndroid Build Coastguard Worker }
740*9880d681SAndroid Build Coastguard Worker 
getRegClass(RegisterKind Is,unsigned RegWidth)741*9880d681SAndroid Build Coastguard Worker static int getRegClass(RegisterKind Is, unsigned RegWidth) {
742*9880d681SAndroid Build Coastguard Worker   if (Is == IS_VGPR) {
743*9880d681SAndroid Build Coastguard Worker     switch (RegWidth) {
744*9880d681SAndroid Build Coastguard Worker       default: return -1;
745*9880d681SAndroid Build Coastguard Worker       case 1: return AMDGPU::VGPR_32RegClassID;
746*9880d681SAndroid Build Coastguard Worker       case 2: return AMDGPU::VReg_64RegClassID;
747*9880d681SAndroid Build Coastguard Worker       case 3: return AMDGPU::VReg_96RegClassID;
748*9880d681SAndroid Build Coastguard Worker       case 4: return AMDGPU::VReg_128RegClassID;
749*9880d681SAndroid Build Coastguard Worker       case 8: return AMDGPU::VReg_256RegClassID;
750*9880d681SAndroid Build Coastguard Worker       case 16: return AMDGPU::VReg_512RegClassID;
751*9880d681SAndroid Build Coastguard Worker     }
752*9880d681SAndroid Build Coastguard Worker   } else if (Is == IS_TTMP) {
753*9880d681SAndroid Build Coastguard Worker     switch (RegWidth) {
754*9880d681SAndroid Build Coastguard Worker       default: return -1;
755*9880d681SAndroid Build Coastguard Worker       case 1: return AMDGPU::TTMP_32RegClassID;
756*9880d681SAndroid Build Coastguard Worker       case 2: return AMDGPU::TTMP_64RegClassID;
757*9880d681SAndroid Build Coastguard Worker       case 4: return AMDGPU::TTMP_128RegClassID;
758*9880d681SAndroid Build Coastguard Worker     }
759*9880d681SAndroid Build Coastguard Worker   } else if (Is == IS_SGPR) {
760*9880d681SAndroid Build Coastguard Worker     switch (RegWidth) {
761*9880d681SAndroid Build Coastguard Worker       default: return -1;
762*9880d681SAndroid Build Coastguard Worker       case 1: return AMDGPU::SGPR_32RegClassID;
763*9880d681SAndroid Build Coastguard Worker       case 2: return AMDGPU::SGPR_64RegClassID;
764*9880d681SAndroid Build Coastguard Worker       case 4: return AMDGPU::SGPR_128RegClassID;
765*9880d681SAndroid Build Coastguard Worker       case 8: return AMDGPU::SReg_256RegClassID;
766*9880d681SAndroid Build Coastguard Worker       case 16: return AMDGPU::SReg_512RegClassID;
767*9880d681SAndroid Build Coastguard Worker     }
768*9880d681SAndroid Build Coastguard Worker   }
769*9880d681SAndroid Build Coastguard Worker   return -1;
770*9880d681SAndroid Build Coastguard Worker }
771*9880d681SAndroid Build Coastguard Worker 
getSpecialRegForName(StringRef RegName)772*9880d681SAndroid Build Coastguard Worker static unsigned getSpecialRegForName(StringRef RegName) {
773*9880d681SAndroid Build Coastguard Worker   return StringSwitch<unsigned>(RegName)
774*9880d681SAndroid Build Coastguard Worker     .Case("exec", AMDGPU::EXEC)
775*9880d681SAndroid Build Coastguard Worker     .Case("vcc", AMDGPU::VCC)
776*9880d681SAndroid Build Coastguard Worker     .Case("flat_scratch", AMDGPU::FLAT_SCR)
777*9880d681SAndroid Build Coastguard Worker     .Case("m0", AMDGPU::M0)
778*9880d681SAndroid Build Coastguard Worker     .Case("scc", AMDGPU::SCC)
779*9880d681SAndroid Build Coastguard Worker     .Case("tba", AMDGPU::TBA)
780*9880d681SAndroid Build Coastguard Worker     .Case("tma", AMDGPU::TMA)
781*9880d681SAndroid Build Coastguard Worker     .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
782*9880d681SAndroid Build Coastguard Worker     .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
783*9880d681SAndroid Build Coastguard Worker     .Case("vcc_lo", AMDGPU::VCC_LO)
784*9880d681SAndroid Build Coastguard Worker     .Case("vcc_hi", AMDGPU::VCC_HI)
785*9880d681SAndroid Build Coastguard Worker     .Case("exec_lo", AMDGPU::EXEC_LO)
786*9880d681SAndroid Build Coastguard Worker     .Case("exec_hi", AMDGPU::EXEC_HI)
787*9880d681SAndroid Build Coastguard Worker     .Case("tma_lo", AMDGPU::TMA_LO)
788*9880d681SAndroid Build Coastguard Worker     .Case("tma_hi", AMDGPU::TMA_HI)
789*9880d681SAndroid Build Coastguard Worker     .Case("tba_lo", AMDGPU::TBA_LO)
790*9880d681SAndroid Build Coastguard Worker     .Case("tba_hi", AMDGPU::TBA_HI)
791*9880d681SAndroid Build Coastguard Worker     .Default(0);
792*9880d681SAndroid Build Coastguard Worker }
793*9880d681SAndroid Build Coastguard Worker 
ParseRegister(unsigned & RegNo,SMLoc & StartLoc,SMLoc & EndLoc)794*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
795*9880d681SAndroid Build Coastguard Worker   auto R = parseRegister();
796*9880d681SAndroid Build Coastguard Worker   if (!R) return true;
797*9880d681SAndroid Build Coastguard Worker   assert(R->isReg());
798*9880d681SAndroid Build Coastguard Worker   RegNo = R->getReg();
799*9880d681SAndroid Build Coastguard Worker   StartLoc = R->getStartLoc();
800*9880d681SAndroid Build Coastguard Worker   EndLoc = R->getEndLoc();
801*9880d681SAndroid Build Coastguard Worker   return false;
802*9880d681SAndroid Build Coastguard Worker }
803*9880d681SAndroid Build Coastguard Worker 
AddNextRegisterToList(unsigned & Reg,unsigned & RegWidth,RegisterKind RegKind,unsigned Reg1,unsigned RegNum)804*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth, RegisterKind RegKind, unsigned Reg1, unsigned RegNum)
805*9880d681SAndroid Build Coastguard Worker {
806*9880d681SAndroid Build Coastguard Worker   switch (RegKind) {
807*9880d681SAndroid Build Coastguard Worker   case IS_SPECIAL:
808*9880d681SAndroid Build Coastguard Worker     if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) { Reg = AMDGPU::EXEC; RegWidth = 2; return true; }
809*9880d681SAndroid Build Coastguard Worker     if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) { Reg = AMDGPU::FLAT_SCR; RegWidth = 2; return true; }
810*9880d681SAndroid Build Coastguard Worker     if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) { Reg = AMDGPU::VCC; RegWidth = 2; return true; }
811*9880d681SAndroid Build Coastguard Worker     if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) { Reg = AMDGPU::TBA; RegWidth = 2; return true; }
812*9880d681SAndroid Build Coastguard Worker     if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) { Reg = AMDGPU::TMA; RegWidth = 2; return true; }
813*9880d681SAndroid Build Coastguard Worker     return false;
814*9880d681SAndroid Build Coastguard Worker   case IS_VGPR:
815*9880d681SAndroid Build Coastguard Worker   case IS_SGPR:
816*9880d681SAndroid Build Coastguard Worker   case IS_TTMP:
817*9880d681SAndroid Build Coastguard Worker     if (Reg1 != Reg + RegWidth) { return false; }
818*9880d681SAndroid Build Coastguard Worker     RegWidth++;
819*9880d681SAndroid Build Coastguard Worker     return true;
820*9880d681SAndroid Build Coastguard Worker   default:
821*9880d681SAndroid Build Coastguard Worker     assert(false); return false;
822*9880d681SAndroid Build Coastguard Worker   }
823*9880d681SAndroid Build Coastguard Worker }
824*9880d681SAndroid Build Coastguard Worker 
ParseAMDGPURegister(RegisterKind & RegKind,unsigned & Reg,unsigned & RegNum,unsigned & RegWidth)825*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg, unsigned& RegNum, unsigned& RegWidth)
826*9880d681SAndroid Build Coastguard Worker {
827*9880d681SAndroid Build Coastguard Worker   const MCRegisterInfo *TRI = getContext().getRegisterInfo();
828*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Identifier)) {
829*9880d681SAndroid Build Coastguard Worker     StringRef RegName = Parser.getTok().getString();
830*9880d681SAndroid Build Coastguard Worker     if ((Reg = getSpecialRegForName(RegName))) {
831*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
832*9880d681SAndroid Build Coastguard Worker       RegKind = IS_SPECIAL;
833*9880d681SAndroid Build Coastguard Worker     } else {
834*9880d681SAndroid Build Coastguard Worker       unsigned RegNumIndex = 0;
835*9880d681SAndroid Build Coastguard Worker       if (RegName[0] == 'v') {
836*9880d681SAndroid Build Coastguard Worker         RegNumIndex = 1;
837*9880d681SAndroid Build Coastguard Worker         RegKind = IS_VGPR;
838*9880d681SAndroid Build Coastguard Worker       } else if (RegName[0] == 's') {
839*9880d681SAndroid Build Coastguard Worker         RegNumIndex = 1;
840*9880d681SAndroid Build Coastguard Worker         RegKind = IS_SGPR;
841*9880d681SAndroid Build Coastguard Worker       } else if (RegName.startswith("ttmp")) {
842*9880d681SAndroid Build Coastguard Worker         RegNumIndex = strlen("ttmp");
843*9880d681SAndroid Build Coastguard Worker         RegKind = IS_TTMP;
844*9880d681SAndroid Build Coastguard Worker       } else {
845*9880d681SAndroid Build Coastguard Worker         return false;
846*9880d681SAndroid Build Coastguard Worker       }
847*9880d681SAndroid Build Coastguard Worker       if (RegName.size() > RegNumIndex) {
848*9880d681SAndroid Build Coastguard Worker         // Single 32-bit register: vXX.
849*9880d681SAndroid Build Coastguard Worker         if (RegName.substr(RegNumIndex).getAsInteger(10, RegNum))
850*9880d681SAndroid Build Coastguard Worker           return false;
851*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
852*9880d681SAndroid Build Coastguard Worker         RegWidth = 1;
853*9880d681SAndroid Build Coastguard Worker       } else {
854*9880d681SAndroid Build Coastguard Worker         // Range of registers: v[XX:YY]. ":YY" is optional.
855*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
856*9880d681SAndroid Build Coastguard Worker         int64_t RegLo, RegHi;
857*9880d681SAndroid Build Coastguard Worker         if (getLexer().isNot(AsmToken::LBrac))
858*9880d681SAndroid Build Coastguard Worker           return false;
859*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
860*9880d681SAndroid Build Coastguard Worker 
861*9880d681SAndroid Build Coastguard Worker         if (getParser().parseAbsoluteExpression(RegLo))
862*9880d681SAndroid Build Coastguard Worker           return false;
863*9880d681SAndroid Build Coastguard Worker 
864*9880d681SAndroid Build Coastguard Worker         const bool isRBrace = getLexer().is(AsmToken::RBrac);
865*9880d681SAndroid Build Coastguard Worker         if (!isRBrace && getLexer().isNot(AsmToken::Colon))
866*9880d681SAndroid Build Coastguard Worker           return false;
867*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
868*9880d681SAndroid Build Coastguard Worker 
869*9880d681SAndroid Build Coastguard Worker         if (isRBrace) {
870*9880d681SAndroid Build Coastguard Worker           RegHi = RegLo;
871*9880d681SAndroid Build Coastguard Worker         } else {
872*9880d681SAndroid Build Coastguard Worker           if (getParser().parseAbsoluteExpression(RegHi))
873*9880d681SAndroid Build Coastguard Worker             return false;
874*9880d681SAndroid Build Coastguard Worker 
875*9880d681SAndroid Build Coastguard Worker           if (getLexer().isNot(AsmToken::RBrac))
876*9880d681SAndroid Build Coastguard Worker             return false;
877*9880d681SAndroid Build Coastguard Worker           Parser.Lex();
878*9880d681SAndroid Build Coastguard Worker         }
879*9880d681SAndroid Build Coastguard Worker         RegNum = (unsigned) RegLo;
880*9880d681SAndroid Build Coastguard Worker         RegWidth = (RegHi - RegLo) + 1;
881*9880d681SAndroid Build Coastguard Worker       }
882*9880d681SAndroid Build Coastguard Worker     }
883*9880d681SAndroid Build Coastguard Worker   } else if (getLexer().is(AsmToken::LBrac)) {
884*9880d681SAndroid Build Coastguard Worker     // List of consecutive registers: [s0,s1,s2,s3]
885*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
886*9880d681SAndroid Build Coastguard Worker     if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth))
887*9880d681SAndroid Build Coastguard Worker       return false;
888*9880d681SAndroid Build Coastguard Worker     if (RegWidth != 1)
889*9880d681SAndroid Build Coastguard Worker       return false;
890*9880d681SAndroid Build Coastguard Worker     RegisterKind RegKind1;
891*9880d681SAndroid Build Coastguard Worker     unsigned Reg1, RegNum1, RegWidth1;
892*9880d681SAndroid Build Coastguard Worker     do {
893*9880d681SAndroid Build Coastguard Worker       if (getLexer().is(AsmToken::Comma)) {
894*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
895*9880d681SAndroid Build Coastguard Worker       } else if (getLexer().is(AsmToken::RBrac)) {
896*9880d681SAndroid Build Coastguard Worker         Parser.Lex();
897*9880d681SAndroid Build Coastguard Worker         break;
898*9880d681SAndroid Build Coastguard Worker       } else if (ParseAMDGPURegister(RegKind1, Reg1, RegNum1, RegWidth1)) {
899*9880d681SAndroid Build Coastguard Worker         if (RegWidth1 != 1) {
900*9880d681SAndroid Build Coastguard Worker           return false;
901*9880d681SAndroid Build Coastguard Worker         }
902*9880d681SAndroid Build Coastguard Worker         if (RegKind1 != RegKind) {
903*9880d681SAndroid Build Coastguard Worker           return false;
904*9880d681SAndroid Build Coastguard Worker         }
905*9880d681SAndroid Build Coastguard Worker         if (!AddNextRegisterToList(Reg, RegWidth, RegKind1, Reg1, RegNum1)) {
906*9880d681SAndroid Build Coastguard Worker           return false;
907*9880d681SAndroid Build Coastguard Worker         }
908*9880d681SAndroid Build Coastguard Worker       } else {
909*9880d681SAndroid Build Coastguard Worker         return false;
910*9880d681SAndroid Build Coastguard Worker       }
911*9880d681SAndroid Build Coastguard Worker     } while (true);
912*9880d681SAndroid Build Coastguard Worker   } else {
913*9880d681SAndroid Build Coastguard Worker     return false;
914*9880d681SAndroid Build Coastguard Worker   }
915*9880d681SAndroid Build Coastguard Worker   switch (RegKind) {
916*9880d681SAndroid Build Coastguard Worker   case IS_SPECIAL:
917*9880d681SAndroid Build Coastguard Worker     RegNum = 0;
918*9880d681SAndroid Build Coastguard Worker     RegWidth = 1;
919*9880d681SAndroid Build Coastguard Worker     break;
920*9880d681SAndroid Build Coastguard Worker   case IS_VGPR:
921*9880d681SAndroid Build Coastguard Worker   case IS_SGPR:
922*9880d681SAndroid Build Coastguard Worker   case IS_TTMP:
923*9880d681SAndroid Build Coastguard Worker   {
924*9880d681SAndroid Build Coastguard Worker     unsigned Size = 1;
925*9880d681SAndroid Build Coastguard Worker     if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
926*9880d681SAndroid Build Coastguard Worker       // SGPR and TTMP registers must be are aligned. Max required alignment is 4 dwords.
927*9880d681SAndroid Build Coastguard Worker       Size = std::min(RegWidth, 4u);
928*9880d681SAndroid Build Coastguard Worker     }
929*9880d681SAndroid Build Coastguard Worker     if (RegNum % Size != 0)
930*9880d681SAndroid Build Coastguard Worker       return false;
931*9880d681SAndroid Build Coastguard Worker     RegNum = RegNum / Size;
932*9880d681SAndroid Build Coastguard Worker     int RCID = getRegClass(RegKind, RegWidth);
933*9880d681SAndroid Build Coastguard Worker     if (RCID == -1)
934*9880d681SAndroid Build Coastguard Worker       return false;
935*9880d681SAndroid Build Coastguard Worker     const MCRegisterClass RC = TRI->getRegClass(RCID);
936*9880d681SAndroid Build Coastguard Worker     if (RegNum >= RC.getNumRegs())
937*9880d681SAndroid Build Coastguard Worker       return false;
938*9880d681SAndroid Build Coastguard Worker     Reg = RC.getRegister(RegNum);
939*9880d681SAndroid Build Coastguard Worker     break;
940*9880d681SAndroid Build Coastguard Worker   }
941*9880d681SAndroid Build Coastguard Worker 
942*9880d681SAndroid Build Coastguard Worker   default:
943*9880d681SAndroid Build Coastguard Worker     assert(false); return false;
944*9880d681SAndroid Build Coastguard Worker   }
945*9880d681SAndroid Build Coastguard Worker 
946*9880d681SAndroid Build Coastguard Worker   if (!subtargetHasRegister(*TRI, Reg))
947*9880d681SAndroid Build Coastguard Worker     return false;
948*9880d681SAndroid Build Coastguard Worker   return true;
949*9880d681SAndroid Build Coastguard Worker }
950*9880d681SAndroid Build Coastguard Worker 
parseRegister()951*9880d681SAndroid Build Coastguard Worker std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
952*9880d681SAndroid Build Coastguard Worker   const auto &Tok = Parser.getTok();
953*9880d681SAndroid Build Coastguard Worker   SMLoc StartLoc = Tok.getLoc();
954*9880d681SAndroid Build Coastguard Worker   SMLoc EndLoc = Tok.getEndLoc();
955*9880d681SAndroid Build Coastguard Worker   const MCRegisterInfo *TRI = getContext().getRegisterInfo();
956*9880d681SAndroid Build Coastguard Worker 
957*9880d681SAndroid Build Coastguard Worker   RegisterKind RegKind;
958*9880d681SAndroid Build Coastguard Worker   unsigned Reg, RegNum, RegWidth;
959*9880d681SAndroid Build Coastguard Worker 
960*9880d681SAndroid Build Coastguard Worker   if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) {
961*9880d681SAndroid Build Coastguard Worker     return nullptr;
962*9880d681SAndroid Build Coastguard Worker   }
963*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateReg(Reg, StartLoc, EndLoc,
964*9880d681SAndroid Build Coastguard Worker                                   TRI, &getSTI(), false);
965*9880d681SAndroid Build Coastguard Worker }
966*9880d681SAndroid Build Coastguard Worker 
967*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseImm(OperandVector & Operands)968*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseImm(OperandVector &Operands) {
969*9880d681SAndroid Build Coastguard Worker   bool Minus = false;
970*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Minus) {
971*9880d681SAndroid Build Coastguard Worker     Minus = true;
972*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
973*9880d681SAndroid Build Coastguard Worker   }
974*9880d681SAndroid Build Coastguard Worker 
975*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
976*9880d681SAndroid Build Coastguard Worker   switch(getLexer().getKind()) {
977*9880d681SAndroid Build Coastguard Worker   case AsmToken::Integer: {
978*9880d681SAndroid Build Coastguard Worker     int64_t IntVal;
979*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(IntVal))
980*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
981*9880d681SAndroid Build Coastguard Worker     if (!isInt<32>(IntVal) && !isUInt<32>(IntVal)) {
982*9880d681SAndroid Build Coastguard Worker       Error(S, "invalid immediate: only 32-bit values are legal");
983*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
984*9880d681SAndroid Build Coastguard Worker     }
985*9880d681SAndroid Build Coastguard Worker 
986*9880d681SAndroid Build Coastguard Worker     if (Minus)
987*9880d681SAndroid Build Coastguard Worker       IntVal *= -1;
988*9880d681SAndroid Build Coastguard Worker     Operands.push_back(AMDGPUOperand::CreateImm(IntVal, S));
989*9880d681SAndroid Build Coastguard Worker     return MatchOperand_Success;
990*9880d681SAndroid Build Coastguard Worker   }
991*9880d681SAndroid Build Coastguard Worker   case AsmToken::Real: {
992*9880d681SAndroid Build Coastguard Worker     // FIXME: We should emit an error if a double precisions floating-point
993*9880d681SAndroid Build Coastguard Worker     // value is used.  I'm not sure the best way to detect this.
994*9880d681SAndroid Build Coastguard Worker     int64_t IntVal;
995*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(IntVal))
996*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
997*9880d681SAndroid Build Coastguard Worker 
998*9880d681SAndroid Build Coastguard Worker     APFloat F((float)BitsToDouble(IntVal));
999*9880d681SAndroid Build Coastguard Worker     if (Minus)
1000*9880d681SAndroid Build Coastguard Worker       F.changeSign();
1001*9880d681SAndroid Build Coastguard Worker     Operands.push_back(
1002*9880d681SAndroid Build Coastguard Worker         AMDGPUOperand::CreateImm(F.bitcastToAPInt().getZExtValue(), S,
1003*9880d681SAndroid Build Coastguard Worker                                  AMDGPUOperand::ImmTyNone, true));
1004*9880d681SAndroid Build Coastguard Worker     return MatchOperand_Success;
1005*9880d681SAndroid Build Coastguard Worker   }
1006*9880d681SAndroid Build Coastguard Worker   default:
1007*9880d681SAndroid Build Coastguard Worker     return Minus ? MatchOperand_ParseFail : MatchOperand_NoMatch;
1008*9880d681SAndroid Build Coastguard Worker   }
1009*9880d681SAndroid Build Coastguard Worker }
1010*9880d681SAndroid Build Coastguard Worker 
1011*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseRegOrImm(OperandVector & Operands)1012*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseRegOrImm(OperandVector &Operands) {
1013*9880d681SAndroid Build Coastguard Worker   auto res = parseImm(Operands);
1014*9880d681SAndroid Build Coastguard Worker   if (res != MatchOperand_NoMatch) {
1015*9880d681SAndroid Build Coastguard Worker     return res;
1016*9880d681SAndroid Build Coastguard Worker   }
1017*9880d681SAndroid Build Coastguard Worker 
1018*9880d681SAndroid Build Coastguard Worker   if (auto R = parseRegister()) {
1019*9880d681SAndroid Build Coastguard Worker     assert(R->isReg());
1020*9880d681SAndroid Build Coastguard Worker     R->Reg.IsForcedVOP3 = isForcedVOP3();
1021*9880d681SAndroid Build Coastguard Worker     Operands.push_back(std::move(R));
1022*9880d681SAndroid Build Coastguard Worker     return MatchOperand_Success;
1023*9880d681SAndroid Build Coastguard Worker   }
1024*9880d681SAndroid Build Coastguard Worker   return MatchOperand_ParseFail;
1025*9880d681SAndroid Build Coastguard Worker }
1026*9880d681SAndroid Build Coastguard Worker 
1027*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseRegOrImmWithFPInputMods(OperandVector & Operands)1028*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands) {
1029*9880d681SAndroid Build Coastguard Worker   // XXX: During parsing we can't determine if minus sign means
1030*9880d681SAndroid Build Coastguard Worker   // negate-modifier or negative immediate value.
1031*9880d681SAndroid Build Coastguard Worker   // By default we suppose it is modifier.
1032*9880d681SAndroid Build Coastguard Worker   bool Negate = false, Abs = false, Abs2 = false;
1033*9880d681SAndroid Build Coastguard Worker 
1034*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind()== AsmToken::Minus) {
1035*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1036*9880d681SAndroid Build Coastguard Worker     Negate = true;
1037*9880d681SAndroid Build Coastguard Worker   }
1038*9880d681SAndroid Build Coastguard Worker 
1039*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "abs") {
1040*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1041*9880d681SAndroid Build Coastguard Worker     Abs2 = true;
1042*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::LParen)) {
1043*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected left paren after abs");
1044*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1045*9880d681SAndroid Build Coastguard Worker     }
1046*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1047*9880d681SAndroid Build Coastguard Worker   }
1048*9880d681SAndroid Build Coastguard Worker 
1049*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Pipe) {
1050*9880d681SAndroid Build Coastguard Worker     if (Abs2) {
1051*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected register or immediate");
1052*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1053*9880d681SAndroid Build Coastguard Worker     }
1054*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1055*9880d681SAndroid Build Coastguard Worker     Abs = true;
1056*9880d681SAndroid Build Coastguard Worker   }
1057*9880d681SAndroid Build Coastguard Worker 
1058*9880d681SAndroid Build Coastguard Worker   auto Res = parseRegOrImm(Operands);
1059*9880d681SAndroid Build Coastguard Worker   if (Res != MatchOperand_Success) {
1060*9880d681SAndroid Build Coastguard Worker     return Res;
1061*9880d681SAndroid Build Coastguard Worker   }
1062*9880d681SAndroid Build Coastguard Worker 
1063*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Modifiers Mods = {false, false, false};
1064*9880d681SAndroid Build Coastguard Worker   if (Negate) {
1065*9880d681SAndroid Build Coastguard Worker     Mods.Neg = true;
1066*9880d681SAndroid Build Coastguard Worker   }
1067*9880d681SAndroid Build Coastguard Worker   if (Abs) {
1068*9880d681SAndroid Build Coastguard Worker     if (getLexer().getKind() != AsmToken::Pipe) {
1069*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected vertical bar");
1070*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1071*9880d681SAndroid Build Coastguard Worker     }
1072*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1073*9880d681SAndroid Build Coastguard Worker     Mods.Abs = true;
1074*9880d681SAndroid Build Coastguard Worker   }
1075*9880d681SAndroid Build Coastguard Worker   if (Abs2) {
1076*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::RParen)) {
1077*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected closing parentheses");
1078*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1079*9880d681SAndroid Build Coastguard Worker     }
1080*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1081*9880d681SAndroid Build Coastguard Worker     Mods.Abs = true;
1082*9880d681SAndroid Build Coastguard Worker   }
1083*9880d681SAndroid Build Coastguard Worker 
1084*9880d681SAndroid Build Coastguard Worker   if (Mods.hasFPModifiers()) {
1085*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1086*9880d681SAndroid Build Coastguard Worker     Op.setModifiers(Mods);
1087*9880d681SAndroid Build Coastguard Worker   }
1088*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1089*9880d681SAndroid Build Coastguard Worker }
1090*9880d681SAndroid Build Coastguard Worker 
1091*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseRegOrImmWithIntInputMods(OperandVector & Operands)1092*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands) {
1093*9880d681SAndroid Build Coastguard Worker   bool Sext = false;
1094*9880d681SAndroid Build Coastguard Worker 
1095*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Identifier && Parser.getTok().getString() == "sext") {
1096*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1097*9880d681SAndroid Build Coastguard Worker     Sext = true;
1098*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::LParen)) {
1099*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected left paren after sext");
1100*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1101*9880d681SAndroid Build Coastguard Worker     }
1102*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1103*9880d681SAndroid Build Coastguard Worker   }
1104*9880d681SAndroid Build Coastguard Worker 
1105*9880d681SAndroid Build Coastguard Worker   auto Res = parseRegOrImm(Operands);
1106*9880d681SAndroid Build Coastguard Worker   if (Res != MatchOperand_Success) {
1107*9880d681SAndroid Build Coastguard Worker     return Res;
1108*9880d681SAndroid Build Coastguard Worker   }
1109*9880d681SAndroid Build Coastguard Worker 
1110*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand::Modifiers Mods = {false, false, false};
1111*9880d681SAndroid Build Coastguard Worker   if (Sext) {
1112*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::RParen)) {
1113*9880d681SAndroid Build Coastguard Worker       Error(Parser.getTok().getLoc(), "expected closing parentheses");
1114*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
1115*9880d681SAndroid Build Coastguard Worker     }
1116*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1117*9880d681SAndroid Build Coastguard Worker     Mods.Sext = true;
1118*9880d681SAndroid Build Coastguard Worker   }
1119*9880d681SAndroid Build Coastguard Worker 
1120*9880d681SAndroid Build Coastguard Worker   if (Mods.hasIntModifiers()) {
1121*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
1122*9880d681SAndroid Build Coastguard Worker     Op.setModifiers(Mods);
1123*9880d681SAndroid Build Coastguard Worker   }
1124*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1125*9880d681SAndroid Build Coastguard Worker }
1126*9880d681SAndroid Build Coastguard Worker 
checkTargetMatchPredicate(MCInst & Inst)1127*9880d681SAndroid Build Coastguard Worker unsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
1128*9880d681SAndroid Build Coastguard Worker 
1129*9880d681SAndroid Build Coastguard Worker   uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
1130*9880d681SAndroid Build Coastguard Worker 
1131*9880d681SAndroid Build Coastguard Worker   if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
1132*9880d681SAndroid Build Coastguard Worker       (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
1133*9880d681SAndroid Build Coastguard Worker       (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
1134*9880d681SAndroid Build Coastguard Worker       (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
1135*9880d681SAndroid Build Coastguard Worker     return Match_InvalidOperand;
1136*9880d681SAndroid Build Coastguard Worker 
1137*9880d681SAndroid Build Coastguard Worker   if ((TSFlags & SIInstrFlags::VOP3) &&
1138*9880d681SAndroid Build Coastguard Worker       (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
1139*9880d681SAndroid Build Coastguard Worker       getForcedEncodingSize() != 64)
1140*9880d681SAndroid Build Coastguard Worker     return Match_PreferE32;
1141*9880d681SAndroid Build Coastguard Worker 
1142*9880d681SAndroid Build Coastguard Worker   return Match_Success;
1143*9880d681SAndroid Build Coastguard Worker }
1144*9880d681SAndroid Build Coastguard Worker 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)1145*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1146*9880d681SAndroid Build Coastguard Worker                                               OperandVector &Operands,
1147*9880d681SAndroid Build Coastguard Worker                                               MCStreamer &Out,
1148*9880d681SAndroid Build Coastguard Worker                                               uint64_t &ErrorInfo,
1149*9880d681SAndroid Build Coastguard Worker                                               bool MatchingInlineAsm) {
1150*9880d681SAndroid Build Coastguard Worker   MCInst Inst;
1151*9880d681SAndroid Build Coastguard Worker 
1152*9880d681SAndroid Build Coastguard Worker   switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
1153*9880d681SAndroid Build Coastguard Worker     default: break;
1154*9880d681SAndroid Build Coastguard Worker     case Match_Success:
1155*9880d681SAndroid Build Coastguard Worker       Inst.setLoc(IDLoc);
1156*9880d681SAndroid Build Coastguard Worker       Out.EmitInstruction(Inst, getSTI());
1157*9880d681SAndroid Build Coastguard Worker       return false;
1158*9880d681SAndroid Build Coastguard Worker     case Match_MissingFeature:
1159*9880d681SAndroid Build Coastguard Worker       return Error(IDLoc, "instruction not supported on this GPU");
1160*9880d681SAndroid Build Coastguard Worker 
1161*9880d681SAndroid Build Coastguard Worker     case Match_MnemonicFail:
1162*9880d681SAndroid Build Coastguard Worker       return Error(IDLoc, "unrecognized instruction mnemonic");
1163*9880d681SAndroid Build Coastguard Worker 
1164*9880d681SAndroid Build Coastguard Worker     case Match_InvalidOperand: {
1165*9880d681SAndroid Build Coastguard Worker       SMLoc ErrorLoc = IDLoc;
1166*9880d681SAndroid Build Coastguard Worker       if (ErrorInfo != ~0ULL) {
1167*9880d681SAndroid Build Coastguard Worker         if (ErrorInfo >= Operands.size()) {
1168*9880d681SAndroid Build Coastguard Worker           return Error(IDLoc, "too few operands for instruction");
1169*9880d681SAndroid Build Coastguard Worker         }
1170*9880d681SAndroid Build Coastguard Worker         ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
1171*9880d681SAndroid Build Coastguard Worker         if (ErrorLoc == SMLoc())
1172*9880d681SAndroid Build Coastguard Worker           ErrorLoc = IDLoc;
1173*9880d681SAndroid Build Coastguard Worker       }
1174*9880d681SAndroid Build Coastguard Worker       return Error(ErrorLoc, "invalid operand for instruction");
1175*9880d681SAndroid Build Coastguard Worker     }
1176*9880d681SAndroid Build Coastguard Worker     case Match_PreferE32:
1177*9880d681SAndroid Build Coastguard Worker       return Error(IDLoc, "internal error: instruction without _e64 suffix "
1178*9880d681SAndroid Build Coastguard Worker                           "should be encoded as e32");
1179*9880d681SAndroid Build Coastguard Worker   }
1180*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Implement any new match types added!");
1181*9880d681SAndroid Build Coastguard Worker }
1182*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveMajorMinor(uint32_t & Major,uint32_t & Minor)1183*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
1184*9880d681SAndroid Build Coastguard Worker                                                uint32_t &Minor) {
1185*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1186*9880d681SAndroid Build Coastguard Worker     return TokError("invalid major version");
1187*9880d681SAndroid Build Coastguard Worker 
1188*9880d681SAndroid Build Coastguard Worker   Major = getLexer().getTok().getIntVal();
1189*9880d681SAndroid Build Coastguard Worker   Lex();
1190*9880d681SAndroid Build Coastguard Worker 
1191*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1192*9880d681SAndroid Build Coastguard Worker     return TokError("minor version number required, comma expected");
1193*9880d681SAndroid Build Coastguard Worker   Lex();
1194*9880d681SAndroid Build Coastguard Worker 
1195*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1196*9880d681SAndroid Build Coastguard Worker     return TokError("invalid minor version");
1197*9880d681SAndroid Build Coastguard Worker 
1198*9880d681SAndroid Build Coastguard Worker   Minor = getLexer().getTok().getIntVal();
1199*9880d681SAndroid Build Coastguard Worker   Lex();
1200*9880d681SAndroid Build Coastguard Worker 
1201*9880d681SAndroid Build Coastguard Worker   return false;
1202*9880d681SAndroid Build Coastguard Worker }
1203*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveHSACodeObjectVersion()1204*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
1205*9880d681SAndroid Build Coastguard Worker 
1206*9880d681SAndroid Build Coastguard Worker   uint32_t Major;
1207*9880d681SAndroid Build Coastguard Worker   uint32_t Minor;
1208*9880d681SAndroid Build Coastguard Worker 
1209*9880d681SAndroid Build Coastguard Worker   if (ParseDirectiveMajorMinor(Major, Minor))
1210*9880d681SAndroid Build Coastguard Worker     return true;
1211*9880d681SAndroid Build Coastguard Worker 
1212*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
1213*9880d681SAndroid Build Coastguard Worker   return false;
1214*9880d681SAndroid Build Coastguard Worker }
1215*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveHSACodeObjectISA()1216*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
1217*9880d681SAndroid Build Coastguard Worker 
1218*9880d681SAndroid Build Coastguard Worker   uint32_t Major;
1219*9880d681SAndroid Build Coastguard Worker   uint32_t Minor;
1220*9880d681SAndroid Build Coastguard Worker   uint32_t Stepping;
1221*9880d681SAndroid Build Coastguard Worker   StringRef VendorName;
1222*9880d681SAndroid Build Coastguard Worker   StringRef ArchName;
1223*9880d681SAndroid Build Coastguard Worker 
1224*9880d681SAndroid Build Coastguard Worker   // If this directive has no arguments, then use the ISA version for the
1225*9880d681SAndroid Build Coastguard Worker   // targeted GPU.
1226*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::EndOfStatement)) {
1227*9880d681SAndroid Build Coastguard Worker     AMDGPU::IsaVersion Isa = AMDGPU::getIsaVersion(getSTI().getFeatureBits());
1228*9880d681SAndroid Build Coastguard Worker     getTargetStreamer().EmitDirectiveHSACodeObjectISA(Isa.Major, Isa.Minor,
1229*9880d681SAndroid Build Coastguard Worker                                                       Isa.Stepping,
1230*9880d681SAndroid Build Coastguard Worker                                                       "AMD", "AMDGPU");
1231*9880d681SAndroid Build Coastguard Worker     return false;
1232*9880d681SAndroid Build Coastguard Worker   }
1233*9880d681SAndroid Build Coastguard Worker 
1234*9880d681SAndroid Build Coastguard Worker 
1235*9880d681SAndroid Build Coastguard Worker   if (ParseDirectiveMajorMinor(Major, Minor))
1236*9880d681SAndroid Build Coastguard Worker     return true;
1237*9880d681SAndroid Build Coastguard Worker 
1238*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1239*9880d681SAndroid Build Coastguard Worker     return TokError("stepping version number required, comma expected");
1240*9880d681SAndroid Build Coastguard Worker   Lex();
1241*9880d681SAndroid Build Coastguard Worker 
1242*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1243*9880d681SAndroid Build Coastguard Worker     return TokError("invalid stepping version");
1244*9880d681SAndroid Build Coastguard Worker 
1245*9880d681SAndroid Build Coastguard Worker   Stepping = getLexer().getTok().getIntVal();
1246*9880d681SAndroid Build Coastguard Worker   Lex();
1247*9880d681SAndroid Build Coastguard Worker 
1248*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1249*9880d681SAndroid Build Coastguard Worker     return TokError("vendor name required, comma expected");
1250*9880d681SAndroid Build Coastguard Worker   Lex();
1251*9880d681SAndroid Build Coastguard Worker 
1252*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::String))
1253*9880d681SAndroid Build Coastguard Worker     return TokError("invalid vendor name");
1254*9880d681SAndroid Build Coastguard Worker 
1255*9880d681SAndroid Build Coastguard Worker   VendorName = getLexer().getTok().getStringContents();
1256*9880d681SAndroid Build Coastguard Worker   Lex();
1257*9880d681SAndroid Build Coastguard Worker 
1258*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1259*9880d681SAndroid Build Coastguard Worker     return TokError("arch name required, comma expected");
1260*9880d681SAndroid Build Coastguard Worker   Lex();
1261*9880d681SAndroid Build Coastguard Worker 
1262*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::String))
1263*9880d681SAndroid Build Coastguard Worker     return TokError("invalid arch name");
1264*9880d681SAndroid Build Coastguard Worker 
1265*9880d681SAndroid Build Coastguard Worker   ArchName = getLexer().getTok().getStringContents();
1266*9880d681SAndroid Build Coastguard Worker   Lex();
1267*9880d681SAndroid Build Coastguard Worker 
1268*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
1269*9880d681SAndroid Build Coastguard Worker                                                     VendorName, ArchName);
1270*9880d681SAndroid Build Coastguard Worker   return false;
1271*9880d681SAndroid Build Coastguard Worker }
1272*9880d681SAndroid Build Coastguard Worker 
ParseAMDKernelCodeTValue(StringRef ID,amd_kernel_code_t & Header)1273*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
1274*9880d681SAndroid Build Coastguard Worker                                                amd_kernel_code_t &Header) {
1275*9880d681SAndroid Build Coastguard Worker   SmallString<40> ErrStr;
1276*9880d681SAndroid Build Coastguard Worker   raw_svector_ostream Err(ErrStr);
1277*9880d681SAndroid Build Coastguard Worker   if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
1278*9880d681SAndroid Build Coastguard Worker     return TokError(Err.str());
1279*9880d681SAndroid Build Coastguard Worker   }
1280*9880d681SAndroid Build Coastguard Worker   Lex();
1281*9880d681SAndroid Build Coastguard Worker   return false;
1282*9880d681SAndroid Build Coastguard Worker }
1283*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveAMDKernelCodeT()1284*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
1285*9880d681SAndroid Build Coastguard Worker 
1286*9880d681SAndroid Build Coastguard Worker   amd_kernel_code_t Header;
1287*9880d681SAndroid Build Coastguard Worker   AMDGPU::initDefaultAMDKernelCodeT(Header, getSTI().getFeatureBits());
1288*9880d681SAndroid Build Coastguard Worker 
1289*9880d681SAndroid Build Coastguard Worker   while (true) {
1290*9880d681SAndroid Build Coastguard Worker 
1291*9880d681SAndroid Build Coastguard Worker     // Lex EndOfStatement.  This is in a while loop, because lexing a comment
1292*9880d681SAndroid Build Coastguard Worker     // will set the current token to EndOfStatement.
1293*9880d681SAndroid Build Coastguard Worker     while(getLexer().is(AsmToken::EndOfStatement))
1294*9880d681SAndroid Build Coastguard Worker       Lex();
1295*9880d681SAndroid Build Coastguard Worker 
1296*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Identifier))
1297*9880d681SAndroid Build Coastguard Worker       return TokError("expected value identifier or .end_amd_kernel_code_t");
1298*9880d681SAndroid Build Coastguard Worker 
1299*9880d681SAndroid Build Coastguard Worker     StringRef ID = getLexer().getTok().getIdentifier();
1300*9880d681SAndroid Build Coastguard Worker     Lex();
1301*9880d681SAndroid Build Coastguard Worker 
1302*9880d681SAndroid Build Coastguard Worker     if (ID == ".end_amd_kernel_code_t")
1303*9880d681SAndroid Build Coastguard Worker       break;
1304*9880d681SAndroid Build Coastguard Worker 
1305*9880d681SAndroid Build Coastguard Worker     if (ParseAMDKernelCodeTValue(ID, Header))
1306*9880d681SAndroid Build Coastguard Worker       return true;
1307*9880d681SAndroid Build Coastguard Worker   }
1308*9880d681SAndroid Build Coastguard Worker 
1309*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitAMDKernelCodeT(Header);
1310*9880d681SAndroid Build Coastguard Worker 
1311*9880d681SAndroid Build Coastguard Worker   return false;
1312*9880d681SAndroid Build Coastguard Worker }
1313*9880d681SAndroid Build Coastguard Worker 
ParseSectionDirectiveHSAText()1314*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseSectionDirectiveHSAText() {
1315*9880d681SAndroid Build Coastguard Worker   getParser().getStreamer().SwitchSection(
1316*9880d681SAndroid Build Coastguard Worker       AMDGPU::getHSATextSection(getContext()));
1317*9880d681SAndroid Build Coastguard Worker   return false;
1318*9880d681SAndroid Build Coastguard Worker }
1319*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveAMDGPUHsaKernel()1320*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
1321*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Identifier))
1322*9880d681SAndroid Build Coastguard Worker     return TokError("expected symbol name");
1323*9880d681SAndroid Build Coastguard Worker 
1324*9880d681SAndroid Build Coastguard Worker   StringRef KernelName = Parser.getTok().getString();
1325*9880d681SAndroid Build Coastguard Worker 
1326*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
1327*9880d681SAndroid Build Coastguard Worker                                            ELF::STT_AMDGPU_HSA_KERNEL);
1328*9880d681SAndroid Build Coastguard Worker   Lex();
1329*9880d681SAndroid Build Coastguard Worker   return false;
1330*9880d681SAndroid Build Coastguard Worker }
1331*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveAMDGPUHsaModuleGlobal()1332*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaModuleGlobal() {
1333*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Identifier))
1334*9880d681SAndroid Build Coastguard Worker     return TokError("expected symbol name");
1335*9880d681SAndroid Build Coastguard Worker 
1336*9880d681SAndroid Build Coastguard Worker   StringRef GlobalName = Parser.getTok().getIdentifier();
1337*9880d681SAndroid Build Coastguard Worker 
1338*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitAMDGPUHsaModuleScopeGlobal(GlobalName);
1339*9880d681SAndroid Build Coastguard Worker   Lex();
1340*9880d681SAndroid Build Coastguard Worker   return false;
1341*9880d681SAndroid Build Coastguard Worker }
1342*9880d681SAndroid Build Coastguard Worker 
ParseDirectiveAMDGPUHsaProgramGlobal()1343*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaProgramGlobal() {
1344*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Identifier))
1345*9880d681SAndroid Build Coastguard Worker     return TokError("expected symbol name");
1346*9880d681SAndroid Build Coastguard Worker 
1347*9880d681SAndroid Build Coastguard Worker   StringRef GlobalName = Parser.getTok().getIdentifier();
1348*9880d681SAndroid Build Coastguard Worker 
1349*9880d681SAndroid Build Coastguard Worker   getTargetStreamer().EmitAMDGPUHsaProgramScopeGlobal(GlobalName);
1350*9880d681SAndroid Build Coastguard Worker   Lex();
1351*9880d681SAndroid Build Coastguard Worker   return false;
1352*9880d681SAndroid Build Coastguard Worker }
1353*9880d681SAndroid Build Coastguard Worker 
ParseSectionDirectiveHSADataGlobalAgent()1354*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalAgent() {
1355*9880d681SAndroid Build Coastguard Worker   getParser().getStreamer().SwitchSection(
1356*9880d681SAndroid Build Coastguard Worker       AMDGPU::getHSADataGlobalAgentSection(getContext()));
1357*9880d681SAndroid Build Coastguard Worker   return false;
1358*9880d681SAndroid Build Coastguard Worker }
1359*9880d681SAndroid Build Coastguard Worker 
ParseSectionDirectiveHSADataGlobalProgram()1360*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseSectionDirectiveHSADataGlobalProgram() {
1361*9880d681SAndroid Build Coastguard Worker   getParser().getStreamer().SwitchSection(
1362*9880d681SAndroid Build Coastguard Worker       AMDGPU::getHSADataGlobalProgramSection(getContext()));
1363*9880d681SAndroid Build Coastguard Worker   return false;
1364*9880d681SAndroid Build Coastguard Worker }
1365*9880d681SAndroid Build Coastguard Worker 
ParseSectionDirectiveHSARodataReadonlyAgent()1366*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseSectionDirectiveHSARodataReadonlyAgent() {
1367*9880d681SAndroid Build Coastguard Worker   getParser().getStreamer().SwitchSection(
1368*9880d681SAndroid Build Coastguard Worker       AMDGPU::getHSARodataReadonlyAgentSection(getContext()));
1369*9880d681SAndroid Build Coastguard Worker   return false;
1370*9880d681SAndroid Build Coastguard Worker }
1371*9880d681SAndroid Build Coastguard Worker 
ParseDirective(AsmToken DirectiveID)1372*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
1373*9880d681SAndroid Build Coastguard Worker   StringRef IDVal = DirectiveID.getString();
1374*9880d681SAndroid Build Coastguard Worker 
1375*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsa_code_object_version")
1376*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveHSACodeObjectVersion();
1377*9880d681SAndroid Build Coastguard Worker 
1378*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsa_code_object_isa")
1379*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveHSACodeObjectISA();
1380*9880d681SAndroid Build Coastguard Worker 
1381*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".amd_kernel_code_t")
1382*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveAMDKernelCodeT();
1383*9880d681SAndroid Build Coastguard Worker 
1384*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsatext")
1385*9880d681SAndroid Build Coastguard Worker     return ParseSectionDirectiveHSAText();
1386*9880d681SAndroid Build Coastguard Worker 
1387*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".amdgpu_hsa_kernel")
1388*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveAMDGPUHsaKernel();
1389*9880d681SAndroid Build Coastguard Worker 
1390*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".amdgpu_hsa_module_global")
1391*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveAMDGPUHsaModuleGlobal();
1392*9880d681SAndroid Build Coastguard Worker 
1393*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".amdgpu_hsa_program_global")
1394*9880d681SAndroid Build Coastguard Worker     return ParseDirectiveAMDGPUHsaProgramGlobal();
1395*9880d681SAndroid Build Coastguard Worker 
1396*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsadata_global_agent")
1397*9880d681SAndroid Build Coastguard Worker     return ParseSectionDirectiveHSADataGlobalAgent();
1398*9880d681SAndroid Build Coastguard Worker 
1399*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsadata_global_program")
1400*9880d681SAndroid Build Coastguard Worker     return ParseSectionDirectiveHSADataGlobalProgram();
1401*9880d681SAndroid Build Coastguard Worker 
1402*9880d681SAndroid Build Coastguard Worker   if (IDVal == ".hsarodata_readonly_agent")
1403*9880d681SAndroid Build Coastguard Worker     return ParseSectionDirectiveHSARodataReadonlyAgent();
1404*9880d681SAndroid Build Coastguard Worker 
1405*9880d681SAndroid Build Coastguard Worker   return true;
1406*9880d681SAndroid Build Coastguard Worker }
1407*9880d681SAndroid Build Coastguard Worker 
subtargetHasRegister(const MCRegisterInfo & MRI,unsigned RegNo) const1408*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
1409*9880d681SAndroid Build Coastguard Worker                                            unsigned RegNo) const {
1410*9880d681SAndroid Build Coastguard Worker   if (isCI())
1411*9880d681SAndroid Build Coastguard Worker     return true;
1412*9880d681SAndroid Build Coastguard Worker 
1413*9880d681SAndroid Build Coastguard Worker   if (isSI()) {
1414*9880d681SAndroid Build Coastguard Worker     // No flat_scr
1415*9880d681SAndroid Build Coastguard Worker     switch (RegNo) {
1416*9880d681SAndroid Build Coastguard Worker     case AMDGPU::FLAT_SCR:
1417*9880d681SAndroid Build Coastguard Worker     case AMDGPU::FLAT_SCR_LO:
1418*9880d681SAndroid Build Coastguard Worker     case AMDGPU::FLAT_SCR_HI:
1419*9880d681SAndroid Build Coastguard Worker       return false;
1420*9880d681SAndroid Build Coastguard Worker     default:
1421*9880d681SAndroid Build Coastguard Worker       return true;
1422*9880d681SAndroid Build Coastguard Worker     }
1423*9880d681SAndroid Build Coastguard Worker   }
1424*9880d681SAndroid Build Coastguard Worker 
1425*9880d681SAndroid Build Coastguard Worker   // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
1426*9880d681SAndroid Build Coastguard Worker   // SI/CI have.
1427*9880d681SAndroid Build Coastguard Worker   for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
1428*9880d681SAndroid Build Coastguard Worker        R.isValid(); ++R) {
1429*9880d681SAndroid Build Coastguard Worker     if (*R == RegNo)
1430*9880d681SAndroid Build Coastguard Worker       return false;
1431*9880d681SAndroid Build Coastguard Worker   }
1432*9880d681SAndroid Build Coastguard Worker 
1433*9880d681SAndroid Build Coastguard Worker   return true;
1434*9880d681SAndroid Build Coastguard Worker }
1435*9880d681SAndroid Build Coastguard Worker 
1436*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseOperand(OperandVector & Operands,StringRef Mnemonic)1437*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
1438*9880d681SAndroid Build Coastguard Worker 
1439*9880d681SAndroid Build Coastguard Worker   // Try to parse with a custom parser
1440*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1441*9880d681SAndroid Build Coastguard Worker 
1442*9880d681SAndroid Build Coastguard Worker   // If we successfully parsed the operand or if there as an error parsing,
1443*9880d681SAndroid Build Coastguard Worker   // we are done.
1444*9880d681SAndroid Build Coastguard Worker   //
1445*9880d681SAndroid Build Coastguard Worker   // If we are parsing after we reach EndOfStatement then this means we
1446*9880d681SAndroid Build Coastguard Worker   // are appending default values to the Operands list.  This is only done
1447*9880d681SAndroid Build Coastguard Worker   // by custom parser, so we shouldn't continue on to the generic parsing.
1448*9880d681SAndroid Build Coastguard Worker   if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
1449*9880d681SAndroid Build Coastguard Worker       getLexer().is(AsmToken::EndOfStatement))
1450*9880d681SAndroid Build Coastguard Worker     return ResTy;
1451*9880d681SAndroid Build Coastguard Worker 
1452*9880d681SAndroid Build Coastguard Worker   ResTy = parseRegOrImm(Operands);
1453*9880d681SAndroid Build Coastguard Worker 
1454*9880d681SAndroid Build Coastguard Worker   if (ResTy == MatchOperand_Success)
1455*9880d681SAndroid Build Coastguard Worker     return ResTy;
1456*9880d681SAndroid Build Coastguard Worker 
1457*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Identifier) {
1458*9880d681SAndroid Build Coastguard Worker     // If this identifier is a symbol, we want to create an expression for it.
1459*9880d681SAndroid Build Coastguard Worker     // It is a little difficult to distinguish between a symbol name, and
1460*9880d681SAndroid Build Coastguard Worker     // an instruction flag like 'gds'.  In order to do this, we parse
1461*9880d681SAndroid Build Coastguard Worker     // all tokens as expressions and then treate the symbol name as the token
1462*9880d681SAndroid Build Coastguard Worker     // string when we want to interpret the operand as a token.
1463*9880d681SAndroid Build Coastguard Worker     const auto &Tok = Parser.getTok();
1464*9880d681SAndroid Build Coastguard Worker     SMLoc S = Tok.getLoc();
1465*9880d681SAndroid Build Coastguard Worker     const MCExpr *Expr = nullptr;
1466*9880d681SAndroid Build Coastguard Worker     if (!Parser.parseExpression(Expr)) {
1467*9880d681SAndroid Build Coastguard Worker       Operands.push_back(AMDGPUOperand::CreateExpr(Expr, S));
1468*9880d681SAndroid Build Coastguard Worker       return MatchOperand_Success;
1469*9880d681SAndroid Build Coastguard Worker     }
1470*9880d681SAndroid Build Coastguard Worker 
1471*9880d681SAndroid Build Coastguard Worker     Operands.push_back(AMDGPUOperand::CreateToken(Tok.getString(), Tok.getLoc()));
1472*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1473*9880d681SAndroid Build Coastguard Worker     return MatchOperand_Success;
1474*9880d681SAndroid Build Coastguard Worker   }
1475*9880d681SAndroid Build Coastguard Worker   return MatchOperand_NoMatch;
1476*9880d681SAndroid Build Coastguard Worker }
1477*9880d681SAndroid Build Coastguard Worker 
parseMnemonicSuffix(StringRef Name)1478*9880d681SAndroid Build Coastguard Worker StringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
1479*9880d681SAndroid Build Coastguard Worker   // Clear any forced encodings from the previous instruction.
1480*9880d681SAndroid Build Coastguard Worker   setForcedEncodingSize(0);
1481*9880d681SAndroid Build Coastguard Worker   setForcedDPP(false);
1482*9880d681SAndroid Build Coastguard Worker   setForcedSDWA(false);
1483*9880d681SAndroid Build Coastguard Worker 
1484*9880d681SAndroid Build Coastguard Worker   if (Name.endswith("_e64")) {
1485*9880d681SAndroid Build Coastguard Worker     setForcedEncodingSize(64);
1486*9880d681SAndroid Build Coastguard Worker     return Name.substr(0, Name.size() - 4);
1487*9880d681SAndroid Build Coastguard Worker   } else if (Name.endswith("_e32")) {
1488*9880d681SAndroid Build Coastguard Worker     setForcedEncodingSize(32);
1489*9880d681SAndroid Build Coastguard Worker     return Name.substr(0, Name.size() - 4);
1490*9880d681SAndroid Build Coastguard Worker   } else if (Name.endswith("_dpp")) {
1491*9880d681SAndroid Build Coastguard Worker     setForcedDPP(true);
1492*9880d681SAndroid Build Coastguard Worker     return Name.substr(0, Name.size() - 4);
1493*9880d681SAndroid Build Coastguard Worker   } else if (Name.endswith("_sdwa")) {
1494*9880d681SAndroid Build Coastguard Worker     setForcedSDWA(true);
1495*9880d681SAndroid Build Coastguard Worker     return Name.substr(0, Name.size() - 5);
1496*9880d681SAndroid Build Coastguard Worker   }
1497*9880d681SAndroid Build Coastguard Worker   return Name;
1498*9880d681SAndroid Build Coastguard Worker }
1499*9880d681SAndroid Build Coastguard Worker 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)1500*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
1501*9880d681SAndroid Build Coastguard Worker                                        StringRef Name,
1502*9880d681SAndroid Build Coastguard Worker                                        SMLoc NameLoc, OperandVector &Operands) {
1503*9880d681SAndroid Build Coastguard Worker   // Add the instruction mnemonic
1504*9880d681SAndroid Build Coastguard Worker   Name = parseMnemonicSuffix(Name);
1505*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateToken(Name, NameLoc));
1506*9880d681SAndroid Build Coastguard Worker 
1507*9880d681SAndroid Build Coastguard Worker   while (!getLexer().is(AsmToken::EndOfStatement)) {
1508*9880d681SAndroid Build Coastguard Worker     AMDGPUAsmParser::OperandMatchResultTy Res = parseOperand(Operands, Name);
1509*9880d681SAndroid Build Coastguard Worker 
1510*9880d681SAndroid Build Coastguard Worker     // Eat the comma or space if there is one.
1511*9880d681SAndroid Build Coastguard Worker     if (getLexer().is(AsmToken::Comma))
1512*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
1513*9880d681SAndroid Build Coastguard Worker 
1514*9880d681SAndroid Build Coastguard Worker     switch (Res) {
1515*9880d681SAndroid Build Coastguard Worker       case MatchOperand_Success: break;
1516*9880d681SAndroid Build Coastguard Worker       case MatchOperand_ParseFail:
1517*9880d681SAndroid Build Coastguard Worker         Error(getLexer().getLoc(), "failed parsing operand.");
1518*9880d681SAndroid Build Coastguard Worker         while (!getLexer().is(AsmToken::EndOfStatement)) {
1519*9880d681SAndroid Build Coastguard Worker           Parser.Lex();
1520*9880d681SAndroid Build Coastguard Worker         }
1521*9880d681SAndroid Build Coastguard Worker         return true;
1522*9880d681SAndroid Build Coastguard Worker       case MatchOperand_NoMatch:
1523*9880d681SAndroid Build Coastguard Worker         Error(getLexer().getLoc(), "not a valid operand.");
1524*9880d681SAndroid Build Coastguard Worker         while (!getLexer().is(AsmToken::EndOfStatement)) {
1525*9880d681SAndroid Build Coastguard Worker           Parser.Lex();
1526*9880d681SAndroid Build Coastguard Worker         }
1527*9880d681SAndroid Build Coastguard Worker         return true;
1528*9880d681SAndroid Build Coastguard Worker     }
1529*9880d681SAndroid Build Coastguard Worker   }
1530*9880d681SAndroid Build Coastguard Worker 
1531*9880d681SAndroid Build Coastguard Worker   return false;
1532*9880d681SAndroid Build Coastguard Worker }
1533*9880d681SAndroid Build Coastguard Worker 
1534*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1535*9880d681SAndroid Build Coastguard Worker // Utility functions
1536*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1537*9880d681SAndroid Build Coastguard Worker 
1538*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseIntWithPrefix(const char * Prefix,int64_t & Int)1539*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &Int) {
1540*9880d681SAndroid Build Coastguard Worker   switch(getLexer().getKind()) {
1541*9880d681SAndroid Build Coastguard Worker     default: return MatchOperand_NoMatch;
1542*9880d681SAndroid Build Coastguard Worker     case AsmToken::Identifier: {
1543*9880d681SAndroid Build Coastguard Worker       StringRef Name = Parser.getTok().getString();
1544*9880d681SAndroid Build Coastguard Worker       if (!Name.equals(Prefix)) {
1545*9880d681SAndroid Build Coastguard Worker         return MatchOperand_NoMatch;
1546*9880d681SAndroid Build Coastguard Worker       }
1547*9880d681SAndroid Build Coastguard Worker 
1548*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
1549*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Colon))
1550*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
1551*9880d681SAndroid Build Coastguard Worker 
1552*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
1553*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
1554*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
1555*9880d681SAndroid Build Coastguard Worker 
1556*9880d681SAndroid Build Coastguard Worker       if (getParser().parseAbsoluteExpression(Int))
1557*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
1558*9880d681SAndroid Build Coastguard Worker       break;
1559*9880d681SAndroid Build Coastguard Worker     }
1560*9880d681SAndroid Build Coastguard Worker   }
1561*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1562*9880d681SAndroid Build Coastguard Worker }
1563*9880d681SAndroid Build Coastguard Worker 
1564*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseIntWithPrefix(const char * Prefix,OperandVector & Operands,enum AMDGPUOperand::ImmTy ImmTy,bool (* ConvertResult)(int64_t &))1565*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1566*9880d681SAndroid Build Coastguard Worker                                     enum AMDGPUOperand::ImmTy ImmTy,
1567*9880d681SAndroid Build Coastguard Worker                                     bool (*ConvertResult)(int64_t&)) {
1568*9880d681SAndroid Build Coastguard Worker 
1569*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
1570*9880d681SAndroid Build Coastguard Worker   int64_t Value = 0;
1571*9880d681SAndroid Build Coastguard Worker 
1572*9880d681SAndroid Build Coastguard Worker   AMDGPUAsmParser::OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
1573*9880d681SAndroid Build Coastguard Worker   if (Res != MatchOperand_Success)
1574*9880d681SAndroid Build Coastguard Worker     return Res;
1575*9880d681SAndroid Build Coastguard Worker 
1576*9880d681SAndroid Build Coastguard Worker   if (ConvertResult && !ConvertResult(Value)) {
1577*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
1578*9880d681SAndroid Build Coastguard Worker   }
1579*9880d681SAndroid Build Coastguard Worker 
1580*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Value, S, ImmTy));
1581*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1582*9880d681SAndroid Build Coastguard Worker }
1583*9880d681SAndroid Build Coastguard Worker 
1584*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseNamedBit(const char * Name,OperandVector & Operands,enum AMDGPUOperand::ImmTy ImmTy)1585*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
1586*9880d681SAndroid Build Coastguard Worker                                enum AMDGPUOperand::ImmTy ImmTy) {
1587*9880d681SAndroid Build Coastguard Worker   int64_t Bit = 0;
1588*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
1589*9880d681SAndroid Build Coastguard Worker 
1590*9880d681SAndroid Build Coastguard Worker   // We are at the end of the statement, and this is a default argument, so
1591*9880d681SAndroid Build Coastguard Worker   // use a default value.
1592*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::EndOfStatement)) {
1593*9880d681SAndroid Build Coastguard Worker     switch(getLexer().getKind()) {
1594*9880d681SAndroid Build Coastguard Worker       case AsmToken::Identifier: {
1595*9880d681SAndroid Build Coastguard Worker         StringRef Tok = Parser.getTok().getString();
1596*9880d681SAndroid Build Coastguard Worker         if (Tok == Name) {
1597*9880d681SAndroid Build Coastguard Worker           Bit = 1;
1598*9880d681SAndroid Build Coastguard Worker           Parser.Lex();
1599*9880d681SAndroid Build Coastguard Worker         } else if (Tok.startswith("no") && Tok.endswith(Name)) {
1600*9880d681SAndroid Build Coastguard Worker           Bit = 0;
1601*9880d681SAndroid Build Coastguard Worker           Parser.Lex();
1602*9880d681SAndroid Build Coastguard Worker         } else {
1603*9880d681SAndroid Build Coastguard Worker           return MatchOperand_NoMatch;
1604*9880d681SAndroid Build Coastguard Worker         }
1605*9880d681SAndroid Build Coastguard Worker         break;
1606*9880d681SAndroid Build Coastguard Worker       }
1607*9880d681SAndroid Build Coastguard Worker       default:
1608*9880d681SAndroid Build Coastguard Worker         return MatchOperand_NoMatch;
1609*9880d681SAndroid Build Coastguard Worker     }
1610*9880d681SAndroid Build Coastguard Worker   }
1611*9880d681SAndroid Build Coastguard Worker 
1612*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Bit, S, ImmTy));
1613*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1614*9880d681SAndroid Build Coastguard Worker }
1615*9880d681SAndroid Build Coastguard Worker 
1616*9880d681SAndroid Build Coastguard Worker typedef std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalImmIndexMap;
1617*9880d681SAndroid Build Coastguard Worker 
addOptionalImmOperand(MCInst & Inst,const OperandVector & Operands,OptionalImmIndexMap & OptionalIdx,enum AMDGPUOperand::ImmTy ImmT,int64_t Default=0)1618*9880d681SAndroid Build Coastguard Worker void addOptionalImmOperand(MCInst& Inst, const OperandVector& Operands,
1619*9880d681SAndroid Build Coastguard Worker                            OptionalImmIndexMap& OptionalIdx,
1620*9880d681SAndroid Build Coastguard Worker                            enum AMDGPUOperand::ImmTy ImmT, int64_t Default = 0) {
1621*9880d681SAndroid Build Coastguard Worker   auto i = OptionalIdx.find(ImmT);
1622*9880d681SAndroid Build Coastguard Worker   if (i != OptionalIdx.end()) {
1623*9880d681SAndroid Build Coastguard Worker     unsigned Idx = i->second;
1624*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
1625*9880d681SAndroid Build Coastguard Worker   } else {
1626*9880d681SAndroid Build Coastguard Worker     Inst.addOperand(MCOperand::createImm(Default));
1627*9880d681SAndroid Build Coastguard Worker   }
1628*9880d681SAndroid Build Coastguard Worker }
1629*9880d681SAndroid Build Coastguard Worker 
1630*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseStringWithPrefix(StringRef Prefix,StringRef & Value)1631*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
1632*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Identifier)) {
1633*9880d681SAndroid Build Coastguard Worker     return MatchOperand_NoMatch;
1634*9880d681SAndroid Build Coastguard Worker   }
1635*9880d681SAndroid Build Coastguard Worker   StringRef Tok = Parser.getTok().getString();
1636*9880d681SAndroid Build Coastguard Worker   if (Tok != Prefix) {
1637*9880d681SAndroid Build Coastguard Worker     return MatchOperand_NoMatch;
1638*9880d681SAndroid Build Coastguard Worker   }
1639*9880d681SAndroid Build Coastguard Worker 
1640*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1641*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Colon)) {
1642*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
1643*9880d681SAndroid Build Coastguard Worker   }
1644*9880d681SAndroid Build Coastguard Worker 
1645*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1646*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Identifier)) {
1647*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
1648*9880d681SAndroid Build Coastguard Worker   }
1649*9880d681SAndroid Build Coastguard Worker 
1650*9880d681SAndroid Build Coastguard Worker   Value = Parser.getTok().getString();
1651*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1652*9880d681SAndroid Build Coastguard Worker }
1653*9880d681SAndroid Build Coastguard Worker 
1654*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1655*9880d681SAndroid Build Coastguard Worker // ds
1656*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1657*9880d681SAndroid Build Coastguard Worker 
cvtDSOffset01(MCInst & Inst,const OperandVector & Operands)1658*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
1659*9880d681SAndroid Build Coastguard Worker                                     const OperandVector &Operands) {
1660*9880d681SAndroid Build Coastguard Worker 
1661*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
1662*9880d681SAndroid Build Coastguard Worker 
1663*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1664*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1665*9880d681SAndroid Build Coastguard Worker 
1666*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
1667*9880d681SAndroid Build Coastguard Worker     if (Op.isReg()) {
1668*9880d681SAndroid Build Coastguard Worker       Op.addRegOperands(Inst, 1);
1669*9880d681SAndroid Build Coastguard Worker       continue;
1670*9880d681SAndroid Build Coastguard Worker     }
1671*9880d681SAndroid Build Coastguard Worker 
1672*9880d681SAndroid Build Coastguard Worker     // Handle optional arguments
1673*9880d681SAndroid Build Coastguard Worker     OptionalIdx[Op.getImmTy()] = i;
1674*9880d681SAndroid Build Coastguard Worker   }
1675*9880d681SAndroid Build Coastguard Worker 
1676*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
1677*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
1678*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1679*9880d681SAndroid Build Coastguard Worker 
1680*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1681*9880d681SAndroid Build Coastguard Worker }
1682*9880d681SAndroid Build Coastguard Worker 
cvtDS(MCInst & Inst,const OperandVector & Operands)1683*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtDS(MCInst &Inst, const OperandVector &Operands) {
1684*9880d681SAndroid Build Coastguard Worker 
1685*9880d681SAndroid Build Coastguard Worker   std::map<enum AMDGPUOperand::ImmTy, unsigned> OptionalIdx;
1686*9880d681SAndroid Build Coastguard Worker   bool GDSOnly = false;
1687*9880d681SAndroid Build Coastguard Worker 
1688*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
1689*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
1690*9880d681SAndroid Build Coastguard Worker 
1691*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
1692*9880d681SAndroid Build Coastguard Worker     if (Op.isReg()) {
1693*9880d681SAndroid Build Coastguard Worker       Op.addRegOperands(Inst, 1);
1694*9880d681SAndroid Build Coastguard Worker       continue;
1695*9880d681SAndroid Build Coastguard Worker     }
1696*9880d681SAndroid Build Coastguard Worker 
1697*9880d681SAndroid Build Coastguard Worker     if (Op.isToken() && Op.getToken() == "gds") {
1698*9880d681SAndroid Build Coastguard Worker       GDSOnly = true;
1699*9880d681SAndroid Build Coastguard Worker       continue;
1700*9880d681SAndroid Build Coastguard Worker     }
1701*9880d681SAndroid Build Coastguard Worker 
1702*9880d681SAndroid Build Coastguard Worker     // Handle optional arguments
1703*9880d681SAndroid Build Coastguard Worker     OptionalIdx[Op.getImmTy()] = i;
1704*9880d681SAndroid Build Coastguard Worker   }
1705*9880d681SAndroid Build Coastguard Worker 
1706*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
1707*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1708*9880d681SAndroid Build Coastguard Worker 
1709*9880d681SAndroid Build Coastguard Worker   if (!GDSOnly) {
1710*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
1711*9880d681SAndroid Build Coastguard Worker   }
1712*9880d681SAndroid Build Coastguard Worker   Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
1713*9880d681SAndroid Build Coastguard Worker }
1714*9880d681SAndroid Build Coastguard Worker 
1715*9880d681SAndroid Build Coastguard Worker 
1716*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1717*9880d681SAndroid Build Coastguard Worker // s_waitcnt
1718*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
1719*9880d681SAndroid Build Coastguard Worker 
parseCnt(int64_t & IntVal)1720*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
1721*9880d681SAndroid Build Coastguard Worker   StringRef CntName = Parser.getTok().getString();
1722*9880d681SAndroid Build Coastguard Worker   int64_t CntVal;
1723*9880d681SAndroid Build Coastguard Worker 
1724*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1725*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::LParen))
1726*9880d681SAndroid Build Coastguard Worker     return true;
1727*9880d681SAndroid Build Coastguard Worker 
1728*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1729*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1730*9880d681SAndroid Build Coastguard Worker     return true;
1731*9880d681SAndroid Build Coastguard Worker 
1732*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(CntVal))
1733*9880d681SAndroid Build Coastguard Worker     return true;
1734*9880d681SAndroid Build Coastguard Worker 
1735*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::RParen))
1736*9880d681SAndroid Build Coastguard Worker     return true;
1737*9880d681SAndroid Build Coastguard Worker 
1738*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1739*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Amp) || getLexer().is(AsmToken::Comma))
1740*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1741*9880d681SAndroid Build Coastguard Worker 
1742*9880d681SAndroid Build Coastguard Worker   int CntShift;
1743*9880d681SAndroid Build Coastguard Worker   int CntMask;
1744*9880d681SAndroid Build Coastguard Worker 
1745*9880d681SAndroid Build Coastguard Worker   if (CntName == "vmcnt") {
1746*9880d681SAndroid Build Coastguard Worker     CntMask = 0xf;
1747*9880d681SAndroid Build Coastguard Worker     CntShift = 0;
1748*9880d681SAndroid Build Coastguard Worker   } else if (CntName == "expcnt") {
1749*9880d681SAndroid Build Coastguard Worker     CntMask = 0x7;
1750*9880d681SAndroid Build Coastguard Worker     CntShift = 4;
1751*9880d681SAndroid Build Coastguard Worker   } else if (CntName == "lgkmcnt") {
1752*9880d681SAndroid Build Coastguard Worker     CntMask = 0xf;
1753*9880d681SAndroid Build Coastguard Worker     CntShift = 8;
1754*9880d681SAndroid Build Coastguard Worker   } else {
1755*9880d681SAndroid Build Coastguard Worker     return true;
1756*9880d681SAndroid Build Coastguard Worker   }
1757*9880d681SAndroid Build Coastguard Worker 
1758*9880d681SAndroid Build Coastguard Worker   IntVal &= ~(CntMask << CntShift);
1759*9880d681SAndroid Build Coastguard Worker   IntVal |= (CntVal << CntShift);
1760*9880d681SAndroid Build Coastguard Worker   return false;
1761*9880d681SAndroid Build Coastguard Worker }
1762*9880d681SAndroid Build Coastguard Worker 
1763*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseSWaitCntOps(OperandVector & Operands)1764*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
1765*9880d681SAndroid Build Coastguard Worker   // Disable all counters by default.
1766*9880d681SAndroid Build Coastguard Worker   // vmcnt   [3:0]
1767*9880d681SAndroid Build Coastguard Worker   // expcnt  [6:4]
1768*9880d681SAndroid Build Coastguard Worker   // lgkmcnt [11:8]
1769*9880d681SAndroid Build Coastguard Worker   int64_t CntVal = 0xf7f;
1770*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
1771*9880d681SAndroid Build Coastguard Worker 
1772*9880d681SAndroid Build Coastguard Worker   switch(getLexer().getKind()) {
1773*9880d681SAndroid Build Coastguard Worker     default: return MatchOperand_ParseFail;
1774*9880d681SAndroid Build Coastguard Worker     case AsmToken::Integer:
1775*9880d681SAndroid Build Coastguard Worker       // The operand can be an integer value.
1776*9880d681SAndroid Build Coastguard Worker       if (getParser().parseAbsoluteExpression(CntVal))
1777*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
1778*9880d681SAndroid Build Coastguard Worker       break;
1779*9880d681SAndroid Build Coastguard Worker 
1780*9880d681SAndroid Build Coastguard Worker     case AsmToken::Identifier:
1781*9880d681SAndroid Build Coastguard Worker       do {
1782*9880d681SAndroid Build Coastguard Worker         if (parseCnt(CntVal))
1783*9880d681SAndroid Build Coastguard Worker           return MatchOperand_ParseFail;
1784*9880d681SAndroid Build Coastguard Worker       } while(getLexer().isNot(AsmToken::EndOfStatement));
1785*9880d681SAndroid Build Coastguard Worker       break;
1786*9880d681SAndroid Build Coastguard Worker   }
1787*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(CntVal, S));
1788*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1789*9880d681SAndroid Build Coastguard Worker }
1790*9880d681SAndroid Build Coastguard Worker 
parseHwregConstruct(OperandInfoTy & HwReg,int64_t & Offset,int64_t & Width)1791*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::parseHwregConstruct(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width) {
1792*9880d681SAndroid Build Coastguard Worker   using namespace llvm::AMDGPU::Hwreg;
1793*9880d681SAndroid Build Coastguard Worker 
1794*9880d681SAndroid Build Coastguard Worker   if (Parser.getTok().getString() != "hwreg")
1795*9880d681SAndroid Build Coastguard Worker     return true;
1796*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1797*9880d681SAndroid Build Coastguard Worker 
1798*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::LParen))
1799*9880d681SAndroid Build Coastguard Worker     return true;
1800*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1801*9880d681SAndroid Build Coastguard Worker 
1802*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Identifier)) {
1803*9880d681SAndroid Build Coastguard Worker     HwReg.IsSymbolic = true;
1804*9880d681SAndroid Build Coastguard Worker     HwReg.Id = ID_UNKNOWN_;
1805*9880d681SAndroid Build Coastguard Worker     const StringRef tok = Parser.getTok().getString();
1806*9880d681SAndroid Build Coastguard Worker     for (int i = ID_SYMBOLIC_FIRST_; i < ID_SYMBOLIC_LAST_; ++i) {
1807*9880d681SAndroid Build Coastguard Worker       if (tok == IdSymbolic[i]) {
1808*9880d681SAndroid Build Coastguard Worker         HwReg.Id = i;
1809*9880d681SAndroid Build Coastguard Worker         break;
1810*9880d681SAndroid Build Coastguard Worker       }
1811*9880d681SAndroid Build Coastguard Worker     }
1812*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1813*9880d681SAndroid Build Coastguard Worker   } else {
1814*9880d681SAndroid Build Coastguard Worker     HwReg.IsSymbolic = false;
1815*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Integer))
1816*9880d681SAndroid Build Coastguard Worker       return true;
1817*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(HwReg.Id))
1818*9880d681SAndroid Build Coastguard Worker       return true;
1819*9880d681SAndroid Build Coastguard Worker   }
1820*9880d681SAndroid Build Coastguard Worker 
1821*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::RParen)) {
1822*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1823*9880d681SAndroid Build Coastguard Worker     return false;
1824*9880d681SAndroid Build Coastguard Worker   }
1825*9880d681SAndroid Build Coastguard Worker 
1826*9880d681SAndroid Build Coastguard Worker   // optional params
1827*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1828*9880d681SAndroid Build Coastguard Worker     return true;
1829*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1830*9880d681SAndroid Build Coastguard Worker 
1831*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1832*9880d681SAndroid Build Coastguard Worker     return true;
1833*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Offset))
1834*9880d681SAndroid Build Coastguard Worker     return true;
1835*9880d681SAndroid Build Coastguard Worker 
1836*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1837*9880d681SAndroid Build Coastguard Worker     return true;
1838*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1839*9880d681SAndroid Build Coastguard Worker 
1840*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Integer))
1841*9880d681SAndroid Build Coastguard Worker     return true;
1842*9880d681SAndroid Build Coastguard Worker   if (getParser().parseAbsoluteExpression(Width))
1843*9880d681SAndroid Build Coastguard Worker     return true;
1844*9880d681SAndroid Build Coastguard Worker 
1845*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::RParen))
1846*9880d681SAndroid Build Coastguard Worker     return true;
1847*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1848*9880d681SAndroid Build Coastguard Worker 
1849*9880d681SAndroid Build Coastguard Worker   return false;
1850*9880d681SAndroid Build Coastguard Worker }
1851*9880d681SAndroid Build Coastguard Worker 
1852*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseHwreg(OperandVector & Operands)1853*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
1854*9880d681SAndroid Build Coastguard Worker   using namespace llvm::AMDGPU::Hwreg;
1855*9880d681SAndroid Build Coastguard Worker 
1856*9880d681SAndroid Build Coastguard Worker   int64_t Imm16Val = 0;
1857*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
1858*9880d681SAndroid Build Coastguard Worker 
1859*9880d681SAndroid Build Coastguard Worker   switch(getLexer().getKind()) {
1860*9880d681SAndroid Build Coastguard Worker     default: return MatchOperand_NoMatch;
1861*9880d681SAndroid Build Coastguard Worker     case AsmToken::Integer:
1862*9880d681SAndroid Build Coastguard Worker       // The operand can be an integer value.
1863*9880d681SAndroid Build Coastguard Worker       if (getParser().parseAbsoluteExpression(Imm16Val))
1864*9880d681SAndroid Build Coastguard Worker         return MatchOperand_NoMatch;
1865*9880d681SAndroid Build Coastguard Worker       if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
1866*9880d681SAndroid Build Coastguard Worker         Error(S, "invalid immediate: only 16-bit values are legal");
1867*9880d681SAndroid Build Coastguard Worker         // Do not return error code, but create an imm operand anyway and proceed
1868*9880d681SAndroid Build Coastguard Worker         // to the next operand, if any. That avoids unneccessary error messages.
1869*9880d681SAndroid Build Coastguard Worker       }
1870*9880d681SAndroid Build Coastguard Worker       break;
1871*9880d681SAndroid Build Coastguard Worker 
1872*9880d681SAndroid Build Coastguard Worker     case AsmToken::Identifier: {
1873*9880d681SAndroid Build Coastguard Worker         OperandInfoTy HwReg(ID_UNKNOWN_);
1874*9880d681SAndroid Build Coastguard Worker         int64_t Offset = OFFSET_DEFAULT_;
1875*9880d681SAndroid Build Coastguard Worker         int64_t Width = WIDTH_M1_DEFAULT_ + 1;
1876*9880d681SAndroid Build Coastguard Worker         if (parseHwregConstruct(HwReg, Offset, Width))
1877*9880d681SAndroid Build Coastguard Worker           return MatchOperand_ParseFail;
1878*9880d681SAndroid Build Coastguard Worker         if (HwReg.Id < 0 || !isUInt<ID_WIDTH_>(HwReg.Id)) {
1879*9880d681SAndroid Build Coastguard Worker           if (HwReg.IsSymbolic)
1880*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid symbolic name of hardware register");
1881*9880d681SAndroid Build Coastguard Worker           else
1882*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid code of hardware register: only 6-bit values are legal");
1883*9880d681SAndroid Build Coastguard Worker         }
1884*9880d681SAndroid Build Coastguard Worker         if (Offset < 0 || !isUInt<OFFSET_WIDTH_>(Offset))
1885*9880d681SAndroid Build Coastguard Worker           Error(S, "invalid bit offset: only 5-bit values are legal");
1886*9880d681SAndroid Build Coastguard Worker         if ((Width-1) < 0 || !isUInt<WIDTH_M1_WIDTH_>(Width-1))
1887*9880d681SAndroid Build Coastguard Worker           Error(S, "invalid bitfield width: only values from 1 to 32 are legal");
1888*9880d681SAndroid Build Coastguard Worker         Imm16Val = (HwReg.Id << ID_SHIFT_) | (Offset << OFFSET_SHIFT_) | ((Width-1) << WIDTH_M1_SHIFT_);
1889*9880d681SAndroid Build Coastguard Worker       }
1890*9880d681SAndroid Build Coastguard Worker       break;
1891*9880d681SAndroid Build Coastguard Worker   }
1892*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTyHwreg));
1893*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
1894*9880d681SAndroid Build Coastguard Worker }
1895*9880d681SAndroid Build Coastguard Worker 
isSWaitCnt() const1896*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isSWaitCnt() const {
1897*9880d681SAndroid Build Coastguard Worker   return isImm();
1898*9880d681SAndroid Build Coastguard Worker }
1899*9880d681SAndroid Build Coastguard Worker 
isHwreg() const1900*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isHwreg() const {
1901*9880d681SAndroid Build Coastguard Worker   return isImmTy(ImmTyHwreg);
1902*9880d681SAndroid Build Coastguard Worker }
1903*9880d681SAndroid Build Coastguard Worker 
parseSendMsgConstruct(OperandInfoTy & Msg,OperandInfoTy & Operation,int64_t & StreamId)1904*9880d681SAndroid Build Coastguard Worker bool AMDGPUAsmParser::parseSendMsgConstruct(OperandInfoTy &Msg, OperandInfoTy &Operation, int64_t &StreamId) {
1905*9880d681SAndroid Build Coastguard Worker   using namespace llvm::AMDGPU::SendMsg;
1906*9880d681SAndroid Build Coastguard Worker 
1907*9880d681SAndroid Build Coastguard Worker   if (Parser.getTok().getString() != "sendmsg")
1908*9880d681SAndroid Build Coastguard Worker     return true;
1909*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1910*9880d681SAndroid Build Coastguard Worker 
1911*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::LParen))
1912*9880d681SAndroid Build Coastguard Worker     return true;
1913*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1914*9880d681SAndroid Build Coastguard Worker 
1915*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Identifier)) {
1916*9880d681SAndroid Build Coastguard Worker     Msg.IsSymbolic = true;
1917*9880d681SAndroid Build Coastguard Worker     Msg.Id = ID_UNKNOWN_;
1918*9880d681SAndroid Build Coastguard Worker     const std::string tok = Parser.getTok().getString();
1919*9880d681SAndroid Build Coastguard Worker     for (int i = ID_GAPS_FIRST_; i < ID_GAPS_LAST_; ++i) {
1920*9880d681SAndroid Build Coastguard Worker       switch(i) {
1921*9880d681SAndroid Build Coastguard Worker         default: continue; // Omit gaps.
1922*9880d681SAndroid Build Coastguard Worker         case ID_INTERRUPT: case ID_GS: case ID_GS_DONE:  case ID_SYSMSG: break;
1923*9880d681SAndroid Build Coastguard Worker       }
1924*9880d681SAndroid Build Coastguard Worker       if (tok == IdSymbolic[i]) {
1925*9880d681SAndroid Build Coastguard Worker         Msg.Id = i;
1926*9880d681SAndroid Build Coastguard Worker         break;
1927*9880d681SAndroid Build Coastguard Worker       }
1928*9880d681SAndroid Build Coastguard Worker     }
1929*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1930*9880d681SAndroid Build Coastguard Worker   } else {
1931*9880d681SAndroid Build Coastguard Worker     Msg.IsSymbolic = false;
1932*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Integer))
1933*9880d681SAndroid Build Coastguard Worker       return true;
1934*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(Msg.Id))
1935*9880d681SAndroid Build Coastguard Worker       return true;
1936*9880d681SAndroid Build Coastguard Worker     if (getLexer().is(AsmToken::Integer))
1937*9880d681SAndroid Build Coastguard Worker       if (getParser().parseAbsoluteExpression(Msg.Id))
1938*9880d681SAndroid Build Coastguard Worker         Msg.Id = ID_UNKNOWN_;
1939*9880d681SAndroid Build Coastguard Worker   }
1940*9880d681SAndroid Build Coastguard Worker   if (Msg.Id == ID_UNKNOWN_) // Don't know how to parse the rest.
1941*9880d681SAndroid Build Coastguard Worker     return false;
1942*9880d681SAndroid Build Coastguard Worker 
1943*9880d681SAndroid Build Coastguard Worker   if (!(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG)) {
1944*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::RParen))
1945*9880d681SAndroid Build Coastguard Worker       return true;
1946*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1947*9880d681SAndroid Build Coastguard Worker     return false;
1948*9880d681SAndroid Build Coastguard Worker   }
1949*9880d681SAndroid Build Coastguard Worker 
1950*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::Comma))
1951*9880d681SAndroid Build Coastguard Worker     return true;
1952*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1953*9880d681SAndroid Build Coastguard Worker 
1954*9880d681SAndroid Build Coastguard Worker   assert(Msg.Id == ID_GS || Msg.Id == ID_GS_DONE || Msg.Id == ID_SYSMSG);
1955*9880d681SAndroid Build Coastguard Worker   Operation.Id = ID_UNKNOWN_;
1956*9880d681SAndroid Build Coastguard Worker   if (getLexer().is(AsmToken::Identifier)) {
1957*9880d681SAndroid Build Coastguard Worker     Operation.IsSymbolic = true;
1958*9880d681SAndroid Build Coastguard Worker     const char* const *S = (Msg.Id == ID_SYSMSG) ? OpSysSymbolic : OpGsSymbolic;
1959*9880d681SAndroid Build Coastguard Worker     const int F = (Msg.Id == ID_SYSMSG) ? OP_SYS_FIRST_ : OP_GS_FIRST_;
1960*9880d681SAndroid Build Coastguard Worker     const int L = (Msg.Id == ID_SYSMSG) ? OP_SYS_LAST_ : OP_GS_LAST_;
1961*9880d681SAndroid Build Coastguard Worker     const StringRef Tok = Parser.getTok().getString();
1962*9880d681SAndroid Build Coastguard Worker     for (int i = F; i < L; ++i) {
1963*9880d681SAndroid Build Coastguard Worker       if (Tok == S[i]) {
1964*9880d681SAndroid Build Coastguard Worker         Operation.Id = i;
1965*9880d681SAndroid Build Coastguard Worker         break;
1966*9880d681SAndroid Build Coastguard Worker       }
1967*9880d681SAndroid Build Coastguard Worker     }
1968*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1969*9880d681SAndroid Build Coastguard Worker   } else {
1970*9880d681SAndroid Build Coastguard Worker     Operation.IsSymbolic = false;
1971*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Integer))
1972*9880d681SAndroid Build Coastguard Worker       return true;
1973*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(Operation.Id))
1974*9880d681SAndroid Build Coastguard Worker       return true;
1975*9880d681SAndroid Build Coastguard Worker   }
1976*9880d681SAndroid Build Coastguard Worker 
1977*9880d681SAndroid Build Coastguard Worker   if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
1978*9880d681SAndroid Build Coastguard Worker     // Stream id is optional.
1979*9880d681SAndroid Build Coastguard Worker     if (getLexer().is(AsmToken::RParen)) {
1980*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
1981*9880d681SAndroid Build Coastguard Worker       return false;
1982*9880d681SAndroid Build Coastguard Worker     }
1983*9880d681SAndroid Build Coastguard Worker 
1984*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Comma))
1985*9880d681SAndroid Build Coastguard Worker       return true;
1986*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
1987*9880d681SAndroid Build Coastguard Worker 
1988*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Integer))
1989*9880d681SAndroid Build Coastguard Worker       return true;
1990*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(StreamId))
1991*9880d681SAndroid Build Coastguard Worker       return true;
1992*9880d681SAndroid Build Coastguard Worker   }
1993*9880d681SAndroid Build Coastguard Worker 
1994*9880d681SAndroid Build Coastguard Worker   if (getLexer().isNot(AsmToken::RParen))
1995*9880d681SAndroid Build Coastguard Worker     return true;
1996*9880d681SAndroid Build Coastguard Worker   Parser.Lex();
1997*9880d681SAndroid Build Coastguard Worker   return false;
1998*9880d681SAndroid Build Coastguard Worker }
1999*9880d681SAndroid Build Coastguard Worker 
2000*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseSendMsgOp(OperandVector & Operands)2001*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
2002*9880d681SAndroid Build Coastguard Worker   using namespace llvm::AMDGPU::SendMsg;
2003*9880d681SAndroid Build Coastguard Worker 
2004*9880d681SAndroid Build Coastguard Worker   int64_t Imm16Val = 0;
2005*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
2006*9880d681SAndroid Build Coastguard Worker 
2007*9880d681SAndroid Build Coastguard Worker   switch(getLexer().getKind()) {
2008*9880d681SAndroid Build Coastguard Worker   default:
2009*9880d681SAndroid Build Coastguard Worker     return MatchOperand_NoMatch;
2010*9880d681SAndroid Build Coastguard Worker   case AsmToken::Integer:
2011*9880d681SAndroid Build Coastguard Worker     // The operand can be an integer value.
2012*9880d681SAndroid Build Coastguard Worker     if (getParser().parseAbsoluteExpression(Imm16Val))
2013*9880d681SAndroid Build Coastguard Worker       return MatchOperand_NoMatch;
2014*9880d681SAndroid Build Coastguard Worker     if (Imm16Val < 0 || !isUInt<16>(Imm16Val)) {
2015*9880d681SAndroid Build Coastguard Worker       Error(S, "invalid immediate: only 16-bit values are legal");
2016*9880d681SAndroid Build Coastguard Worker       // Do not return error code, but create an imm operand anyway and proceed
2017*9880d681SAndroid Build Coastguard Worker       // to the next operand, if any. That avoids unneccessary error messages.
2018*9880d681SAndroid Build Coastguard Worker     }
2019*9880d681SAndroid Build Coastguard Worker     break;
2020*9880d681SAndroid Build Coastguard Worker   case AsmToken::Identifier: {
2021*9880d681SAndroid Build Coastguard Worker       OperandInfoTy Msg(ID_UNKNOWN_);
2022*9880d681SAndroid Build Coastguard Worker       OperandInfoTy Operation(OP_UNKNOWN_);
2023*9880d681SAndroid Build Coastguard Worker       int64_t StreamId = STREAM_ID_DEFAULT_;
2024*9880d681SAndroid Build Coastguard Worker       if (parseSendMsgConstruct(Msg, Operation, StreamId))
2025*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2026*9880d681SAndroid Build Coastguard Worker       do {
2027*9880d681SAndroid Build Coastguard Worker         // Validate and encode message ID.
2028*9880d681SAndroid Build Coastguard Worker         if (! ((ID_INTERRUPT <= Msg.Id && Msg.Id <= ID_GS_DONE)
2029*9880d681SAndroid Build Coastguard Worker                 || Msg.Id == ID_SYSMSG)) {
2030*9880d681SAndroid Build Coastguard Worker           if (Msg.IsSymbolic)
2031*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid/unsupported symbolic name of message");
2032*9880d681SAndroid Build Coastguard Worker           else
2033*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid/unsupported code of message");
2034*9880d681SAndroid Build Coastguard Worker           break;
2035*9880d681SAndroid Build Coastguard Worker         }
2036*9880d681SAndroid Build Coastguard Worker         Imm16Val = (Msg.Id << ID_SHIFT_);
2037*9880d681SAndroid Build Coastguard Worker         // Validate and encode operation ID.
2038*9880d681SAndroid Build Coastguard Worker         if (Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) {
2039*9880d681SAndroid Build Coastguard Worker           if (! (OP_GS_FIRST_ <= Operation.Id && Operation.Id < OP_GS_LAST_)) {
2040*9880d681SAndroid Build Coastguard Worker             if (Operation.IsSymbolic)
2041*9880d681SAndroid Build Coastguard Worker               Error(S, "invalid symbolic name of GS_OP");
2042*9880d681SAndroid Build Coastguard Worker             else
2043*9880d681SAndroid Build Coastguard Worker               Error(S, "invalid code of GS_OP: only 2-bit values are legal");
2044*9880d681SAndroid Build Coastguard Worker             break;
2045*9880d681SAndroid Build Coastguard Worker           }
2046*9880d681SAndroid Build Coastguard Worker           if (Operation.Id == OP_GS_NOP
2047*9880d681SAndroid Build Coastguard Worker               && Msg.Id != ID_GS_DONE) {
2048*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid GS_OP: NOP is for GS_DONE only");
2049*9880d681SAndroid Build Coastguard Worker             break;
2050*9880d681SAndroid Build Coastguard Worker           }
2051*9880d681SAndroid Build Coastguard Worker           Imm16Val |= (Operation.Id << OP_SHIFT_);
2052*9880d681SAndroid Build Coastguard Worker         }
2053*9880d681SAndroid Build Coastguard Worker         if (Msg.Id == ID_SYSMSG) {
2054*9880d681SAndroid Build Coastguard Worker           if (! (OP_SYS_FIRST_ <= Operation.Id && Operation.Id < OP_SYS_LAST_)) {
2055*9880d681SAndroid Build Coastguard Worker             if (Operation.IsSymbolic)
2056*9880d681SAndroid Build Coastguard Worker               Error(S, "invalid/unsupported symbolic name of SYSMSG_OP");
2057*9880d681SAndroid Build Coastguard Worker             else
2058*9880d681SAndroid Build Coastguard Worker               Error(S, "invalid/unsupported code of SYSMSG_OP");
2059*9880d681SAndroid Build Coastguard Worker             break;
2060*9880d681SAndroid Build Coastguard Worker           }
2061*9880d681SAndroid Build Coastguard Worker           Imm16Val |= (Operation.Id << OP_SHIFT_);
2062*9880d681SAndroid Build Coastguard Worker         }
2063*9880d681SAndroid Build Coastguard Worker         // Validate and encode stream ID.
2064*9880d681SAndroid Build Coastguard Worker         if ((Msg.Id == ID_GS || Msg.Id == ID_GS_DONE) && Operation.Id != OP_GS_NOP) {
2065*9880d681SAndroid Build Coastguard Worker           if (! (STREAM_ID_FIRST_ <= StreamId && StreamId < STREAM_ID_LAST_)) {
2066*9880d681SAndroid Build Coastguard Worker             Error(S, "invalid stream id: only 2-bit values are legal");
2067*9880d681SAndroid Build Coastguard Worker             break;
2068*9880d681SAndroid Build Coastguard Worker           }
2069*9880d681SAndroid Build Coastguard Worker           Imm16Val |= (StreamId << STREAM_ID_SHIFT_);
2070*9880d681SAndroid Build Coastguard Worker         }
2071*9880d681SAndroid Build Coastguard Worker       } while (0);
2072*9880d681SAndroid Build Coastguard Worker     }
2073*9880d681SAndroid Build Coastguard Worker     break;
2074*9880d681SAndroid Build Coastguard Worker   }
2075*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Imm16Val, S, AMDGPUOperand::ImmTySendMsg));
2076*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
2077*9880d681SAndroid Build Coastguard Worker }
2078*9880d681SAndroid Build Coastguard Worker 
isSendMsg() const2079*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isSendMsg() const {
2080*9880d681SAndroid Build Coastguard Worker   return isImmTy(ImmTySendMsg);
2081*9880d681SAndroid Build Coastguard Worker }
2082*9880d681SAndroid Build Coastguard Worker 
2083*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2084*9880d681SAndroid Build Coastguard Worker // sopp branch targets
2085*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2086*9880d681SAndroid Build Coastguard Worker 
2087*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseSOppBrTarget(OperandVector & Operands)2088*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
2089*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
2090*9880d681SAndroid Build Coastguard Worker 
2091*9880d681SAndroid Build Coastguard Worker   switch (getLexer().getKind()) {
2092*9880d681SAndroid Build Coastguard Worker     default: return MatchOperand_ParseFail;
2093*9880d681SAndroid Build Coastguard Worker     case AsmToken::Integer: {
2094*9880d681SAndroid Build Coastguard Worker       int64_t Imm;
2095*9880d681SAndroid Build Coastguard Worker       if (getParser().parseAbsoluteExpression(Imm))
2096*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2097*9880d681SAndroid Build Coastguard Worker       Operands.push_back(AMDGPUOperand::CreateImm(Imm, S));
2098*9880d681SAndroid Build Coastguard Worker       return MatchOperand_Success;
2099*9880d681SAndroid Build Coastguard Worker     }
2100*9880d681SAndroid Build Coastguard Worker 
2101*9880d681SAndroid Build Coastguard Worker     case AsmToken::Identifier:
2102*9880d681SAndroid Build Coastguard Worker       Operands.push_back(AMDGPUOperand::CreateExpr(
2103*9880d681SAndroid Build Coastguard Worker           MCSymbolRefExpr::create(getContext().getOrCreateSymbol(
2104*9880d681SAndroid Build Coastguard Worker                                   Parser.getTok().getString()), getContext()), S));
2105*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2106*9880d681SAndroid Build Coastguard Worker       return MatchOperand_Success;
2107*9880d681SAndroid Build Coastguard Worker   }
2108*9880d681SAndroid Build Coastguard Worker }
2109*9880d681SAndroid Build Coastguard Worker 
2110*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2111*9880d681SAndroid Build Coastguard Worker // mubuf
2112*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2113*9880d681SAndroid Build Coastguard Worker 
defaultGLC() const2114*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
2115*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyGLC);
2116*9880d681SAndroid Build Coastguard Worker }
2117*9880d681SAndroid Build Coastguard Worker 
defaultSLC() const2118*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
2119*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTySLC);
2120*9880d681SAndroid Build Coastguard Worker }
2121*9880d681SAndroid Build Coastguard Worker 
defaultTFE() const2122*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultTFE() const {
2123*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyTFE);
2124*9880d681SAndroid Build Coastguard Worker }
2125*9880d681SAndroid Build Coastguard Worker 
cvtMubufImpl(MCInst & Inst,const OperandVector & Operands,bool IsAtomic,bool IsAtomicReturn)2126*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
2127*9880d681SAndroid Build Coastguard Worker                                const OperandVector &Operands,
2128*9880d681SAndroid Build Coastguard Worker                                bool IsAtomic, bool IsAtomicReturn) {
2129*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2130*9880d681SAndroid Build Coastguard Worker   assert(IsAtomicReturn ? IsAtomic : true);
2131*9880d681SAndroid Build Coastguard Worker 
2132*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
2133*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
2134*9880d681SAndroid Build Coastguard Worker 
2135*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
2136*9880d681SAndroid Build Coastguard Worker     if (Op.isReg()) {
2137*9880d681SAndroid Build Coastguard Worker       Op.addRegOperands(Inst, 1);
2138*9880d681SAndroid Build Coastguard Worker       continue;
2139*9880d681SAndroid Build Coastguard Worker     }
2140*9880d681SAndroid Build Coastguard Worker 
2141*9880d681SAndroid Build Coastguard Worker     // Handle the case where soffset is an immediate
2142*9880d681SAndroid Build Coastguard Worker     if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
2143*9880d681SAndroid Build Coastguard Worker       Op.addImmOperands(Inst, 1);
2144*9880d681SAndroid Build Coastguard Worker       continue;
2145*9880d681SAndroid Build Coastguard Worker     }
2146*9880d681SAndroid Build Coastguard Worker 
2147*9880d681SAndroid Build Coastguard Worker     // Handle tokens like 'offen' which are sometimes hard-coded into the
2148*9880d681SAndroid Build Coastguard Worker     // asm string.  There are no MCInst operands for these.
2149*9880d681SAndroid Build Coastguard Worker     if (Op.isToken()) {
2150*9880d681SAndroid Build Coastguard Worker       continue;
2151*9880d681SAndroid Build Coastguard Worker     }
2152*9880d681SAndroid Build Coastguard Worker     assert(Op.isImm());
2153*9880d681SAndroid Build Coastguard Worker 
2154*9880d681SAndroid Build Coastguard Worker     // Handle optional arguments
2155*9880d681SAndroid Build Coastguard Worker     OptionalIdx[Op.getImmTy()] = i;
2156*9880d681SAndroid Build Coastguard Worker   }
2157*9880d681SAndroid Build Coastguard Worker 
2158*9880d681SAndroid Build Coastguard Worker   // Copy $vdata_in operand and insert as $vdata for MUBUF_Atomic RTN insns.
2159*9880d681SAndroid Build Coastguard Worker   if (IsAtomicReturn) {
2160*9880d681SAndroid Build Coastguard Worker     MCInst::iterator I = Inst.begin(); // $vdata_in is always at the beginning.
2161*9880d681SAndroid Build Coastguard Worker     Inst.insert(I, *I);
2162*9880d681SAndroid Build Coastguard Worker   }
2163*9880d681SAndroid Build Coastguard Worker 
2164*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
2165*9880d681SAndroid Build Coastguard Worker   if (!IsAtomic) { // glc is hard-coded.
2166*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2167*9880d681SAndroid Build Coastguard Worker   }
2168*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2169*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2170*9880d681SAndroid Build Coastguard Worker }
2171*9880d681SAndroid Build Coastguard Worker 
2172*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2173*9880d681SAndroid Build Coastguard Worker // mimg
2174*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2175*9880d681SAndroid Build Coastguard Worker 
cvtMIMG(MCInst & Inst,const OperandVector & Operands)2176*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands) {
2177*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2178*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2179*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2180*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2181*9880d681SAndroid Build Coastguard Worker   }
2182*9880d681SAndroid Build Coastguard Worker 
2183*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2184*9880d681SAndroid Build Coastguard Worker 
2185*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I) {
2186*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2187*9880d681SAndroid Build Coastguard Worker 
2188*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
2189*9880d681SAndroid Build Coastguard Worker     if (Op.isRegOrImm()) {
2190*9880d681SAndroid Build Coastguard Worker       Op.addRegOrImmOperands(Inst, 1);
2191*9880d681SAndroid Build Coastguard Worker       continue;
2192*9880d681SAndroid Build Coastguard Worker     } else if (Op.isImmModifier()) {
2193*9880d681SAndroid Build Coastguard Worker       OptionalIdx[Op.getImmTy()] = I;
2194*9880d681SAndroid Build Coastguard Worker     } else {
2195*9880d681SAndroid Build Coastguard Worker       assert(false);
2196*9880d681SAndroid Build Coastguard Worker     }
2197*9880d681SAndroid Build Coastguard Worker   }
2198*9880d681SAndroid Build Coastguard Worker 
2199*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2200*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2201*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2202*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2203*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2204*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2205*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2206*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2207*9880d681SAndroid Build Coastguard Worker }
2208*9880d681SAndroid Build Coastguard Worker 
cvtMIMGAtomic(MCInst & Inst,const OperandVector & Operands)2209*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
2210*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2211*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2212*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2213*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2214*9880d681SAndroid Build Coastguard Worker   }
2215*9880d681SAndroid Build Coastguard Worker 
2216*9880d681SAndroid Build Coastguard Worker   // Add src, same as dst
2217*9880d681SAndroid Build Coastguard Worker   ((AMDGPUOperand &)*Operands[I]).addRegOperands(Inst, 1);
2218*9880d681SAndroid Build Coastguard Worker 
2219*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2220*9880d681SAndroid Build Coastguard Worker 
2221*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I) {
2222*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2223*9880d681SAndroid Build Coastguard Worker 
2224*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
2225*9880d681SAndroid Build Coastguard Worker     if (Op.isRegOrImm()) {
2226*9880d681SAndroid Build Coastguard Worker       Op.addRegOrImmOperands(Inst, 1);
2227*9880d681SAndroid Build Coastguard Worker       continue;
2228*9880d681SAndroid Build Coastguard Worker     } else if (Op.isImmModifier()) {
2229*9880d681SAndroid Build Coastguard Worker       OptionalIdx[Op.getImmTy()] = I;
2230*9880d681SAndroid Build Coastguard Worker     } else {
2231*9880d681SAndroid Build Coastguard Worker       assert(false);
2232*9880d681SAndroid Build Coastguard Worker     }
2233*9880d681SAndroid Build Coastguard Worker   }
2234*9880d681SAndroid Build Coastguard Worker 
2235*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
2236*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
2237*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
2238*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
2239*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128);
2240*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
2241*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
2242*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
2243*9880d681SAndroid Build Coastguard Worker }
2244*9880d681SAndroid Build Coastguard Worker 
defaultDMask() const2245*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDMask() const {
2246*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDMask);
2247*9880d681SAndroid Build Coastguard Worker }
2248*9880d681SAndroid Build Coastguard Worker 
defaultUNorm() const2249*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultUNorm() const {
2250*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyUNorm);
2251*9880d681SAndroid Build Coastguard Worker }
2252*9880d681SAndroid Build Coastguard Worker 
defaultDA() const2253*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultDA() const {
2254*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDA);
2255*9880d681SAndroid Build Coastguard Worker }
2256*9880d681SAndroid Build Coastguard Worker 
defaultR128() const2257*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultR128() const {
2258*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyR128);
2259*9880d681SAndroid Build Coastguard Worker }
2260*9880d681SAndroid Build Coastguard Worker 
defaultLWE() const2261*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultLWE() const {
2262*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyLWE);
2263*9880d681SAndroid Build Coastguard Worker }
2264*9880d681SAndroid Build Coastguard Worker 
2265*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2266*9880d681SAndroid Build Coastguard Worker // smrd
2267*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2268*9880d681SAndroid Build Coastguard Worker 
isSMRDOffset() const2269*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isSMRDOffset() const {
2270*9880d681SAndroid Build Coastguard Worker 
2271*9880d681SAndroid Build Coastguard Worker   // FIXME: Support 20-bit offsets on VI.  We need to to pass subtarget
2272*9880d681SAndroid Build Coastguard Worker   // information here.
2273*9880d681SAndroid Build Coastguard Worker   return isImm() && isUInt<8>(getImm());
2274*9880d681SAndroid Build Coastguard Worker }
2275*9880d681SAndroid Build Coastguard Worker 
isSMRDLiteralOffset() const2276*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isSMRDLiteralOffset() const {
2277*9880d681SAndroid Build Coastguard Worker   // 32-bit literals are only supported on CI and we only want to use them
2278*9880d681SAndroid Build Coastguard Worker   // when the offset is > 8-bits.
2279*9880d681SAndroid Build Coastguard Worker   return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
2280*9880d681SAndroid Build Coastguard Worker }
2281*9880d681SAndroid Build Coastguard Worker 
defaultSMRDOffset() const2282*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset() const {
2283*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyOffset);
2284*9880d681SAndroid Build Coastguard Worker }
2285*9880d681SAndroid Build Coastguard Worker 
defaultSMRDLiteralOffset() const2286*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
2287*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyOffset);
2288*9880d681SAndroid Build Coastguard Worker }
2289*9880d681SAndroid Build Coastguard Worker 
2290*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2291*9880d681SAndroid Build Coastguard Worker // vop3
2292*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2293*9880d681SAndroid Build Coastguard Worker 
ConvertOmodMul(int64_t & Mul)2294*9880d681SAndroid Build Coastguard Worker static bool ConvertOmodMul(int64_t &Mul) {
2295*9880d681SAndroid Build Coastguard Worker   if (Mul != 1 && Mul != 2 && Mul != 4)
2296*9880d681SAndroid Build Coastguard Worker     return false;
2297*9880d681SAndroid Build Coastguard Worker 
2298*9880d681SAndroid Build Coastguard Worker   Mul >>= 1;
2299*9880d681SAndroid Build Coastguard Worker   return true;
2300*9880d681SAndroid Build Coastguard Worker }
2301*9880d681SAndroid Build Coastguard Worker 
ConvertOmodDiv(int64_t & Div)2302*9880d681SAndroid Build Coastguard Worker static bool ConvertOmodDiv(int64_t &Div) {
2303*9880d681SAndroid Build Coastguard Worker   if (Div == 1) {
2304*9880d681SAndroid Build Coastguard Worker     Div = 0;
2305*9880d681SAndroid Build Coastguard Worker     return true;
2306*9880d681SAndroid Build Coastguard Worker   }
2307*9880d681SAndroid Build Coastguard Worker 
2308*9880d681SAndroid Build Coastguard Worker   if (Div == 2) {
2309*9880d681SAndroid Build Coastguard Worker     Div = 3;
2310*9880d681SAndroid Build Coastguard Worker     return true;
2311*9880d681SAndroid Build Coastguard Worker   }
2312*9880d681SAndroid Build Coastguard Worker 
2313*9880d681SAndroid Build Coastguard Worker   return false;
2314*9880d681SAndroid Build Coastguard Worker }
2315*9880d681SAndroid Build Coastguard Worker 
ConvertBoundCtrl(int64_t & BoundCtrl)2316*9880d681SAndroid Build Coastguard Worker static bool ConvertBoundCtrl(int64_t &BoundCtrl) {
2317*9880d681SAndroid Build Coastguard Worker   if (BoundCtrl == 0) {
2318*9880d681SAndroid Build Coastguard Worker     BoundCtrl = 1;
2319*9880d681SAndroid Build Coastguard Worker     return true;
2320*9880d681SAndroid Build Coastguard Worker   } else if (BoundCtrl == -1) {
2321*9880d681SAndroid Build Coastguard Worker     BoundCtrl = 0;
2322*9880d681SAndroid Build Coastguard Worker     return true;
2323*9880d681SAndroid Build Coastguard Worker   }
2324*9880d681SAndroid Build Coastguard Worker   return false;
2325*9880d681SAndroid Build Coastguard Worker }
2326*9880d681SAndroid Build Coastguard Worker 
2327*9880d681SAndroid Build Coastguard Worker // Note: the order in this table matches the order of operands in AsmString.
2328*9880d681SAndroid Build Coastguard Worker static const OptionalOperand AMDGPUOptionalOperandTable[] = {
2329*9880d681SAndroid Build Coastguard Worker   {"offen",   AMDGPUOperand::ImmTyOffen, true, nullptr},
2330*9880d681SAndroid Build Coastguard Worker   {"idxen",   AMDGPUOperand::ImmTyIdxen, true, nullptr},
2331*9880d681SAndroid Build Coastguard Worker   {"addr64",  AMDGPUOperand::ImmTyAddr64, true, nullptr},
2332*9880d681SAndroid Build Coastguard Worker   {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
2333*9880d681SAndroid Build Coastguard Worker   {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
2334*9880d681SAndroid Build Coastguard Worker   {"gds",     AMDGPUOperand::ImmTyGDS, true, nullptr},
2335*9880d681SAndroid Build Coastguard Worker   {"offset",  AMDGPUOperand::ImmTyOffset, false, nullptr},
2336*9880d681SAndroid Build Coastguard Worker   {"glc",     AMDGPUOperand::ImmTyGLC, true, nullptr},
2337*9880d681SAndroid Build Coastguard Worker   {"slc",     AMDGPUOperand::ImmTySLC, true, nullptr},
2338*9880d681SAndroid Build Coastguard Worker   {"tfe",     AMDGPUOperand::ImmTyTFE, true, nullptr},
2339*9880d681SAndroid Build Coastguard Worker   {"clamp",   AMDGPUOperand::ImmTyClampSI, true, nullptr},
2340*9880d681SAndroid Build Coastguard Worker   {"omod",    AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
2341*9880d681SAndroid Build Coastguard Worker   {"unorm",   AMDGPUOperand::ImmTyUNorm, true, nullptr},
2342*9880d681SAndroid Build Coastguard Worker   {"da",      AMDGPUOperand::ImmTyDA,    true, nullptr},
2343*9880d681SAndroid Build Coastguard Worker   {"r128",    AMDGPUOperand::ImmTyR128,  true, nullptr},
2344*9880d681SAndroid Build Coastguard Worker   {"lwe",     AMDGPUOperand::ImmTyLWE,   true, nullptr},
2345*9880d681SAndroid Build Coastguard Worker   {"dmask",   AMDGPUOperand::ImmTyDMask, false, nullptr},
2346*9880d681SAndroid Build Coastguard Worker   {"row_mask",   AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
2347*9880d681SAndroid Build Coastguard Worker   {"bank_mask",  AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
2348*9880d681SAndroid Build Coastguard Worker   {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
2349*9880d681SAndroid Build Coastguard Worker   {"dst_sel",    AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
2350*9880d681SAndroid Build Coastguard Worker   {"src0_sel",   AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
2351*9880d681SAndroid Build Coastguard Worker   {"src1_sel",   AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
2352*9880d681SAndroid Build Coastguard Worker   {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
2353*9880d681SAndroid Build Coastguard Worker };
2354*9880d681SAndroid Build Coastguard Worker 
parseOptionalOperand(OperandVector & Operands)2355*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
2356*9880d681SAndroid Build Coastguard Worker   OperandMatchResultTy res;
2357*9880d681SAndroid Build Coastguard Worker   for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
2358*9880d681SAndroid Build Coastguard Worker     // try to parse any optional operand here
2359*9880d681SAndroid Build Coastguard Worker     if (Op.IsBit) {
2360*9880d681SAndroid Build Coastguard Worker       res = parseNamedBit(Op.Name, Operands, Op.Type);
2361*9880d681SAndroid Build Coastguard Worker     } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
2362*9880d681SAndroid Build Coastguard Worker       res = parseOModOperand(Operands);
2363*9880d681SAndroid Build Coastguard Worker     } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
2364*9880d681SAndroid Build Coastguard Worker                Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
2365*9880d681SAndroid Build Coastguard Worker                Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
2366*9880d681SAndroid Build Coastguard Worker       res = parseSDWASel(Operands, Op.Name, Op.Type);
2367*9880d681SAndroid Build Coastguard Worker     } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
2368*9880d681SAndroid Build Coastguard Worker       res = parseSDWADstUnused(Operands);
2369*9880d681SAndroid Build Coastguard Worker     } else {
2370*9880d681SAndroid Build Coastguard Worker       res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
2371*9880d681SAndroid Build Coastguard Worker     }
2372*9880d681SAndroid Build Coastguard Worker     if (res != MatchOperand_NoMatch) {
2373*9880d681SAndroid Build Coastguard Worker       return res;
2374*9880d681SAndroid Build Coastguard Worker     }
2375*9880d681SAndroid Build Coastguard Worker   }
2376*9880d681SAndroid Build Coastguard Worker   return MatchOperand_NoMatch;
2377*9880d681SAndroid Build Coastguard Worker }
2378*9880d681SAndroid Build Coastguard Worker 
parseOModOperand(OperandVector & Operands)2379*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands)
2380*9880d681SAndroid Build Coastguard Worker {
2381*9880d681SAndroid Build Coastguard Worker   StringRef Name = Parser.getTok().getString();
2382*9880d681SAndroid Build Coastguard Worker   if (Name == "mul") {
2383*9880d681SAndroid Build Coastguard Worker     return parseIntWithPrefix("mul", Operands, AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
2384*9880d681SAndroid Build Coastguard Worker   } else if (Name == "div") {
2385*9880d681SAndroid Build Coastguard Worker     return parseIntWithPrefix("div", Operands, AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
2386*9880d681SAndroid Build Coastguard Worker   } else {
2387*9880d681SAndroid Build Coastguard Worker     return MatchOperand_NoMatch;
2388*9880d681SAndroid Build Coastguard Worker   }
2389*9880d681SAndroid Build Coastguard Worker }
2390*9880d681SAndroid Build Coastguard Worker 
cvtId(MCInst & Inst,const OperandVector & Operands)2391*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtId(MCInst &Inst, const OperandVector &Operands) {
2392*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2393*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2394*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2395*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2396*9880d681SAndroid Build Coastguard Worker   }
2397*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I)
2398*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I]).addRegOrImmOperands(Inst, 1);
2399*9880d681SAndroid Build Coastguard Worker }
2400*9880d681SAndroid Build Coastguard Worker 
cvtVOP3_2_mod(MCInst & Inst,const OperandVector & Operands)2401*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtVOP3_2_mod(MCInst &Inst, const OperandVector &Operands) {
2402*9880d681SAndroid Build Coastguard Worker   uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2403*9880d681SAndroid Build Coastguard Worker   if (TSFlags & SIInstrFlags::VOP3) {
2404*9880d681SAndroid Build Coastguard Worker     cvtVOP3(Inst, Operands);
2405*9880d681SAndroid Build Coastguard Worker   } else {
2406*9880d681SAndroid Build Coastguard Worker     cvtId(Inst, Operands);
2407*9880d681SAndroid Build Coastguard Worker   }
2408*9880d681SAndroid Build Coastguard Worker }
2409*9880d681SAndroid Build Coastguard Worker 
cvtVOP3(MCInst & Inst,const OperandVector & Operands)2410*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
2411*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2412*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2413*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2414*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2415*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2416*9880d681SAndroid Build Coastguard Worker   }
2417*9880d681SAndroid Build Coastguard Worker 
2418*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I) {
2419*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2420*9880d681SAndroid Build Coastguard Worker     if (Op.isRegOrImmWithInputMods()) {
2421*9880d681SAndroid Build Coastguard Worker       // only fp modifiers allowed in VOP3
2422*9880d681SAndroid Build Coastguard Worker       Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
2423*9880d681SAndroid Build Coastguard Worker     } else if (Op.isImm()) {
2424*9880d681SAndroid Build Coastguard Worker       OptionalIdx[Op.getImmTy()] = I;
2425*9880d681SAndroid Build Coastguard Worker     } else {
2426*9880d681SAndroid Build Coastguard Worker       assert(false);
2427*9880d681SAndroid Build Coastguard Worker     }
2428*9880d681SAndroid Build Coastguard Worker   }
2429*9880d681SAndroid Build Coastguard Worker 
2430*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
2431*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
2432*9880d681SAndroid Build Coastguard Worker }
2433*9880d681SAndroid Build Coastguard Worker 
2434*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2435*9880d681SAndroid Build Coastguard Worker // dpp
2436*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2437*9880d681SAndroid Build Coastguard Worker 
isDPPCtrl() const2438*9880d681SAndroid Build Coastguard Worker bool AMDGPUOperand::isDPPCtrl() const {
2439*9880d681SAndroid Build Coastguard Worker   bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
2440*9880d681SAndroid Build Coastguard Worker   if (result) {
2441*9880d681SAndroid Build Coastguard Worker     int64_t Imm = getImm();
2442*9880d681SAndroid Build Coastguard Worker     return ((Imm >= 0x000) && (Imm <= 0x0ff)) ||
2443*9880d681SAndroid Build Coastguard Worker            ((Imm >= 0x101) && (Imm <= 0x10f)) ||
2444*9880d681SAndroid Build Coastguard Worker            ((Imm >= 0x111) && (Imm <= 0x11f)) ||
2445*9880d681SAndroid Build Coastguard Worker            ((Imm >= 0x121) && (Imm <= 0x12f)) ||
2446*9880d681SAndroid Build Coastguard Worker            (Imm == 0x130) ||
2447*9880d681SAndroid Build Coastguard Worker            (Imm == 0x134) ||
2448*9880d681SAndroid Build Coastguard Worker            (Imm == 0x138) ||
2449*9880d681SAndroid Build Coastguard Worker            (Imm == 0x13c) ||
2450*9880d681SAndroid Build Coastguard Worker            (Imm == 0x140) ||
2451*9880d681SAndroid Build Coastguard Worker            (Imm == 0x141) ||
2452*9880d681SAndroid Build Coastguard Worker            (Imm == 0x142) ||
2453*9880d681SAndroid Build Coastguard Worker            (Imm == 0x143);
2454*9880d681SAndroid Build Coastguard Worker   }
2455*9880d681SAndroid Build Coastguard Worker   return false;
2456*9880d681SAndroid Build Coastguard Worker }
2457*9880d681SAndroid Build Coastguard Worker 
2458*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseDPPCtrl(OperandVector & Operands)2459*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
2460*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
2461*9880d681SAndroid Build Coastguard Worker   StringRef Prefix;
2462*9880d681SAndroid Build Coastguard Worker   int64_t Int;
2463*9880d681SAndroid Build Coastguard Worker 
2464*9880d681SAndroid Build Coastguard Worker   if (getLexer().getKind() == AsmToken::Identifier) {
2465*9880d681SAndroid Build Coastguard Worker     Prefix = Parser.getTok().getString();
2466*9880d681SAndroid Build Coastguard Worker   } else {
2467*9880d681SAndroid Build Coastguard Worker     return MatchOperand_NoMatch;
2468*9880d681SAndroid Build Coastguard Worker   }
2469*9880d681SAndroid Build Coastguard Worker 
2470*9880d681SAndroid Build Coastguard Worker   if (Prefix == "row_mirror") {
2471*9880d681SAndroid Build Coastguard Worker     Int = 0x140;
2472*9880d681SAndroid Build Coastguard Worker   } else if (Prefix == "row_half_mirror") {
2473*9880d681SAndroid Build Coastguard Worker     Int = 0x141;
2474*9880d681SAndroid Build Coastguard Worker   } else {
2475*9880d681SAndroid Build Coastguard Worker     // Check to prevent parseDPPCtrlOps from eating invalid tokens
2476*9880d681SAndroid Build Coastguard Worker     if (Prefix != "quad_perm"
2477*9880d681SAndroid Build Coastguard Worker         && Prefix != "row_shl"
2478*9880d681SAndroid Build Coastguard Worker         && Prefix != "row_shr"
2479*9880d681SAndroid Build Coastguard Worker         && Prefix != "row_ror"
2480*9880d681SAndroid Build Coastguard Worker         && Prefix != "wave_shl"
2481*9880d681SAndroid Build Coastguard Worker         && Prefix != "wave_rol"
2482*9880d681SAndroid Build Coastguard Worker         && Prefix != "wave_shr"
2483*9880d681SAndroid Build Coastguard Worker         && Prefix != "wave_ror"
2484*9880d681SAndroid Build Coastguard Worker         && Prefix != "row_bcast") {
2485*9880d681SAndroid Build Coastguard Worker       return MatchOperand_NoMatch;
2486*9880d681SAndroid Build Coastguard Worker     }
2487*9880d681SAndroid Build Coastguard Worker 
2488*9880d681SAndroid Build Coastguard Worker     Parser.Lex();
2489*9880d681SAndroid Build Coastguard Worker     if (getLexer().isNot(AsmToken::Colon))
2490*9880d681SAndroid Build Coastguard Worker       return MatchOperand_ParseFail;
2491*9880d681SAndroid Build Coastguard Worker 
2492*9880d681SAndroid Build Coastguard Worker     if (Prefix == "quad_perm") {
2493*9880d681SAndroid Build Coastguard Worker       // quad_perm:[%d,%d,%d,%d]
2494*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2495*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::LBrac))
2496*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2497*9880d681SAndroid Build Coastguard Worker 
2498*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2499*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
2500*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2501*9880d681SAndroid Build Coastguard Worker       Int = getLexer().getTok().getIntVal();
2502*9880d681SAndroid Build Coastguard Worker 
2503*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2504*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Comma))
2505*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2506*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2507*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
2508*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2509*9880d681SAndroid Build Coastguard Worker       Int += (getLexer().getTok().getIntVal() << 2);
2510*9880d681SAndroid Build Coastguard Worker 
2511*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2512*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Comma))
2513*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2514*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2515*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
2516*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2517*9880d681SAndroid Build Coastguard Worker       Int += (getLexer().getTok().getIntVal() << 4);
2518*9880d681SAndroid Build Coastguard Worker 
2519*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2520*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Comma))
2521*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2522*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2523*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
2524*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2525*9880d681SAndroid Build Coastguard Worker       Int += (getLexer().getTok().getIntVal() << 6);
2526*9880d681SAndroid Build Coastguard Worker 
2527*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2528*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::RBrac))
2529*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2530*9880d681SAndroid Build Coastguard Worker 
2531*9880d681SAndroid Build Coastguard Worker     } else {
2532*9880d681SAndroid Build Coastguard Worker       // sel:%d
2533*9880d681SAndroid Build Coastguard Worker       Parser.Lex();
2534*9880d681SAndroid Build Coastguard Worker       if (getLexer().isNot(AsmToken::Integer))
2535*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2536*9880d681SAndroid Build Coastguard Worker       Int = getLexer().getTok().getIntVal();
2537*9880d681SAndroid Build Coastguard Worker 
2538*9880d681SAndroid Build Coastguard Worker       if (Prefix == "row_shl") {
2539*9880d681SAndroid Build Coastguard Worker         Int |= 0x100;
2540*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "row_shr") {
2541*9880d681SAndroid Build Coastguard Worker         Int |= 0x110;
2542*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "row_ror") {
2543*9880d681SAndroid Build Coastguard Worker         Int |= 0x120;
2544*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "wave_shl") {
2545*9880d681SAndroid Build Coastguard Worker         Int = 0x130;
2546*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "wave_rol") {
2547*9880d681SAndroid Build Coastguard Worker         Int = 0x134;
2548*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "wave_shr") {
2549*9880d681SAndroid Build Coastguard Worker         Int = 0x138;
2550*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "wave_ror") {
2551*9880d681SAndroid Build Coastguard Worker         Int = 0x13C;
2552*9880d681SAndroid Build Coastguard Worker       } else if (Prefix == "row_bcast") {
2553*9880d681SAndroid Build Coastguard Worker         if (Int == 15) {
2554*9880d681SAndroid Build Coastguard Worker           Int = 0x142;
2555*9880d681SAndroid Build Coastguard Worker         } else if (Int == 31) {
2556*9880d681SAndroid Build Coastguard Worker           Int = 0x143;
2557*9880d681SAndroid Build Coastguard Worker         } else {
2558*9880d681SAndroid Build Coastguard Worker           return MatchOperand_ParseFail;
2559*9880d681SAndroid Build Coastguard Worker         }
2560*9880d681SAndroid Build Coastguard Worker       } else {
2561*9880d681SAndroid Build Coastguard Worker         return MatchOperand_ParseFail;
2562*9880d681SAndroid Build Coastguard Worker       }
2563*9880d681SAndroid Build Coastguard Worker     }
2564*9880d681SAndroid Build Coastguard Worker   }
2565*9880d681SAndroid Build Coastguard Worker   Parser.Lex(); // eat last token
2566*9880d681SAndroid Build Coastguard Worker 
2567*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Int, S,
2568*9880d681SAndroid Build Coastguard Worker                                               AMDGPUOperand::ImmTyDppCtrl));
2569*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
2570*9880d681SAndroid Build Coastguard Worker }
2571*9880d681SAndroid Build Coastguard Worker 
defaultRowMask() const2572*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
2573*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
2574*9880d681SAndroid Build Coastguard Worker }
2575*9880d681SAndroid Build Coastguard Worker 
defaultBankMask() const2576*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
2577*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
2578*9880d681SAndroid Build Coastguard Worker }
2579*9880d681SAndroid Build Coastguard Worker 
defaultBoundCtrl() const2580*9880d681SAndroid Build Coastguard Worker AMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
2581*9880d681SAndroid Build Coastguard Worker   return AMDGPUOperand::CreateImm(0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
2582*9880d681SAndroid Build Coastguard Worker }
2583*9880d681SAndroid Build Coastguard Worker 
cvtDPP(MCInst & Inst,const OperandVector & Operands)2584*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands) {
2585*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2586*9880d681SAndroid Build Coastguard Worker 
2587*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2588*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2589*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2590*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2591*9880d681SAndroid Build Coastguard Worker   }
2592*9880d681SAndroid Build Coastguard Worker 
2593*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I) {
2594*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2595*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
2596*9880d681SAndroid Build Coastguard Worker     if (Op.isRegOrImmWithInputMods()) {
2597*9880d681SAndroid Build Coastguard Worker       // Only float modifiers supported in DPP
2598*9880d681SAndroid Build Coastguard Worker       Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
2599*9880d681SAndroid Build Coastguard Worker     } else if (Op.isDPPCtrl()) {
2600*9880d681SAndroid Build Coastguard Worker       Op.addImmOperands(Inst, 1);
2601*9880d681SAndroid Build Coastguard Worker     } else if (Op.isImm()) {
2602*9880d681SAndroid Build Coastguard Worker       // Handle optional arguments
2603*9880d681SAndroid Build Coastguard Worker       OptionalIdx[Op.getImmTy()] = I;
2604*9880d681SAndroid Build Coastguard Worker     } else {
2605*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid operand type");
2606*9880d681SAndroid Build Coastguard Worker     }
2607*9880d681SAndroid Build Coastguard Worker   }
2608*9880d681SAndroid Build Coastguard Worker 
2609*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
2610*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
2611*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
2612*9880d681SAndroid Build Coastguard Worker }
2613*9880d681SAndroid Build Coastguard Worker 
2614*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2615*9880d681SAndroid Build Coastguard Worker // sdwa
2616*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
2617*9880d681SAndroid Build Coastguard Worker 
2618*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseSDWASel(OperandVector & Operands,StringRef Prefix,AMDGPUOperand::ImmTy Type)2619*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
2620*9880d681SAndroid Build Coastguard Worker                               AMDGPUOperand::ImmTy Type) {
2621*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
2622*9880d681SAndroid Build Coastguard Worker   StringRef Value;
2623*9880d681SAndroid Build Coastguard Worker   AMDGPUAsmParser::OperandMatchResultTy res;
2624*9880d681SAndroid Build Coastguard Worker 
2625*9880d681SAndroid Build Coastguard Worker   res = parseStringWithPrefix(Prefix, Value);
2626*9880d681SAndroid Build Coastguard Worker   if (res != MatchOperand_Success) {
2627*9880d681SAndroid Build Coastguard Worker     return res;
2628*9880d681SAndroid Build Coastguard Worker   }
2629*9880d681SAndroid Build Coastguard Worker 
2630*9880d681SAndroid Build Coastguard Worker   int64_t Int;
2631*9880d681SAndroid Build Coastguard Worker   Int = StringSwitch<int64_t>(Value)
2632*9880d681SAndroid Build Coastguard Worker         .Case("BYTE_0", 0)
2633*9880d681SAndroid Build Coastguard Worker         .Case("BYTE_1", 1)
2634*9880d681SAndroid Build Coastguard Worker         .Case("BYTE_2", 2)
2635*9880d681SAndroid Build Coastguard Worker         .Case("BYTE_3", 3)
2636*9880d681SAndroid Build Coastguard Worker         .Case("WORD_0", 4)
2637*9880d681SAndroid Build Coastguard Worker         .Case("WORD_1", 5)
2638*9880d681SAndroid Build Coastguard Worker         .Case("DWORD", 6)
2639*9880d681SAndroid Build Coastguard Worker         .Default(0xffffffff);
2640*9880d681SAndroid Build Coastguard Worker   Parser.Lex(); // eat last token
2641*9880d681SAndroid Build Coastguard Worker 
2642*9880d681SAndroid Build Coastguard Worker   if (Int == 0xffffffff) {
2643*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
2644*9880d681SAndroid Build Coastguard Worker   }
2645*9880d681SAndroid Build Coastguard Worker 
2646*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Int, S, Type));
2647*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
2648*9880d681SAndroid Build Coastguard Worker }
2649*9880d681SAndroid Build Coastguard Worker 
2650*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::OperandMatchResultTy
parseSDWADstUnused(OperandVector & Operands)2651*9880d681SAndroid Build Coastguard Worker AMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
2652*9880d681SAndroid Build Coastguard Worker   SMLoc S = Parser.getTok().getLoc();
2653*9880d681SAndroid Build Coastguard Worker   StringRef Value;
2654*9880d681SAndroid Build Coastguard Worker   AMDGPUAsmParser::OperandMatchResultTy res;
2655*9880d681SAndroid Build Coastguard Worker 
2656*9880d681SAndroid Build Coastguard Worker   res = parseStringWithPrefix("dst_unused", Value);
2657*9880d681SAndroid Build Coastguard Worker   if (res != MatchOperand_Success) {
2658*9880d681SAndroid Build Coastguard Worker     return res;
2659*9880d681SAndroid Build Coastguard Worker   }
2660*9880d681SAndroid Build Coastguard Worker 
2661*9880d681SAndroid Build Coastguard Worker   int64_t Int;
2662*9880d681SAndroid Build Coastguard Worker   Int = StringSwitch<int64_t>(Value)
2663*9880d681SAndroid Build Coastguard Worker         .Case("UNUSED_PAD", 0)
2664*9880d681SAndroid Build Coastguard Worker         .Case("UNUSED_SEXT", 1)
2665*9880d681SAndroid Build Coastguard Worker         .Case("UNUSED_PRESERVE", 2)
2666*9880d681SAndroid Build Coastguard Worker         .Default(0xffffffff);
2667*9880d681SAndroid Build Coastguard Worker   Parser.Lex(); // eat last token
2668*9880d681SAndroid Build Coastguard Worker 
2669*9880d681SAndroid Build Coastguard Worker   if (Int == 0xffffffff) {
2670*9880d681SAndroid Build Coastguard Worker     return MatchOperand_ParseFail;
2671*9880d681SAndroid Build Coastguard Worker   }
2672*9880d681SAndroid Build Coastguard Worker 
2673*9880d681SAndroid Build Coastguard Worker   Operands.push_back(AMDGPUOperand::CreateImm(Int, S,
2674*9880d681SAndroid Build Coastguard Worker                                               AMDGPUOperand::ImmTySdwaDstUnused));
2675*9880d681SAndroid Build Coastguard Worker   return MatchOperand_Success;
2676*9880d681SAndroid Build Coastguard Worker }
2677*9880d681SAndroid Build Coastguard Worker 
cvtSdwaVOP1(MCInst & Inst,const OperandVector & Operands)2678*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
2679*9880d681SAndroid Build Coastguard Worker   cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
2680*9880d681SAndroid Build Coastguard Worker }
2681*9880d681SAndroid Build Coastguard Worker 
cvtSdwaVOP2(MCInst & Inst,const OperandVector & Operands)2682*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
2683*9880d681SAndroid Build Coastguard Worker   cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
2684*9880d681SAndroid Build Coastguard Worker }
2685*9880d681SAndroid Build Coastguard Worker 
cvtSdwaVOPC(MCInst & Inst,const OperandVector & Operands)2686*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
2687*9880d681SAndroid Build Coastguard Worker   cvtSDWA(Inst, Operands, SIInstrFlags::VOPC);
2688*9880d681SAndroid Build Coastguard Worker }
2689*9880d681SAndroid Build Coastguard Worker 
cvtSDWA(MCInst & Inst,const OperandVector & Operands,uint64_t BasicInstType)2690*9880d681SAndroid Build Coastguard Worker void AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
2691*9880d681SAndroid Build Coastguard Worker                               uint64_t BasicInstType) {
2692*9880d681SAndroid Build Coastguard Worker   OptionalImmIndexMap OptionalIdx;
2693*9880d681SAndroid Build Coastguard Worker 
2694*9880d681SAndroid Build Coastguard Worker   unsigned I = 1;
2695*9880d681SAndroid Build Coastguard Worker   const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2696*9880d681SAndroid Build Coastguard Worker   for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
2697*9880d681SAndroid Build Coastguard Worker     ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
2698*9880d681SAndroid Build Coastguard Worker   }
2699*9880d681SAndroid Build Coastguard Worker 
2700*9880d681SAndroid Build Coastguard Worker   for (unsigned E = Operands.size(); I != E; ++I) {
2701*9880d681SAndroid Build Coastguard Worker     AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
2702*9880d681SAndroid Build Coastguard Worker     // Add the register arguments
2703*9880d681SAndroid Build Coastguard Worker     if (BasicInstType == SIInstrFlags::VOPC &&
2704*9880d681SAndroid Build Coastguard Worker         Op.isReg() &&
2705*9880d681SAndroid Build Coastguard Worker         Op.Reg.RegNo == AMDGPU::VCC) {
2706*9880d681SAndroid Build Coastguard Worker       // VOPC sdwa use "vcc" token as dst. Skip it.
2707*9880d681SAndroid Build Coastguard Worker       continue;
2708*9880d681SAndroid Build Coastguard Worker     } else if (Op.isRegOrImmWithInputMods()) {
2709*9880d681SAndroid Build Coastguard Worker        Op.addRegOrImmWithInputModsOperands(Inst, 2);
2710*9880d681SAndroid Build Coastguard Worker     } else if (Op.isImm()) {
2711*9880d681SAndroid Build Coastguard Worker       // Handle optional arguments
2712*9880d681SAndroid Build Coastguard Worker       OptionalIdx[Op.getImmTy()] = I;
2713*9880d681SAndroid Build Coastguard Worker     } else {
2714*9880d681SAndroid Build Coastguard Worker       llvm_unreachable("Invalid operand type");
2715*9880d681SAndroid Build Coastguard Worker     }
2716*9880d681SAndroid Build Coastguard Worker   }
2717*9880d681SAndroid Build Coastguard Worker 
2718*9880d681SAndroid Build Coastguard Worker   addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
2719*9880d681SAndroid Build Coastguard Worker 
2720*9880d681SAndroid Build Coastguard Worker   if (Inst.getOpcode() == AMDGPU::V_NOP_sdwa) {
2721*9880d681SAndroid Build Coastguard Worker     // V_NOP_sdwa has no optional sdwa arguments
2722*9880d681SAndroid Build Coastguard Worker     return;
2723*9880d681SAndroid Build Coastguard Worker   }
2724*9880d681SAndroid Build Coastguard Worker   switch (BasicInstType) {
2725*9880d681SAndroid Build Coastguard Worker   case SIInstrFlags::VOP1: {
2726*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2727*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2728*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2729*9880d681SAndroid Build Coastguard Worker     break;
2730*9880d681SAndroid Build Coastguard Worker   }
2731*9880d681SAndroid Build Coastguard Worker   case SIInstrFlags::VOP2: {
2732*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, 6);
2733*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, 2);
2734*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2735*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
2736*9880d681SAndroid Build Coastguard Worker     break;
2737*9880d681SAndroid Build Coastguard Worker   }
2738*9880d681SAndroid Build Coastguard Worker   case SIInstrFlags::VOPC: {
2739*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, 6);
2740*9880d681SAndroid Build Coastguard Worker     addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, 6);
2741*9880d681SAndroid Build Coastguard Worker     break;
2742*9880d681SAndroid Build Coastguard Worker   }
2743*9880d681SAndroid Build Coastguard Worker   default:
2744*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
2745*9880d681SAndroid Build Coastguard Worker   }
2746*9880d681SAndroid Build Coastguard Worker }
2747*9880d681SAndroid Build Coastguard Worker 
2748*9880d681SAndroid Build Coastguard Worker /// Force static initialization.
LLVMInitializeAMDGPUAsmParser()2749*9880d681SAndroid Build Coastguard Worker extern "C" void LLVMInitializeAMDGPUAsmParser() {
2750*9880d681SAndroid Build Coastguard Worker   RegisterMCAsmParser<AMDGPUAsmParser> A(TheAMDGPUTarget);
2751*9880d681SAndroid Build Coastguard Worker   RegisterMCAsmParser<AMDGPUAsmParser> B(TheGCNTarget);
2752*9880d681SAndroid Build Coastguard Worker }
2753*9880d681SAndroid Build Coastguard Worker 
2754*9880d681SAndroid Build Coastguard Worker #define GET_REGISTER_MATCHER
2755*9880d681SAndroid Build Coastguard Worker #define GET_MATCHER_IMPLEMENTATION
2756*9880d681SAndroid Build Coastguard Worker #include "AMDGPUGenAsmMatcher.inc"
2757*9880d681SAndroid Build Coastguard Worker 
2758*9880d681SAndroid Build Coastguard Worker 
2759*9880d681SAndroid Build Coastguard Worker // This fuction should be defined after auto-generated include so that we have
2760*9880d681SAndroid Build Coastguard Worker // MatchClassKind enum defined
validateTargetOperandClass(MCParsedAsmOperand & Op,unsigned Kind)2761*9880d681SAndroid Build Coastguard Worker unsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
2762*9880d681SAndroid Build Coastguard Worker                                                      unsigned Kind) {
2763*9880d681SAndroid Build Coastguard Worker   // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
2764*9880d681SAndroid Build Coastguard Worker   // But MatchInstructionImpl() expects to meet token and fails to validate
2765*9880d681SAndroid Build Coastguard Worker   // operand. This method checks if we are given immediate operand but expect to
2766*9880d681SAndroid Build Coastguard Worker   // get corresponding token.
2767*9880d681SAndroid Build Coastguard Worker   AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
2768*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
2769*9880d681SAndroid Build Coastguard Worker   case MCK_addr64:
2770*9880d681SAndroid Build Coastguard Worker     return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
2771*9880d681SAndroid Build Coastguard Worker   case MCK_gds:
2772*9880d681SAndroid Build Coastguard Worker     return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
2773*9880d681SAndroid Build Coastguard Worker   case MCK_glc:
2774*9880d681SAndroid Build Coastguard Worker     return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
2775*9880d681SAndroid Build Coastguard Worker   case MCK_idxen:
2776*9880d681SAndroid Build Coastguard Worker     return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
2777*9880d681SAndroid Build Coastguard Worker   case MCK_offen:
2778*9880d681SAndroid Build Coastguard Worker     return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
2779*9880d681SAndroid Build Coastguard Worker   case MCK_SSrc32:
2780*9880d681SAndroid Build Coastguard Worker     // When operands have expression values, they will return true for isToken,
2781*9880d681SAndroid Build Coastguard Worker     // because it is not possible to distinguish between a token and an
2782*9880d681SAndroid Build Coastguard Worker     // expression at parse time. MatchInstructionImpl() will always try to
2783*9880d681SAndroid Build Coastguard Worker     // match an operand as a token, when isToken returns true, and when the
2784*9880d681SAndroid Build Coastguard Worker     // name of the expression is not a valid token, the match will fail,
2785*9880d681SAndroid Build Coastguard Worker     // so we need to handle it here.
2786*9880d681SAndroid Build Coastguard Worker     return Operand.isSSrc32() ? Match_Success : Match_InvalidOperand;
2787*9880d681SAndroid Build Coastguard Worker   case MCK_SoppBrTarget:
2788*9880d681SAndroid Build Coastguard Worker     return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
2789*9880d681SAndroid Build Coastguard Worker   default: return Match_InvalidOperand;
2790*9880d681SAndroid Build Coastguard Worker   }
2791*9880d681SAndroid Build Coastguard Worker }
2792