1327952Sdim//===- AMDGPUAsmParser.cpp - Parse SI asm to MCInst instructions ----------===//
2284677Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6284677Sdim//
7284677Sdim//===----------------------------------------------------------------------===//
8284677Sdim
9327952Sdim#include "AMDGPU.h"
10309124Sdim#include "AMDKernelCodeT.h"
11284677Sdim#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
12285181Sdim#include "MCTargetDesc/AMDGPUTargetStreamer.h"
13309124Sdim#include "SIDefines.h"
14341825Sdim#include "SIInstrInfo.h"
15353358Sdim#include "TargetInfo/AMDGPUTargetInfo.h"
16321369Sdim#include "Utils/AMDGPUAsmUtils.h"
17285181Sdim#include "Utils/AMDGPUBaseInfo.h"
18309124Sdim#include "Utils/AMDKernelCodeTUtils.h"
19284677Sdim#include "llvm/ADT/APFloat.h"
20314564Sdim#include "llvm/ADT/APInt.h"
21321369Sdim#include "llvm/ADT/ArrayRef.h"
22321369Sdim#include "llvm/ADT/STLExtras.h"
23309124Sdim#include "llvm/ADT/SmallBitVector.h"
24284677Sdim#include "llvm/ADT/SmallString.h"
25314564Sdim#include "llvm/ADT/StringRef.h"
26284677Sdim#include "llvm/ADT/StringSwitch.h"
27284677Sdim#include "llvm/ADT/Twine.h"
28321369Sdim#include "llvm/BinaryFormat/ELF.h"
29314564Sdim#include "llvm/MC/MCAsmInfo.h"
30284677Sdim#include "llvm/MC/MCContext.h"
31284677Sdim#include "llvm/MC/MCExpr.h"
32284677Sdim#include "llvm/MC/MCInst.h"
33314564Sdim#include "llvm/MC/MCInstrDesc.h"
34284677Sdim#include "llvm/MC/MCInstrInfo.h"
35284677Sdim#include "llvm/MC/MCParser/MCAsmLexer.h"
36284677Sdim#include "llvm/MC/MCParser/MCAsmParser.h"
37314564Sdim#include "llvm/MC/MCParser/MCAsmParserExtension.h"
38284677Sdim#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
39309124Sdim#include "llvm/MC/MCParser/MCTargetAsmParser.h"
40284677Sdim#include "llvm/MC/MCRegisterInfo.h"
41284677Sdim#include "llvm/MC/MCStreamer.h"
42284677Sdim#include "llvm/MC/MCSubtargetInfo.h"
43314564Sdim#include "llvm/MC/MCSymbol.h"
44327952Sdim#include "llvm/Support/AMDGPUMetadata.h"
45341825Sdim#include "llvm/Support/AMDHSAKernelDescriptor.h"
46314564Sdim#include "llvm/Support/Casting.h"
47327952Sdim#include "llvm/Support/Compiler.h"
48360784Sdim#include "llvm/Support/Error.h"
49341825Sdim#include "llvm/Support/MachineValueType.h"
50314564Sdim#include "llvm/Support/MathExtras.h"
51314564Sdim#include "llvm/Support/SMLoc.h"
52344779Sdim#include "llvm/Support/TargetParser.h"
53284677Sdim#include "llvm/Support/TargetRegistry.h"
54284677Sdim#include "llvm/Support/raw_ostream.h"
55314564Sdim#include <algorithm>
56314564Sdim#include <cassert>
57314564Sdim#include <cstdint>
58314564Sdim#include <cstring>
59314564Sdim#include <iterator>
60314564Sdim#include <map>
61314564Sdim#include <memory>
62314564Sdim#include <string>
63284677Sdim
64284677Sdimusing namespace llvm;
65314564Sdimusing namespace llvm::AMDGPU;
66341825Sdimusing namespace llvm::amdhsa;
67284677Sdim
68284677Sdimnamespace {
69284677Sdim
70314564Sdimclass AMDGPUAsmParser;
71284677Sdim
72353358Sdimenum RegisterKind { IS_UNKNOWN, IS_VGPR, IS_SGPR, IS_AGPR, IS_TTMP, IS_SPECIAL };
73309124Sdim
74314564Sdim//===----------------------------------------------------------------------===//
75314564Sdim// Operand
76314564Sdim//===----------------------------------------------------------------------===//
77314564Sdim
78284677Sdimclass AMDGPUOperand : public MCParsedAsmOperand {
79284677Sdim  enum KindTy {
80284677Sdim    Token,
81284677Sdim    Immediate,
82284677Sdim    Register,
83284677Sdim    Expression
84284677Sdim  } Kind;
85284677Sdim
86284677Sdim  SMLoc StartLoc, EndLoc;
87314564Sdim  const AMDGPUAsmParser *AsmParser;
88284677Sdim
89284677Sdimpublic:
90321369Sdim  AMDGPUOperand(KindTy Kind_, const AMDGPUAsmParser *AsmParser_)
91314564Sdim    : MCParsedAsmOperand(), Kind(Kind_), AsmParser(AsmParser_) {}
92284677Sdim
93327952Sdim  using Ptr = std::unique_ptr<AMDGPUOperand>;
94284677Sdim
95309124Sdim  struct Modifiers {
96314564Sdim    bool Abs = false;
97314564Sdim    bool Neg = false;
98314564Sdim    bool Sext = false;
99309124Sdim
100309124Sdim    bool hasFPModifiers() const { return Abs || Neg; }
101309124Sdim    bool hasIntModifiers() const { return Sext; }
102309124Sdim    bool hasModifiers() const { return hasFPModifiers() || hasIntModifiers(); }
103309124Sdim
104309124Sdim    int64_t getFPModifiersOperand() const {
105309124Sdim      int64_t Operand = 0;
106353358Sdim      Operand |= Abs ? SISrcMods::ABS : 0u;
107353358Sdim      Operand |= Neg ? SISrcMods::NEG : 0u;
108309124Sdim      return Operand;
109309124Sdim    }
110309124Sdim
111309124Sdim    int64_t getIntModifiersOperand() const {
112309124Sdim      int64_t Operand = 0;
113353358Sdim      Operand |= Sext ? SISrcMods::SEXT : 0u;
114309124Sdim      return Operand;
115309124Sdim    }
116309124Sdim
117309124Sdim    int64_t getModifiersOperand() const {
118309124Sdim      assert(!(hasFPModifiers() && hasIntModifiers())
119309124Sdim           && "fp and int modifiers should not be used simultaneously");
120309124Sdim      if (hasFPModifiers()) {
121309124Sdim        return getFPModifiersOperand();
122309124Sdim      } else if (hasIntModifiers()) {
123309124Sdim        return getIntModifiersOperand();
124309124Sdim      } else {
125309124Sdim        return 0;
126309124Sdim      }
127309124Sdim    }
128309124Sdim
129309124Sdim    friend raw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods);
130309124Sdim  };
131309124Sdim
132284677Sdim  enum ImmTy {
133284677Sdim    ImmTyNone,
134284677Sdim    ImmTyGDS,
135341825Sdim    ImmTyLDS,
136309124Sdim    ImmTyOffen,
137309124Sdim    ImmTyIdxen,
138309124Sdim    ImmTyAddr64,
139284677Sdim    ImmTyOffset,
140327952Sdim    ImmTyInstOffset,
141309124Sdim    ImmTyOffset0,
142309124Sdim    ImmTyOffset1,
143353358Sdim    ImmTyDLC,
144284677Sdim    ImmTyGLC,
145284677Sdim    ImmTySLC,
146360784Sdim    ImmTySWZ,
147284677Sdim    ImmTyTFE,
148341825Sdim    ImmTyD16,
149309124Sdim    ImmTyClampSI,
150309124Sdim    ImmTyOModSI,
151353358Sdim    ImmTyDPP8,
152309124Sdim    ImmTyDppCtrl,
153309124Sdim    ImmTyDppRowMask,
154309124Sdim    ImmTyDppBankMask,
155309124Sdim    ImmTyDppBoundCtrl,
156353358Sdim    ImmTyDppFi,
157309124Sdim    ImmTySdwaDstSel,
158309124Sdim    ImmTySdwaSrc0Sel,
159309124Sdim    ImmTySdwaSrc1Sel,
160309124Sdim    ImmTySdwaDstUnused,
161309124Sdim    ImmTyDMask,
162353358Sdim    ImmTyDim,
163309124Sdim    ImmTyUNorm,
164309124Sdim    ImmTyDA,
165344779Sdim    ImmTyR128A16,
166309124Sdim    ImmTyLWE,
167314564Sdim    ImmTyExpTgt,
168314564Sdim    ImmTyExpCompr,
169314564Sdim    ImmTyExpVM,
170344779Sdim    ImmTyFORMAT,
171309124Sdim    ImmTyHwreg,
172314564Sdim    ImmTyOff,
173309124Sdim    ImmTySendMsg,
174314564Sdim    ImmTyInterpSlot,
175314564Sdim    ImmTyInterpAttr,
176321369Sdim    ImmTyAttrChan,
177321369Sdim    ImmTyOpSel,
178321369Sdim    ImmTyOpSelHi,
179321369Sdim    ImmTyNegLo,
180321369Sdim    ImmTyNegHi,
181327952Sdim    ImmTySwizzle,
182353358Sdim    ImmTyGprIdxMode,
183353358Sdim    ImmTyHigh,
184353358Sdim    ImmTyBLGP,
185353358Sdim    ImmTyCBSZ,
186353358Sdim    ImmTyABID,
187353358Sdim    ImmTyEndpgm,
188284677Sdim  };
189284677Sdim
190353358Sdimprivate:
191284677Sdim  struct TokOp {
192284677Sdim    const char *Data;
193284677Sdim    unsigned Length;
194284677Sdim  };
195284677Sdim
196284677Sdim  struct ImmOp {
197314564Sdim    int64_t Val;
198314564Sdim    ImmTy Type;
199284677Sdim    bool IsFPImm;
200309124Sdim    Modifiers Mods;
201284677Sdim  };
202284677Sdim
203284677Sdim  struct RegOp {
204284677Sdim    unsigned RegNo;
205309124Sdim    Modifiers Mods;
206284677Sdim  };
207284677Sdim
208284677Sdim  union {
209284677Sdim    TokOp Tok;
210284677Sdim    ImmOp Imm;
211284677Sdim    RegOp Reg;
212284677Sdim    const MCExpr *Expr;
213284677Sdim  };
214284677Sdim
215353358Sdimpublic:
216309124Sdim  bool isToken() const override {
217309124Sdim    if (Kind == Token)
218309124Sdim      return true;
219284677Sdim
220309124Sdim    // When parsing operands, we can't always tell if something was meant to be
221309124Sdim    // a token, like 'gds', or an expression that references a global variable.
222309124Sdim    // In this case, we assume the string is an expression, and if we need to
223309124Sdim    // interpret is a token, then we treat the symbol name as the token.
224360784Sdim    return isSymbolRefExpr();
225284677Sdim  }
226284677Sdim
227360784Sdim  bool isSymbolRefExpr() const {
228360784Sdim    return isExpr() && Expr && isa<MCSymbolRefExpr>(Expr);
229360784Sdim  }
230360784Sdim
231284677Sdim  bool isImm() const override {
232284677Sdim    return Kind == Immediate;
233284677Sdim  }
234284677Sdim
235314564Sdim  bool isInlinableImm(MVT type) const;
236314564Sdim  bool isLiteralImm(MVT type) const;
237284677Sdim
238284677Sdim  bool isRegKind() const {
239284677Sdim    return Kind == Register;
240284677Sdim  }
241284677Sdim
242284677Sdim  bool isReg() const override {
243314564Sdim    return isRegKind() && !hasModifiers();
244284677Sdim  }
245284677Sdim
246353358Sdim  bool isRegOrImmWithInputMods(unsigned RCID, MVT type) const {
247353358Sdim    return isRegClass(RCID) || isInlinableImm(type) || isLiteralImm(type);
248284677Sdim  }
249284677Sdim
250314564Sdim  bool isRegOrImmWithInt16InputMods() const {
251353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i16);
252314564Sdim  }
253314564Sdim
254314564Sdim  bool isRegOrImmWithInt32InputMods() const {
255353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::i32);
256314564Sdim  }
257314564Sdim
258314564Sdim  bool isRegOrImmWithInt64InputMods() const {
259353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::i64);
260314564Sdim  }
261314564Sdim
262314564Sdim  bool isRegOrImmWithFP16InputMods() const {
263353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f16);
264314564Sdim  }
265314564Sdim
266314564Sdim  bool isRegOrImmWithFP32InputMods() const {
267353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_32RegClassID, MVT::f32);
268314564Sdim  }
269314564Sdim
270314564Sdim  bool isRegOrImmWithFP64InputMods() const {
271353358Sdim    return isRegOrImmWithInputMods(AMDGPU::VS_64RegClassID, MVT::f64);
272314564Sdim  }
273314564Sdim
274314564Sdim  bool isVReg() const {
275314564Sdim    return isRegClass(AMDGPU::VGPR_32RegClassID) ||
276314564Sdim           isRegClass(AMDGPU::VReg_64RegClassID) ||
277314564Sdim           isRegClass(AMDGPU::VReg_96RegClassID) ||
278314564Sdim           isRegClass(AMDGPU::VReg_128RegClassID) ||
279360784Sdim           isRegClass(AMDGPU::VReg_160RegClassID) ||
280314564Sdim           isRegClass(AMDGPU::VReg_256RegClassID) ||
281360784Sdim           isRegClass(AMDGPU::VReg_512RegClassID) ||
282360784Sdim           isRegClass(AMDGPU::VReg_1024RegClassID);
283314564Sdim  }
284314564Sdim
285353358Sdim  bool isVReg32() const {
286353358Sdim    return isRegClass(AMDGPU::VGPR_32RegClassID);
287353358Sdim  }
288353358Sdim
289314564Sdim  bool isVReg32OrOff() const {
290353358Sdim    return isOff() || isVReg32();
291314564Sdim  }
292314564Sdim
293360784Sdim  bool isNull() const {
294360784Sdim    return isRegKind() && getReg() == AMDGPU::SGPR_NULL;
295360784Sdim  }
296360784Sdim
297341825Sdim  bool isSDWAOperand(MVT type) const;
298341825Sdim  bool isSDWAFP16Operand() const;
299341825Sdim  bool isSDWAFP32Operand() const;
300341825Sdim  bool isSDWAInt16Operand() const;
301341825Sdim  bool isSDWAInt32Operand() const;
302321369Sdim
303309124Sdim  bool isImmTy(ImmTy ImmT) const {
304309124Sdim    return isImm() && Imm.Type == ImmT;
305284677Sdim  }
306314564Sdim
307309124Sdim  bool isImmModifier() const {
308309124Sdim    return isImm() && Imm.Type != ImmTyNone;
309284677Sdim  }
310314564Sdim
311309124Sdim  bool isClampSI() const { return isImmTy(ImmTyClampSI); }
312309124Sdim  bool isOModSI() const { return isImmTy(ImmTyOModSI); }
313309124Sdim  bool isDMask() const { return isImmTy(ImmTyDMask); }
314353358Sdim  bool isDim() const { return isImmTy(ImmTyDim); }
315309124Sdim  bool isUNorm() const { return isImmTy(ImmTyUNorm); }
316309124Sdim  bool isDA() const { return isImmTy(ImmTyDA); }
317344779Sdim  bool isR128A16() const { return isImmTy(ImmTyR128A16); }
318309124Sdim  bool isLWE() const { return isImmTy(ImmTyLWE); }
319314564Sdim  bool isOff() const { return isImmTy(ImmTyOff); }
320314564Sdim  bool isExpTgt() const { return isImmTy(ImmTyExpTgt); }
321314564Sdim  bool isExpVM() const { return isImmTy(ImmTyExpVM); }
322314564Sdim  bool isExpCompr() const { return isImmTy(ImmTyExpCompr); }
323309124Sdim  bool isOffen() const { return isImmTy(ImmTyOffen); }
324309124Sdim  bool isIdxen() const { return isImmTy(ImmTyIdxen); }
325309124Sdim  bool isAddr64() const { return isImmTy(ImmTyAddr64); }
326309124Sdim  bool isOffset() const { return isImmTy(ImmTyOffset) && isUInt<16>(getImm()); }
327353358Sdim  bool isOffset0() const { return isImmTy(ImmTyOffset0) && isUInt<8>(getImm()); }
328309124Sdim  bool isOffset1() const { return isImmTy(ImmTyOffset1) && isUInt<8>(getImm()); }
329321369Sdim
330353358Sdim  bool isFlatOffset() const { return isImmTy(ImmTyOffset) || isImmTy(ImmTyInstOffset); }
331309124Sdim  bool isGDS() const { return isImmTy(ImmTyGDS); }
332341825Sdim  bool isLDS() const { return isImmTy(ImmTyLDS); }
333353358Sdim  bool isDLC() const { return isImmTy(ImmTyDLC); }
334309124Sdim  bool isGLC() const { return isImmTy(ImmTyGLC); }
335309124Sdim  bool isSLC() const { return isImmTy(ImmTySLC); }
336360784Sdim  bool isSWZ() const { return isImmTy(ImmTySWZ); }
337309124Sdim  bool isTFE() const { return isImmTy(ImmTyTFE); }
338341825Sdim  bool isD16() const { return isImmTy(ImmTyD16); }
339344779Sdim  bool isFORMAT() const { return isImmTy(ImmTyFORMAT) && isUInt<8>(getImm()); }
340309124Sdim  bool isBankMask() const { return isImmTy(ImmTyDppBankMask); }
341309124Sdim  bool isRowMask() const { return isImmTy(ImmTyDppRowMask); }
342309124Sdim  bool isBoundCtrl() const { return isImmTy(ImmTyDppBoundCtrl); }
343353358Sdim  bool isFI() const { return isImmTy(ImmTyDppFi); }
344309124Sdim  bool isSDWADstSel() const { return isImmTy(ImmTySdwaDstSel); }
345309124Sdim  bool isSDWASrc0Sel() const { return isImmTy(ImmTySdwaSrc0Sel); }
346309124Sdim  bool isSDWASrc1Sel() const { return isImmTy(ImmTySdwaSrc1Sel); }
347309124Sdim  bool isSDWADstUnused() const { return isImmTy(ImmTySdwaDstUnused); }
348314564Sdim  bool isInterpSlot() const { return isImmTy(ImmTyInterpSlot); }
349314564Sdim  bool isInterpAttr() const { return isImmTy(ImmTyInterpAttr); }
350314564Sdim  bool isAttrChan() const { return isImmTy(ImmTyAttrChan); }
351321369Sdim  bool isOpSel() const { return isImmTy(ImmTyOpSel); }
352321369Sdim  bool isOpSelHi() const { return isImmTy(ImmTyOpSelHi); }
353321369Sdim  bool isNegLo() const { return isImmTy(ImmTyNegLo); }
354321369Sdim  bool isNegHi() const { return isImmTy(ImmTyNegHi); }
355327952Sdim  bool isHigh() const { return isImmTy(ImmTyHigh); }
356314564Sdim
357309124Sdim  bool isMod() const {
358309124Sdim    return isClampSI() || isOModSI();
359284677Sdim  }
360284677Sdim
361284677Sdim  bool isRegOrImm() const {
362284677Sdim    return isReg() || isImm();
363284677Sdim  }
364284677Sdim
365314564Sdim  bool isRegClass(unsigned RCID) const;
366314564Sdim
367353358Sdim  bool isInlineValue() const;
368353358Sdim
369314564Sdim  bool isRegOrInlineNoMods(unsigned RCID, MVT type) const {
370314564Sdim    return (isRegClass(RCID) || isInlinableImm(type)) && !hasModifiers();
371284677Sdim  }
372284677Sdim
373314564Sdim  bool isSCSrcB16() const {
374314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i16);
375284677Sdim  }
376284677Sdim
377321369Sdim  bool isSCSrcV2B16() const {
378321369Sdim    return isSCSrcB16();
379321369Sdim  }
380321369Sdim
381314564Sdim  bool isSCSrcB32() const {
382314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::i32);
383309124Sdim  }
384309124Sdim
385314564Sdim  bool isSCSrcB64() const {
386314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::i64);
387284677Sdim  }
388284677Sdim
389353358Sdim  bool isBoolReg() const;
390353358Sdim
391314564Sdim  bool isSCSrcF16() const {
392314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f16);
393314564Sdim  }
394314564Sdim
395321369Sdim  bool isSCSrcV2F16() const {
396321369Sdim    return isSCSrcF16();
397321369Sdim  }
398321369Sdim
399314564Sdim  bool isSCSrcF32() const {
400314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_32RegClassID, MVT::f32);
401314564Sdim  }
402314564Sdim
403314564Sdim  bool isSCSrcF64() const {
404314564Sdim    return isRegOrInlineNoMods(AMDGPU::SReg_64RegClassID, MVT::f64);
405314564Sdim  }
406314564Sdim
407314564Sdim  bool isSSrcB32() const {
408314564Sdim    return isSCSrcB32() || isLiteralImm(MVT::i32) || isExpr();
409314564Sdim  }
410314564Sdim
411314564Sdim  bool isSSrcB16() const {
412314564Sdim    return isSCSrcB16() || isLiteralImm(MVT::i16);
413314564Sdim  }
414314564Sdim
415321369Sdim  bool isSSrcV2B16() const {
416321369Sdim    llvm_unreachable("cannot happen");
417321369Sdim    return isSSrcB16();
418321369Sdim  }
419321369Sdim
420314564Sdim  bool isSSrcB64() const {
421309124Sdim    // TODO: Find out how SALU supports extension of 32-bit literals to 64 bits.
422309124Sdim    // See isVSrc64().
423314564Sdim    return isSCSrcB64() || isLiteralImm(MVT::i64);
424284677Sdim  }
425284677Sdim
426314564Sdim  bool isSSrcF32() const {
427314564Sdim    return isSCSrcB32() || isLiteralImm(MVT::f32) || isExpr();
428284677Sdim  }
429284677Sdim
430314564Sdim  bool isSSrcF64() const {
431314564Sdim    return isSCSrcB64() || isLiteralImm(MVT::f64);
432284677Sdim  }
433284677Sdim
434314564Sdim  bool isSSrcF16() const {
435314564Sdim    return isSCSrcB16() || isLiteralImm(MVT::f16);
436284677Sdim  }
437284677Sdim
438321369Sdim  bool isSSrcV2F16() const {
439321369Sdim    llvm_unreachable("cannot happen");
440321369Sdim    return isSSrcF16();
441321369Sdim  }
442321369Sdim
443353358Sdim  bool isSSrcOrLdsB32() const {
444353358Sdim    return isRegOrInlineNoMods(AMDGPU::SRegOrLds_32RegClassID, MVT::i32) ||
445353358Sdim           isLiteralImm(MVT::i32) || isExpr();
446353358Sdim  }
447353358Sdim
448314564Sdim  bool isVCSrcB32() const {
449314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i32);
450284677Sdim  }
451284677Sdim
452314564Sdim  bool isVCSrcB64() const {
453314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::i64);
454314564Sdim  }
455314564Sdim
456314564Sdim  bool isVCSrcB16() const {
457314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::i16);
458314564Sdim  }
459314564Sdim
460321369Sdim  bool isVCSrcV2B16() const {
461321369Sdim    return isVCSrcB16();
462321369Sdim  }
463321369Sdim
464314564Sdim  bool isVCSrcF32() const {
465314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f32);
466314564Sdim  }
467314564Sdim
468314564Sdim  bool isVCSrcF64() const {
469314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_64RegClassID, MVT::f64);
470314564Sdim  }
471314564Sdim
472314564Sdim  bool isVCSrcF16() const {
473314564Sdim    return isRegOrInlineNoMods(AMDGPU::VS_32RegClassID, MVT::f16);
474314564Sdim  }
475314564Sdim
476321369Sdim  bool isVCSrcV2F16() const {
477321369Sdim    return isVCSrcF16();
478321369Sdim  }
479321369Sdim
480314564Sdim  bool isVSrcB32() const {
481341825Sdim    return isVCSrcF32() || isLiteralImm(MVT::i32) || isExpr();
482314564Sdim  }
483314564Sdim
484314564Sdim  bool isVSrcB64() const {
485314564Sdim    return isVCSrcF64() || isLiteralImm(MVT::i64);
486314564Sdim  }
487314564Sdim
488314564Sdim  bool isVSrcB16() const {
489314564Sdim    return isVCSrcF16() || isLiteralImm(MVT::i16);
490314564Sdim  }
491314564Sdim
492321369Sdim  bool isVSrcV2B16() const {
493353358Sdim    return isVSrcB16() || isLiteralImm(MVT::v2i16);
494321369Sdim  }
495321369Sdim
496314564Sdim  bool isVSrcF32() const {
497341825Sdim    return isVCSrcF32() || isLiteralImm(MVT::f32) || isExpr();
498314564Sdim  }
499314564Sdim
500314564Sdim  bool isVSrcF64() const {
501314564Sdim    return isVCSrcF64() || isLiteralImm(MVT::f64);
502314564Sdim  }
503314564Sdim
504314564Sdim  bool isVSrcF16() const {
505314564Sdim    return isVCSrcF16() || isLiteralImm(MVT::f16);
506314564Sdim  }
507314564Sdim
508321369Sdim  bool isVSrcV2F16() const {
509353358Sdim    return isVSrcF16() || isLiteralImm(MVT::v2f16);
510321369Sdim  }
511321369Sdim
512353358Sdim  bool isVISrcB32() const {
513353358Sdim    return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i32);
514353358Sdim  }
515353358Sdim
516353358Sdim  bool isVISrcB16() const {
517353358Sdim    return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::i16);
518353358Sdim  }
519353358Sdim
520353358Sdim  bool isVISrcV2B16() const {
521353358Sdim    return isVISrcB16();
522353358Sdim  }
523353358Sdim
524353358Sdim  bool isVISrcF32() const {
525353358Sdim    return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f32);
526353358Sdim  }
527353358Sdim
528353358Sdim  bool isVISrcF16() const {
529353358Sdim    return isRegOrInlineNoMods(AMDGPU::VGPR_32RegClassID, MVT::f16);
530353358Sdim  }
531353358Sdim
532353358Sdim  bool isVISrcV2F16() const {
533353358Sdim    return isVISrcF16() || isVISrcB32();
534353358Sdim  }
535353358Sdim
536353358Sdim  bool isAISrcB32() const {
537353358Sdim    return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i32);
538353358Sdim  }
539353358Sdim
540353358Sdim  bool isAISrcB16() const {
541353358Sdim    return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::i16);
542353358Sdim  }
543353358Sdim
544353358Sdim  bool isAISrcV2B16() const {
545353358Sdim    return isAISrcB16();
546353358Sdim  }
547353358Sdim
548353358Sdim  bool isAISrcF32() const {
549353358Sdim    return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f32);
550353358Sdim  }
551353358Sdim
552353358Sdim  bool isAISrcF16() const {
553353358Sdim    return isRegOrInlineNoMods(AMDGPU::AGPR_32RegClassID, MVT::f16);
554353358Sdim  }
555353358Sdim
556353358Sdim  bool isAISrcV2F16() const {
557353358Sdim    return isAISrcF16() || isAISrcB32();
558353358Sdim  }
559353358Sdim
560353358Sdim  bool isAISrc_128B32() const {
561353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i32);
562353358Sdim  }
563353358Sdim
564353358Sdim  bool isAISrc_128B16() const {
565353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::i16);
566353358Sdim  }
567353358Sdim
568353358Sdim  bool isAISrc_128V2B16() const {
569353358Sdim    return isAISrc_128B16();
570353358Sdim  }
571353358Sdim
572353358Sdim  bool isAISrc_128F32() const {
573353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f32);
574353358Sdim  }
575353358Sdim
576353358Sdim  bool isAISrc_128F16() const {
577353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_128RegClassID, MVT::f16);
578353358Sdim  }
579353358Sdim
580353358Sdim  bool isAISrc_128V2F16() const {
581353358Sdim    return isAISrc_128F16() || isAISrc_128B32();
582353358Sdim  }
583353358Sdim
584353358Sdim  bool isAISrc_512B32() const {
585353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i32);
586353358Sdim  }
587353358Sdim
588353358Sdim  bool isAISrc_512B16() const {
589353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::i16);
590353358Sdim  }
591353358Sdim
592353358Sdim  bool isAISrc_512V2B16() const {
593353358Sdim    return isAISrc_512B16();
594353358Sdim  }
595353358Sdim
596353358Sdim  bool isAISrc_512F32() const {
597353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f32);
598353358Sdim  }
599353358Sdim
600353358Sdim  bool isAISrc_512F16() const {
601353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_512RegClassID, MVT::f16);
602353358Sdim  }
603353358Sdim
604353358Sdim  bool isAISrc_512V2F16() const {
605353358Sdim    return isAISrc_512F16() || isAISrc_512B32();
606353358Sdim  }
607353358Sdim
608353358Sdim  bool isAISrc_1024B32() const {
609353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i32);
610353358Sdim  }
611353358Sdim
612353358Sdim  bool isAISrc_1024B16() const {
613353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::i16);
614353358Sdim  }
615353358Sdim
616353358Sdim  bool isAISrc_1024V2B16() const {
617353358Sdim    return isAISrc_1024B16();
618353358Sdim  }
619353358Sdim
620353358Sdim  bool isAISrc_1024F32() const {
621353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f32);
622353358Sdim  }
623353358Sdim
624353358Sdim  bool isAISrc_1024F16() const {
625353358Sdim    return isRegOrInlineNoMods(AMDGPU::AReg_1024RegClassID, MVT::f16);
626353358Sdim  }
627353358Sdim
628353358Sdim  bool isAISrc_1024V2F16() const {
629353358Sdim    return isAISrc_1024F16() || isAISrc_1024B32();
630353358Sdim  }
631353358Sdim
632314564Sdim  bool isKImmFP32() const {
633314564Sdim    return isLiteralImm(MVT::f32);
634314564Sdim  }
635314564Sdim
636314564Sdim  bool isKImmFP16() const {
637314564Sdim    return isLiteralImm(MVT::f16);
638314564Sdim  }
639314564Sdim
640284677Sdim  bool isMem() const override {
641284677Sdim    return false;
642284677Sdim  }
643284677Sdim
644284677Sdim  bool isExpr() const {
645284677Sdim    return Kind == Expression;
646284677Sdim  }
647284677Sdim
648284677Sdim  bool isSoppBrTarget() const {
649284677Sdim    return isExpr() || isImm();
650284677Sdim  }
651284677Sdim
652309124Sdim  bool isSWaitCnt() const;
653309124Sdim  bool isHwreg() const;
654309124Sdim  bool isSendMsg() const;
655321369Sdim  bool isSwizzle() const;
656314564Sdim  bool isSMRDOffset8() const;
657314564Sdim  bool isSMRDOffset20() const;
658309124Sdim  bool isSMRDLiteralOffset() const;
659353358Sdim  bool isDPP8() const;
660309124Sdim  bool isDPPCtrl() const;
661353358Sdim  bool isBLGP() const;
662353358Sdim  bool isCBSZ() const;
663353358Sdim  bool isABID() const;
664314564Sdim  bool isGPRIdxMode() const;
665321369Sdim  bool isS16Imm() const;
666321369Sdim  bool isU16Imm() const;
667353358Sdim  bool isEndpgm() const;
668309124Sdim
669309124Sdim  StringRef getExpressionAsToken() const {
670309124Sdim    assert(isExpr());
671309124Sdim    const MCSymbolRefExpr *S = cast<MCSymbolRefExpr>(Expr);
672309124Sdim    return S->getSymbol().getName();
673309124Sdim  }
674309124Sdim
675309124Sdim  StringRef getToken() const {
676309124Sdim    assert(isToken());
677309124Sdim
678309124Sdim    if (Kind == Expression)
679309124Sdim      return getExpressionAsToken();
680309124Sdim
681309124Sdim    return StringRef(Tok.Data, Tok.Length);
682309124Sdim  }
683309124Sdim
684309124Sdim  int64_t getImm() const {
685309124Sdim    assert(isImm());
686309124Sdim    return Imm.Val;
687309124Sdim  }
688309124Sdim
689321369Sdim  ImmTy getImmTy() const {
690309124Sdim    assert(isImm());
691309124Sdim    return Imm.Type;
692309124Sdim  }
693309124Sdim
694309124Sdim  unsigned getReg() const override {
695353358Sdim    assert(isRegKind());
696309124Sdim    return Reg.RegNo;
697309124Sdim  }
698309124Sdim
699284677Sdim  SMLoc getStartLoc() const override {
700284677Sdim    return StartLoc;
701284677Sdim  }
702284677Sdim
703284677Sdim  SMLoc getEndLoc() const override {
704284677Sdim    return EndLoc;
705284677Sdim  }
706284677Sdim
707327952Sdim  SMRange getLocRange() const {
708327952Sdim    return SMRange(StartLoc, EndLoc);
709327952Sdim  }
710327952Sdim
711309124Sdim  Modifiers getModifiers() const {
712309124Sdim    assert(isRegKind() || isImmTy(ImmTyNone));
713309124Sdim    return isRegKind() ? Reg.Mods : Imm.Mods;
714309124Sdim  }
715309124Sdim
716309124Sdim  void setModifiers(Modifiers Mods) {
717309124Sdim    assert(isRegKind() || isImmTy(ImmTyNone));
718309124Sdim    if (isRegKind())
719309124Sdim      Reg.Mods = Mods;
720309124Sdim    else
721309124Sdim      Imm.Mods = Mods;
722309124Sdim  }
723309124Sdim
724309124Sdim  bool hasModifiers() const {
725309124Sdim    return getModifiers().hasModifiers();
726309124Sdim  }
727314564Sdim
728309124Sdim  bool hasFPModifiers() const {
729309124Sdim    return getModifiers().hasFPModifiers();
730309124Sdim  }
731309124Sdim
732309124Sdim  bool hasIntModifiers() const {
733309124Sdim    return getModifiers().hasIntModifiers();
734309124Sdim  }
735309124Sdim
736321369Sdim  uint64_t applyInputFPModifiers(uint64_t Val, unsigned Size) const;
737321369Sdim
738314564Sdim  void addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers = true) const;
739314564Sdim
740321369Sdim  void addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const;
741314564Sdim
742314564Sdim  template <unsigned Bitwidth>
743314564Sdim  void addKImmFPOperands(MCInst &Inst, unsigned N) const;
744314564Sdim
745314564Sdim  void addKImmFP16Operands(MCInst &Inst, unsigned N) const {
746314564Sdim    addKImmFPOperands<16>(Inst, N);
747309124Sdim  }
748309124Sdim
749314564Sdim  void addKImmFP32Operands(MCInst &Inst, unsigned N) const {
750314564Sdim    addKImmFPOperands<32>(Inst, N);
751309124Sdim  }
752309124Sdim
753314564Sdim  void addRegOperands(MCInst &Inst, unsigned N) const;
754314564Sdim
755353358Sdim  void addBoolRegOperands(MCInst &Inst, unsigned N) const {
756353358Sdim    addRegOperands(Inst, N);
757353358Sdim  }
758353358Sdim
759309124Sdim  void addRegOrImmOperands(MCInst &Inst, unsigned N) const {
760309124Sdim    if (isRegKind())
761309124Sdim      addRegOperands(Inst, N);
762309124Sdim    else if (isExpr())
763309124Sdim      Inst.addOperand(MCOperand::createExpr(Expr));
764309124Sdim    else
765309124Sdim      addImmOperands(Inst, N);
766309124Sdim  }
767309124Sdim
768309124Sdim  void addRegOrImmWithInputModsOperands(MCInst &Inst, unsigned N) const {
769309124Sdim    Modifiers Mods = getModifiers();
770309124Sdim    Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
771309124Sdim    if (isRegKind()) {
772309124Sdim      addRegOperands(Inst, N);
773309124Sdim    } else {
774309124Sdim      addImmOperands(Inst, N, false);
775309124Sdim    }
776309124Sdim  }
777309124Sdim
778309124Sdim  void addRegOrImmWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
779309124Sdim    assert(!hasIntModifiers());
780309124Sdim    addRegOrImmWithInputModsOperands(Inst, N);
781309124Sdim  }
782309124Sdim
783309124Sdim  void addRegOrImmWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
784309124Sdim    assert(!hasFPModifiers());
785309124Sdim    addRegOrImmWithInputModsOperands(Inst, N);
786309124Sdim  }
787309124Sdim
788314564Sdim  void addRegWithInputModsOperands(MCInst &Inst, unsigned N) const {
789314564Sdim    Modifiers Mods = getModifiers();
790314564Sdim    Inst.addOperand(MCOperand::createImm(Mods.getModifiersOperand()));
791314564Sdim    assert(isRegKind());
792314564Sdim    addRegOperands(Inst, N);
793314564Sdim  }
794314564Sdim
795314564Sdim  void addRegWithFPInputModsOperands(MCInst &Inst, unsigned N) const {
796314564Sdim    assert(!hasIntModifiers());
797314564Sdim    addRegWithInputModsOperands(Inst, N);
798314564Sdim  }
799314564Sdim
800314564Sdim  void addRegWithIntInputModsOperands(MCInst &Inst, unsigned N) const {
801314564Sdim    assert(!hasFPModifiers());
802314564Sdim    addRegWithInputModsOperands(Inst, N);
803314564Sdim  }
804314564Sdim
805309124Sdim  void addSoppBrTargetOperands(MCInst &Inst, unsigned N) const {
806309124Sdim    if (isImm())
807309124Sdim      addImmOperands(Inst, N);
808309124Sdim    else {
809309124Sdim      assert(isExpr());
810309124Sdim      Inst.addOperand(MCOperand::createExpr(Expr));
811309124Sdim    }
812309124Sdim  }
813309124Sdim
814314564Sdim  static void printImmTy(raw_ostream& OS, ImmTy Type) {
815309124Sdim    switch (Type) {
816309124Sdim    case ImmTyNone: OS << "None"; break;
817309124Sdim    case ImmTyGDS: OS << "GDS"; break;
818341825Sdim    case ImmTyLDS: OS << "LDS"; break;
819309124Sdim    case ImmTyOffen: OS << "Offen"; break;
820309124Sdim    case ImmTyIdxen: OS << "Idxen"; break;
821309124Sdim    case ImmTyAddr64: OS << "Addr64"; break;
822309124Sdim    case ImmTyOffset: OS << "Offset"; break;
823327952Sdim    case ImmTyInstOffset: OS << "InstOffset"; break;
824309124Sdim    case ImmTyOffset0: OS << "Offset0"; break;
825309124Sdim    case ImmTyOffset1: OS << "Offset1"; break;
826353358Sdim    case ImmTyDLC: OS << "DLC"; break;
827309124Sdim    case ImmTyGLC: OS << "GLC"; break;
828309124Sdim    case ImmTySLC: OS << "SLC"; break;
829360784Sdim    case ImmTySWZ: OS << "SWZ"; break;
830309124Sdim    case ImmTyTFE: OS << "TFE"; break;
831341825Sdim    case ImmTyD16: OS << "D16"; break;
832344779Sdim    case ImmTyFORMAT: OS << "FORMAT"; break;
833309124Sdim    case ImmTyClampSI: OS << "ClampSI"; break;
834309124Sdim    case ImmTyOModSI: OS << "OModSI"; break;
835353358Sdim    case ImmTyDPP8: OS << "DPP8"; break;
836309124Sdim    case ImmTyDppCtrl: OS << "DppCtrl"; break;
837309124Sdim    case ImmTyDppRowMask: OS << "DppRowMask"; break;
838309124Sdim    case ImmTyDppBankMask: OS << "DppBankMask"; break;
839309124Sdim    case ImmTyDppBoundCtrl: OS << "DppBoundCtrl"; break;
840353358Sdim    case ImmTyDppFi: OS << "FI"; break;
841309124Sdim    case ImmTySdwaDstSel: OS << "SdwaDstSel"; break;
842309124Sdim    case ImmTySdwaSrc0Sel: OS << "SdwaSrc0Sel"; break;
843309124Sdim    case ImmTySdwaSrc1Sel: OS << "SdwaSrc1Sel"; break;
844309124Sdim    case ImmTySdwaDstUnused: OS << "SdwaDstUnused"; break;
845309124Sdim    case ImmTyDMask: OS << "DMask"; break;
846353358Sdim    case ImmTyDim: OS << "Dim"; break;
847309124Sdim    case ImmTyUNorm: OS << "UNorm"; break;
848309124Sdim    case ImmTyDA: OS << "DA"; break;
849344779Sdim    case ImmTyR128A16: OS << "R128A16"; break;
850309124Sdim    case ImmTyLWE: OS << "LWE"; break;
851314564Sdim    case ImmTyOff: OS << "Off"; break;
852314564Sdim    case ImmTyExpTgt: OS << "ExpTgt"; break;
853314564Sdim    case ImmTyExpCompr: OS << "ExpCompr"; break;
854314564Sdim    case ImmTyExpVM: OS << "ExpVM"; break;
855309124Sdim    case ImmTyHwreg: OS << "Hwreg"; break;
856309124Sdim    case ImmTySendMsg: OS << "SendMsg"; break;
857314564Sdim    case ImmTyInterpSlot: OS << "InterpSlot"; break;
858314564Sdim    case ImmTyInterpAttr: OS << "InterpAttr"; break;
859314564Sdim    case ImmTyAttrChan: OS << "AttrChan"; break;
860321369Sdim    case ImmTyOpSel: OS << "OpSel"; break;
861321369Sdim    case ImmTyOpSelHi: OS << "OpSelHi"; break;
862321369Sdim    case ImmTyNegLo: OS << "NegLo"; break;
863321369Sdim    case ImmTyNegHi: OS << "NegHi"; break;
864321369Sdim    case ImmTySwizzle: OS << "Swizzle"; break;
865353358Sdim    case ImmTyGprIdxMode: OS << "GprIdxMode"; break;
866327952Sdim    case ImmTyHigh: OS << "High"; break;
867353358Sdim    case ImmTyBLGP: OS << "BLGP"; break;
868353358Sdim    case ImmTyCBSZ: OS << "CBSZ"; break;
869353358Sdim    case ImmTyABID: OS << "ABID"; break;
870353358Sdim    case ImmTyEndpgm: OS << "Endpgm"; break;
871309124Sdim    }
872309124Sdim  }
873309124Sdim
874296417Sdim  void print(raw_ostream &OS) const override {
875296417Sdim    switch (Kind) {
876296417Sdim    case Register:
877309124Sdim      OS << "<register " << getReg() << " mods: " << Reg.Mods << '>';
878296417Sdim      break;
879296417Sdim    case Immediate:
880309124Sdim      OS << '<' << getImm();
881309124Sdim      if (getImmTy() != ImmTyNone) {
882309124Sdim        OS << " type: "; printImmTy(OS, getImmTy());
883309124Sdim      }
884309124Sdim      OS << " mods: " << Imm.Mods << '>';
885296417Sdim      break;
886296417Sdim    case Token:
887296417Sdim      OS << '\'' << getToken() << '\'';
888296417Sdim      break;
889296417Sdim    case Expression:
890296417Sdim      OS << "<expr " << *Expr << '>';
891296417Sdim      break;
892296417Sdim    }
893296417Sdim  }
894284677Sdim
895314564Sdim  static AMDGPUOperand::Ptr CreateImm(const AMDGPUAsmParser *AsmParser,
896314564Sdim                                      int64_t Val, SMLoc Loc,
897321369Sdim                                      ImmTy Type = ImmTyNone,
898309124Sdim                                      bool IsFPImm = false) {
899360784Sdim    auto Op = std::make_unique<AMDGPUOperand>(Immediate, AsmParser);
900284677Sdim    Op->Imm.Val = Val;
901284677Sdim    Op->Imm.IsFPImm = IsFPImm;
902284677Sdim    Op->Imm.Type = Type;
903314564Sdim    Op->Imm.Mods = Modifiers();
904284677Sdim    Op->StartLoc = Loc;
905284677Sdim    Op->EndLoc = Loc;
906284677Sdim    return Op;
907284677Sdim  }
908284677Sdim
909314564Sdim  static AMDGPUOperand::Ptr CreateToken(const AMDGPUAsmParser *AsmParser,
910314564Sdim                                        StringRef Str, SMLoc Loc,
911309124Sdim                                        bool HasExplicitEncodingSize = true) {
912360784Sdim    auto Res = std::make_unique<AMDGPUOperand>(Token, AsmParser);
913284677Sdim    Res->Tok.Data = Str.data();
914284677Sdim    Res->Tok.Length = Str.size();
915284677Sdim    Res->StartLoc = Loc;
916284677Sdim    Res->EndLoc = Loc;
917284677Sdim    return Res;
918284677Sdim  }
919284677Sdim
920314564Sdim  static AMDGPUOperand::Ptr CreateReg(const AMDGPUAsmParser *AsmParser,
921314564Sdim                                      unsigned RegNo, SMLoc S,
922353358Sdim                                      SMLoc E) {
923360784Sdim    auto Op = std::make_unique<AMDGPUOperand>(Register, AsmParser);
924284677Sdim    Op->Reg.RegNo = RegNo;
925314564Sdim    Op->Reg.Mods = Modifiers();
926284677Sdim    Op->StartLoc = S;
927284677Sdim    Op->EndLoc = E;
928284677Sdim    return Op;
929284677Sdim  }
930284677Sdim
931314564Sdim  static AMDGPUOperand::Ptr CreateExpr(const AMDGPUAsmParser *AsmParser,
932314564Sdim                                       const class MCExpr *Expr, SMLoc S) {
933360784Sdim    auto Op = std::make_unique<AMDGPUOperand>(Expression, AsmParser);
934284677Sdim    Op->Expr = Expr;
935284677Sdim    Op->StartLoc = S;
936284677Sdim    Op->EndLoc = S;
937284677Sdim    return Op;
938284677Sdim  }
939284677Sdim};
940284677Sdim
941309124Sdimraw_ostream &operator <<(raw_ostream &OS, AMDGPUOperand::Modifiers Mods) {
942309124Sdim  OS << "abs:" << Mods.Abs << " neg: " << Mods.Neg << " sext:" << Mods.Sext;
943309124Sdim  return OS;
944309124Sdim}
945309124Sdim
946314564Sdim//===----------------------------------------------------------------------===//
947314564Sdim// AsmParser
948314564Sdim//===----------------------------------------------------------------------===//
949314564Sdim
950314564Sdim// Holds info related to the current kernel, e.g. count of SGPRs used.
951314564Sdim// Kernel scope begins at .amdgpu_hsa_kernel directive, ends at next
952314564Sdim// .amdgpu_hsa_kernel or at EOF.
953314564Sdimclass KernelScopeInfo {
954321369Sdim  int SgprIndexUnusedMin = -1;
955321369Sdim  int VgprIndexUnusedMin = -1;
956321369Sdim  MCContext *Ctx = nullptr;
957314564Sdim
958314564Sdim  void usesSgprAt(int i) {
959314564Sdim    if (i >= SgprIndexUnusedMin) {
960314564Sdim      SgprIndexUnusedMin = ++i;
961314564Sdim      if (Ctx) {
962314564Sdim        MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.sgpr_count"));
963314564Sdim        Sym->setVariableValue(MCConstantExpr::create(SgprIndexUnusedMin, *Ctx));
964314564Sdim      }
965314564Sdim    }
966314564Sdim  }
967321369Sdim
968314564Sdim  void usesVgprAt(int i) {
969314564Sdim    if (i >= VgprIndexUnusedMin) {
970314564Sdim      VgprIndexUnusedMin = ++i;
971314564Sdim      if (Ctx) {
972314564Sdim        MCSymbol * const Sym = Ctx->getOrCreateSymbol(Twine(".kernel.vgpr_count"));
973314564Sdim        Sym->setVariableValue(MCConstantExpr::create(VgprIndexUnusedMin, *Ctx));
974314564Sdim      }
975314564Sdim    }
976314564Sdim  }
977321369Sdim
978314564Sdimpublic:
979321369Sdim  KernelScopeInfo() = default;
980321369Sdim
981314564Sdim  void initialize(MCContext &Context) {
982314564Sdim    Ctx = &Context;
983314564Sdim    usesSgprAt(SgprIndexUnusedMin = -1);
984314564Sdim    usesVgprAt(VgprIndexUnusedMin = -1);
985314564Sdim  }
986321369Sdim
987314564Sdim  void usesRegister(RegisterKind RegKind, unsigned DwordRegIndex, unsigned RegWidth) {
988314564Sdim    switch (RegKind) {
989314564Sdim      case IS_SGPR: usesSgprAt(DwordRegIndex + RegWidth - 1); break;
990353358Sdim      case IS_AGPR: // fall through
991314564Sdim      case IS_VGPR: usesVgprAt(DwordRegIndex + RegWidth - 1); break;
992314564Sdim      default: break;
993314564Sdim    }
994314564Sdim  }
995314564Sdim};
996314564Sdim
997284677Sdimclass AMDGPUAsmParser : public MCTargetAsmParser {
998284677Sdim  MCAsmParser &Parser;
999284677Sdim
1000327952Sdim  // Number of extra operands parsed after the first optional operand.
1001327952Sdim  // This may be necessary to skip hardcoded mandatory operands.
1002341825Sdim  static const unsigned MAX_OPR_LOOKAHEAD = 8;
1003327952Sdim
1004321369Sdim  unsigned ForcedEncodingSize = 0;
1005321369Sdim  bool ForcedDPP = false;
1006321369Sdim  bool ForcedSDWA = false;
1007314564Sdim  KernelScopeInfo KernelScope;
1008296417Sdim
1009284677Sdim  /// @name Auto-generated Match Functions
1010284677Sdim  /// {
1011284677Sdim
1012284677Sdim#define GET_ASSEMBLER_HEADER
1013284677Sdim#include "AMDGPUGenAsmMatcher.inc"
1014284677Sdim
1015284677Sdim  /// }
1016284677Sdim
1017285181Sdimprivate:
1018314564Sdim  bool ParseAsAbsoluteExpression(uint32_t &Ret);
1019341825Sdim  bool OutOfRangeError(SMRange Range);
1020341825Sdim  /// Calculate VGPR/SGPR blocks required for given target, reserved
1021341825Sdim  /// registers, and user-specified NextFreeXGPR values.
1022341825Sdim  ///
1023341825Sdim  /// \param Features [in] Target features, used for bug corrections.
1024341825Sdim  /// \param VCCUsed [in] Whether VCC special SGPR is reserved.
1025341825Sdim  /// \param FlatScrUsed [in] Whether FLAT_SCRATCH special SGPR is reserved.
1026341825Sdim  /// \param XNACKUsed [in] Whether XNACK_MASK special SGPR is reserved.
1027353358Sdim  /// \param EnableWavefrontSize32 [in] Value of ENABLE_WAVEFRONT_SIZE32 kernel
1028353358Sdim  /// descriptor field, if valid.
1029341825Sdim  /// \param NextFreeVGPR [in] Max VGPR number referenced, plus one.
1030341825Sdim  /// \param VGPRRange [in] Token range, used for VGPR diagnostics.
1031341825Sdim  /// \param NextFreeSGPR [in] Max SGPR number referenced, plus one.
1032341825Sdim  /// \param SGPRRange [in] Token range, used for SGPR diagnostics.
1033341825Sdim  /// \param VGPRBlocks [out] Result VGPR block count.
1034341825Sdim  /// \param SGPRBlocks [out] Result SGPR block count.
1035341825Sdim  bool calculateGPRBlocks(const FeatureBitset &Features, bool VCCUsed,
1036341825Sdim                          bool FlatScrUsed, bool XNACKUsed,
1037353358Sdim                          Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR,
1038353358Sdim                          SMRange VGPRRange, unsigned NextFreeSGPR,
1039353358Sdim                          SMRange SGPRRange, unsigned &VGPRBlocks,
1040353358Sdim                          unsigned &SGPRBlocks);
1041341825Sdim  bool ParseDirectiveAMDGCNTarget();
1042341825Sdim  bool ParseDirectiveAMDHSAKernel();
1043285181Sdim  bool ParseDirectiveMajorMinor(uint32_t &Major, uint32_t &Minor);
1044285181Sdim  bool ParseDirectiveHSACodeObjectVersion();
1045285181Sdim  bool ParseDirectiveHSACodeObjectISA();
1046285181Sdim  bool ParseAMDKernelCodeTValue(StringRef ID, amd_kernel_code_t &Header);
1047285181Sdim  bool ParseDirectiveAMDKernelCodeT();
1048296417Sdim  bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const;
1049296417Sdim  bool ParseDirectiveAMDGPUHsaKernel();
1050327952Sdim
1051327952Sdim  bool ParseDirectiveISAVersion();
1052327952Sdim  bool ParseDirectiveHSAMetadata();
1053353358Sdim  bool ParseDirectivePALMetadataBegin();
1054327952Sdim  bool ParseDirectivePALMetadata();
1055353358Sdim  bool ParseDirectiveAMDGPULDS();
1056327952Sdim
1057353358Sdim  /// Common code to parse out a block of text (typically YAML) between start and
1058353358Sdim  /// end directives.
1059353358Sdim  bool ParseToEndDirective(const char *AssemblerDirectiveBegin,
1060353358Sdim                           const char *AssemblerDirectiveEnd,
1061353358Sdim                           std::string &CollectString);
1062353358Sdim
1063321369Sdim  bool AddNextRegisterToList(unsigned& Reg, unsigned& RegWidth,
1064360784Sdim                             RegisterKind RegKind, unsigned Reg1);
1065321369Sdim  bool ParseAMDGPURegister(RegisterKind& RegKind, unsigned& Reg,
1066360784Sdim                           unsigned& RegNum, unsigned& RegWidth);
1067360784Sdim  unsigned ParseRegularReg(RegisterKind &RegKind,
1068360784Sdim                           unsigned &RegNum,
1069360784Sdim                           unsigned &RegWidth);
1070360784Sdim  unsigned ParseSpecialReg(RegisterKind &RegKind,
1071360784Sdim                           unsigned &RegNum,
1072360784Sdim                           unsigned &RegWidth);
1073360784Sdim  unsigned ParseRegList(RegisterKind &RegKind,
1074360784Sdim                        unsigned &RegNum,
1075360784Sdim                        unsigned &RegWidth);
1076360784Sdim  bool ParseRegRange(unsigned& Num, unsigned& Width);
1077360784Sdim  unsigned getRegularReg(RegisterKind RegKind,
1078360784Sdim                         unsigned RegNum,
1079360784Sdim                         unsigned RegWidth);
1080360784Sdim
1081353358Sdim  bool isRegister();
1082353358Sdim  bool isRegister(const AsmToken &Token, const AsmToken &NextToken) const;
1083341825Sdim  Optional<StringRef> getGprCountSymbolName(RegisterKind RegKind);
1084341825Sdim  void initializeGprCountSymbol(RegisterKind RegKind);
1085341825Sdim  bool updateGprCountSymbols(RegisterKind RegKind, unsigned DwordRegIndex,
1086341825Sdim                             unsigned RegWidth);
1087321369Sdim  void cvtMubufImpl(MCInst &Inst, const OperandVector &Operands,
1088341825Sdim                    bool IsAtomic, bool IsAtomicReturn, bool IsLds = false);
1089321369Sdim  void cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
1090321369Sdim                 bool IsGdsHardcoded);
1091285181Sdim
1092284677Sdimpublic:
1093296417Sdim  enum AMDGPUMatchResultTy {
1094296417Sdim    Match_PreferE32 = FIRST_TARGET_MATCH_RESULT_TY
1095296417Sdim  };
1096353358Sdim  enum OperandMode {
1097353358Sdim    OperandMode_Default,
1098353358Sdim    OperandMode_NSA,
1099353358Sdim  };
1100296417Sdim
1101327952Sdim  using OptionalImmIndexMap = std::map<AMDGPUOperand::ImmTy, unsigned>;
1102321369Sdim
1103296417Sdim  AMDGPUAsmParser(const MCSubtargetInfo &STI, MCAsmParser &_Parser,
1104284677Sdim               const MCInstrInfo &MII,
1105284677Sdim               const MCTargetOptions &Options)
1106327952Sdim      : MCTargetAsmParser(Options, STI, MII), Parser(_Parser) {
1107296417Sdim    MCAsmParserExtension::Initialize(Parser);
1108284677Sdim
1109321369Sdim    if (getFeatureBits().none()) {
1110284677Sdim      // Set default features.
1111353358Sdim      copySTI().ToggleFeature("southern-islands");
1112284677Sdim    }
1113284677Sdim
1114321369Sdim    setAvailableFeatures(ComputeAvailableFeatures(getFeatureBits()));
1115309124Sdim
1116309124Sdim    {
1117309124Sdim      // TODO: make those pre-defined variables read-only.
1118309124Sdim      // Currently there is none suitable machinery in the core llvm-mc for this.
1119309124Sdim      // MCSymbol::isRedefinable is intended for another purpose, and
1120309124Sdim      // AsmParser::parseDirectiveSet() cannot be specialized for specific target.
1121344779Sdim      AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
1122309124Sdim      MCContext &Ctx = getContext();
1123341825Sdim      if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
1124341825Sdim        MCSymbol *Sym =
1125341825Sdim            Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_number"));
1126341825Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
1127353358Sdim        Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_minor"));
1128353358Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1129353358Sdim        Sym = Ctx.getOrCreateSymbol(Twine(".amdgcn.gfx_generation_stepping"));
1130353358Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
1131341825Sdim      } else {
1132341825Sdim        MCSymbol *Sym =
1133341825Sdim            Ctx.getOrCreateSymbol(Twine(".option.machine_version_major"));
1134341825Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Major, Ctx));
1135341825Sdim        Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_minor"));
1136341825Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Minor, Ctx));
1137341825Sdim        Sym = Ctx.getOrCreateSymbol(Twine(".option.machine_version_stepping"));
1138341825Sdim        Sym->setVariableValue(MCConstantExpr::create(ISA.Stepping, Ctx));
1139341825Sdim      }
1140341825Sdim      if (ISA.Major >= 6 && AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
1141341825Sdim        initializeGprCountSymbol(IS_VGPR);
1142341825Sdim        initializeGprCountSymbol(IS_SGPR);
1143341825Sdim      } else
1144341825Sdim        KernelScope.initialize(getContext());
1145309124Sdim    }
1146284677Sdim  }
1147284677Sdim
1148341825Sdim  bool hasXNACK() const {
1149341825Sdim    return AMDGPU::hasXNACK(getSTI());
1150341825Sdim  }
1151341825Sdim
1152341825Sdim  bool hasMIMG_R128() const {
1153341825Sdim    return AMDGPU::hasMIMG_R128(getSTI());
1154341825Sdim  }
1155341825Sdim
1156341825Sdim  bool hasPackedD16() const {
1157341825Sdim    return AMDGPU::hasPackedD16(getSTI());
1158341825Sdim  }
1159341825Sdim
1160314564Sdim  bool isSI() const {
1161314564Sdim    return AMDGPU::isSI(getSTI());
1162314564Sdim  }
1163314564Sdim
1164314564Sdim  bool isCI() const {
1165314564Sdim    return AMDGPU::isCI(getSTI());
1166314564Sdim  }
1167314564Sdim
1168314564Sdim  bool isVI() const {
1169314564Sdim    return AMDGPU::isVI(getSTI());
1170314564Sdim  }
1171314564Sdim
1172321369Sdim  bool isGFX9() const {
1173321369Sdim    return AMDGPU::isGFX9(getSTI());
1174321369Sdim  }
1175321369Sdim
1176353358Sdim  bool isGFX10() const {
1177353358Sdim    return AMDGPU::isGFX10(getSTI());
1178353358Sdim  }
1179353358Sdim
1180314564Sdim  bool hasInv2PiInlineImm() const {
1181321369Sdim    return getFeatureBits()[AMDGPU::FeatureInv2PiInlineImm];
1182314564Sdim  }
1183314564Sdim
1184321369Sdim  bool hasFlatOffsets() const {
1185321369Sdim    return getFeatureBits()[AMDGPU::FeatureFlatInstOffsets];
1186321369Sdim  }
1187321369Sdim
1188314564Sdim  bool hasSGPR102_SGPR103() const {
1189353358Sdim    return !isVI() && !isGFX9();
1190314564Sdim  }
1191314564Sdim
1192353358Sdim  bool hasSGPR104_SGPR105() const {
1193353358Sdim    return isGFX10();
1194353358Sdim  }
1195353358Sdim
1196327952Sdim  bool hasIntClamp() const {
1197327952Sdim    return getFeatureBits()[AMDGPU::FeatureIntClamp];
1198327952Sdim  }
1199327952Sdim
1200285181Sdim  AMDGPUTargetStreamer &getTargetStreamer() {
1201285181Sdim    MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1202285181Sdim    return static_cast<AMDGPUTargetStreamer &>(TS);
1203285181Sdim  }
1204285181Sdim
1205314564Sdim  const MCRegisterInfo *getMRI() const {
1206314564Sdim    // We need this const_cast because for some reason getContext() is not const
1207314564Sdim    // in MCAsmParser.
1208314564Sdim    return const_cast<AMDGPUAsmParser*>(this)->getContext().getRegisterInfo();
1209314564Sdim  }
1210314564Sdim
1211314564Sdim  const MCInstrInfo *getMII() const {
1212314564Sdim    return &MII;
1213314564Sdim  }
1214314564Sdim
1215321369Sdim  const FeatureBitset &getFeatureBits() const {
1216321369Sdim    return getSTI().getFeatureBits();
1217321369Sdim  }
1218321369Sdim
1219309124Sdim  void setForcedEncodingSize(unsigned Size) { ForcedEncodingSize = Size; }
1220309124Sdim  void setForcedDPP(bool ForceDPP_) { ForcedDPP = ForceDPP_; }
1221309124Sdim  void setForcedSDWA(bool ForceSDWA_) { ForcedSDWA = ForceSDWA_; }
1222284677Sdim
1223309124Sdim  unsigned getForcedEncodingSize() const { return ForcedEncodingSize; }
1224309124Sdim  bool isForcedVOP3() const { return ForcedEncodingSize == 64; }
1225309124Sdim  bool isForcedDPP() const { return ForcedDPP; }
1226309124Sdim  bool isForcedSDWA() const { return ForcedSDWA; }
1227314564Sdim  ArrayRef<unsigned> getMatchedVariants() const;
1228284677Sdim
1229309124Sdim  std::unique_ptr<AMDGPUOperand> parseRegister();
1230284677Sdim  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
1231284677Sdim  unsigned checkTargetMatchPredicate(MCInst &Inst) override;
1232309124Sdim  unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
1233309124Sdim                                      unsigned Kind) override;
1234284677Sdim  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
1235284677Sdim                               OperandVector &Operands, MCStreamer &Out,
1236284677Sdim                               uint64_t &ErrorInfo,
1237284677Sdim                               bool MatchingInlineAsm) override;
1238284677Sdim  bool ParseDirective(AsmToken DirectiveID) override;
1239353358Sdim  OperandMatchResultTy parseOperand(OperandVector &Operands, StringRef Mnemonic,
1240353358Sdim                                    OperandMode Mode = OperandMode_Default);
1241309124Sdim  StringRef parseMnemonicSuffix(StringRef Name);
1242284677Sdim  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
1243284677Sdim                        SMLoc NameLoc, OperandVector &Operands) override;
1244314564Sdim  //bool ProcessInstruction(MCInst &Inst);
1245284677Sdim
1246309124Sdim  OperandMatchResultTy parseIntWithPrefix(const char *Prefix, int64_t &Int);
1247321369Sdim
1248314564Sdim  OperandMatchResultTy
1249314564Sdim  parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
1250321369Sdim                     AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1251314564Sdim                     bool (*ConvertResult)(int64_t &) = nullptr);
1252321369Sdim
1253353358Sdim  OperandMatchResultTy
1254353358Sdim  parseOperandArrayWithPrefix(const char *Prefix,
1255353358Sdim                              OperandVector &Operands,
1256353358Sdim                              AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone,
1257353358Sdim                              bool (*ConvertResult)(int64_t&) = nullptr);
1258321369Sdim
1259314564Sdim  OperandMatchResultTy
1260314564Sdim  parseNamedBit(const char *Name, OperandVector &Operands,
1261321369Sdim                AMDGPUOperand::ImmTy ImmTy = AMDGPUOperand::ImmTyNone);
1262314564Sdim  OperandMatchResultTy parseStringWithPrefix(StringRef Prefix,
1263314564Sdim                                             StringRef &Value);
1264284677Sdim
1265353358Sdim  bool isModifier();
1266353358Sdim  bool isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1267353358Sdim  bool isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1268353358Sdim  bool isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const;
1269353358Sdim  bool isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const;
1270353358Sdim  bool parseSP3NegModifier();
1271353358Sdim  OperandMatchResultTy parseImm(OperandVector &Operands, bool HasSP3AbsModifier = false);
1272314564Sdim  OperandMatchResultTy parseReg(OperandVector &Operands);
1273353358Sdim  OperandMatchResultTy parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod = false);
1274314564Sdim  OperandMatchResultTy parseRegOrImmWithFPInputMods(OperandVector &Operands, bool AllowImm = true);
1275314564Sdim  OperandMatchResultTy parseRegOrImmWithIntInputMods(OperandVector &Operands, bool AllowImm = true);
1276314564Sdim  OperandMatchResultTy parseRegWithFPInputMods(OperandVector &Operands);
1277314564Sdim  OperandMatchResultTy parseRegWithIntInputMods(OperandVector &Operands);
1278314564Sdim  OperandMatchResultTy parseVReg32OrOff(OperandVector &Operands);
1279344779Sdim  OperandMatchResultTy parseDfmtNfmt(OperandVector &Operands);
1280284677Sdim
1281284677Sdim  void cvtDSOffset01(MCInst &Inst, const OperandVector &Operands);
1282321369Sdim  void cvtDS(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, false); }
1283321369Sdim  void cvtDSGds(MCInst &Inst, const OperandVector &Operands) { cvtDSImpl(Inst, Operands, true); }
1284314564Sdim  void cvtExp(MCInst &Inst, const OperandVector &Operands);
1285284677Sdim
1286284677Sdim  bool parseCnt(int64_t &IntVal);
1287284677Sdim  OperandMatchResultTy parseSWaitCntOps(OperandVector &Operands);
1288309124Sdim  OperandMatchResultTy parseHwreg(OperandVector &Operands);
1289309124Sdim
1290309124Sdimprivate:
1291309124Sdim  struct OperandInfoTy {
1292309124Sdim    int64_t Id;
1293327952Sdim    bool IsSymbolic = false;
1294353358Sdim    bool IsDefined = false;
1295327952Sdim
1296327952Sdim    OperandInfoTy(int64_t Id_) : Id(Id_) {}
1297309124Sdim  };
1298309124Sdim
1299353358Sdim  bool parseSendMsgBody(OperandInfoTy &Msg, OperandInfoTy &Op, OperandInfoTy &Stream);
1300353358Sdim  bool validateSendMsg(const OperandInfoTy &Msg,
1301353358Sdim                       const OperandInfoTy &Op,
1302353358Sdim                       const OperandInfoTy &Stream,
1303353358Sdim                       const SMLoc Loc);
1304314564Sdim
1305353358Sdim  bool parseHwregBody(OperandInfoTy &HwReg, int64_t &Offset, int64_t &Width);
1306353358Sdim  bool validateHwreg(const OperandInfoTy &HwReg,
1307353358Sdim                     const int64_t Offset,
1308353358Sdim                     const int64_t Width,
1309353358Sdim                     const SMLoc Loc);
1310353358Sdim
1311314564Sdim  void errorExpTgt();
1312314564Sdim  OperandMatchResultTy parseExpTgtImpl(StringRef Str, uint8_t &Val);
1313353358Sdim  SMLoc getFlatOffsetLoc(const OperandVector &Operands) const;
1314314564Sdim
1315353358Sdim  bool validateInstruction(const MCInst &Inst, const SMLoc &IDLoc, const OperandVector &Operands);
1316353358Sdim  bool validateFlatOffset(const MCInst &Inst, const OperandVector &Operands);
1317353358Sdim  bool validateSOPLiteral(const MCInst &Inst) const;
1318321369Sdim  bool validateConstantBusLimitations(const MCInst &Inst);
1319321369Sdim  bool validateEarlyClobberLimitations(const MCInst &Inst);
1320327952Sdim  bool validateIntClampSupported(const MCInst &Inst);
1321341825Sdim  bool validateMIMGAtomicDMask(const MCInst &Inst);
1322341825Sdim  bool validateMIMGGatherDMask(const MCInst &Inst);
1323360784Sdim  bool validateMovrels(const MCInst &Inst);
1324341825Sdim  bool validateMIMGDataSize(const MCInst &Inst);
1325353358Sdim  bool validateMIMGAddrSize(const MCInst &Inst);
1326341825Sdim  bool validateMIMGD16(const MCInst &Inst);
1327353358Sdim  bool validateMIMGDim(const MCInst &Inst);
1328353358Sdim  bool validateLdsDirect(const MCInst &Inst);
1329353358Sdim  bool validateOpSel(const MCInst &Inst);
1330353358Sdim  bool validateVccOperand(unsigned Reg) const;
1331353358Sdim  bool validateVOP3Literal(const MCInst &Inst) const;
1332360784Sdim  unsigned getConstantBusLimit(unsigned Opcode) const;
1333321369Sdim  bool usesConstantBus(const MCInst &Inst, unsigned OpIdx);
1334321369Sdim  bool isInlineConstant(const MCInst &Inst, unsigned OpIdx) const;
1335321369Sdim  unsigned findImplicitSGPRReadInVOP(const MCInst &Inst) const;
1336321369Sdim
1337353358Sdim  bool isId(const StringRef Id) const;
1338353358Sdim  bool isId(const AsmToken &Token, const StringRef Id) const;
1339353358Sdim  bool isToken(const AsmToken::TokenKind Kind) const;
1340321369Sdim  bool trySkipId(const StringRef Id);
1341353358Sdim  bool trySkipId(const StringRef Id, const AsmToken::TokenKind Kind);
1342321369Sdim  bool trySkipToken(const AsmToken::TokenKind Kind);
1343321369Sdim  bool skipToken(const AsmToken::TokenKind Kind, const StringRef ErrMsg);
1344321369Sdim  bool parseString(StringRef &Val, const StringRef ErrMsg = "expected a string");
1345353358Sdim  void peekTokens(MutableArrayRef<AsmToken> Tokens);
1346353358Sdim  AsmToken::TokenKind getTokenKind() const;
1347321369Sdim  bool parseExpr(int64_t &Imm);
1348360784Sdim  bool parseExpr(OperandVector &Operands);
1349353358Sdim  StringRef getTokenStr() const;
1350353358Sdim  AsmToken peekToken();
1351353358Sdim  AsmToken getToken() const;
1352353358Sdim  SMLoc getLoc() const;
1353353358Sdim  void lex();
1354321369Sdim
1355309124Sdimpublic:
1356309124Sdim  OperandMatchResultTy parseOptionalOperand(OperandVector &Operands);
1357327952Sdim  OperandMatchResultTy parseOptionalOpr(OperandVector &Operands);
1358309124Sdim
1359314564Sdim  OperandMatchResultTy parseExpTgt(OperandVector &Operands);
1360309124Sdim  OperandMatchResultTy parseSendMsgOp(OperandVector &Operands);
1361314564Sdim  OperandMatchResultTy parseInterpSlot(OperandVector &Operands);
1362314564Sdim  OperandMatchResultTy parseInterpAttr(OperandVector &Operands);
1363284677Sdim  OperandMatchResultTy parseSOppBrTarget(OperandVector &Operands);
1364353358Sdim  OperandMatchResultTy parseBoolReg(OperandVector &Operands);
1365284677Sdim
1366321369Sdim  bool parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
1367321369Sdim                            const unsigned MinVal,
1368321369Sdim                            const unsigned MaxVal,
1369321369Sdim                            const StringRef ErrMsg);
1370321369Sdim  OperandMatchResultTy parseSwizzleOp(OperandVector &Operands);
1371321369Sdim  bool parseSwizzleOffset(int64_t &Imm);
1372321369Sdim  bool parseSwizzleMacro(int64_t &Imm);
1373321369Sdim  bool parseSwizzleQuadPerm(int64_t &Imm);
1374321369Sdim  bool parseSwizzleBitmaskPerm(int64_t &Imm);
1375321369Sdim  bool parseSwizzleBroadcast(int64_t &Imm);
1376321369Sdim  bool parseSwizzleSwap(int64_t &Imm);
1377321369Sdim  bool parseSwizzleReverse(int64_t &Imm);
1378321369Sdim
1379353358Sdim  OperandMatchResultTy parseGPRIdxMode(OperandVector &Operands);
1380353358Sdim  int64_t parseGPRIdxMacro();
1381353358Sdim
1382309124Sdim  void cvtMubuf(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false); }
1383309124Sdim  void cvtMubufAtomic(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, false); }
1384309124Sdim  void cvtMubufAtomicReturn(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, true, true); }
1385341825Sdim  void cvtMubufLds(MCInst &Inst, const OperandVector &Operands) { cvtMubufImpl(Inst, Operands, false, false, true); }
1386321369Sdim  void cvtMtbuf(MCInst &Inst, const OperandVector &Operands);
1387321369Sdim
1388353358Sdim  AMDGPUOperand::Ptr defaultDLC() const;
1389309124Sdim  AMDGPUOperand::Ptr defaultGLC() const;
1390309124Sdim  AMDGPUOperand::Ptr defaultSLC() const;
1391284677Sdim
1392314564Sdim  AMDGPUOperand::Ptr defaultSMRDOffset8() const;
1393314564Sdim  AMDGPUOperand::Ptr defaultSMRDOffset20() const;
1394309124Sdim  AMDGPUOperand::Ptr defaultSMRDLiteralOffset() const;
1395353358Sdim  AMDGPUOperand::Ptr defaultFlatOffset() const;
1396284677Sdim
1397309124Sdim  OperandMatchResultTy parseOModOperand(OperandVector &Operands);
1398284677Sdim
1399321369Sdim  void cvtVOP3(MCInst &Inst, const OperandVector &Operands,
1400321369Sdim               OptionalImmIndexMap &OptionalIdx);
1401327952Sdim  void cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands);
1402284677Sdim  void cvtVOP3(MCInst &Inst, const OperandVector &Operands);
1403321369Sdim  void cvtVOP3P(MCInst &Inst, const OperandVector &Operands);
1404309124Sdim
1405327952Sdim  void cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands);
1406327952Sdim
1407321369Sdim  void cvtMIMG(MCInst &Inst, const OperandVector &Operands,
1408321369Sdim               bool IsAtomic = false);
1409309124Sdim  void cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands);
1410309124Sdim
1411353358Sdim  OperandMatchResultTy parseDim(OperandVector &Operands);
1412353358Sdim  OperandMatchResultTy parseDPP8(OperandVector &Operands);
1413309124Sdim  OperandMatchResultTy parseDPPCtrl(OperandVector &Operands);
1414309124Sdim  AMDGPUOperand::Ptr defaultRowMask() const;
1415309124Sdim  AMDGPUOperand::Ptr defaultBankMask() const;
1416309124Sdim  AMDGPUOperand::Ptr defaultBoundCtrl() const;
1417353358Sdim  AMDGPUOperand::Ptr defaultFI() const;
1418353358Sdim  void cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8 = false);
1419353358Sdim  void cvtDPP8(MCInst &Inst, const OperandVector &Operands) { cvtDPP(Inst, Operands, true); }
1420309124Sdim
1421309124Sdim  OperandMatchResultTy parseSDWASel(OperandVector &Operands, StringRef Prefix,
1422309124Sdim                                    AMDGPUOperand::ImmTy Type);
1423309124Sdim  OperandMatchResultTy parseSDWADstUnused(OperandVector &Operands);
1424309124Sdim  void cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands);
1425309124Sdim  void cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands);
1426321369Sdim  void cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands);
1427360784Sdim  void cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands);
1428309124Sdim  void cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands);
1429309124Sdim  void cvtSDWA(MCInst &Inst, const OperandVector &Operands,
1430360784Sdim               uint64_t BasicInstType,
1431360784Sdim               bool SkipDstVcc = false,
1432360784Sdim               bool SkipSrcVcc = false);
1433353358Sdim
1434353358Sdim  AMDGPUOperand::Ptr defaultBLGP() const;
1435353358Sdim  AMDGPUOperand::Ptr defaultCBSZ() const;
1436353358Sdim  AMDGPUOperand::Ptr defaultABID() const;
1437353358Sdim
1438353358Sdim  OperandMatchResultTy parseEndpgmOp(OperandVector &Operands);
1439353358Sdim  AMDGPUOperand::Ptr defaultEndpgmImmOperands() const;
1440284677Sdim};
1441284677Sdim
1442284677Sdimstruct OptionalOperand {
1443284677Sdim  const char *Name;
1444284677Sdim  AMDGPUOperand::ImmTy Type;
1445284677Sdim  bool IsBit;
1446284677Sdim  bool (*ConvertResult)(int64_t&);
1447284677Sdim};
1448284677Sdim
1449314564Sdim} // end anonymous namespace
1450314564Sdim
1451314564Sdim// May be called with integer type with equivalent bitwidth.
1452314564Sdimstatic const fltSemantics *getFltSemantics(unsigned Size) {
1453314564Sdim  switch (Size) {
1454314564Sdim  case 4:
1455314564Sdim    return &APFloat::IEEEsingle();
1456314564Sdim  case 8:
1457314564Sdim    return &APFloat::IEEEdouble();
1458314564Sdim  case 2:
1459314564Sdim    return &APFloat::IEEEhalf();
1460314564Sdim  default:
1461314564Sdim    llvm_unreachable("unsupported fp type");
1462314564Sdim  }
1463285181Sdim}
1464284677Sdim
1465314564Sdimstatic const fltSemantics *getFltSemantics(MVT VT) {
1466314564Sdim  return getFltSemantics(VT.getSizeInBits() / 8);
1467314564Sdim}
1468314564Sdim
1469321369Sdimstatic const fltSemantics *getOpFltSemantics(uint8_t OperandType) {
1470321369Sdim  switch (OperandType) {
1471321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT32:
1472321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP32:
1473321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1474321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1475353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1476353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
1477321369Sdim    return &APFloat::IEEEsingle();
1478321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT64:
1479321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP64:
1480321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1481321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1482321369Sdim    return &APFloat::IEEEdouble();
1483321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT16:
1484321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP16:
1485321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1486321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1487321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1488321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1489353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1490353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
1491353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1492353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
1493353358Sdim  case AMDGPU::OPERAND_REG_IMM_V2INT16:
1494353358Sdim  case AMDGPU::OPERAND_REG_IMM_V2FP16:
1495321369Sdim    return &APFloat::IEEEhalf();
1496321369Sdim  default:
1497321369Sdim    llvm_unreachable("unsupported fp type");
1498321369Sdim  }
1499321369Sdim}
1500321369Sdim
1501314564Sdim//===----------------------------------------------------------------------===//
1502314564Sdim// Operand
1503314564Sdim//===----------------------------------------------------------------------===//
1504314564Sdim
1505314564Sdimstatic bool canLosslesslyConvertToFPType(APFloat &FPLiteral, MVT VT) {
1506314564Sdim  bool Lost;
1507314564Sdim
1508314564Sdim  // Convert literal to single precision
1509314564Sdim  APFloat::opStatus Status = FPLiteral.convert(*getFltSemantics(VT),
1510314564Sdim                                               APFloat::rmNearestTiesToEven,
1511314564Sdim                                               &Lost);
1512314564Sdim  // We allow precision lost but not overflow or underflow
1513314564Sdim  if (Status != APFloat::opOK &&
1514314564Sdim      Lost &&
1515314564Sdim      ((Status & APFloat::opOverflow)  != 0 ||
1516314564Sdim       (Status & APFloat::opUnderflow) != 0)) {
1517314564Sdim    return false;
1518314564Sdim  }
1519314564Sdim
1520314564Sdim  return true;
1521314564Sdim}
1522314564Sdim
1523353358Sdimstatic bool isSafeTruncation(int64_t Val, unsigned Size) {
1524353358Sdim  return isUIntN(Size, Val) || isIntN(Size, Val);
1525353358Sdim}
1526353358Sdim
1527314564Sdimbool AMDGPUOperand::isInlinableImm(MVT type) const {
1528353358Sdim
1529353358Sdim  // This is a hack to enable named inline values like
1530353358Sdim  // shared_base with both 32-bit and 64-bit operands.
1531353358Sdim  // Note that these values are defined as
1532353358Sdim  // 32-bit operands only.
1533353358Sdim  if (isInlineValue()) {
1534353358Sdim    return true;
1535353358Sdim  }
1536353358Sdim
1537314564Sdim  if (!isImmTy(ImmTyNone)) {
1538314564Sdim    // Only plain immediates are inlinable (e.g. "clamp" attribute is not)
1539314564Sdim    return false;
1540314564Sdim  }
1541314564Sdim  // TODO: We should avoid using host float here. It would be better to
1542314564Sdim  // check the float bit values which is what a few other places do.
1543314564Sdim  // We've had bot failures before due to weird NaN support on mips hosts.
1544314564Sdim
1545314564Sdim  APInt Literal(64, Imm.Val);
1546314564Sdim
1547314564Sdim  if (Imm.IsFPImm) { // We got fp literal token
1548314564Sdim    if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1549314564Sdim      return AMDGPU::isInlinableLiteral64(Imm.Val,
1550314564Sdim                                          AsmParser->hasInv2PiInlineImm());
1551314564Sdim    }
1552314564Sdim
1553314564Sdim    APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1554314564Sdim    if (!canLosslesslyConvertToFPType(FPLiteral, type))
1555314564Sdim      return false;
1556314564Sdim
1557321369Sdim    if (type.getScalarSizeInBits() == 16) {
1558321369Sdim      return AMDGPU::isInlinableLiteral16(
1559321369Sdim        static_cast<int16_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1560321369Sdim        AsmParser->hasInv2PiInlineImm());
1561321369Sdim    }
1562321369Sdim
1563314564Sdim    // Check if single precision literal is inlinable
1564314564Sdim    return AMDGPU::isInlinableLiteral32(
1565314564Sdim      static_cast<int32_t>(FPLiteral.bitcastToAPInt().getZExtValue()),
1566314564Sdim      AsmParser->hasInv2PiInlineImm());
1567314564Sdim  }
1568314564Sdim
1569314564Sdim  // We got int literal token.
1570314564Sdim  if (type == MVT::f64 || type == MVT::i64) { // Expected 64-bit operand
1571314564Sdim    return AMDGPU::isInlinableLiteral64(Imm.Val,
1572314564Sdim                                        AsmParser->hasInv2PiInlineImm());
1573314564Sdim  }
1574314564Sdim
1575353358Sdim  if (!isSafeTruncation(Imm.Val, type.getScalarSizeInBits())) {
1576353358Sdim    return false;
1577353358Sdim  }
1578353358Sdim
1579314564Sdim  if (type.getScalarSizeInBits() == 16) {
1580314564Sdim    return AMDGPU::isInlinableLiteral16(
1581314564Sdim      static_cast<int16_t>(Literal.getLoBits(16).getSExtValue()),
1582314564Sdim      AsmParser->hasInv2PiInlineImm());
1583314564Sdim  }
1584314564Sdim
1585314564Sdim  return AMDGPU::isInlinableLiteral32(
1586314564Sdim    static_cast<int32_t>(Literal.getLoBits(32).getZExtValue()),
1587314564Sdim    AsmParser->hasInv2PiInlineImm());
1588314564Sdim}
1589314564Sdim
1590314564Sdimbool AMDGPUOperand::isLiteralImm(MVT type) const {
1591321369Sdim  // Check that this immediate can be added as literal
1592314564Sdim  if (!isImmTy(ImmTyNone)) {
1593314564Sdim    return false;
1594314564Sdim  }
1595314564Sdim
1596314564Sdim  if (!Imm.IsFPImm) {
1597314564Sdim    // We got int literal token.
1598314564Sdim
1599321369Sdim    if (type == MVT::f64 && hasFPModifiers()) {
1600321369Sdim      // Cannot apply fp modifiers to int literals preserving the same semantics
1601321369Sdim      // for VOP1/2/C and VOP3 because of integer truncation. To avoid ambiguity,
1602321369Sdim      // disable these cases.
1603321369Sdim      return false;
1604321369Sdim    }
1605321369Sdim
1606314564Sdim    unsigned Size = type.getSizeInBits();
1607314564Sdim    if (Size == 64)
1608314564Sdim      Size = 32;
1609314564Sdim
1610314564Sdim    // FIXME: 64-bit operands can zero extend, sign extend, or pad zeroes for FP
1611314564Sdim    // types.
1612353358Sdim    return isSafeTruncation(Imm.Val, Size);
1613314564Sdim  }
1614314564Sdim
1615314564Sdim  // We got fp literal token
1616314564Sdim  if (type == MVT::f64) { // Expected 64-bit fp operand
1617314564Sdim    // We would set low 64-bits of literal to zeroes but we accept this literals
1618314564Sdim    return true;
1619314564Sdim  }
1620314564Sdim
1621314564Sdim  if (type == MVT::i64) { // Expected 64-bit int operand
1622314564Sdim    // We don't allow fp literals in 64-bit integer instructions. It is
1623314564Sdim    // unclear how we should encode them.
1624314564Sdim    return false;
1625314564Sdim  }
1626314564Sdim
1627353358Sdim  // We allow fp literals with f16x2 operands assuming that the specified
1628353358Sdim  // literal goes into the lower half and the upper half is zero. We also
1629353358Sdim  // require that the literal may be losslesly converted to f16.
1630353358Sdim  MVT ExpectedType = (type == MVT::v2f16)? MVT::f16 :
1631353358Sdim                     (type == MVT::v2i16)? MVT::i16 : type;
1632353358Sdim
1633314564Sdim  APFloat FPLiteral(APFloat::IEEEdouble(), APInt(64, Imm.Val));
1634353358Sdim  return canLosslesslyConvertToFPType(FPLiteral, ExpectedType);
1635314564Sdim}
1636314564Sdim
1637314564Sdimbool AMDGPUOperand::isRegClass(unsigned RCID) const {
1638314564Sdim  return isRegKind() && AsmParser->getMRI()->getRegClass(RCID).contains(getReg());
1639314564Sdim}
1640314564Sdim
1641341825Sdimbool AMDGPUOperand::isSDWAOperand(MVT type) const {
1642321369Sdim  if (AsmParser->isVI())
1643353358Sdim    return isVReg32();
1644353358Sdim  else if (AsmParser->isGFX9() || AsmParser->isGFX10())
1645353358Sdim    return isRegClass(AMDGPU::VS_32RegClassID) || isInlinableImm(type);
1646321369Sdim  else
1647321369Sdim    return false;
1648321369Sdim}
1649321369Sdim
1650341825Sdimbool AMDGPUOperand::isSDWAFP16Operand() const {
1651341825Sdim  return isSDWAOperand(MVT::f16);
1652341825Sdim}
1653341825Sdim
1654341825Sdimbool AMDGPUOperand::isSDWAFP32Operand() const {
1655341825Sdim  return isSDWAOperand(MVT::f32);
1656341825Sdim}
1657341825Sdim
1658341825Sdimbool AMDGPUOperand::isSDWAInt16Operand() const {
1659341825Sdim  return isSDWAOperand(MVT::i16);
1660341825Sdim}
1661341825Sdim
1662341825Sdimbool AMDGPUOperand::isSDWAInt32Operand() const {
1663341825Sdim  return isSDWAOperand(MVT::i32);
1664341825Sdim}
1665341825Sdim
1666353358Sdimbool AMDGPUOperand::isBoolReg() const {
1667360784Sdim  return (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize64] && isSCSrcB64()) ||
1668360784Sdim         (AsmParser->getFeatureBits()[AMDGPU::FeatureWavefrontSize32] && isSCSrcB32());
1669353358Sdim}
1670353358Sdim
1671321369Sdimuint64_t AMDGPUOperand::applyInputFPModifiers(uint64_t Val, unsigned Size) const
1672321369Sdim{
1673321369Sdim  assert(isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1674321369Sdim  assert(Size == 2 || Size == 4 || Size == 8);
1675321369Sdim
1676321369Sdim  const uint64_t FpSignMask = (1ULL << (Size * 8 - 1));
1677321369Sdim
1678321369Sdim  if (Imm.Mods.Abs) {
1679321369Sdim    Val &= ~FpSignMask;
1680314564Sdim  }
1681321369Sdim  if (Imm.Mods.Neg) {
1682321369Sdim    Val ^= FpSignMask;
1683321369Sdim  }
1684314564Sdim
1685321369Sdim  return Val;
1686321369Sdim}
1687321369Sdim
1688321369Sdimvoid AMDGPUOperand::addImmOperands(MCInst &Inst, unsigned N, bool ApplyModifiers) const {
1689314564Sdim  if (AMDGPU::isSISrcOperand(AsmParser->getMII()->get(Inst.getOpcode()),
1690314564Sdim                             Inst.getNumOperands())) {
1691321369Sdim    addLiteralImmOperand(Inst, Imm.Val,
1692321369Sdim                         ApplyModifiers &
1693321369Sdim                         isImmTy(ImmTyNone) && Imm.Mods.hasFPModifiers());
1694314564Sdim  } else {
1695321369Sdim    assert(!isImmTy(ImmTyNone) || !hasModifiers());
1696321369Sdim    Inst.addOperand(MCOperand::createImm(Imm.Val));
1697314564Sdim  }
1698314564Sdim}
1699314564Sdim
1700321369Sdimvoid AMDGPUOperand::addLiteralImmOperand(MCInst &Inst, int64_t Val, bool ApplyModifiers) const {
1701314564Sdim  const auto& InstDesc = AsmParser->getMII()->get(Inst.getOpcode());
1702314564Sdim  auto OpNum = Inst.getNumOperands();
1703314564Sdim  // Check that this operand accepts literals
1704314564Sdim  assert(AMDGPU::isSISrcOperand(InstDesc, OpNum));
1705314564Sdim
1706321369Sdim  if (ApplyModifiers) {
1707321369Sdim    assert(AMDGPU::isSISrcFPOperand(InstDesc, OpNum));
1708321369Sdim    const unsigned Size = Imm.IsFPImm ? sizeof(double) : getOperandSize(InstDesc, OpNum);
1709321369Sdim    Val = applyInputFPModifiers(Val, Size);
1710321369Sdim  }
1711314564Sdim
1712321369Sdim  APInt Literal(64, Val);
1713321369Sdim  uint8_t OpTy = InstDesc.OpInfo[OpNum].OperandType;
1714321369Sdim
1715314564Sdim  if (Imm.IsFPImm) { // We got fp literal token
1716321369Sdim    switch (OpTy) {
1717321369Sdim    case AMDGPU::OPERAND_REG_IMM_INT64:
1718321369Sdim    case AMDGPU::OPERAND_REG_IMM_FP64:
1719321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1720327952Sdim    case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1721314564Sdim      if (AMDGPU::isInlinableLiteral64(Literal.getZExtValue(),
1722314564Sdim                                       AsmParser->hasInv2PiInlineImm())) {
1723314564Sdim        Inst.addOperand(MCOperand::createImm(Literal.getZExtValue()));
1724314564Sdim        return;
1725314564Sdim      }
1726314564Sdim
1727314564Sdim      // Non-inlineable
1728314564Sdim      if (AMDGPU::isSISrcFPOperand(InstDesc, OpNum)) { // Expected 64-bit fp operand
1729314564Sdim        // For fp operands we check if low 32 bits are zeros
1730314564Sdim        if (Literal.getLoBits(32) != 0) {
1731314564Sdim          const_cast<AMDGPUAsmParser *>(AsmParser)->Warning(Inst.getLoc(),
1732314564Sdim          "Can't encode literal as exact 64-bit floating-point operand. "
1733314564Sdim          "Low 32-bits will be set to zero");
1734314564Sdim        }
1735314564Sdim
1736314564Sdim        Inst.addOperand(MCOperand::createImm(Literal.lshr(32).getZExtValue()));
1737314564Sdim        return;
1738314564Sdim      }
1739314564Sdim
1740314564Sdim      // We don't allow fp literals in 64-bit integer instructions. It is
1741314564Sdim      // unclear how we should encode them. This case should be checked earlier
1742314564Sdim      // in predicate methods (isLiteralImm())
1743314564Sdim      llvm_unreachable("fp literal in 64-bit integer instruction.");
1744327952Sdim
1745321369Sdim    case AMDGPU::OPERAND_REG_IMM_INT32:
1746321369Sdim    case AMDGPU::OPERAND_REG_IMM_FP32:
1747321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1748321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1749353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1750353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
1751321369Sdim    case AMDGPU::OPERAND_REG_IMM_INT16:
1752321369Sdim    case AMDGPU::OPERAND_REG_IMM_FP16:
1753321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1754321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1755321369Sdim    case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1756353358Sdim    case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1757353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1758353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
1759353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1760353358Sdim    case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16:
1761353358Sdim    case AMDGPU::OPERAND_REG_IMM_V2INT16:
1762353358Sdim    case AMDGPU::OPERAND_REG_IMM_V2FP16: {
1763314564Sdim      bool lost;
1764314564Sdim      APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1765314564Sdim      // Convert literal to single precision
1766321369Sdim      FPLiteral.convert(*getOpFltSemantics(OpTy),
1767314564Sdim                        APFloat::rmNearestTiesToEven, &lost);
1768314564Sdim      // We allow precision lost but not overflow or underflow. This should be
1769314564Sdim      // checked earlier in isLiteralImm()
1770321369Sdim
1771321369Sdim      uint64_t ImmVal = FPLiteral.bitcastToAPInt().getZExtValue();
1772321369Sdim      Inst.addOperand(MCOperand::createImm(ImmVal));
1773314564Sdim      return;
1774314564Sdim    }
1775314564Sdim    default:
1776314564Sdim      llvm_unreachable("invalid operand size");
1777314564Sdim    }
1778314564Sdim
1779314564Sdim    return;
1780314564Sdim  }
1781314564Sdim
1782353358Sdim  // We got int literal token.
1783314564Sdim  // Only sign extend inline immediates.
1784321369Sdim  switch (OpTy) {
1785321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT32:
1786321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP32:
1787321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1788327952Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1789353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1790353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
1791353358Sdim  case AMDGPU::OPERAND_REG_IMM_V2INT16:
1792353358Sdim  case AMDGPU::OPERAND_REG_IMM_V2FP16:
1793353358Sdim    if (isSafeTruncation(Val, 32) &&
1794314564Sdim        AMDGPU::isInlinableLiteral32(static_cast<int32_t>(Val),
1795314564Sdim                                     AsmParser->hasInv2PiInlineImm())) {
1796314564Sdim      Inst.addOperand(MCOperand::createImm(Val));
1797314564Sdim      return;
1798314564Sdim    }
1799314564Sdim
1800314564Sdim    Inst.addOperand(MCOperand::createImm(Val & 0xffffffff));
1801314564Sdim    return;
1802327952Sdim
1803321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT64:
1804321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP64:
1805321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1806327952Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1807321369Sdim    if (AMDGPU::isInlinableLiteral64(Val, AsmParser->hasInv2PiInlineImm())) {
1808314564Sdim      Inst.addOperand(MCOperand::createImm(Val));
1809314564Sdim      return;
1810314564Sdim    }
1811314564Sdim
1812314564Sdim    Inst.addOperand(MCOperand::createImm(Lo_32(Val)));
1813314564Sdim    return;
1814327952Sdim
1815321369Sdim  case AMDGPU::OPERAND_REG_IMM_INT16:
1816321369Sdim  case AMDGPU::OPERAND_REG_IMM_FP16:
1817321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1818327952Sdim  case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1819353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_INT16:
1820353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_FP16:
1821353358Sdim    if (isSafeTruncation(Val, 16) &&
1822314564Sdim        AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1823314564Sdim                                     AsmParser->hasInv2PiInlineImm())) {
1824314564Sdim      Inst.addOperand(MCOperand::createImm(Val));
1825314564Sdim      return;
1826314564Sdim    }
1827314564Sdim
1828314564Sdim    Inst.addOperand(MCOperand::createImm(Val & 0xffff));
1829314564Sdim    return;
1830327952Sdim
1831321369Sdim  case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1832353358Sdim  case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1833353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_V2INT16:
1834353358Sdim  case AMDGPU::OPERAND_REG_INLINE_AC_V2FP16: {
1835353358Sdim    assert(isSafeTruncation(Val, 16));
1836353358Sdim    assert(AMDGPU::isInlinableLiteral16(static_cast<int16_t>(Val),
1837321369Sdim                                        AsmParser->hasInv2PiInlineImm()));
1838321369Sdim
1839353358Sdim    Inst.addOperand(MCOperand::createImm(Val));
1840321369Sdim    return;
1841321369Sdim  }
1842314564Sdim  default:
1843314564Sdim    llvm_unreachable("invalid operand size");
1844314564Sdim  }
1845314564Sdim}
1846314564Sdim
1847314564Sdimtemplate <unsigned Bitwidth>
1848314564Sdimvoid AMDGPUOperand::addKImmFPOperands(MCInst &Inst, unsigned N) const {
1849314564Sdim  APInt Literal(64, Imm.Val);
1850314564Sdim
1851314564Sdim  if (!Imm.IsFPImm) {
1852314564Sdim    // We got int literal token.
1853314564Sdim    Inst.addOperand(MCOperand::createImm(Literal.getLoBits(Bitwidth).getZExtValue()));
1854314564Sdim    return;
1855314564Sdim  }
1856314564Sdim
1857314564Sdim  bool Lost;
1858314564Sdim  APFloat FPLiteral(APFloat::IEEEdouble(), Literal);
1859314564Sdim  FPLiteral.convert(*getFltSemantics(Bitwidth / 8),
1860314564Sdim                    APFloat::rmNearestTiesToEven, &Lost);
1861314564Sdim  Inst.addOperand(MCOperand::createImm(FPLiteral.bitcastToAPInt().getZExtValue()));
1862314564Sdim}
1863314564Sdim
1864314564Sdimvoid AMDGPUOperand::addRegOperands(MCInst &Inst, unsigned N) const {
1865314564Sdim  Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI())));
1866314564Sdim}
1867314564Sdim
1868353358Sdimstatic bool isInlineValue(unsigned Reg) {
1869353358Sdim  switch (Reg) {
1870353358Sdim  case AMDGPU::SRC_SHARED_BASE:
1871353358Sdim  case AMDGPU::SRC_SHARED_LIMIT:
1872353358Sdim  case AMDGPU::SRC_PRIVATE_BASE:
1873353358Sdim  case AMDGPU::SRC_PRIVATE_LIMIT:
1874353358Sdim  case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
1875353358Sdim    return true;
1876353358Sdim  case AMDGPU::SRC_VCCZ:
1877353358Sdim  case AMDGPU::SRC_EXECZ:
1878353358Sdim  case AMDGPU::SRC_SCC:
1879353358Sdim    return true;
1880360784Sdim  case AMDGPU::SGPR_NULL:
1881360784Sdim    return true;
1882353358Sdim  default:
1883353358Sdim    return false;
1884353358Sdim  }
1885353358Sdim}
1886353358Sdim
1887353358Sdimbool AMDGPUOperand::isInlineValue() const {
1888353358Sdim  return isRegKind() && ::isInlineValue(getReg());
1889353358Sdim}
1890353358Sdim
1891314564Sdim//===----------------------------------------------------------------------===//
1892314564Sdim// AsmParser
1893314564Sdim//===----------------------------------------------------------------------===//
1894314564Sdim
1895309124Sdimstatic int getRegClass(RegisterKind Is, unsigned RegWidth) {
1896309124Sdim  if (Is == IS_VGPR) {
1897284677Sdim    switch (RegWidth) {
1898296417Sdim      default: return -1;
1899284677Sdim      case 1: return AMDGPU::VGPR_32RegClassID;
1900284677Sdim      case 2: return AMDGPU::VReg_64RegClassID;
1901284677Sdim      case 3: return AMDGPU::VReg_96RegClassID;
1902284677Sdim      case 4: return AMDGPU::VReg_128RegClassID;
1903360784Sdim      case 5: return AMDGPU::VReg_160RegClassID;
1904284677Sdim      case 8: return AMDGPU::VReg_256RegClassID;
1905284677Sdim      case 16: return AMDGPU::VReg_512RegClassID;
1906360784Sdim      case 32: return AMDGPU::VReg_1024RegClassID;
1907284677Sdim    }
1908309124Sdim  } else if (Is == IS_TTMP) {
1909309124Sdim    switch (RegWidth) {
1910309124Sdim      default: return -1;
1911309124Sdim      case 1: return AMDGPU::TTMP_32RegClassID;
1912309124Sdim      case 2: return AMDGPU::TTMP_64RegClassID;
1913309124Sdim      case 4: return AMDGPU::TTMP_128RegClassID;
1914327952Sdim      case 8: return AMDGPU::TTMP_256RegClassID;
1915327952Sdim      case 16: return AMDGPU::TTMP_512RegClassID;
1916309124Sdim    }
1917309124Sdim  } else if (Is == IS_SGPR) {
1918309124Sdim    switch (RegWidth) {
1919309124Sdim      default: return -1;
1920309124Sdim      case 1: return AMDGPU::SGPR_32RegClassID;
1921309124Sdim      case 2: return AMDGPU::SGPR_64RegClassID;
1922309124Sdim      case 4: return AMDGPU::SGPR_128RegClassID;
1923327952Sdim      case 8: return AMDGPU::SGPR_256RegClassID;
1924327952Sdim      case 16: return AMDGPU::SGPR_512RegClassID;
1925309124Sdim    }
1926353358Sdim  } else if (Is == IS_AGPR) {
1927353358Sdim    switch (RegWidth) {
1928353358Sdim      default: return -1;
1929353358Sdim      case 1: return AMDGPU::AGPR_32RegClassID;
1930353358Sdim      case 2: return AMDGPU::AReg_64RegClassID;
1931353358Sdim      case 4: return AMDGPU::AReg_128RegClassID;
1932353358Sdim      case 16: return AMDGPU::AReg_512RegClassID;
1933353358Sdim      case 32: return AMDGPU::AReg_1024RegClassID;
1934353358Sdim    }
1935284677Sdim  }
1936309124Sdim  return -1;
1937284677Sdim}
1938284677Sdim
1939309124Sdimstatic unsigned getSpecialRegForName(StringRef RegName) {
1940284677Sdim  return StringSwitch<unsigned>(RegName)
1941284677Sdim    .Case("exec", AMDGPU::EXEC)
1942284677Sdim    .Case("vcc", AMDGPU::VCC)
1943296417Sdim    .Case("flat_scratch", AMDGPU::FLAT_SCR)
1944341825Sdim    .Case("xnack_mask", AMDGPU::XNACK_MASK)
1945353358Sdim    .Case("shared_base", AMDGPU::SRC_SHARED_BASE)
1946353358Sdim    .Case("src_shared_base", AMDGPU::SRC_SHARED_BASE)
1947353358Sdim    .Case("shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1948353358Sdim    .Case("src_shared_limit", AMDGPU::SRC_SHARED_LIMIT)
1949353358Sdim    .Case("private_base", AMDGPU::SRC_PRIVATE_BASE)
1950353358Sdim    .Case("src_private_base", AMDGPU::SRC_PRIVATE_BASE)
1951353358Sdim    .Case("private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1952353358Sdim    .Case("src_private_limit", AMDGPU::SRC_PRIVATE_LIMIT)
1953353358Sdim    .Case("pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
1954353358Sdim    .Case("src_pops_exiting_wave_id", AMDGPU::SRC_POPS_EXITING_WAVE_ID)
1955353358Sdim    .Case("lds_direct", AMDGPU::LDS_DIRECT)
1956353358Sdim    .Case("src_lds_direct", AMDGPU::LDS_DIRECT)
1957284677Sdim    .Case("m0", AMDGPU::M0)
1958353358Sdim    .Case("vccz", AMDGPU::SRC_VCCZ)
1959353358Sdim    .Case("src_vccz", AMDGPU::SRC_VCCZ)
1960353358Sdim    .Case("execz", AMDGPU::SRC_EXECZ)
1961353358Sdim    .Case("src_execz", AMDGPU::SRC_EXECZ)
1962353358Sdim    .Case("scc", AMDGPU::SRC_SCC)
1963353358Sdim    .Case("src_scc", AMDGPU::SRC_SCC)
1964309124Sdim    .Case("tba", AMDGPU::TBA)
1965309124Sdim    .Case("tma", AMDGPU::TMA)
1966296417Sdim    .Case("flat_scratch_lo", AMDGPU::FLAT_SCR_LO)
1967296417Sdim    .Case("flat_scratch_hi", AMDGPU::FLAT_SCR_HI)
1968341825Sdim    .Case("xnack_mask_lo", AMDGPU::XNACK_MASK_LO)
1969341825Sdim    .Case("xnack_mask_hi", AMDGPU::XNACK_MASK_HI)
1970284677Sdim    .Case("vcc_lo", AMDGPU::VCC_LO)
1971284677Sdim    .Case("vcc_hi", AMDGPU::VCC_HI)
1972284677Sdim    .Case("exec_lo", AMDGPU::EXEC_LO)
1973284677Sdim    .Case("exec_hi", AMDGPU::EXEC_HI)
1974309124Sdim    .Case("tma_lo", AMDGPU::TMA_LO)
1975309124Sdim    .Case("tma_hi", AMDGPU::TMA_HI)
1976309124Sdim    .Case("tba_lo", AMDGPU::TBA_LO)
1977309124Sdim    .Case("tba_hi", AMDGPU::TBA_HI)
1978353358Sdim    .Case("null", AMDGPU::SGPR_NULL)
1979360784Sdim    .Default(AMDGPU::NoRegister);
1980284677Sdim}
1981284677Sdim
1982321369Sdimbool AMDGPUAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1983321369Sdim                                    SMLoc &EndLoc) {
1984309124Sdim  auto R = parseRegister();
1985309124Sdim  if (!R) return true;
1986309124Sdim  assert(R->isReg());
1987309124Sdim  RegNo = R->getReg();
1988309124Sdim  StartLoc = R->getStartLoc();
1989309124Sdim  EndLoc = R->getEndLoc();
1990309124Sdim  return false;
1991309124Sdim}
1992309124Sdim
1993321369Sdimbool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
1994360784Sdim                                            RegisterKind RegKind, unsigned Reg1) {
1995309124Sdim  switch (RegKind) {
1996309124Sdim  case IS_SPECIAL:
1997321369Sdim    if (Reg == AMDGPU::EXEC_LO && Reg1 == AMDGPU::EXEC_HI) {
1998321369Sdim      Reg = AMDGPU::EXEC;
1999321369Sdim      RegWidth = 2;
2000321369Sdim      return true;
2001321369Sdim    }
2002321369Sdim    if (Reg == AMDGPU::FLAT_SCR_LO && Reg1 == AMDGPU::FLAT_SCR_HI) {
2003321369Sdim      Reg = AMDGPU::FLAT_SCR;
2004321369Sdim      RegWidth = 2;
2005321369Sdim      return true;
2006321369Sdim    }
2007341825Sdim    if (Reg == AMDGPU::XNACK_MASK_LO && Reg1 == AMDGPU::XNACK_MASK_HI) {
2008341825Sdim      Reg = AMDGPU::XNACK_MASK;
2009341825Sdim      RegWidth = 2;
2010341825Sdim      return true;
2011341825Sdim    }
2012321369Sdim    if (Reg == AMDGPU::VCC_LO && Reg1 == AMDGPU::VCC_HI) {
2013321369Sdim      Reg = AMDGPU::VCC;
2014321369Sdim      RegWidth = 2;
2015321369Sdim      return true;
2016321369Sdim    }
2017321369Sdim    if (Reg == AMDGPU::TBA_LO && Reg1 == AMDGPU::TBA_HI) {
2018321369Sdim      Reg = AMDGPU::TBA;
2019321369Sdim      RegWidth = 2;
2020321369Sdim      return true;
2021321369Sdim    }
2022321369Sdim    if (Reg == AMDGPU::TMA_LO && Reg1 == AMDGPU::TMA_HI) {
2023321369Sdim      Reg = AMDGPU::TMA;
2024321369Sdim      RegWidth = 2;
2025321369Sdim      return true;
2026321369Sdim    }
2027309124Sdim    return false;
2028309124Sdim  case IS_VGPR:
2029309124Sdim  case IS_SGPR:
2030353358Sdim  case IS_AGPR:
2031309124Sdim  case IS_TTMP:
2032321369Sdim    if (Reg1 != Reg + RegWidth) {
2033321369Sdim      return false;
2034321369Sdim    }
2035309124Sdim    RegWidth++;
2036309124Sdim    return true;
2037309124Sdim  default:
2038314564Sdim    llvm_unreachable("unexpected register kind");
2039309124Sdim  }
2040309124Sdim}
2041309124Sdim
2042360784Sdimstruct RegInfo {
2043360784Sdim  StringLiteral Name;
2044360784Sdim  RegisterKind Kind;
2045353358Sdim};
2046353358Sdim
2047360784Sdimstatic constexpr RegInfo RegularRegisters[] = {
2048360784Sdim  {{"v"},    IS_VGPR},
2049360784Sdim  {{"s"},    IS_SGPR},
2050360784Sdim  {{"ttmp"}, IS_TTMP},
2051360784Sdim  {{"acc"},  IS_AGPR},
2052360784Sdim  {{"a"},    IS_AGPR},
2053360784Sdim};
2054360784Sdim
2055360784Sdimstatic bool isRegularReg(RegisterKind Kind) {
2056360784Sdim  return Kind == IS_VGPR ||
2057360784Sdim         Kind == IS_SGPR ||
2058360784Sdim         Kind == IS_TTMP ||
2059360784Sdim         Kind == IS_AGPR;
2060360784Sdim}
2061360784Sdim
2062360784Sdimstatic const RegInfo* getRegularRegInfo(StringRef Str) {
2063360784Sdim  for (const RegInfo &Reg : RegularRegisters)
2064360784Sdim    if (Str.startswith(Reg.Name))
2065360784Sdim      return &Reg;
2066360784Sdim  return nullptr;
2067360784Sdim}
2068360784Sdim
2069360784Sdimstatic bool getRegNum(StringRef Str, unsigned& Num) {
2070360784Sdim  return !Str.getAsInteger(10, Num);
2071360784Sdim}
2072360784Sdim
2073353358Sdimbool
2074353358SdimAMDGPUAsmParser::isRegister(const AsmToken &Token,
2075353358Sdim                            const AsmToken &NextToken) const {
2076353358Sdim
2077353358Sdim  // A list of consecutive registers: [s0,s1,s2,s3]
2078353358Sdim  if (Token.is(AsmToken::LBrac))
2079353358Sdim    return true;
2080353358Sdim
2081353358Sdim  if (!Token.is(AsmToken::Identifier))
2082353358Sdim    return false;
2083353358Sdim
2084353358Sdim  // A single register like s0 or a range of registers like s[0:1]
2085353358Sdim
2086360784Sdim  StringRef Str = Token.getString();
2087360784Sdim  const RegInfo *Reg = getRegularRegInfo(Str);
2088360784Sdim  if (Reg) {
2089360784Sdim    StringRef RegName = Reg->Name;
2090360784Sdim    StringRef RegSuffix = Str.substr(RegName.size());
2091360784Sdim    if (!RegSuffix.empty()) {
2092360784Sdim      unsigned Num;
2093360784Sdim      // A single register with an index: rXX
2094360784Sdim      if (getRegNum(RegSuffix, Num))
2095360784Sdim        return true;
2096360784Sdim    } else {
2097360784Sdim      // A range of registers: r[XX:YY].
2098360784Sdim      if (NextToken.is(AsmToken::LBrac))
2099360784Sdim        return true;
2100353358Sdim    }
2101353358Sdim  }
2102353358Sdim
2103360784Sdim  return getSpecialRegForName(Str) != AMDGPU::NoRegister;
2104353358Sdim}
2105353358Sdim
2106353358Sdimbool
2107353358SdimAMDGPUAsmParser::isRegister()
2108353358Sdim{
2109353358Sdim  return isRegister(getToken(), peekToken());
2110353358Sdim}
2111353358Sdim
2112360784Sdimunsigned
2113360784SdimAMDGPUAsmParser::getRegularReg(RegisterKind RegKind,
2114360784Sdim                               unsigned RegNum,
2115360784Sdim                               unsigned RegWidth) {
2116360784Sdim
2117360784Sdim  assert(isRegularReg(RegKind));
2118360784Sdim
2119360784Sdim  unsigned AlignSize = 1;
2120360784Sdim  if (RegKind == IS_SGPR || RegKind == IS_TTMP) {
2121360784Sdim    // SGPR and TTMP registers must be aligned.
2122360784Sdim    // Max required alignment is 4 dwords.
2123360784Sdim    AlignSize = std::min(RegWidth, 4u);
2124360784Sdim  }
2125360784Sdim
2126360784Sdim  if (RegNum % AlignSize != 0)
2127360784Sdim    return AMDGPU::NoRegister;
2128360784Sdim
2129360784Sdim  unsigned RegIdx = RegNum / AlignSize;
2130360784Sdim  int RCID = getRegClass(RegKind, RegWidth);
2131360784Sdim  if (RCID == -1)
2132360784Sdim    return AMDGPU::NoRegister;
2133360784Sdim
2134296417Sdim  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2135360784Sdim  const MCRegisterClass RC = TRI->getRegClass(RCID);
2136360784Sdim  if (RegIdx >= RC.getNumRegs())
2137360784Sdim    return AMDGPU::NoRegister;
2138296417Sdim
2139360784Sdim  return RC.getRegister(RegIdx);
2140360784Sdim}
2141284677Sdim
2142360784Sdimbool
2143360784SdimAMDGPUAsmParser::ParseRegRange(unsigned& Num, unsigned& Width) {
2144360784Sdim  int64_t RegLo, RegHi;
2145360784Sdim  if (!trySkipToken(AsmToken::LBrac))
2146360784Sdim    return false;
2147309124Sdim
2148360784Sdim  if (!parseExpr(RegLo))
2149360784Sdim    return false;
2150309124Sdim
2151360784Sdim  if (trySkipToken(AsmToken::Colon)) {
2152360784Sdim    if (!parseExpr(RegHi))
2153309124Sdim      return false;
2154309124Sdim  } else {
2155360784Sdim    RegHi = RegLo;
2156360784Sdim  }
2157360784Sdim
2158360784Sdim  if (!trySkipToken(AsmToken::RBrac))
2159309124Sdim    return false;
2160360784Sdim
2161360784Sdim  if (!isUInt<32>(RegLo) || !isUInt<32>(RegHi) || RegLo > RegHi)
2162360784Sdim    return false;
2163360784Sdim
2164360784Sdim  Num = static_cast<unsigned>(RegLo);
2165360784Sdim  Width = (RegHi - RegLo) + 1;
2166360784Sdim  return true;
2167360784Sdim}
2168360784Sdim
2169360784Sdimunsigned
2170360784SdimAMDGPUAsmParser::ParseSpecialReg(RegisterKind &RegKind,
2171360784Sdim                                 unsigned &RegNum,
2172360784Sdim                                 unsigned &RegWidth) {
2173360784Sdim  assert(isToken(AsmToken::Identifier));
2174360784Sdim  unsigned Reg = getSpecialRegForName(getTokenStr());
2175360784Sdim  if (Reg) {
2176309124Sdim    RegNum = 0;
2177309124Sdim    RegWidth = 1;
2178360784Sdim    RegKind = IS_SPECIAL;
2179360784Sdim    lex(); // skip register name
2180309124Sdim  }
2181360784Sdim  return Reg;
2182360784Sdim}
2183284677Sdim
2184360784Sdimunsigned
2185360784SdimAMDGPUAsmParser::ParseRegularReg(RegisterKind &RegKind,
2186360784Sdim                                 unsigned &RegNum,
2187360784Sdim                                 unsigned &RegWidth) {
2188360784Sdim  assert(isToken(AsmToken::Identifier));
2189360784Sdim  StringRef RegName = getTokenStr();
2190360784Sdim
2191360784Sdim  const RegInfo *RI = getRegularRegInfo(RegName);
2192360784Sdim  if (!RI)
2193360784Sdim    return AMDGPU::NoRegister;
2194360784Sdim  lex(); // skip register name
2195360784Sdim
2196360784Sdim  RegKind = RI->Kind;
2197360784Sdim  StringRef RegSuffix = RegName.substr(RI->Name.size());
2198360784Sdim  if (!RegSuffix.empty()) {
2199360784Sdim    // Single 32-bit register: vXX.
2200360784Sdim    if (!getRegNum(RegSuffix, RegNum))
2201360784Sdim      return AMDGPU::NoRegister;
2202360784Sdim    RegWidth = 1;
2203360784Sdim  } else {
2204360784Sdim    // Range of registers: v[XX:YY]. ":YY" is optional.
2205360784Sdim    if (!ParseRegRange(RegNum, RegWidth))
2206360784Sdim      return AMDGPU::NoRegister;
2207309124Sdim  }
2208284677Sdim
2209360784Sdim  return getRegularReg(RegKind, RegNum, RegWidth);
2210309124Sdim}
2211309124Sdim
2212360784Sdimunsigned
2213360784SdimAMDGPUAsmParser::ParseRegList(RegisterKind &RegKind,
2214360784Sdim                              unsigned &RegNum,
2215360784Sdim                              unsigned &RegWidth) {
2216360784Sdim  unsigned Reg = AMDGPU::NoRegister;
2217360784Sdim
2218360784Sdim  if (!trySkipToken(AsmToken::LBrac))
2219360784Sdim    return AMDGPU::NoRegister;
2220360784Sdim
2221360784Sdim  // List of consecutive registers, e.g.: [s0,s1,s2,s3]
2222360784Sdim
2223360784Sdim  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth))
2224360784Sdim    return AMDGPU::NoRegister;
2225360784Sdim  if (RegWidth != 1)
2226360784Sdim    return AMDGPU::NoRegister;
2227360784Sdim
2228360784Sdim  for (; trySkipToken(AsmToken::Comma); ) {
2229360784Sdim    RegisterKind NextRegKind;
2230360784Sdim    unsigned NextReg, NextRegNum, NextRegWidth;
2231360784Sdim
2232360784Sdim    if (!ParseAMDGPURegister(NextRegKind, NextReg, NextRegNum, NextRegWidth))
2233360784Sdim      return AMDGPU::NoRegister;
2234360784Sdim    if (NextRegWidth != 1)
2235360784Sdim      return AMDGPU::NoRegister;
2236360784Sdim    if (NextRegKind != RegKind)
2237360784Sdim      return AMDGPU::NoRegister;
2238360784Sdim    if (!AddNextRegisterToList(Reg, RegWidth, RegKind, NextReg))
2239360784Sdim      return AMDGPU::NoRegister;
2240360784Sdim  }
2241360784Sdim
2242360784Sdim  if (!trySkipToken(AsmToken::RBrac))
2243360784Sdim    return AMDGPU::NoRegister;
2244360784Sdim
2245360784Sdim  if (isRegularReg(RegKind))
2246360784Sdim    Reg = getRegularReg(RegKind, RegNum, RegWidth);
2247360784Sdim
2248360784Sdim  return Reg;
2249360784Sdim}
2250360784Sdim
2251360784Sdimbool AMDGPUAsmParser::ParseAMDGPURegister(RegisterKind &RegKind,
2252360784Sdim                                          unsigned &Reg,
2253360784Sdim                                          unsigned &RegNum,
2254360784Sdim                                          unsigned &RegWidth) {
2255360784Sdim  Reg = AMDGPU::NoRegister;
2256360784Sdim
2257360784Sdim  if (isToken(AsmToken::Identifier)) {
2258360784Sdim    Reg = ParseSpecialReg(RegKind, RegNum, RegWidth);
2259360784Sdim    if (Reg == AMDGPU::NoRegister)
2260360784Sdim      Reg = ParseRegularReg(RegKind, RegNum, RegWidth);
2261360784Sdim  } else {
2262360784Sdim    Reg = ParseRegList(RegKind, RegNum, RegWidth);
2263360784Sdim  }
2264360784Sdim
2265360784Sdim  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2266360784Sdim  return Reg != AMDGPU::NoRegister && subtargetHasRegister(*TRI, Reg);
2267360784Sdim}
2268360784Sdim
2269341825SdimOptional<StringRef>
2270341825SdimAMDGPUAsmParser::getGprCountSymbolName(RegisterKind RegKind) {
2271341825Sdim  switch (RegKind) {
2272341825Sdim  case IS_VGPR:
2273341825Sdim    return StringRef(".amdgcn.next_free_vgpr");
2274341825Sdim  case IS_SGPR:
2275341825Sdim    return StringRef(".amdgcn.next_free_sgpr");
2276341825Sdim  default:
2277341825Sdim    return None;
2278341825Sdim  }
2279341825Sdim}
2280341825Sdim
2281341825Sdimvoid AMDGPUAsmParser::initializeGprCountSymbol(RegisterKind RegKind) {
2282341825Sdim  auto SymbolName = getGprCountSymbolName(RegKind);
2283341825Sdim  assert(SymbolName && "initializing invalid register kind");
2284341825Sdim  MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2285341825Sdim  Sym->setVariableValue(MCConstantExpr::create(0, getContext()));
2286341825Sdim}
2287341825Sdim
2288341825Sdimbool AMDGPUAsmParser::updateGprCountSymbols(RegisterKind RegKind,
2289341825Sdim                                            unsigned DwordRegIndex,
2290341825Sdim                                            unsigned RegWidth) {
2291341825Sdim  // Symbols are only defined for GCN targets
2292344779Sdim  if (AMDGPU::getIsaVersion(getSTI().getCPU()).Major < 6)
2293341825Sdim    return true;
2294341825Sdim
2295341825Sdim  auto SymbolName = getGprCountSymbolName(RegKind);
2296341825Sdim  if (!SymbolName)
2297341825Sdim    return true;
2298341825Sdim  MCSymbol *Sym = getContext().getOrCreateSymbol(*SymbolName);
2299341825Sdim
2300341825Sdim  int64_t NewMax = DwordRegIndex + RegWidth - 1;
2301341825Sdim  int64_t OldCount;
2302341825Sdim
2303341825Sdim  if (!Sym->isVariable())
2304341825Sdim    return !Error(getParser().getTok().getLoc(),
2305341825Sdim                  ".amdgcn.next_free_{v,s}gpr symbols must be variable");
2306341825Sdim  if (!Sym->getVariableValue(false)->evaluateAsAbsolute(OldCount))
2307341825Sdim    return !Error(
2308341825Sdim        getParser().getTok().getLoc(),
2309341825Sdim        ".amdgcn.next_free_{v,s}gpr symbols must be absolute expressions");
2310341825Sdim
2311341825Sdim  if (OldCount <= NewMax)
2312341825Sdim    Sym->setVariableValue(MCConstantExpr::create(NewMax + 1, getContext()));
2313341825Sdim
2314341825Sdim  return true;
2315341825Sdim}
2316341825Sdim
2317309124Sdimstd::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::parseRegister() {
2318309124Sdim  const auto &Tok = Parser.getTok();
2319309124Sdim  SMLoc StartLoc = Tok.getLoc();
2320309124Sdim  SMLoc EndLoc = Tok.getEndLoc();
2321309124Sdim  RegisterKind RegKind;
2322360784Sdim  unsigned Reg, RegNum, RegWidth;
2323309124Sdim
2324360784Sdim  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) {
2325353358Sdim    //FIXME: improve error messages (bug 41303).
2326353358Sdim    Error(StartLoc, "not a valid operand.");
2327309124Sdim    return nullptr;
2328309124Sdim  }
2329341825Sdim  if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
2330360784Sdim    if (!updateGprCountSymbols(RegKind, RegNum, RegWidth))
2331341825Sdim      return nullptr;
2332341825Sdim  } else
2333360784Sdim    KernelScope.usesRegister(RegKind, RegNum, RegWidth);
2334353358Sdim  return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
2335309124Sdim}
2336309124Sdim
2337353358SdimOperandMatchResultTy
2338353358SdimAMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
2339353358Sdim  // TODO: add syntactic sugar for 1/(2*PI)
2340321369Sdim
2341353358Sdim  assert(!isRegister());
2342353358Sdim  assert(!isModifier());
2343321369Sdim
2344353358Sdim  const auto& Tok = getToken();
2345353358Sdim  const auto& NextTok = peekToken();
2346353358Sdim  bool IsReal = Tok.is(AsmToken::Real);
2347353358Sdim  SMLoc S = getLoc();
2348353358Sdim  bool Negate = false;
2349321369Sdim
2350353358Sdim  if (!IsReal && Tok.is(AsmToken::Minus) && NextTok.is(AsmToken::Real)) {
2351353358Sdim    lex();
2352353358Sdim    IsReal = true;
2353353358Sdim    Negate = true;
2354321369Sdim  }
2355321369Sdim
2356353358Sdim  if (IsReal) {
2357353358Sdim    // Floating-point expressions are not supported.
2358353358Sdim    // Can only allow floating-point literals with an
2359353358Sdim    // optional sign.
2360321369Sdim
2361353358Sdim    StringRef Num = getTokenStr();
2362353358Sdim    lex();
2363353358Sdim
2364353358Sdim    APFloat RealVal(APFloat::IEEEdouble());
2365353358Sdim    auto roundMode = APFloat::rmNearestTiesToEven;
2366360784Sdim    if (errorToBool(RealVal.convertFromString(Num, roundMode).takeError())) {
2367353358Sdim      return MatchOperand_ParseFail;
2368327952Sdim    }
2369353358Sdim    if (Negate)
2370353358Sdim      RealVal.changeSign();
2371284677Sdim
2372353358Sdim    Operands.push_back(
2373353358Sdim      AMDGPUOperand::CreateImm(this, RealVal.bitcastToAPInt().getZExtValue(), S,
2374353358Sdim                               AMDGPUOperand::ImmTyNone, true));
2375353358Sdim
2376309124Sdim    return MatchOperand_Success;
2377353358Sdim
2378353358Sdim  } else {
2379309124Sdim    int64_t IntVal;
2380353358Sdim    const MCExpr *Expr;
2381353358Sdim    SMLoc S = getLoc();
2382309124Sdim
2383353358Sdim    if (HasSP3AbsModifier) {
2384353358Sdim      // This is a workaround for handling expressions
2385353358Sdim      // as arguments of SP3 'abs' modifier, for example:
2386353358Sdim      //     |1.0|
2387353358Sdim      //     |-1|
2388353358Sdim      //     |1+x|
2389353358Sdim      // This syntax is not compatible with syntax of standard
2390353358Sdim      // MC expressions (due to the trailing '|').
2391353358Sdim      SMLoc EndLoc;
2392353358Sdim      if (getParser().parsePrimaryExpr(Expr, EndLoc))
2393353358Sdim        return MatchOperand_ParseFail;
2394353358Sdim    } else {
2395353358Sdim      if (Parser.parseExpression(Expr))
2396353358Sdim        return MatchOperand_ParseFail;
2397353358Sdim    }
2398353358Sdim
2399353358Sdim    if (Expr->evaluateAsAbsolute(IntVal)) {
2400353358Sdim      Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
2401353358Sdim    } else {
2402353358Sdim      Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
2403353358Sdim    }
2404353358Sdim
2405309124Sdim    return MatchOperand_Success;
2406309124Sdim  }
2407353358Sdim
2408353358Sdim  return MatchOperand_NoMatch;
2409309124Sdim}
2410309124Sdim
2411314564SdimOperandMatchResultTy
2412314564SdimAMDGPUAsmParser::parseReg(OperandVector &Operands) {
2413353358Sdim  if (!isRegister())
2414353358Sdim    return MatchOperand_NoMatch;
2415353358Sdim
2416309124Sdim  if (auto R = parseRegister()) {
2417309124Sdim    assert(R->isReg());
2418309124Sdim    Operands.push_back(std::move(R));
2419309124Sdim    return MatchOperand_Success;
2420309124Sdim  }
2421353358Sdim  return MatchOperand_ParseFail;
2422309124Sdim}
2423309124Sdim
2424314564SdimOperandMatchResultTy
2425353358SdimAMDGPUAsmParser::parseRegOrImm(OperandVector &Operands, bool HasSP3AbsMod) {
2426353358Sdim  auto res = parseReg(Operands);
2427314564Sdim  if (res != MatchOperand_NoMatch) {
2428314564Sdim    return res;
2429353358Sdim  } else if (isModifier()) {
2430353358Sdim    return MatchOperand_NoMatch;
2431353358Sdim  } else {
2432353358Sdim    return parseImm(Operands, HasSP3AbsMod);
2433314564Sdim  }
2434353358Sdim}
2435314564Sdim
2436353358Sdimbool
2437353358SdimAMDGPUAsmParser::isNamedOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2438353358Sdim  if (Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::LParen)) {
2439353358Sdim    const auto &str = Token.getString();
2440353358Sdim    return str == "abs" || str == "neg" || str == "sext";
2441353358Sdim  }
2442353358Sdim  return false;
2443314564Sdim}
2444314564Sdim
2445353358Sdimbool
2446353358SdimAMDGPUAsmParser::isOpcodeModifierWithVal(const AsmToken &Token, const AsmToken &NextToken) const {
2447353358Sdim  return Token.is(AsmToken::Identifier) && NextToken.is(AsmToken::Colon);
2448353358Sdim}
2449353358Sdim
2450353358Sdimbool
2451353358SdimAMDGPUAsmParser::isOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2452353358Sdim  return isNamedOperandModifier(Token, NextToken) || Token.is(AsmToken::Pipe);
2453353358Sdim}
2454353358Sdim
2455353358Sdimbool
2456353358SdimAMDGPUAsmParser::isRegOrOperandModifier(const AsmToken &Token, const AsmToken &NextToken) const {
2457353358Sdim  return isRegister(Token, NextToken) || isOperandModifier(Token, NextToken);
2458353358Sdim}
2459353358Sdim
2460353358Sdim// Check if this is an operand modifier or an opcode modifier
2461353358Sdim// which may look like an expression but it is not. We should
2462353358Sdim// avoid parsing these modifiers as expressions. Currently
2463353358Sdim// recognized sequences are:
2464353358Sdim//   |...|
2465353358Sdim//   abs(...)
2466353358Sdim//   neg(...)
2467353358Sdim//   sext(...)
2468353358Sdim//   -reg
2469353358Sdim//   -|...|
2470353358Sdim//   -abs(...)
2471353358Sdim//   name:...
2472353358Sdim// Note that simple opcode modifiers like 'gds' may be parsed as
2473353358Sdim// expressions; this is a special case. See getExpressionAsToken.
2474353358Sdim//
2475353358Sdimbool
2476353358SdimAMDGPUAsmParser::isModifier() {
2477353358Sdim
2478353358Sdim  AsmToken Tok = getToken();
2479353358Sdim  AsmToken NextToken[2];
2480353358Sdim  peekTokens(NextToken);
2481353358Sdim
2482353358Sdim  return isOperandModifier(Tok, NextToken[0]) ||
2483353358Sdim         (Tok.is(AsmToken::Minus) && isRegOrOperandModifier(NextToken[0], NextToken[1])) ||
2484353358Sdim         isOpcodeModifierWithVal(Tok, NextToken[0]);
2485353358Sdim}
2486353358Sdim
2487353358Sdim// Check if the current token is an SP3 'neg' modifier.
2488353358Sdim// Currently this modifier is allowed in the following context:
2489353358Sdim//
2490353358Sdim// 1. Before a register, e.g. "-v0", "-v[...]" or "-[v0,v1]".
2491353358Sdim// 2. Before an 'abs' modifier: -abs(...)
2492353358Sdim// 3. Before an SP3 'abs' modifier: -|...|
2493353358Sdim//
2494353358Sdim// In all other cases "-" is handled as a part
2495353358Sdim// of an expression that follows the sign.
2496353358Sdim//
2497353358Sdim// Note: When "-" is followed by an integer literal,
2498353358Sdim// this is interpreted as integer negation rather
2499353358Sdim// than a floating-point NEG modifier applied to N.
2500353358Sdim// Beside being contr-intuitive, such use of floating-point
2501353358Sdim// NEG modifier would have resulted in different meaning
2502353358Sdim// of integer literals used with VOP1/2/C and VOP3,
2503353358Sdim// for example:
2504353358Sdim//    v_exp_f32_e32 v5, -1 // VOP1: src0 = 0xFFFFFFFF
2505353358Sdim//    v_exp_f32_e64 v5, -1 // VOP3: src0 = 0x80000001
2506353358Sdim// Negative fp literals with preceding "-" are
2507353358Sdim// handled likewise for unifomtity
2508353358Sdim//
2509353358Sdimbool
2510353358SdimAMDGPUAsmParser::parseSP3NegModifier() {
2511353358Sdim
2512353358Sdim  AsmToken NextToken[2];
2513353358Sdim  peekTokens(NextToken);
2514353358Sdim
2515353358Sdim  if (isToken(AsmToken::Minus) &&
2516353358Sdim      (isRegister(NextToken[0], NextToken[1]) ||
2517353358Sdim       NextToken[0].is(AsmToken::Pipe) ||
2518353358Sdim       isId(NextToken[0], "abs"))) {
2519353358Sdim    lex();
2520353358Sdim    return true;
2521353358Sdim  }
2522353358Sdim
2523353358Sdim  return false;
2524353358Sdim}
2525353358Sdim
2526314564SdimOperandMatchResultTy
2527321369SdimAMDGPUAsmParser::parseRegOrImmWithFPInputMods(OperandVector &Operands,
2528321369Sdim                                              bool AllowImm) {
2529353358Sdim  bool Neg, SP3Neg;
2530353358Sdim  bool Abs, SP3Abs;
2531353358Sdim  SMLoc Loc;
2532309124Sdim
2533353358Sdim  // Disable ambiguous constructs like '--1' etc. Should use neg(-1) instead.
2534353358Sdim  if (isToken(AsmToken::Minus) && peekToken().is(AsmToken::Minus)) {
2535353358Sdim    Error(getLoc(), "invalid syntax, expected 'neg' modifier");
2536353358Sdim    return MatchOperand_ParseFail;
2537353358Sdim  }
2538321369Sdim
2539353358Sdim  SP3Neg = parseSP3NegModifier();
2540321369Sdim
2541353358Sdim  Loc = getLoc();
2542353358Sdim  Neg = trySkipId("neg");
2543353358Sdim  if (Neg && SP3Neg) {
2544353358Sdim    Error(Loc, "expected register or immediate");
2545353358Sdim    return MatchOperand_ParseFail;
2546321369Sdim  }
2547353358Sdim  if (Neg && !skipToken(AsmToken::LParen, "expected left paren after neg"))
2548353358Sdim    return MatchOperand_ParseFail;
2549321369Sdim
2550353358Sdim  Abs = trySkipId("abs");
2551353358Sdim  if (Abs && !skipToken(AsmToken::LParen, "expected left paren after abs"))
2552353358Sdim    return MatchOperand_ParseFail;
2553284677Sdim
2554353358Sdim  Loc = getLoc();
2555353358Sdim  SP3Abs = trySkipToken(AsmToken::Pipe);
2556353358Sdim  if (Abs && SP3Abs) {
2557353358Sdim    Error(Loc, "expected register or immediate");
2558353358Sdim    return MatchOperand_ParseFail;
2559309124Sdim  }
2560284677Sdim
2561314564Sdim  OperandMatchResultTy Res;
2562314564Sdim  if (AllowImm) {
2563353358Sdim    Res = parseRegOrImm(Operands, SP3Abs);
2564314564Sdim  } else {
2565314564Sdim    Res = parseReg(Operands);
2566314564Sdim  }
2567309124Sdim  if (Res != MatchOperand_Success) {
2568353358Sdim    return (SP3Neg || Neg || SP3Abs || Abs)? MatchOperand_ParseFail : Res;
2569309124Sdim  }
2570309124Sdim
2571353358Sdim  if (SP3Abs && !skipToken(AsmToken::Pipe, "expected vertical bar"))
2572353358Sdim    return MatchOperand_ParseFail;
2573353358Sdim  if (Abs && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2574353358Sdim    return MatchOperand_ParseFail;
2575353358Sdim  if (Neg && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2576353358Sdim    return MatchOperand_ParseFail;
2577353358Sdim
2578314564Sdim  AMDGPUOperand::Modifiers Mods;
2579353358Sdim  Mods.Abs = Abs || SP3Abs;
2580353358Sdim  Mods.Neg = Neg || SP3Neg;
2581284677Sdim
2582353358Sdim  if (Mods.hasFPModifiers()) {
2583353358Sdim    AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
2584353358Sdim    if (Op.isExpr()) {
2585353358Sdim      Error(Op.getStartLoc(), "expected an absolute expression");
2586321369Sdim      return MatchOperand_ParseFail;
2587321369Sdim    }
2588309124Sdim    Op.setModifiers(Mods);
2589309124Sdim  }
2590309124Sdim  return MatchOperand_Success;
2591309124Sdim}
2592284677Sdim
2593314564SdimOperandMatchResultTy
2594321369SdimAMDGPUAsmParser::parseRegOrImmWithIntInputMods(OperandVector &Operands,
2595321369Sdim                                               bool AllowImm) {
2596353358Sdim  bool Sext = trySkipId("sext");
2597353358Sdim  if (Sext && !skipToken(AsmToken::LParen, "expected left paren after sext"))
2598353358Sdim    return MatchOperand_ParseFail;
2599309124Sdim
2600314564Sdim  OperandMatchResultTy Res;
2601314564Sdim  if (AllowImm) {
2602314564Sdim    Res = parseRegOrImm(Operands);
2603314564Sdim  } else {
2604314564Sdim    Res = parseReg(Operands);
2605314564Sdim  }
2606309124Sdim  if (Res != MatchOperand_Success) {
2607353358Sdim    return Sext? MatchOperand_ParseFail : Res;
2608309124Sdim  }
2609296417Sdim
2610353358Sdim  if (Sext && !skipToken(AsmToken::RParen, "expected closing parentheses"))
2611353358Sdim    return MatchOperand_ParseFail;
2612353358Sdim
2613314564Sdim  AMDGPUOperand::Modifiers Mods;
2614353358Sdim  Mods.Sext = Sext;
2615314564Sdim
2616309124Sdim  if (Mods.hasIntModifiers()) {
2617309124Sdim    AMDGPUOperand &Op = static_cast<AMDGPUOperand &>(*Operands.back());
2618353358Sdim    if (Op.isExpr()) {
2619353358Sdim      Error(Op.getStartLoc(), "expected an absolute expression");
2620353358Sdim      return MatchOperand_ParseFail;
2621353358Sdim    }
2622309124Sdim    Op.setModifiers(Mods);
2623309124Sdim  }
2624314564Sdim
2625309124Sdim  return MatchOperand_Success;
2626284677Sdim}
2627284677Sdim
2628314564SdimOperandMatchResultTy
2629314564SdimAMDGPUAsmParser::parseRegWithFPInputMods(OperandVector &Operands) {
2630314564Sdim  return parseRegOrImmWithFPInputMods(Operands, false);
2631314564Sdim}
2632314564Sdim
2633314564SdimOperandMatchResultTy
2634314564SdimAMDGPUAsmParser::parseRegWithIntInputMods(OperandVector &Operands) {
2635314564Sdim  return parseRegOrImmWithIntInputMods(Operands, false);
2636314564Sdim}
2637314564Sdim
2638314564SdimOperandMatchResultTy AMDGPUAsmParser::parseVReg32OrOff(OperandVector &Operands) {
2639353358Sdim  auto Loc = getLoc();
2640353358Sdim  if (trySkipId("off")) {
2641353358Sdim    Operands.push_back(AMDGPUOperand::CreateImm(this, 0, Loc,
2642353358Sdim                                                AMDGPUOperand::ImmTyOff, false));
2643353358Sdim    return MatchOperand_Success;
2644353358Sdim  }
2645353358Sdim
2646353358Sdim  if (!isRegister())
2647353358Sdim    return MatchOperand_NoMatch;
2648353358Sdim
2649314564Sdim  std::unique_ptr<AMDGPUOperand> Reg = parseRegister();
2650314564Sdim  if (Reg) {
2651314564Sdim    Operands.push_back(std::move(Reg));
2652314564Sdim    return MatchOperand_Success;
2653314564Sdim  }
2654314564Sdim
2655353358Sdim  return MatchOperand_ParseFail;
2656314564Sdim
2657314564Sdim}
2658314564Sdim
2659284677Sdimunsigned AMDGPUAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
2660284677Sdim  uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
2661284677Sdim
2662284677Sdim  if ((getForcedEncodingSize() == 32 && (TSFlags & SIInstrFlags::VOP3)) ||
2663309124Sdim      (getForcedEncodingSize() == 64 && !(TSFlags & SIInstrFlags::VOP3)) ||
2664309124Sdim      (isForcedDPP() && !(TSFlags & SIInstrFlags::DPP)) ||
2665309124Sdim      (isForcedSDWA() && !(TSFlags & SIInstrFlags::SDWA)) )
2666284677Sdim    return Match_InvalidOperand;
2667284677Sdim
2668296417Sdim  if ((TSFlags & SIInstrFlags::VOP3) &&
2669296417Sdim      (TSFlags & SIInstrFlags::VOPAsmPrefer32Bit) &&
2670296417Sdim      getForcedEncodingSize() != 64)
2671296417Sdim    return Match_PreferE32;
2672296417Sdim
2673314564Sdim  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
2674314564Sdim      Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi) {
2675314564Sdim    // v_mac_f32/16 allow only dst_sel == DWORD;
2676314564Sdim    auto OpNum =
2677314564Sdim        AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::dst_sel);
2678314564Sdim    const auto &Op = Inst.getOperand(OpNum);
2679314564Sdim    if (!Op.isImm() || Op.getImm() != AMDGPU::SDWA::SdwaSel::DWORD) {
2680314564Sdim      return Match_InvalidOperand;
2681314564Sdim    }
2682314564Sdim  }
2683314564Sdim
2684284677Sdim  return Match_Success;
2685284677Sdim}
2686284677Sdim
2687314564Sdim// What asm variants we should check
2688314564SdimArrayRef<unsigned> AMDGPUAsmParser::getMatchedVariants() const {
2689314564Sdim  if (getForcedEncodingSize() == 32) {
2690314564Sdim    static const unsigned Variants[] = {AMDGPUAsmVariants::DEFAULT};
2691314564Sdim    return makeArrayRef(Variants);
2692314564Sdim  }
2693314564Sdim
2694314564Sdim  if (isForcedVOP3()) {
2695314564Sdim    static const unsigned Variants[] = {AMDGPUAsmVariants::VOP3};
2696314564Sdim    return makeArrayRef(Variants);
2697314564Sdim  }
2698314564Sdim
2699314564Sdim  if (isForcedSDWA()) {
2700321369Sdim    static const unsigned Variants[] = {AMDGPUAsmVariants::SDWA,
2701321369Sdim                                        AMDGPUAsmVariants::SDWA9};
2702314564Sdim    return makeArrayRef(Variants);
2703314564Sdim  }
2704314564Sdim
2705314564Sdim  if (isForcedDPP()) {
2706314564Sdim    static const unsigned Variants[] = {AMDGPUAsmVariants::DPP};
2707314564Sdim    return makeArrayRef(Variants);
2708314564Sdim  }
2709314564Sdim
2710314564Sdim  static const unsigned Variants[] = {
2711314564Sdim    AMDGPUAsmVariants::DEFAULT, AMDGPUAsmVariants::VOP3,
2712321369Sdim    AMDGPUAsmVariants::SDWA, AMDGPUAsmVariants::SDWA9, AMDGPUAsmVariants::DPP
2713314564Sdim  };
2714314564Sdim
2715314564Sdim  return makeArrayRef(Variants);
2716314564Sdim}
2717314564Sdim
2718321369Sdimunsigned AMDGPUAsmParser::findImplicitSGPRReadInVOP(const MCInst &Inst) const {
2719321369Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2720321369Sdim  const unsigned Num = Desc.getNumImplicitUses();
2721321369Sdim  for (unsigned i = 0; i < Num; ++i) {
2722321369Sdim    unsigned Reg = Desc.ImplicitUses[i];
2723321369Sdim    switch (Reg) {
2724321369Sdim    case AMDGPU::FLAT_SCR:
2725321369Sdim    case AMDGPU::VCC:
2726353358Sdim    case AMDGPU::VCC_LO:
2727353358Sdim    case AMDGPU::VCC_HI:
2728321369Sdim    case AMDGPU::M0:
2729321369Sdim      return Reg;
2730321369Sdim    default:
2731321369Sdim      break;
2732321369Sdim    }
2733321369Sdim  }
2734321369Sdim  return AMDGPU::NoRegister;
2735321369Sdim}
2736321369Sdim
2737321369Sdim// NB: This code is correct only when used to check constant
2738321369Sdim// bus limitations because GFX7 support no f16 inline constants.
2739321369Sdim// Note that there are no cases when a GFX7 opcode violates
2740321369Sdim// constant bus limitations due to the use of an f16 constant.
2741321369Sdimbool AMDGPUAsmParser::isInlineConstant(const MCInst &Inst,
2742321369Sdim                                       unsigned OpIdx) const {
2743321369Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
2744321369Sdim
2745321369Sdim  if (!AMDGPU::isSISrcOperand(Desc, OpIdx)) {
2746321369Sdim    return false;
2747321369Sdim  }
2748321369Sdim
2749321369Sdim  const MCOperand &MO = Inst.getOperand(OpIdx);
2750321369Sdim
2751321369Sdim  int64_t Val = MO.getImm();
2752321369Sdim  auto OpSize = AMDGPU::getOperandSize(Desc, OpIdx);
2753321369Sdim
2754321369Sdim  switch (OpSize) { // expected operand size
2755321369Sdim  case 8:
2756321369Sdim    return AMDGPU::isInlinableLiteral64(Val, hasInv2PiInlineImm());
2757321369Sdim  case 4:
2758321369Sdim    return AMDGPU::isInlinableLiteral32(Val, hasInv2PiInlineImm());
2759321369Sdim  case 2: {
2760321369Sdim    const unsigned OperandType = Desc.OpInfo[OpIdx].OperandType;
2761321369Sdim    if (OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2INT16 ||
2762353358Sdim        OperandType == AMDGPU::OPERAND_REG_INLINE_C_V2FP16 ||
2763353358Sdim        OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2INT16 ||
2764353358Sdim        OperandType == AMDGPU::OPERAND_REG_INLINE_AC_V2FP16 ||
2765353358Sdim        OperandType == AMDGPU::OPERAND_REG_IMM_V2INT16 ||
2766353358Sdim        OperandType == AMDGPU::OPERAND_REG_IMM_V2FP16) {
2767321369Sdim      return AMDGPU::isInlinableLiteralV216(Val, hasInv2PiInlineImm());
2768321369Sdim    } else {
2769321369Sdim      return AMDGPU::isInlinableLiteral16(Val, hasInv2PiInlineImm());
2770321369Sdim    }
2771321369Sdim  }
2772321369Sdim  default:
2773321369Sdim    llvm_unreachable("invalid operand size");
2774321369Sdim  }
2775321369Sdim}
2776321369Sdim
2777360784Sdimunsigned AMDGPUAsmParser::getConstantBusLimit(unsigned Opcode) const {
2778360784Sdim  if (!isGFX10())
2779360784Sdim    return 1;
2780360784Sdim
2781360784Sdim  switch (Opcode) {
2782360784Sdim  // 64-bit shift instructions can use only one scalar value input
2783360784Sdim  case AMDGPU::V_LSHLREV_B64:
2784360784Sdim  case AMDGPU::V_LSHLREV_B64_gfx10:
2785360784Sdim  case AMDGPU::V_LSHL_B64:
2786360784Sdim  case AMDGPU::V_LSHRREV_B64:
2787360784Sdim  case AMDGPU::V_LSHRREV_B64_gfx10:
2788360784Sdim  case AMDGPU::V_LSHR_B64:
2789360784Sdim  case AMDGPU::V_ASHRREV_I64:
2790360784Sdim  case AMDGPU::V_ASHRREV_I64_gfx10:
2791360784Sdim  case AMDGPU::V_ASHR_I64:
2792360784Sdim    return 1;
2793360784Sdim  default:
2794360784Sdim    return 2;
2795360784Sdim  }
2796360784Sdim}
2797360784Sdim
2798321369Sdimbool AMDGPUAsmParser::usesConstantBus(const MCInst &Inst, unsigned OpIdx) {
2799321369Sdim  const MCOperand &MO = Inst.getOperand(OpIdx);
2800321369Sdim  if (MO.isImm()) {
2801321369Sdim    return !isInlineConstant(Inst, OpIdx);
2802360784Sdim  } else if (MO.isReg()) {
2803360784Sdim    auto Reg = MO.getReg();
2804360784Sdim    const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2805360784Sdim    return isSGPR(mc2PseudoReg(Reg), TRI) && Reg != SGPR_NULL;
2806360784Sdim  } else {
2807360784Sdim    return true;
2808321369Sdim  }
2809321369Sdim}
2810321369Sdim
2811321369Sdimbool AMDGPUAsmParser::validateConstantBusLimitations(const MCInst &Inst) {
2812321369Sdim  const unsigned Opcode = Inst.getOpcode();
2813321369Sdim  const MCInstrDesc &Desc = MII.get(Opcode);
2814321369Sdim  unsigned ConstantBusUseCount = 0;
2815353358Sdim  unsigned NumLiterals = 0;
2816353358Sdim  unsigned LiteralSize;
2817321369Sdim
2818321369Sdim  if (Desc.TSFlags &
2819321369Sdim      (SIInstrFlags::VOPC |
2820321369Sdim       SIInstrFlags::VOP1 | SIInstrFlags::VOP2 |
2821321369Sdim       SIInstrFlags::VOP3 | SIInstrFlags::VOP3P |
2822321369Sdim       SIInstrFlags::SDWA)) {
2823321369Sdim    // Check special imm operands (used by madmk, etc)
2824321369Sdim    if (AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm) != -1) {
2825321369Sdim      ++ConstantBusUseCount;
2826321369Sdim    }
2827321369Sdim
2828353358Sdim    SmallDenseSet<unsigned> SGPRsUsed;
2829321369Sdim    unsigned SGPRUsed = findImplicitSGPRReadInVOP(Inst);
2830321369Sdim    if (SGPRUsed != AMDGPU::NoRegister) {
2831353358Sdim      SGPRsUsed.insert(SGPRUsed);
2832321369Sdim      ++ConstantBusUseCount;
2833321369Sdim    }
2834321369Sdim
2835321369Sdim    const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2836321369Sdim    const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2837321369Sdim    const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2838321369Sdim
2839321369Sdim    const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2840321369Sdim
2841321369Sdim    for (int OpIdx : OpIndices) {
2842321369Sdim      if (OpIdx == -1) break;
2843321369Sdim
2844321369Sdim      const MCOperand &MO = Inst.getOperand(OpIdx);
2845321369Sdim      if (usesConstantBus(Inst, OpIdx)) {
2846321369Sdim        if (MO.isReg()) {
2847321369Sdim          const unsigned Reg = mc2PseudoReg(MO.getReg());
2848321369Sdim          // Pairs of registers with a partial intersections like these
2849321369Sdim          //   s0, s[0:1]
2850321369Sdim          //   flat_scratch_lo, flat_scratch
2851321369Sdim          //   flat_scratch_lo, flat_scratch_hi
2852321369Sdim          // are theoretically valid but they are disabled anyway.
2853321369Sdim          // Note that this code mimics SIInstrInfo::verifyInstruction
2854353358Sdim          if (!SGPRsUsed.count(Reg)) {
2855353358Sdim            SGPRsUsed.insert(Reg);
2856321369Sdim            ++ConstantBusUseCount;
2857321369Sdim          }
2858321369Sdim        } else { // Expression or a literal
2859353358Sdim
2860353358Sdim          if (Desc.OpInfo[OpIdx].OperandType == MCOI::OPERAND_IMMEDIATE)
2861353358Sdim            continue; // special operand like VINTERP attr_chan
2862353358Sdim
2863353358Sdim          // An instruction may use only one literal.
2864353358Sdim          // This has been validated on the previous step.
2865353358Sdim          // See validateVOP3Literal.
2866353358Sdim          // This literal may be used as more than one operand.
2867353358Sdim          // If all these operands are of the same size,
2868353358Sdim          // this literal counts as one scalar value.
2869353358Sdim          // Otherwise it counts as 2 scalar values.
2870353358Sdim          // See "GFX10 Shader Programming", section 3.6.2.3.
2871353358Sdim
2872353358Sdim          unsigned Size = AMDGPU::getOperandSize(Desc, OpIdx);
2873353358Sdim          if (Size < 4) Size = 4;
2874353358Sdim
2875353358Sdim          if (NumLiterals == 0) {
2876353358Sdim            NumLiterals = 1;
2877353358Sdim            LiteralSize = Size;
2878353358Sdim          } else if (LiteralSize != Size) {
2879353358Sdim            NumLiterals = 2;
2880353358Sdim          }
2881321369Sdim        }
2882321369Sdim      }
2883321369Sdim    }
2884321369Sdim  }
2885353358Sdim  ConstantBusUseCount += NumLiterals;
2886321369Sdim
2887360784Sdim  return ConstantBusUseCount <= getConstantBusLimit(Opcode);
2888321369Sdim}
2889321369Sdim
2890321369Sdimbool AMDGPUAsmParser::validateEarlyClobberLimitations(const MCInst &Inst) {
2891321369Sdim  const unsigned Opcode = Inst.getOpcode();
2892321369Sdim  const MCInstrDesc &Desc = MII.get(Opcode);
2893321369Sdim
2894321369Sdim  const int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);
2895321369Sdim  if (DstIdx == -1 ||
2896321369Sdim      Desc.getOperandConstraint(DstIdx, MCOI::EARLY_CLOBBER) == -1) {
2897321369Sdim    return true;
2898321369Sdim  }
2899321369Sdim
2900321369Sdim  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
2901321369Sdim
2902321369Sdim  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
2903321369Sdim  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
2904321369Sdim  const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
2905321369Sdim
2906321369Sdim  assert(DstIdx != -1);
2907321369Sdim  const MCOperand &Dst = Inst.getOperand(DstIdx);
2908321369Sdim  assert(Dst.isReg());
2909321369Sdim  const unsigned DstReg = mc2PseudoReg(Dst.getReg());
2910321369Sdim
2911321369Sdim  const int SrcIndices[] = { Src0Idx, Src1Idx, Src2Idx };
2912321369Sdim
2913321369Sdim  for (int SrcIdx : SrcIndices) {
2914321369Sdim    if (SrcIdx == -1) break;
2915321369Sdim    const MCOperand &Src = Inst.getOperand(SrcIdx);
2916321369Sdim    if (Src.isReg()) {
2917321369Sdim      const unsigned SrcReg = mc2PseudoReg(Src.getReg());
2918321369Sdim      if (isRegIntersect(DstReg, SrcReg, TRI)) {
2919321369Sdim        return false;
2920321369Sdim      }
2921321369Sdim    }
2922321369Sdim  }
2923321369Sdim
2924321369Sdim  return true;
2925321369Sdim}
2926321369Sdim
2927327952Sdimbool AMDGPUAsmParser::validateIntClampSupported(const MCInst &Inst) {
2928327952Sdim
2929327952Sdim  const unsigned Opc = Inst.getOpcode();
2930327952Sdim  const MCInstrDesc &Desc = MII.get(Opc);
2931327952Sdim
2932327952Sdim  if ((Desc.TSFlags & SIInstrFlags::IntClamp) != 0 && !hasIntClamp()) {
2933327952Sdim    int ClampIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp);
2934327952Sdim    assert(ClampIdx != -1);
2935327952Sdim    return Inst.getOperand(ClampIdx).getImm() == 0;
2936327952Sdim  }
2937327952Sdim
2938327952Sdim  return true;
2939327952Sdim}
2940327952Sdim
2941341825Sdimbool AMDGPUAsmParser::validateMIMGDataSize(const MCInst &Inst) {
2942341825Sdim
2943341825Sdim  const unsigned Opc = Inst.getOpcode();
2944341825Sdim  const MCInstrDesc &Desc = MII.get(Opc);
2945341825Sdim
2946341825Sdim  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
2947341825Sdim    return true;
2948341825Sdim
2949341825Sdim  int VDataIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
2950341825Sdim  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
2951341825Sdim  int TFEIdx   = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::tfe);
2952341825Sdim
2953341825Sdim  assert(VDataIdx != -1);
2954341825Sdim  assert(DMaskIdx != -1);
2955341825Sdim  assert(TFEIdx != -1);
2956341825Sdim
2957341825Sdim  unsigned VDataSize = AMDGPU::getRegOperandSize(getMRI(), Desc, VDataIdx);
2958341825Sdim  unsigned TFESize = Inst.getOperand(TFEIdx).getImm()? 1 : 0;
2959341825Sdim  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
2960341825Sdim  if (DMask == 0)
2961341825Sdim    DMask = 1;
2962341825Sdim
2963341825Sdim  unsigned DataSize =
2964341825Sdim    (Desc.TSFlags & SIInstrFlags::Gather4) ? 4 : countPopulation(DMask);
2965341825Sdim  if (hasPackedD16()) {
2966341825Sdim    int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
2967341825Sdim    if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm())
2968341825Sdim      DataSize = (DataSize + 1) / 2;
2969341825Sdim  }
2970341825Sdim
2971341825Sdim  return (VDataSize / 4) == DataSize + TFESize;
2972341825Sdim}
2973341825Sdim
2974353358Sdimbool AMDGPUAsmParser::validateMIMGAddrSize(const MCInst &Inst) {
2975353358Sdim  const unsigned Opc = Inst.getOpcode();
2976353358Sdim  const MCInstrDesc &Desc = MII.get(Opc);
2977353358Sdim
2978353358Sdim  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0 || !isGFX10())
2979353358Sdim    return true;
2980353358Sdim
2981353358Sdim  const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc);
2982353358Sdim  const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
2983353358Sdim      AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
2984353358Sdim  int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
2985353358Sdim  int SrsrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
2986353358Sdim  int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
2987353358Sdim
2988353358Sdim  assert(VAddr0Idx != -1);
2989353358Sdim  assert(SrsrcIdx != -1);
2990353358Sdim  assert(DimIdx != -1);
2991353358Sdim  assert(SrsrcIdx > VAddr0Idx);
2992353358Sdim
2993353358Sdim  unsigned Dim = Inst.getOperand(DimIdx).getImm();
2994353358Sdim  const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByEncoding(Dim);
2995353358Sdim  bool IsNSA = SrsrcIdx - VAddr0Idx > 1;
2996353358Sdim  unsigned VAddrSize =
2997353358Sdim      IsNSA ? SrsrcIdx - VAddr0Idx
2998353358Sdim            : AMDGPU::getRegOperandSize(getMRI(), Desc, VAddr0Idx) / 4;
2999353358Sdim
3000353358Sdim  unsigned AddrSize = BaseOpcode->NumExtraArgs +
3001353358Sdim                      (BaseOpcode->Gradients ? DimInfo->NumGradients : 0) +
3002353358Sdim                      (BaseOpcode->Coordinates ? DimInfo->NumCoords : 0) +
3003353358Sdim                      (BaseOpcode->LodOrClampOrMip ? 1 : 0);
3004353358Sdim  if (!IsNSA) {
3005353358Sdim    if (AddrSize > 8)
3006353358Sdim      AddrSize = 16;
3007353358Sdim    else if (AddrSize > 4)
3008353358Sdim      AddrSize = 8;
3009353358Sdim  }
3010353358Sdim
3011353358Sdim  return VAddrSize == AddrSize;
3012353358Sdim}
3013353358Sdim
3014341825Sdimbool AMDGPUAsmParser::validateMIMGAtomicDMask(const MCInst &Inst) {
3015341825Sdim
3016341825Sdim  const unsigned Opc = Inst.getOpcode();
3017341825Sdim  const MCInstrDesc &Desc = MII.get(Opc);
3018341825Sdim
3019341825Sdim  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
3020341825Sdim    return true;
3021341825Sdim  if (!Desc.mayLoad() || !Desc.mayStore())
3022341825Sdim    return true; // Not atomic
3023341825Sdim
3024341825Sdim  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
3025341825Sdim  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
3026341825Sdim
3027341825Sdim  // This is an incomplete check because image_atomic_cmpswap
3028341825Sdim  // may only use 0x3 and 0xf while other atomic operations
3029341825Sdim  // may use 0x1 and 0x3. However these limitations are
3030341825Sdim  // verified when we check that dmask matches dst size.
3031341825Sdim  return DMask == 0x1 || DMask == 0x3 || DMask == 0xf;
3032341825Sdim}
3033341825Sdim
3034341825Sdimbool AMDGPUAsmParser::validateMIMGGatherDMask(const MCInst &Inst) {
3035341825Sdim
3036341825Sdim  const unsigned Opc = Inst.getOpcode();
3037341825Sdim  const MCInstrDesc &Desc = MII.get(Opc);
3038341825Sdim
3039341825Sdim  if ((Desc.TSFlags & SIInstrFlags::Gather4) == 0)
3040341825Sdim    return true;
3041341825Sdim
3042341825Sdim  int DMaskIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dmask);
3043341825Sdim  unsigned DMask = Inst.getOperand(DMaskIdx).getImm() & 0xf;
3044341825Sdim
3045341825Sdim  // GATHER4 instructions use dmask in a different fashion compared to
3046341825Sdim  // other MIMG instructions. The only useful DMASK values are
3047341825Sdim  // 1=red, 2=green, 4=blue, 8=alpha. (e.g. 1 returns
3048341825Sdim  // (red,red,red,red) etc.) The ISA document doesn't mention
3049341825Sdim  // this.
3050341825Sdim  return DMask == 0x1 || DMask == 0x2 || DMask == 0x4 || DMask == 0x8;
3051341825Sdim}
3052341825Sdim
3053360784Sdimstatic bool IsMovrelsSDWAOpcode(const unsigned Opcode)
3054360784Sdim{
3055360784Sdim  switch (Opcode) {
3056360784Sdim  case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
3057360784Sdim  case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
3058360784Sdim  case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
3059360784Sdim    return true;
3060360784Sdim  default:
3061360784Sdim    return false;
3062360784Sdim  }
3063360784Sdim}
3064360784Sdim
3065360784Sdim// movrels* opcodes should only allow VGPRS as src0.
3066360784Sdim// This is specified in .td description for vop1/vop3,
3067360784Sdim// but sdwa is handled differently. See isSDWAOperand.
3068360784Sdimbool AMDGPUAsmParser::validateMovrels(const MCInst &Inst) {
3069360784Sdim
3070360784Sdim  const unsigned Opc = Inst.getOpcode();
3071360784Sdim  const MCInstrDesc &Desc = MII.get(Opc);
3072360784Sdim
3073360784Sdim  if ((Desc.TSFlags & SIInstrFlags::SDWA) == 0 || !IsMovrelsSDWAOpcode(Opc))
3074360784Sdim    return true;
3075360784Sdim
3076360784Sdim  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
3077360784Sdim  assert(Src0Idx != -1);
3078360784Sdim
3079360784Sdim  const MCOperand &Src0 = Inst.getOperand(Src0Idx);
3080360784Sdim  if (!Src0.isReg())
3081360784Sdim    return false;
3082360784Sdim
3083360784Sdim  auto Reg = Src0.getReg();
3084360784Sdim  const MCRegisterInfo *TRI = getContext().getRegisterInfo();
3085360784Sdim  return !isSGPR(mc2PseudoReg(Reg), TRI);
3086360784Sdim}
3087360784Sdim
3088341825Sdimbool AMDGPUAsmParser::validateMIMGD16(const MCInst &Inst) {
3089341825Sdim
3090341825Sdim  const unsigned Opc = Inst.getOpcode();
3091341825Sdim  const MCInstrDesc &Desc = MII.get(Opc);
3092341825Sdim
3093341825Sdim  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
3094341825Sdim    return true;
3095341825Sdim
3096341825Sdim  int D16Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::d16);
3097341825Sdim  if (D16Idx >= 0 && Inst.getOperand(D16Idx).getImm()) {
3098341825Sdim    if (isCI() || isSI())
3099341825Sdim      return false;
3100341825Sdim  }
3101341825Sdim
3102341825Sdim  return true;
3103341825Sdim}
3104341825Sdim
3105353358Sdimbool AMDGPUAsmParser::validateMIMGDim(const MCInst &Inst) {
3106353358Sdim  const unsigned Opc = Inst.getOpcode();
3107353358Sdim  const MCInstrDesc &Desc = MII.get(Opc);
3108353358Sdim
3109353358Sdim  if ((Desc.TSFlags & SIInstrFlags::MIMG) == 0)
3110353358Sdim    return true;
3111353358Sdim
3112353358Sdim  int DimIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::dim);
3113353358Sdim  if (DimIdx < 0)
3114353358Sdim    return true;
3115353358Sdim
3116353358Sdim  long Imm = Inst.getOperand(DimIdx).getImm();
3117353358Sdim  if (Imm < 0 || Imm >= 8)
3118353358Sdim    return false;
3119353358Sdim
3120353358Sdim  return true;
3121353358Sdim}
3122353358Sdim
3123353358Sdimstatic bool IsRevOpcode(const unsigned Opcode)
3124353358Sdim{
3125353358Sdim  switch (Opcode) {
3126353358Sdim  case AMDGPU::V_SUBREV_F32_e32:
3127353358Sdim  case AMDGPU::V_SUBREV_F32_e64:
3128353358Sdim  case AMDGPU::V_SUBREV_F32_e32_gfx10:
3129353358Sdim  case AMDGPU::V_SUBREV_F32_e32_gfx6_gfx7:
3130353358Sdim  case AMDGPU::V_SUBREV_F32_e32_vi:
3131353358Sdim  case AMDGPU::V_SUBREV_F32_e64_gfx10:
3132353358Sdim  case AMDGPU::V_SUBREV_F32_e64_gfx6_gfx7:
3133353358Sdim  case AMDGPU::V_SUBREV_F32_e64_vi:
3134353358Sdim
3135353358Sdim  case AMDGPU::V_SUBREV_I32_e32:
3136353358Sdim  case AMDGPU::V_SUBREV_I32_e64:
3137353358Sdim  case AMDGPU::V_SUBREV_I32_e32_gfx6_gfx7:
3138353358Sdim  case AMDGPU::V_SUBREV_I32_e64_gfx6_gfx7:
3139353358Sdim
3140353358Sdim  case AMDGPU::V_SUBBREV_U32_e32:
3141353358Sdim  case AMDGPU::V_SUBBREV_U32_e64:
3142353358Sdim  case AMDGPU::V_SUBBREV_U32_e32_gfx6_gfx7:
3143353358Sdim  case AMDGPU::V_SUBBREV_U32_e32_vi:
3144353358Sdim  case AMDGPU::V_SUBBREV_U32_e64_gfx6_gfx7:
3145353358Sdim  case AMDGPU::V_SUBBREV_U32_e64_vi:
3146353358Sdim
3147353358Sdim  case AMDGPU::V_SUBREV_U32_e32:
3148353358Sdim  case AMDGPU::V_SUBREV_U32_e64:
3149353358Sdim  case AMDGPU::V_SUBREV_U32_e32_gfx9:
3150353358Sdim  case AMDGPU::V_SUBREV_U32_e32_vi:
3151353358Sdim  case AMDGPU::V_SUBREV_U32_e64_gfx9:
3152353358Sdim  case AMDGPU::V_SUBREV_U32_e64_vi:
3153353358Sdim
3154353358Sdim  case AMDGPU::V_SUBREV_F16_e32:
3155353358Sdim  case AMDGPU::V_SUBREV_F16_e64:
3156353358Sdim  case AMDGPU::V_SUBREV_F16_e32_gfx10:
3157353358Sdim  case AMDGPU::V_SUBREV_F16_e32_vi:
3158353358Sdim  case AMDGPU::V_SUBREV_F16_e64_gfx10:
3159353358Sdim  case AMDGPU::V_SUBREV_F16_e64_vi:
3160353358Sdim
3161353358Sdim  case AMDGPU::V_SUBREV_U16_e32:
3162353358Sdim  case AMDGPU::V_SUBREV_U16_e64:
3163353358Sdim  case AMDGPU::V_SUBREV_U16_e32_vi:
3164353358Sdim  case AMDGPU::V_SUBREV_U16_e64_vi:
3165353358Sdim
3166353358Sdim  case AMDGPU::V_SUBREV_CO_U32_e32_gfx9:
3167353358Sdim  case AMDGPU::V_SUBREV_CO_U32_e64_gfx10:
3168353358Sdim  case AMDGPU::V_SUBREV_CO_U32_e64_gfx9:
3169353358Sdim
3170353358Sdim  case AMDGPU::V_SUBBREV_CO_U32_e32_gfx9:
3171353358Sdim  case AMDGPU::V_SUBBREV_CO_U32_e64_gfx9:
3172353358Sdim
3173353358Sdim  case AMDGPU::V_SUBREV_NC_U32_e32_gfx10:
3174353358Sdim  case AMDGPU::V_SUBREV_NC_U32_e64_gfx10:
3175353358Sdim
3176353358Sdim  case AMDGPU::V_SUBREV_CO_CI_U32_e32_gfx10:
3177353358Sdim  case AMDGPU::V_SUBREV_CO_CI_U32_e64_gfx10:
3178353358Sdim
3179353358Sdim  case AMDGPU::V_LSHRREV_B32_e32:
3180353358Sdim  case AMDGPU::V_LSHRREV_B32_e64:
3181353358Sdim  case AMDGPU::V_LSHRREV_B32_e32_gfx6_gfx7:
3182353358Sdim  case AMDGPU::V_LSHRREV_B32_e64_gfx6_gfx7:
3183353358Sdim  case AMDGPU::V_LSHRREV_B32_e32_vi:
3184353358Sdim  case AMDGPU::V_LSHRREV_B32_e64_vi:
3185353358Sdim  case AMDGPU::V_LSHRREV_B32_e32_gfx10:
3186353358Sdim  case AMDGPU::V_LSHRREV_B32_e64_gfx10:
3187353358Sdim
3188353358Sdim  case AMDGPU::V_ASHRREV_I32_e32:
3189353358Sdim  case AMDGPU::V_ASHRREV_I32_e64:
3190353358Sdim  case AMDGPU::V_ASHRREV_I32_e32_gfx10:
3191353358Sdim  case AMDGPU::V_ASHRREV_I32_e32_gfx6_gfx7:
3192353358Sdim  case AMDGPU::V_ASHRREV_I32_e32_vi:
3193353358Sdim  case AMDGPU::V_ASHRREV_I32_e64_gfx10:
3194353358Sdim  case AMDGPU::V_ASHRREV_I32_e64_gfx6_gfx7:
3195353358Sdim  case AMDGPU::V_ASHRREV_I32_e64_vi:
3196353358Sdim
3197353358Sdim  case AMDGPU::V_LSHLREV_B32_e32:
3198353358Sdim  case AMDGPU::V_LSHLREV_B32_e64:
3199353358Sdim  case AMDGPU::V_LSHLREV_B32_e32_gfx10:
3200353358Sdim  case AMDGPU::V_LSHLREV_B32_e32_gfx6_gfx7:
3201353358Sdim  case AMDGPU::V_LSHLREV_B32_e32_vi:
3202353358Sdim  case AMDGPU::V_LSHLREV_B32_e64_gfx10:
3203353358Sdim  case AMDGPU::V_LSHLREV_B32_e64_gfx6_gfx7:
3204353358Sdim  case AMDGPU::V_LSHLREV_B32_e64_vi:
3205353358Sdim
3206353358Sdim  case AMDGPU::V_LSHLREV_B16_e32:
3207353358Sdim  case AMDGPU::V_LSHLREV_B16_e64:
3208353358Sdim  case AMDGPU::V_LSHLREV_B16_e32_vi:
3209353358Sdim  case AMDGPU::V_LSHLREV_B16_e64_vi:
3210353358Sdim  case AMDGPU::V_LSHLREV_B16_gfx10:
3211353358Sdim
3212353358Sdim  case AMDGPU::V_LSHRREV_B16_e32:
3213353358Sdim  case AMDGPU::V_LSHRREV_B16_e64:
3214353358Sdim  case AMDGPU::V_LSHRREV_B16_e32_vi:
3215353358Sdim  case AMDGPU::V_LSHRREV_B16_e64_vi:
3216353358Sdim  case AMDGPU::V_LSHRREV_B16_gfx10:
3217353358Sdim
3218353358Sdim  case AMDGPU::V_ASHRREV_I16_e32:
3219353358Sdim  case AMDGPU::V_ASHRREV_I16_e64:
3220353358Sdim  case AMDGPU::V_ASHRREV_I16_e32_vi:
3221353358Sdim  case AMDGPU::V_ASHRREV_I16_e64_vi:
3222353358Sdim  case AMDGPU::V_ASHRREV_I16_gfx10:
3223353358Sdim
3224353358Sdim  case AMDGPU::V_LSHLREV_B64:
3225353358Sdim  case AMDGPU::V_LSHLREV_B64_gfx10:
3226353358Sdim  case AMDGPU::V_LSHLREV_B64_vi:
3227353358Sdim
3228353358Sdim  case AMDGPU::V_LSHRREV_B64:
3229353358Sdim  case AMDGPU::V_LSHRREV_B64_gfx10:
3230353358Sdim  case AMDGPU::V_LSHRREV_B64_vi:
3231353358Sdim
3232353358Sdim  case AMDGPU::V_ASHRREV_I64:
3233353358Sdim  case AMDGPU::V_ASHRREV_I64_gfx10:
3234353358Sdim  case AMDGPU::V_ASHRREV_I64_vi:
3235353358Sdim
3236353358Sdim  case AMDGPU::V_PK_LSHLREV_B16:
3237353358Sdim  case AMDGPU::V_PK_LSHLREV_B16_gfx10:
3238353358Sdim  case AMDGPU::V_PK_LSHLREV_B16_vi:
3239353358Sdim
3240353358Sdim  case AMDGPU::V_PK_LSHRREV_B16:
3241353358Sdim  case AMDGPU::V_PK_LSHRREV_B16_gfx10:
3242353358Sdim  case AMDGPU::V_PK_LSHRREV_B16_vi:
3243353358Sdim  case AMDGPU::V_PK_ASHRREV_I16:
3244353358Sdim  case AMDGPU::V_PK_ASHRREV_I16_gfx10:
3245353358Sdim  case AMDGPU::V_PK_ASHRREV_I16_vi:
3246353358Sdim    return true;
3247353358Sdim  default:
3248353358Sdim    return false;
3249353358Sdim  }
3250353358Sdim}
3251353358Sdim
3252353358Sdimbool AMDGPUAsmParser::validateLdsDirect(const MCInst &Inst) {
3253353358Sdim
3254353358Sdim  using namespace SIInstrFlags;
3255353358Sdim  const unsigned Opcode = Inst.getOpcode();
3256353358Sdim  const MCInstrDesc &Desc = MII.get(Opcode);
3257353358Sdim
3258353358Sdim  // lds_direct register is defined so that it can be used
3259353358Sdim  // with 9-bit operands only. Ignore encodings which do not accept these.
3260353358Sdim  if ((Desc.TSFlags & (VOP1 | VOP2 | VOP3 | VOPC | VOP3P | SIInstrFlags::SDWA)) == 0)
3261353358Sdim    return true;
3262353358Sdim
3263353358Sdim  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3264353358Sdim  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3265353358Sdim  const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
3266353358Sdim
3267353358Sdim  const int SrcIndices[] = { Src1Idx, Src2Idx };
3268353358Sdim
3269353358Sdim  // lds_direct cannot be specified as either src1 or src2.
3270353358Sdim  for (int SrcIdx : SrcIndices) {
3271353358Sdim    if (SrcIdx == -1) break;
3272353358Sdim    const MCOperand &Src = Inst.getOperand(SrcIdx);
3273353358Sdim    if (Src.isReg() && Src.getReg() == LDS_DIRECT) {
3274353358Sdim      return false;
3275353358Sdim    }
3276353358Sdim  }
3277353358Sdim
3278353358Sdim  if (Src0Idx == -1)
3279353358Sdim    return true;
3280353358Sdim
3281353358Sdim  const MCOperand &Src = Inst.getOperand(Src0Idx);
3282353358Sdim  if (!Src.isReg() || Src.getReg() != LDS_DIRECT)
3283353358Sdim    return true;
3284353358Sdim
3285353358Sdim  // lds_direct is specified as src0. Check additional limitations.
3286353358Sdim  return (Desc.TSFlags & SIInstrFlags::SDWA) == 0 && !IsRevOpcode(Opcode);
3287353358Sdim}
3288353358Sdim
3289353358SdimSMLoc AMDGPUAsmParser::getFlatOffsetLoc(const OperandVector &Operands) const {
3290353358Sdim  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
3291353358Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
3292353358Sdim    if (Op.isFlatOffset())
3293353358Sdim      return Op.getStartLoc();
3294353358Sdim  }
3295353358Sdim  return getLoc();
3296353358Sdim}
3297353358Sdim
3298353358Sdimbool AMDGPUAsmParser::validateFlatOffset(const MCInst &Inst,
3299353358Sdim                                         const OperandVector &Operands) {
3300353358Sdim  uint64_t TSFlags = MII.get(Inst.getOpcode()).TSFlags;
3301353358Sdim  if ((TSFlags & SIInstrFlags::FLAT) == 0)
3302353358Sdim    return true;
3303353358Sdim
3304353358Sdim  auto Opcode = Inst.getOpcode();
3305353358Sdim  auto OpNum = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::offset);
3306353358Sdim  assert(OpNum != -1);
3307353358Sdim
3308353358Sdim  const auto &Op = Inst.getOperand(OpNum);
3309353358Sdim  if (!hasFlatOffsets() && Op.getImm() != 0) {
3310353358Sdim    Error(getFlatOffsetLoc(Operands),
3311353358Sdim          "flat offset modifier is not supported on this GPU");
3312353358Sdim    return false;
3313353358Sdim  }
3314353358Sdim
3315353358Sdim  // Address offset is 12-bit signed for GFX10, 13-bit for GFX9.
3316353358Sdim  // For FLAT segment the offset must be positive;
3317353358Sdim  // MSB is ignored and forced to zero.
3318353358Sdim  unsigned OffsetSize = isGFX9() ? 13 : 12;
3319353358Sdim  if (TSFlags & SIInstrFlags::IsNonFlatSeg) {
3320353358Sdim    if (!isIntN(OffsetSize, Op.getImm())) {
3321353358Sdim      Error(getFlatOffsetLoc(Operands),
3322353358Sdim            isGFX9() ? "expected a 13-bit signed offset" :
3323353358Sdim                       "expected a 12-bit signed offset");
3324353358Sdim      return false;
3325353358Sdim    }
3326353358Sdim  } else {
3327353358Sdim    if (!isUIntN(OffsetSize - 1, Op.getImm())) {
3328353358Sdim      Error(getFlatOffsetLoc(Operands),
3329353358Sdim            isGFX9() ? "expected a 12-bit unsigned offset" :
3330353358Sdim                       "expected an 11-bit unsigned offset");
3331353358Sdim      return false;
3332353358Sdim    }
3333353358Sdim  }
3334353358Sdim
3335353358Sdim  return true;
3336353358Sdim}
3337353358Sdim
3338353358Sdimbool AMDGPUAsmParser::validateSOPLiteral(const MCInst &Inst) const {
3339353358Sdim  unsigned Opcode = Inst.getOpcode();
3340353358Sdim  const MCInstrDesc &Desc = MII.get(Opcode);
3341353358Sdim  if (!(Desc.TSFlags & (SIInstrFlags::SOP2 | SIInstrFlags::SOPC)))
3342353358Sdim    return true;
3343353358Sdim
3344353358Sdim  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3345353358Sdim  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3346353358Sdim
3347353358Sdim  const int OpIndices[] = { Src0Idx, Src1Idx };
3348353358Sdim
3349360784Sdim  unsigned NumExprs = 0;
3350353358Sdim  unsigned NumLiterals = 0;
3351353358Sdim  uint32_t LiteralValue;
3352353358Sdim
3353353358Sdim  for (int OpIdx : OpIndices) {
3354353358Sdim    if (OpIdx == -1) break;
3355353358Sdim
3356353358Sdim    const MCOperand &MO = Inst.getOperand(OpIdx);
3357360784Sdim    // Exclude special imm operands (like that used by s_set_gpr_idx_on)
3358360784Sdim    if (AMDGPU::isSISrcOperand(Desc, OpIdx)) {
3359360784Sdim      if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) {
3360360784Sdim        uint32_t Value = static_cast<uint32_t>(MO.getImm());
3361360784Sdim        if (NumLiterals == 0 || LiteralValue != Value) {
3362360784Sdim          LiteralValue = Value;
3363360784Sdim          ++NumLiterals;
3364360784Sdim        }
3365360784Sdim      } else if (MO.isExpr()) {
3366360784Sdim        ++NumExprs;
3367353358Sdim      }
3368353358Sdim    }
3369353358Sdim  }
3370353358Sdim
3371360784Sdim  return NumLiterals + NumExprs <= 1;
3372353358Sdim}
3373353358Sdim
3374353358Sdimbool AMDGPUAsmParser::validateOpSel(const MCInst &Inst) {
3375353358Sdim  const unsigned Opc = Inst.getOpcode();
3376353358Sdim  if (Opc == AMDGPU::V_PERMLANE16_B32_gfx10 ||
3377353358Sdim      Opc == AMDGPU::V_PERMLANEX16_B32_gfx10) {
3378353358Sdim    int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
3379353358Sdim    unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
3380353358Sdim
3381353358Sdim    if (OpSel & ~3)
3382353358Sdim      return false;
3383353358Sdim  }
3384353358Sdim  return true;
3385353358Sdim}
3386353358Sdim
3387353358Sdim// Check if VCC register matches wavefront size
3388353358Sdimbool AMDGPUAsmParser::validateVccOperand(unsigned Reg) const {
3389353358Sdim  auto FB = getFeatureBits();
3390353358Sdim  return (FB[AMDGPU::FeatureWavefrontSize64] && Reg == AMDGPU::VCC) ||
3391353358Sdim    (FB[AMDGPU::FeatureWavefrontSize32] && Reg == AMDGPU::VCC_LO);
3392353358Sdim}
3393353358Sdim
3394353358Sdim// VOP3 literal is only allowed in GFX10+ and only one can be used
3395353358Sdimbool AMDGPUAsmParser::validateVOP3Literal(const MCInst &Inst) const {
3396353358Sdim  unsigned Opcode = Inst.getOpcode();
3397353358Sdim  const MCInstrDesc &Desc = MII.get(Opcode);
3398353358Sdim  if (!(Desc.TSFlags & (SIInstrFlags::VOP3 | SIInstrFlags::VOP3P)))
3399353358Sdim    return true;
3400353358Sdim
3401353358Sdim  const int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
3402353358Sdim  const int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
3403353358Sdim  const int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
3404353358Sdim
3405353358Sdim  const int OpIndices[] = { Src0Idx, Src1Idx, Src2Idx };
3406353358Sdim
3407360784Sdim  unsigned NumExprs = 0;
3408353358Sdim  unsigned NumLiterals = 0;
3409353358Sdim  uint32_t LiteralValue;
3410353358Sdim
3411353358Sdim  for (int OpIdx : OpIndices) {
3412353358Sdim    if (OpIdx == -1) break;
3413353358Sdim
3414353358Sdim    const MCOperand &MO = Inst.getOperand(OpIdx);
3415360784Sdim    if (!MO.isImm() && !MO.isExpr())
3416353358Sdim      continue;
3417360784Sdim    if (!AMDGPU::isSISrcOperand(Desc, OpIdx))
3418360784Sdim      continue;
3419353358Sdim
3420360784Sdim    if (OpIdx == Src2Idx && (Desc.TSFlags & SIInstrFlags::IsMAI) &&
3421360784Sdim        getFeatureBits()[AMDGPU::FeatureMFMAInlineLiteralBug])
3422360784Sdim      return false;
3423360784Sdim
3424360784Sdim    if (MO.isImm() && !isInlineConstant(Inst, OpIdx)) {
3425353358Sdim      uint32_t Value = static_cast<uint32_t>(MO.getImm());
3426353358Sdim      if (NumLiterals == 0 || LiteralValue != Value) {
3427353358Sdim        LiteralValue = Value;
3428353358Sdim        ++NumLiterals;
3429353358Sdim      }
3430360784Sdim    } else if (MO.isExpr()) {
3431360784Sdim      ++NumExprs;
3432353358Sdim    }
3433353358Sdim  }
3434360784Sdim  NumLiterals += NumExprs;
3435353358Sdim
3436353358Sdim  return !NumLiterals ||
3437353358Sdim         (NumLiterals == 1 && getFeatureBits()[AMDGPU::FeatureVOP3Literal]);
3438353358Sdim}
3439353358Sdim
3440321369Sdimbool AMDGPUAsmParser::validateInstruction(const MCInst &Inst,
3441353358Sdim                                          const SMLoc &IDLoc,
3442353358Sdim                                          const OperandVector &Operands) {
3443353358Sdim  if (!validateLdsDirect(Inst)) {
3444353358Sdim    Error(IDLoc,
3445353358Sdim      "invalid use of lds_direct");
3446353358Sdim    return false;
3447353358Sdim  }
3448353358Sdim  if (!validateSOPLiteral(Inst)) {
3449353358Sdim    Error(IDLoc,
3450353358Sdim      "only one literal operand is allowed");
3451353358Sdim    return false;
3452353358Sdim  }
3453353358Sdim  if (!validateVOP3Literal(Inst)) {
3454353358Sdim    Error(IDLoc,
3455353358Sdim      "invalid literal operand");
3456353358Sdim    return false;
3457353358Sdim  }
3458321369Sdim  if (!validateConstantBusLimitations(Inst)) {
3459321369Sdim    Error(IDLoc,
3460321369Sdim      "invalid operand (violates constant bus restrictions)");
3461321369Sdim    return false;
3462321369Sdim  }
3463321369Sdim  if (!validateEarlyClobberLimitations(Inst)) {
3464321369Sdim    Error(IDLoc,
3465321369Sdim      "destination must be different than all sources");
3466321369Sdim    return false;
3467321369Sdim  }
3468327952Sdim  if (!validateIntClampSupported(Inst)) {
3469327952Sdim    Error(IDLoc,
3470327952Sdim      "integer clamping is not supported on this GPU");
3471327952Sdim    return false;
3472327952Sdim  }
3473353358Sdim  if (!validateOpSel(Inst)) {
3474353358Sdim    Error(IDLoc,
3475353358Sdim      "invalid op_sel operand");
3476353358Sdim    return false;
3477353358Sdim  }
3478341825Sdim  // For MUBUF/MTBUF d16 is a part of opcode, so there is nothing to validate.
3479341825Sdim  if (!validateMIMGD16(Inst)) {
3480341825Sdim    Error(IDLoc,
3481341825Sdim      "d16 modifier is not supported on this GPU");
3482341825Sdim    return false;
3483341825Sdim  }
3484353358Sdim  if (!validateMIMGDim(Inst)) {
3485353358Sdim    Error(IDLoc, "dim modifier is required on this GPU");
3486353358Sdim    return false;
3487353358Sdim  }
3488341825Sdim  if (!validateMIMGDataSize(Inst)) {
3489341825Sdim    Error(IDLoc,
3490341825Sdim      "image data size does not match dmask and tfe");
3491341825Sdim    return false;
3492341825Sdim  }
3493353358Sdim  if (!validateMIMGAddrSize(Inst)) {
3494353358Sdim    Error(IDLoc,
3495353358Sdim      "image address size does not match dim and a16");
3496353358Sdim    return false;
3497353358Sdim  }
3498341825Sdim  if (!validateMIMGAtomicDMask(Inst)) {
3499341825Sdim    Error(IDLoc,
3500341825Sdim      "invalid atomic image dmask");
3501341825Sdim    return false;
3502341825Sdim  }
3503341825Sdim  if (!validateMIMGGatherDMask(Inst)) {
3504341825Sdim    Error(IDLoc,
3505341825Sdim      "invalid image_gather dmask: only one bit must be set");
3506341825Sdim    return false;
3507341825Sdim  }
3508360784Sdim  if (!validateMovrels(Inst)) {
3509360784Sdim    Error(IDLoc, "source operand must be a VGPR");
3510360784Sdim    return false;
3511360784Sdim  }
3512353358Sdim  if (!validateFlatOffset(Inst, Operands)) {
3513353358Sdim    return false;
3514353358Sdim  }
3515321369Sdim
3516321369Sdim  return true;
3517321369Sdim}
3518321369Sdim
3519353358Sdimstatic std::string AMDGPUMnemonicSpellCheck(StringRef S,
3520353358Sdim                                            const FeatureBitset &FBS,
3521327952Sdim                                            unsigned VariantID = 0);
3522327952Sdim
3523284677Sdimbool AMDGPUAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3524284677Sdim                                              OperandVector &Operands,
3525284677Sdim                                              MCStreamer &Out,
3526284677Sdim                                              uint64_t &ErrorInfo,
3527284677Sdim                                              bool MatchingInlineAsm) {
3528284677Sdim  MCInst Inst;
3529314564Sdim  unsigned Result = Match_Success;
3530314564Sdim  for (auto Variant : getMatchedVariants()) {
3531314564Sdim    uint64_t EI;
3532314564Sdim    auto R = MatchInstructionImpl(Operands, Inst, EI, MatchingInlineAsm,
3533314564Sdim                                  Variant);
3534314564Sdim    // We order match statuses from least to most specific. We use most specific
3535314564Sdim    // status as resulting
3536314564Sdim    // Match_MnemonicFail < Match_InvalidOperand < Match_MissingFeature < Match_PreferE32
3537314564Sdim    if ((R == Match_Success) ||
3538314564Sdim        (R == Match_PreferE32) ||
3539314564Sdim        (R == Match_MissingFeature && Result != Match_PreferE32) ||
3540314564Sdim        (R == Match_InvalidOperand && Result != Match_MissingFeature
3541314564Sdim                                   && Result != Match_PreferE32) ||
3542314564Sdim        (R == Match_MnemonicFail   && Result != Match_InvalidOperand
3543314564Sdim                                   && Result != Match_MissingFeature
3544314564Sdim                                   && Result != Match_PreferE32)) {
3545314564Sdim      Result = R;
3546314564Sdim      ErrorInfo = EI;
3547314564Sdim    }
3548314564Sdim    if (R == Match_Success)
3549314564Sdim      break;
3550314564Sdim  }
3551284677Sdim
3552314564Sdim  switch (Result) {
3553314564Sdim  default: break;
3554314564Sdim  case Match_Success:
3555353358Sdim    if (!validateInstruction(Inst, IDLoc, Operands)) {
3556321369Sdim      return true;
3557321369Sdim    }
3558314564Sdim    Inst.setLoc(IDLoc);
3559314564Sdim    Out.EmitInstruction(Inst, getSTI());
3560314564Sdim    return false;
3561284677Sdim
3562314564Sdim  case Match_MissingFeature:
3563314564Sdim    return Error(IDLoc, "instruction not supported on this GPU");
3564284677Sdim
3565327952Sdim  case Match_MnemonicFail: {
3566353358Sdim    FeatureBitset FBS = ComputeAvailableFeatures(getSTI().getFeatureBits());
3567327952Sdim    std::string Suggestion = AMDGPUMnemonicSpellCheck(
3568327952Sdim        ((AMDGPUOperand &)*Operands[0]).getToken(), FBS);
3569327952Sdim    return Error(IDLoc, "invalid instruction" + Suggestion,
3570327952Sdim                 ((AMDGPUOperand &)*Operands[0]).getLocRange());
3571327952Sdim  }
3572314564Sdim
3573314564Sdim  case Match_InvalidOperand: {
3574314564Sdim    SMLoc ErrorLoc = IDLoc;
3575314564Sdim    if (ErrorInfo != ~0ULL) {
3576314564Sdim      if (ErrorInfo >= Operands.size()) {
3577314564Sdim        return Error(IDLoc, "too few operands for instruction");
3578284677Sdim      }
3579314564Sdim      ErrorLoc = ((AMDGPUOperand &)*Operands[ErrorInfo]).getStartLoc();
3580314564Sdim      if (ErrorLoc == SMLoc())
3581314564Sdim        ErrorLoc = IDLoc;
3582284677Sdim    }
3583314564Sdim    return Error(ErrorLoc, "invalid operand for instruction");
3584284677Sdim  }
3585314564Sdim
3586314564Sdim  case Match_PreferE32:
3587314564Sdim    return Error(IDLoc, "internal error: instruction without _e64 suffix "
3588314564Sdim                        "should be encoded as e32");
3589314564Sdim  }
3590284677Sdim  llvm_unreachable("Implement any new match types added!");
3591284677Sdim}
3592284677Sdim
3593314564Sdimbool AMDGPUAsmParser::ParseAsAbsoluteExpression(uint32_t &Ret) {
3594314564Sdim  int64_t Tmp = -1;
3595314564Sdim  if (getLexer().isNot(AsmToken::Integer) && getLexer().isNot(AsmToken::Identifier)) {
3596314564Sdim    return true;
3597314564Sdim  }
3598314564Sdim  if (getParser().parseAbsoluteExpression(Tmp)) {
3599314564Sdim    return true;
3600314564Sdim  }
3601314564Sdim  Ret = static_cast<uint32_t>(Tmp);
3602314564Sdim  return false;
3603314564Sdim}
3604314564Sdim
3605285181Sdimbool AMDGPUAsmParser::ParseDirectiveMajorMinor(uint32_t &Major,
3606285181Sdim                                               uint32_t &Minor) {
3607314564Sdim  if (ParseAsAbsoluteExpression(Major))
3608285181Sdim    return TokError("invalid major version");
3609285181Sdim
3610285181Sdim  if (getLexer().isNot(AsmToken::Comma))
3611285181Sdim    return TokError("minor version number required, comma expected");
3612285181Sdim  Lex();
3613285181Sdim
3614314564Sdim  if (ParseAsAbsoluteExpression(Minor))
3615285181Sdim    return TokError("invalid minor version");
3616285181Sdim
3617285181Sdim  return false;
3618285181Sdim}
3619285181Sdim
3620341825Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGCNTarget() {
3621341825Sdim  if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3622341825Sdim    return TokError("directive only supported for amdgcn architecture");
3623341825Sdim
3624341825Sdim  std::string Target;
3625341825Sdim
3626341825Sdim  SMLoc TargetStart = getTok().getLoc();
3627341825Sdim  if (getParser().parseEscapedString(Target))
3628341825Sdim    return true;
3629341825Sdim  SMRange TargetRange = SMRange(TargetStart, getTok().getLoc());
3630341825Sdim
3631341825Sdim  std::string ExpectedTarget;
3632341825Sdim  raw_string_ostream ExpectedTargetOS(ExpectedTarget);
3633341825Sdim  IsaInfo::streamIsaVersion(&getSTI(), ExpectedTargetOS);
3634341825Sdim
3635341825Sdim  if (Target != ExpectedTargetOS.str())
3636341825Sdim    return getParser().Error(TargetRange.Start, "target must match options",
3637341825Sdim                             TargetRange);
3638341825Sdim
3639341825Sdim  getTargetStreamer().EmitDirectiveAMDGCNTarget(Target);
3640341825Sdim  return false;
3641341825Sdim}
3642341825Sdim
3643341825Sdimbool AMDGPUAsmParser::OutOfRangeError(SMRange Range) {
3644341825Sdim  return getParser().Error(Range.Start, "value out of range", Range);
3645341825Sdim}
3646341825Sdim
3647341825Sdimbool AMDGPUAsmParser::calculateGPRBlocks(
3648341825Sdim    const FeatureBitset &Features, bool VCCUsed, bool FlatScrUsed,
3649353358Sdim    bool XNACKUsed, Optional<bool> EnableWavefrontSize32, unsigned NextFreeVGPR,
3650353358Sdim    SMRange VGPRRange, unsigned NextFreeSGPR, SMRange SGPRRange,
3651353358Sdim    unsigned &VGPRBlocks, unsigned &SGPRBlocks) {
3652341825Sdim  // TODO(scott.linder): These calculations are duplicated from
3653341825Sdim  // AMDGPUAsmPrinter::getSIProgramInfo and could be unified.
3654344779Sdim  IsaVersion Version = getIsaVersion(getSTI().getCPU());
3655341825Sdim
3656341825Sdim  unsigned NumVGPRs = NextFreeVGPR;
3657341825Sdim  unsigned NumSGPRs = NextFreeSGPR;
3658341825Sdim
3659353358Sdim  if (Version.Major >= 10)
3660353358Sdim    NumSGPRs = 0;
3661353358Sdim  else {
3662353358Sdim    unsigned MaxAddressableNumSGPRs =
3663353358Sdim        IsaInfo::getAddressableNumSGPRs(&getSTI());
3664341825Sdim
3665353358Sdim    if (Version.Major >= 8 && !Features.test(FeatureSGPRInitBug) &&
3666353358Sdim        NumSGPRs > MaxAddressableNumSGPRs)
3667353358Sdim      return OutOfRangeError(SGPRRange);
3668341825Sdim
3669353358Sdim    NumSGPRs +=
3670353358Sdim        IsaInfo::getNumExtraSGPRs(&getSTI(), VCCUsed, FlatScrUsed, XNACKUsed);
3671341825Sdim
3672353358Sdim    if ((Version.Major <= 7 || Features.test(FeatureSGPRInitBug)) &&
3673353358Sdim        NumSGPRs > MaxAddressableNumSGPRs)
3674353358Sdim      return OutOfRangeError(SGPRRange);
3675341825Sdim
3676353358Sdim    if (Features.test(FeatureSGPRInitBug))
3677353358Sdim      NumSGPRs = IsaInfo::FIXED_NUM_SGPRS_FOR_INIT_BUG;
3678353358Sdim  }
3679353358Sdim
3680353358Sdim  VGPRBlocks =
3681353358Sdim      IsaInfo::getNumVGPRBlocks(&getSTI(), NumVGPRs, EnableWavefrontSize32);
3682344779Sdim  SGPRBlocks = IsaInfo::getNumSGPRBlocks(&getSTI(), NumSGPRs);
3683341825Sdim
3684341825Sdim  return false;
3685341825Sdim}
3686341825Sdim
3687341825Sdimbool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() {
3688341825Sdim  if (getSTI().getTargetTriple().getArch() != Triple::amdgcn)
3689341825Sdim    return TokError("directive only supported for amdgcn architecture");
3690341825Sdim
3691341825Sdim  if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA)
3692341825Sdim    return TokError("directive only supported for amdhsa OS");
3693341825Sdim
3694341825Sdim  StringRef KernelName;
3695341825Sdim  if (getParser().parseIdentifier(KernelName))
3696341825Sdim    return true;
3697341825Sdim
3698353358Sdim  kernel_descriptor_t KD = getDefaultAmdhsaKernelDescriptor(&getSTI());
3699341825Sdim
3700341825Sdim  StringSet<> Seen;
3701341825Sdim
3702344779Sdim  IsaVersion IVersion = getIsaVersion(getSTI().getCPU());
3703341825Sdim
3704341825Sdim  SMRange VGPRRange;
3705341825Sdim  uint64_t NextFreeVGPR = 0;
3706341825Sdim  SMRange SGPRRange;
3707341825Sdim  uint64_t NextFreeSGPR = 0;
3708341825Sdim  unsigned UserSGPRCount = 0;
3709341825Sdim  bool ReserveVCC = true;
3710341825Sdim  bool ReserveFlatScr = true;
3711341825Sdim  bool ReserveXNACK = hasXNACK();
3712353358Sdim  Optional<bool> EnableWavefrontSize32;
3713341825Sdim
3714341825Sdim  while (true) {
3715341825Sdim    while (getLexer().is(AsmToken::EndOfStatement))
3716341825Sdim      Lex();
3717341825Sdim
3718341825Sdim    if (getLexer().isNot(AsmToken::Identifier))
3719341825Sdim      return TokError("expected .amdhsa_ directive or .end_amdhsa_kernel");
3720341825Sdim
3721341825Sdim    StringRef ID = getTok().getIdentifier();
3722341825Sdim    SMRange IDRange = getTok().getLocRange();
3723341825Sdim    Lex();
3724341825Sdim
3725341825Sdim    if (ID == ".end_amdhsa_kernel")
3726341825Sdim      break;
3727341825Sdim
3728341825Sdim    if (Seen.find(ID) != Seen.end())
3729341825Sdim      return TokError(".amdhsa_ directives cannot be repeated");
3730341825Sdim    Seen.insert(ID);
3731341825Sdim
3732341825Sdim    SMLoc ValStart = getTok().getLoc();
3733341825Sdim    int64_t IVal;
3734341825Sdim    if (getParser().parseAbsoluteExpression(IVal))
3735341825Sdim      return true;
3736341825Sdim    SMLoc ValEnd = getTok().getLoc();
3737341825Sdim    SMRange ValRange = SMRange(ValStart, ValEnd);
3738341825Sdim
3739341825Sdim    if (IVal < 0)
3740341825Sdim      return OutOfRangeError(ValRange);
3741341825Sdim
3742341825Sdim    uint64_t Val = IVal;
3743341825Sdim
3744341825Sdim#define PARSE_BITS_ENTRY(FIELD, ENTRY, VALUE, RANGE)                           \
3745341825Sdim  if (!isUInt<ENTRY##_WIDTH>(VALUE))                                           \
3746341825Sdim    return OutOfRangeError(RANGE);                                             \
3747341825Sdim  AMDHSA_BITS_SET(FIELD, ENTRY, VALUE);
3748341825Sdim
3749341825Sdim    if (ID == ".amdhsa_group_segment_fixed_size") {
3750341825Sdim      if (!isUInt<sizeof(KD.group_segment_fixed_size) * CHAR_BIT>(Val))
3751341825Sdim        return OutOfRangeError(ValRange);
3752341825Sdim      KD.group_segment_fixed_size = Val;
3753341825Sdim    } else if (ID == ".amdhsa_private_segment_fixed_size") {
3754341825Sdim      if (!isUInt<sizeof(KD.private_segment_fixed_size) * CHAR_BIT>(Val))
3755341825Sdim        return OutOfRangeError(ValRange);
3756341825Sdim      KD.private_segment_fixed_size = Val;
3757341825Sdim    } else if (ID == ".amdhsa_user_sgpr_private_segment_buffer") {
3758341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3759341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER,
3760341825Sdim                       Val, ValRange);
3761360784Sdim      if (Val)
3762360784Sdim        UserSGPRCount += 4;
3763341825Sdim    } else if (ID == ".amdhsa_user_sgpr_dispatch_ptr") {
3764341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3765341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR, Val,
3766341825Sdim                       ValRange);
3767360784Sdim      if (Val)
3768360784Sdim        UserSGPRCount += 2;
3769341825Sdim    } else if (ID == ".amdhsa_user_sgpr_queue_ptr") {
3770341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3771341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR, Val,
3772341825Sdim                       ValRange);
3773360784Sdim      if (Val)
3774360784Sdim        UserSGPRCount += 2;
3775341825Sdim    } else if (ID == ".amdhsa_user_sgpr_kernarg_segment_ptr") {
3776341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3777341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR,
3778341825Sdim                       Val, ValRange);
3779360784Sdim      if (Val)
3780360784Sdim        UserSGPRCount += 2;
3781341825Sdim    } else if (ID == ".amdhsa_user_sgpr_dispatch_id") {
3782341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3783341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID, Val,
3784341825Sdim                       ValRange);
3785360784Sdim      if (Val)
3786360784Sdim        UserSGPRCount += 2;
3787341825Sdim    } else if (ID == ".amdhsa_user_sgpr_flat_scratch_init") {
3788341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3789341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT, Val,
3790341825Sdim                       ValRange);
3791360784Sdim      if (Val)
3792360784Sdim        UserSGPRCount += 2;
3793341825Sdim    } else if (ID == ".amdhsa_user_sgpr_private_segment_size") {
3794341825Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3795341825Sdim                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE,
3796341825Sdim                       Val, ValRange);
3797360784Sdim      if (Val)
3798360784Sdim        UserSGPRCount += 1;
3799353358Sdim    } else if (ID == ".amdhsa_wavefront_size32") {
3800353358Sdim      if (IVersion.Major < 10)
3801353358Sdim        return getParser().Error(IDRange.Start, "directive requires gfx10+",
3802353358Sdim                                 IDRange);
3803353358Sdim      EnableWavefrontSize32 = Val;
3804353358Sdim      PARSE_BITS_ENTRY(KD.kernel_code_properties,
3805353358Sdim                       KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32,
3806353358Sdim                       Val, ValRange);
3807341825Sdim    } else if (ID == ".amdhsa_system_sgpr_private_segment_wavefront_offset") {
3808341825Sdim      PARSE_BITS_ENTRY(
3809341825Sdim          KD.compute_pgm_rsrc2,
3810341825Sdim          COMPUTE_PGM_RSRC2_ENABLE_SGPR_PRIVATE_SEGMENT_WAVEFRONT_OFFSET, Val,
3811341825Sdim          ValRange);
3812341825Sdim    } else if (ID == ".amdhsa_system_sgpr_workgroup_id_x") {
3813341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3814341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X, Val,
3815341825Sdim                       ValRange);
3816341825Sdim    } else if (ID == ".amdhsa_system_sgpr_workgroup_id_y") {
3817341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3818341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y, Val,
3819341825Sdim                       ValRange);
3820341825Sdim    } else if (ID == ".amdhsa_system_sgpr_workgroup_id_z") {
3821341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3822341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z, Val,
3823341825Sdim                       ValRange);
3824341825Sdim    } else if (ID == ".amdhsa_system_sgpr_workgroup_info") {
3825341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3826341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO, Val,
3827341825Sdim                       ValRange);
3828341825Sdim    } else if (ID == ".amdhsa_system_vgpr_workitem_id") {
3829341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3830341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID, Val,
3831341825Sdim                       ValRange);
3832341825Sdim    } else if (ID == ".amdhsa_next_free_vgpr") {
3833341825Sdim      VGPRRange = ValRange;
3834341825Sdim      NextFreeVGPR = Val;
3835341825Sdim    } else if (ID == ".amdhsa_next_free_sgpr") {
3836341825Sdim      SGPRRange = ValRange;
3837341825Sdim      NextFreeSGPR = Val;
3838341825Sdim    } else if (ID == ".amdhsa_reserve_vcc") {
3839341825Sdim      if (!isUInt<1>(Val))
3840341825Sdim        return OutOfRangeError(ValRange);
3841341825Sdim      ReserveVCC = Val;
3842341825Sdim    } else if (ID == ".amdhsa_reserve_flat_scratch") {
3843341825Sdim      if (IVersion.Major < 7)
3844341825Sdim        return getParser().Error(IDRange.Start, "directive requires gfx7+",
3845341825Sdim                                 IDRange);
3846341825Sdim      if (!isUInt<1>(Val))
3847341825Sdim        return OutOfRangeError(ValRange);
3848341825Sdim      ReserveFlatScr = Val;
3849341825Sdim    } else if (ID == ".amdhsa_reserve_xnack_mask") {
3850341825Sdim      if (IVersion.Major < 8)
3851341825Sdim        return getParser().Error(IDRange.Start, "directive requires gfx8+",
3852341825Sdim                                 IDRange);
3853341825Sdim      if (!isUInt<1>(Val))
3854341825Sdim        return OutOfRangeError(ValRange);
3855341825Sdim      ReserveXNACK = Val;
3856341825Sdim    } else if (ID == ".amdhsa_float_round_mode_32") {
3857341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3858341825Sdim                       COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32, Val, ValRange);
3859341825Sdim    } else if (ID == ".amdhsa_float_round_mode_16_64") {
3860341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3861341825Sdim                       COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64, Val, ValRange);
3862341825Sdim    } else if (ID == ".amdhsa_float_denorm_mode_32") {
3863341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3864341825Sdim                       COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32, Val, ValRange);
3865341825Sdim    } else if (ID == ".amdhsa_float_denorm_mode_16_64") {
3866341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3867341825Sdim                       COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64, Val,
3868341825Sdim                       ValRange);
3869341825Sdim    } else if (ID == ".amdhsa_dx10_clamp") {
3870341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1,
3871341825Sdim                       COMPUTE_PGM_RSRC1_ENABLE_DX10_CLAMP, Val, ValRange);
3872341825Sdim    } else if (ID == ".amdhsa_ieee_mode") {
3873341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_ENABLE_IEEE_MODE,
3874341825Sdim                       Val, ValRange);
3875341825Sdim    } else if (ID == ".amdhsa_fp16_overflow") {
3876341825Sdim      if (IVersion.Major < 9)
3877341825Sdim        return getParser().Error(IDRange.Start, "directive requires gfx9+",
3878341825Sdim                                 IDRange);
3879341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FP16_OVFL, Val,
3880341825Sdim                       ValRange);
3881353358Sdim    } else if (ID == ".amdhsa_workgroup_processor_mode") {
3882353358Sdim      if (IVersion.Major < 10)
3883353358Sdim        return getParser().Error(IDRange.Start, "directive requires gfx10+",
3884353358Sdim                                 IDRange);
3885353358Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_WGP_MODE, Val,
3886353358Sdim                       ValRange);
3887353358Sdim    } else if (ID == ".amdhsa_memory_ordered") {
3888353358Sdim      if (IVersion.Major < 10)
3889353358Sdim        return getParser().Error(IDRange.Start, "directive requires gfx10+",
3890353358Sdim                                 IDRange);
3891353358Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_MEM_ORDERED, Val,
3892353358Sdim                       ValRange);
3893353358Sdim    } else if (ID == ".amdhsa_forward_progress") {
3894353358Sdim      if (IVersion.Major < 10)
3895353358Sdim        return getParser().Error(IDRange.Start, "directive requires gfx10+",
3896353358Sdim                                 IDRange);
3897353358Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc1, COMPUTE_PGM_RSRC1_FWD_PROGRESS, Val,
3898353358Sdim                       ValRange);
3899341825Sdim    } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") {
3900341825Sdim      PARSE_BITS_ENTRY(
3901341825Sdim          KD.compute_pgm_rsrc2,
3902341825Sdim          COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION, Val,
3903341825Sdim          ValRange);
3904341825Sdim    } else if (ID == ".amdhsa_exception_fp_denorm_src") {
3905341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3906341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE,
3907341825Sdim                       Val, ValRange);
3908341825Sdim    } else if (ID == ".amdhsa_exception_fp_ieee_div_zero") {
3909341825Sdim      PARSE_BITS_ENTRY(
3910341825Sdim          KD.compute_pgm_rsrc2,
3911341825Sdim          COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO, Val,
3912341825Sdim          ValRange);
3913341825Sdim    } else if (ID == ".amdhsa_exception_fp_ieee_overflow") {
3914341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3915341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW,
3916341825Sdim                       Val, ValRange);
3917341825Sdim    } else if (ID == ".amdhsa_exception_fp_ieee_underflow") {
3918341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3919341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW,
3920341825Sdim                       Val, ValRange);
3921341825Sdim    } else if (ID == ".amdhsa_exception_fp_ieee_inexact") {
3922341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3923341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT,
3924341825Sdim                       Val, ValRange);
3925341825Sdim    } else if (ID == ".amdhsa_exception_int_div_zero") {
3926341825Sdim      PARSE_BITS_ENTRY(KD.compute_pgm_rsrc2,
3927341825Sdim                       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO,
3928341825Sdim                       Val, ValRange);
3929341825Sdim    } else {
3930341825Sdim      return getParser().Error(IDRange.Start,
3931341825Sdim                               "unknown .amdhsa_kernel directive", IDRange);
3932341825Sdim    }
3933341825Sdim
3934341825Sdim#undef PARSE_BITS_ENTRY
3935341825Sdim  }
3936341825Sdim
3937341825Sdim  if (Seen.find(".amdhsa_next_free_vgpr") == Seen.end())
3938341825Sdim    return TokError(".amdhsa_next_free_vgpr directive is required");
3939341825Sdim
3940341825Sdim  if (Seen.find(".amdhsa_next_free_sgpr") == Seen.end())
3941341825Sdim    return TokError(".amdhsa_next_free_sgpr directive is required");
3942341825Sdim
3943341825Sdim  unsigned VGPRBlocks;
3944341825Sdim  unsigned SGPRBlocks;
3945341825Sdim  if (calculateGPRBlocks(getFeatureBits(), ReserveVCC, ReserveFlatScr,
3946353358Sdim                         ReserveXNACK, EnableWavefrontSize32, NextFreeVGPR,
3947353358Sdim                         VGPRRange, NextFreeSGPR, SGPRRange, VGPRBlocks,
3948353358Sdim                         SGPRBlocks))
3949341825Sdim    return true;
3950341825Sdim
3951341825Sdim  if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT_WIDTH>(
3952341825Sdim          VGPRBlocks))
3953341825Sdim    return OutOfRangeError(VGPRRange);
3954341825Sdim  AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3955341825Sdim                  COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT, VGPRBlocks);
3956341825Sdim
3957341825Sdim  if (!isUInt<COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT_WIDTH>(
3958341825Sdim          SGPRBlocks))
3959341825Sdim    return OutOfRangeError(SGPRRange);
3960341825Sdim  AMDHSA_BITS_SET(KD.compute_pgm_rsrc1,
3961341825Sdim                  COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
3962341825Sdim                  SGPRBlocks);
3963341825Sdim
3964341825Sdim  if (!isUInt<COMPUTE_PGM_RSRC2_USER_SGPR_COUNT_WIDTH>(UserSGPRCount))
3965341825Sdim    return TokError("too many user SGPRs enabled");
3966341825Sdim  AMDHSA_BITS_SET(KD.compute_pgm_rsrc2, COMPUTE_PGM_RSRC2_USER_SGPR_COUNT,
3967341825Sdim                  UserSGPRCount);
3968341825Sdim
3969341825Sdim  getTargetStreamer().EmitAmdhsaKernelDescriptor(
3970341825Sdim      getSTI(), KernelName, KD, NextFreeVGPR, NextFreeSGPR, ReserveVCC,
3971341825Sdim      ReserveFlatScr, ReserveXNACK);
3972341825Sdim  return false;
3973341825Sdim}
3974341825Sdim
3975285181Sdimbool AMDGPUAsmParser::ParseDirectiveHSACodeObjectVersion() {
3976285181Sdim  uint32_t Major;
3977285181Sdim  uint32_t Minor;
3978285181Sdim
3979285181Sdim  if (ParseDirectiveMajorMinor(Major, Minor))
3980285181Sdim    return true;
3981285181Sdim
3982285181Sdim  getTargetStreamer().EmitDirectiveHSACodeObjectVersion(Major, Minor);
3983285181Sdim  return false;
3984285181Sdim}
3985285181Sdim
3986285181Sdimbool AMDGPUAsmParser::ParseDirectiveHSACodeObjectISA() {
3987285181Sdim  uint32_t Major;
3988285181Sdim  uint32_t Minor;
3989285181Sdim  uint32_t Stepping;
3990285181Sdim  StringRef VendorName;
3991285181Sdim  StringRef ArchName;
3992285181Sdim
3993285181Sdim  // If this directive has no arguments, then use the ISA version for the
3994285181Sdim  // targeted GPU.
3995285181Sdim  if (getLexer().is(AsmToken::EndOfStatement)) {
3996344779Sdim    AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
3997321369Sdim    getTargetStreamer().EmitDirectiveHSACodeObjectISA(ISA.Major, ISA.Minor,
3998321369Sdim                                                      ISA.Stepping,
3999285181Sdim                                                      "AMD", "AMDGPU");
4000285181Sdim    return false;
4001285181Sdim  }
4002285181Sdim
4003285181Sdim  if (ParseDirectiveMajorMinor(Major, Minor))
4004285181Sdim    return true;
4005285181Sdim
4006285181Sdim  if (getLexer().isNot(AsmToken::Comma))
4007285181Sdim    return TokError("stepping version number required, comma expected");
4008285181Sdim  Lex();
4009285181Sdim
4010314564Sdim  if (ParseAsAbsoluteExpression(Stepping))
4011285181Sdim    return TokError("invalid stepping version");
4012285181Sdim
4013285181Sdim  if (getLexer().isNot(AsmToken::Comma))
4014285181Sdim    return TokError("vendor name required, comma expected");
4015285181Sdim  Lex();
4016285181Sdim
4017285181Sdim  if (getLexer().isNot(AsmToken::String))
4018285181Sdim    return TokError("invalid vendor name");
4019285181Sdim
4020285181Sdim  VendorName = getLexer().getTok().getStringContents();
4021285181Sdim  Lex();
4022285181Sdim
4023285181Sdim  if (getLexer().isNot(AsmToken::Comma))
4024285181Sdim    return TokError("arch name required, comma expected");
4025285181Sdim  Lex();
4026285181Sdim
4027285181Sdim  if (getLexer().isNot(AsmToken::String))
4028285181Sdim    return TokError("invalid arch name");
4029285181Sdim
4030285181Sdim  ArchName = getLexer().getTok().getStringContents();
4031285181Sdim  Lex();
4032285181Sdim
4033285181Sdim  getTargetStreamer().EmitDirectiveHSACodeObjectISA(Major, Minor, Stepping,
4034285181Sdim                                                    VendorName, ArchName);
4035285181Sdim  return false;
4036285181Sdim}
4037285181Sdim
4038285181Sdimbool AMDGPUAsmParser::ParseAMDKernelCodeTValue(StringRef ID,
4039285181Sdim                                               amd_kernel_code_t &Header) {
4040341825Sdim  // max_scratch_backing_memory_byte_size is deprecated. Ignore it while parsing
4041341825Sdim  // assembly for backwards compatibility.
4042341825Sdim  if (ID == "max_scratch_backing_memory_byte_size") {
4043341825Sdim    Parser.eatToEndOfStatement();
4044341825Sdim    return false;
4045341825Sdim  }
4046341825Sdim
4047309124Sdim  SmallString<40> ErrStr;
4048309124Sdim  raw_svector_ostream Err(ErrStr);
4049309124Sdim  if (!parseAmdKernelCodeField(ID, getParser(), Header, Err)) {
4050309124Sdim    return TokError(Err.str());
4051309124Sdim  }
4052285181Sdim  Lex();
4053353358Sdim
4054353358Sdim  if (ID == "enable_wavefront_size32") {
4055353358Sdim    if (Header.code_properties & AMD_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32) {
4056353358Sdim      if (!isGFX10())
4057353358Sdim        return TokError("enable_wavefront_size32=1 is only allowed on GFX10+");
4058353358Sdim      if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32])
4059353358Sdim        return TokError("enable_wavefront_size32=1 requires +WavefrontSize32");
4060353358Sdim    } else {
4061353358Sdim      if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64])
4062353358Sdim        return TokError("enable_wavefront_size32=0 requires +WavefrontSize64");
4063353358Sdim    }
4064353358Sdim  }
4065353358Sdim
4066353358Sdim  if (ID == "wavefront_size") {
4067353358Sdim    if (Header.wavefront_size == 5) {
4068353358Sdim      if (!isGFX10())
4069353358Sdim        return TokError("wavefront_size=5 is only allowed on GFX10+");
4070353358Sdim      if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize32])
4071353358Sdim        return TokError("wavefront_size=5 requires +WavefrontSize32");
4072353358Sdim    } else if (Header.wavefront_size == 6) {
4073353358Sdim      if (!getFeatureBits()[AMDGPU::FeatureWavefrontSize64])
4074353358Sdim        return TokError("wavefront_size=6 requires +WavefrontSize64");
4075353358Sdim    }
4076353358Sdim  }
4077353358Sdim
4078353358Sdim  if (ID == "enable_wgp_mode") {
4079353358Sdim    if (G_00B848_WGP_MODE(Header.compute_pgm_resource_registers) && !isGFX10())
4080353358Sdim      return TokError("enable_wgp_mode=1 is only allowed on GFX10+");
4081353358Sdim  }
4082353358Sdim
4083353358Sdim  if (ID == "enable_mem_ordered") {
4084353358Sdim    if (G_00B848_MEM_ORDERED(Header.compute_pgm_resource_registers) && !isGFX10())
4085353358Sdim      return TokError("enable_mem_ordered=1 is only allowed on GFX10+");
4086353358Sdim  }
4087353358Sdim
4088353358Sdim  if (ID == "enable_fwd_progress") {
4089353358Sdim    if (G_00B848_FWD_PROGRESS(Header.compute_pgm_resource_registers) && !isGFX10())
4090353358Sdim      return TokError("enable_fwd_progress=1 is only allowed on GFX10+");
4091353358Sdim  }
4092353358Sdim
4093285181Sdim  return false;
4094285181Sdim}
4095285181Sdim
4096285181Sdimbool AMDGPUAsmParser::ParseDirectiveAMDKernelCodeT() {
4097285181Sdim  amd_kernel_code_t Header;
4098344779Sdim  AMDGPU::initDefaultAMDKernelCodeT(Header, &getSTI());
4099285181Sdim
4100285181Sdim  while (true) {
4101285181Sdim    // Lex EndOfStatement.  This is in a while loop, because lexing a comment
4102285181Sdim    // will set the current token to EndOfStatement.
4103285181Sdim    while(getLexer().is(AsmToken::EndOfStatement))
4104285181Sdim      Lex();
4105285181Sdim
4106285181Sdim    if (getLexer().isNot(AsmToken::Identifier))
4107285181Sdim      return TokError("expected value identifier or .end_amd_kernel_code_t");
4108285181Sdim
4109285181Sdim    StringRef ID = getLexer().getTok().getIdentifier();
4110285181Sdim    Lex();
4111285181Sdim
4112285181Sdim    if (ID == ".end_amd_kernel_code_t")
4113285181Sdim      break;
4114285181Sdim
4115285181Sdim    if (ParseAMDKernelCodeTValue(ID, Header))
4116285181Sdim      return true;
4117285181Sdim  }
4118285181Sdim
4119285181Sdim  getTargetStreamer().EmitAMDKernelCodeT(Header);
4120285181Sdim
4121285181Sdim  return false;
4122285181Sdim}
4123285181Sdim
4124296417Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGPUHsaKernel() {
4125296417Sdim  if (getLexer().isNot(AsmToken::Identifier))
4126296417Sdim    return TokError("expected symbol name");
4127296417Sdim
4128296417Sdim  StringRef KernelName = Parser.getTok().getString();
4129296417Sdim
4130296417Sdim  getTargetStreamer().EmitAMDGPUSymbolType(KernelName,
4131296417Sdim                                           ELF::STT_AMDGPU_HSA_KERNEL);
4132296417Sdim  Lex();
4133341825Sdim  if (!AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI()))
4134341825Sdim    KernelScope.initialize(getContext());
4135296417Sdim  return false;
4136296417Sdim}
4137296417Sdim
4138327952Sdimbool AMDGPUAsmParser::ParseDirectiveISAVersion() {
4139327952Sdim  if (getSTI().getTargetTriple().getArch() != Triple::amdgcn) {
4140327952Sdim    return Error(getParser().getTok().getLoc(),
4141327952Sdim                 ".amd_amdgpu_isa directive is not available on non-amdgcn "
4142327952Sdim                 "architectures");
4143327952Sdim  }
4144327952Sdim
4145327952Sdim  auto ISAVersionStringFromASM = getLexer().getTok().getStringContents();
4146327952Sdim
4147327952Sdim  std::string ISAVersionStringFromSTI;
4148327952Sdim  raw_string_ostream ISAVersionStreamFromSTI(ISAVersionStringFromSTI);
4149327952Sdim  IsaInfo::streamIsaVersion(&getSTI(), ISAVersionStreamFromSTI);
4150327952Sdim
4151327952Sdim  if (ISAVersionStringFromASM != ISAVersionStreamFromSTI.str()) {
4152327952Sdim    return Error(getParser().getTok().getLoc(),
4153327952Sdim                 ".amd_amdgpu_isa directive does not match triple and/or mcpu "
4154327952Sdim                 "arguments specified through the command line");
4155327952Sdim  }
4156327952Sdim
4157327952Sdim  getTargetStreamer().EmitISAVersion(ISAVersionStreamFromSTI.str());
4158327952Sdim  Lex();
4159327952Sdim
4160327952Sdim  return false;
4161327952Sdim}
4162327952Sdim
4163327952Sdimbool AMDGPUAsmParser::ParseDirectiveHSAMetadata() {
4164344779Sdim  const char *AssemblerDirectiveBegin;
4165344779Sdim  const char *AssemblerDirectiveEnd;
4166344779Sdim  std::tie(AssemblerDirectiveBegin, AssemblerDirectiveEnd) =
4167344779Sdim      AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())
4168344779Sdim          ? std::make_tuple(HSAMD::V3::AssemblerDirectiveBegin,
4169344779Sdim                            HSAMD::V3::AssemblerDirectiveEnd)
4170344779Sdim          : std::make_tuple(HSAMD::AssemblerDirectiveBegin,
4171344779Sdim                            HSAMD::AssemblerDirectiveEnd);
4172344779Sdim
4173327952Sdim  if (getSTI().getTargetTriple().getOS() != Triple::AMDHSA) {
4174327952Sdim    return Error(getParser().getTok().getLoc(),
4175344779Sdim                 (Twine(AssemblerDirectiveBegin) + Twine(" directive is "
4176327952Sdim                 "not available on non-amdhsa OSes")).str());
4177327952Sdim  }
4178327952Sdim
4179327952Sdim  std::string HSAMetadataString;
4180353358Sdim  if (ParseToEndDirective(AssemblerDirectiveBegin, AssemblerDirectiveEnd,
4181353358Sdim                          HSAMetadataString))
4182353358Sdim    return true;
4183327952Sdim
4184353358Sdim  if (IsaInfo::hasCodeObjectV3(&getSTI())) {
4185353358Sdim    if (!getTargetStreamer().EmitHSAMetadataV3(HSAMetadataString))
4186353358Sdim      return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
4187353358Sdim  } else {
4188353358Sdim    if (!getTargetStreamer().EmitHSAMetadataV2(HSAMetadataString))
4189353358Sdim      return Error(getParser().getTok().getLoc(), "invalid HSA metadata");
4190353358Sdim  }
4191353358Sdim
4192353358Sdim  return false;
4193353358Sdim}
4194353358Sdim
4195353358Sdim/// Common code to parse out a block of text (typically YAML) between start and
4196353358Sdim/// end directives.
4197353358Sdimbool AMDGPUAsmParser::ParseToEndDirective(const char *AssemblerDirectiveBegin,
4198353358Sdim                                          const char *AssemblerDirectiveEnd,
4199353358Sdim                                          std::string &CollectString) {
4200353358Sdim
4201353358Sdim  raw_string_ostream CollectStream(CollectString);
4202353358Sdim
4203327952Sdim  getLexer().setSkipSpace(false);
4204327952Sdim
4205327952Sdim  bool FoundEnd = false;
4206327952Sdim  while (!getLexer().is(AsmToken::Eof)) {
4207327952Sdim    while (getLexer().is(AsmToken::Space)) {
4208353358Sdim      CollectStream << getLexer().getTok().getString();
4209327952Sdim      Lex();
4210327952Sdim    }
4211327952Sdim
4212327952Sdim    if (getLexer().is(AsmToken::Identifier)) {
4213327952Sdim      StringRef ID = getLexer().getTok().getIdentifier();
4214344779Sdim      if (ID == AssemblerDirectiveEnd) {
4215327952Sdim        Lex();
4216327952Sdim        FoundEnd = true;
4217327952Sdim        break;
4218327952Sdim      }
4219327952Sdim    }
4220327952Sdim
4221353358Sdim    CollectStream << Parser.parseStringToEndOfStatement()
4222353358Sdim                  << getContext().getAsmInfo()->getSeparatorString();
4223327952Sdim
4224327952Sdim    Parser.eatToEndOfStatement();
4225327952Sdim  }
4226327952Sdim
4227327952Sdim  getLexer().setSkipSpace(true);
4228327952Sdim
4229327952Sdim  if (getLexer().is(AsmToken::Eof) && !FoundEnd) {
4230327952Sdim    return TokError(Twine("expected directive ") +
4231353358Sdim                    Twine(AssemblerDirectiveEnd) + Twine(" not found"));
4232327952Sdim  }
4233327952Sdim
4234353358Sdim  CollectStream.flush();
4235353358Sdim  return false;
4236353358Sdim}
4237327952Sdim
4238353358Sdim/// Parse the assembler directive for new MsgPack-format PAL metadata.
4239353358Sdimbool AMDGPUAsmParser::ParseDirectivePALMetadataBegin() {
4240353358Sdim  std::string String;
4241353358Sdim  if (ParseToEndDirective(AMDGPU::PALMD::AssemblerDirectiveBegin,
4242353358Sdim                          AMDGPU::PALMD::AssemblerDirectiveEnd, String))
4243353358Sdim    return true;
4244327952Sdim
4245353358Sdim  auto PALMetadata = getTargetStreamer().getPALMetadata();
4246353358Sdim  if (!PALMetadata->setFromString(String))
4247353358Sdim    return Error(getParser().getTok().getLoc(), "invalid PAL metadata");
4248327952Sdim  return false;
4249327952Sdim}
4250327952Sdim
4251353358Sdim/// Parse the assembler directive for old linear-format PAL metadata.
4252327952Sdimbool AMDGPUAsmParser::ParseDirectivePALMetadata() {
4253327952Sdim  if (getSTI().getTargetTriple().getOS() != Triple::AMDPAL) {
4254327952Sdim    return Error(getParser().getTok().getLoc(),
4255327952Sdim                 (Twine(PALMD::AssemblerDirective) + Twine(" directive is "
4256327952Sdim                 "not available on non-amdpal OSes")).str());
4257327952Sdim  }
4258327952Sdim
4259353358Sdim  auto PALMetadata = getTargetStreamer().getPALMetadata();
4260353358Sdim  PALMetadata->setLegacy();
4261327952Sdim  for (;;) {
4262353358Sdim    uint32_t Key, Value;
4263353358Sdim    if (ParseAsAbsoluteExpression(Key)) {
4264353358Sdim      return TokError(Twine("invalid value in ") +
4265353358Sdim                      Twine(PALMD::AssemblerDirective));
4266353358Sdim    }
4267353358Sdim    if (getLexer().isNot(AsmToken::Comma)) {
4268353358Sdim      return TokError(Twine("expected an even number of values in ") +
4269353358Sdim                      Twine(PALMD::AssemblerDirective));
4270353358Sdim    }
4271353358Sdim    Lex();
4272327952Sdim    if (ParseAsAbsoluteExpression(Value)) {
4273327952Sdim      return TokError(Twine("invalid value in ") +
4274327952Sdim                      Twine(PALMD::AssemblerDirective));
4275327952Sdim    }
4276353358Sdim    PALMetadata->setRegister(Key, Value);
4277327952Sdim    if (getLexer().isNot(AsmToken::Comma))
4278327952Sdim      break;
4279327952Sdim    Lex();
4280327952Sdim  }
4281327952Sdim  return false;
4282327952Sdim}
4283327952Sdim
4284353358Sdim/// ParseDirectiveAMDGPULDS
4285353358Sdim///  ::= .amdgpu_lds identifier ',' size_expression [',' align_expression]
4286353358Sdimbool AMDGPUAsmParser::ParseDirectiveAMDGPULDS() {
4287353358Sdim  if (getParser().checkForValidSection())
4288353358Sdim    return true;
4289353358Sdim
4290353358Sdim  StringRef Name;
4291353358Sdim  SMLoc NameLoc = getLexer().getLoc();
4292353358Sdim  if (getParser().parseIdentifier(Name))
4293353358Sdim    return TokError("expected identifier in directive");
4294353358Sdim
4295353358Sdim  MCSymbol *Symbol = getContext().getOrCreateSymbol(Name);
4296353358Sdim  if (parseToken(AsmToken::Comma, "expected ','"))
4297353358Sdim    return true;
4298353358Sdim
4299353358Sdim  unsigned LocalMemorySize = AMDGPU::IsaInfo::getLocalMemorySize(&getSTI());
4300353358Sdim
4301353358Sdim  int64_t Size;
4302353358Sdim  SMLoc SizeLoc = getLexer().getLoc();
4303353358Sdim  if (getParser().parseAbsoluteExpression(Size))
4304353358Sdim    return true;
4305353358Sdim  if (Size < 0)
4306353358Sdim    return Error(SizeLoc, "size must be non-negative");
4307353358Sdim  if (Size > LocalMemorySize)
4308353358Sdim    return Error(SizeLoc, "size is too large");
4309353358Sdim
4310353358Sdim  int64_t Align = 4;
4311353358Sdim  if (getLexer().is(AsmToken::Comma)) {
4312353358Sdim    Lex();
4313353358Sdim    SMLoc AlignLoc = getLexer().getLoc();
4314353358Sdim    if (getParser().parseAbsoluteExpression(Align))
4315353358Sdim      return true;
4316353358Sdim    if (Align < 0 || !isPowerOf2_64(Align))
4317353358Sdim      return Error(AlignLoc, "alignment must be a power of two");
4318353358Sdim
4319353358Sdim    // Alignment larger than the size of LDS is possible in theory, as long
4320353358Sdim    // as the linker manages to place to symbol at address 0, but we do want
4321353358Sdim    // to make sure the alignment fits nicely into a 32-bit integer.
4322353358Sdim    if (Align >= 1u << 31)
4323353358Sdim      return Error(AlignLoc, "alignment is too large");
4324353358Sdim  }
4325353358Sdim
4326353358Sdim  if (parseToken(AsmToken::EndOfStatement,
4327353358Sdim                 "unexpected token in '.amdgpu_lds' directive"))
4328353358Sdim    return true;
4329353358Sdim
4330353358Sdim  Symbol->redefineIfPossible();
4331353358Sdim  if (!Symbol->isUndefined())
4332353358Sdim    return Error(NameLoc, "invalid symbol redefinition");
4333353358Sdim
4334353358Sdim  getTargetStreamer().emitAMDGPULDS(Symbol, Size, Align);
4335353358Sdim  return false;
4336353358Sdim}
4337353358Sdim
4338284677Sdimbool AMDGPUAsmParser::ParseDirective(AsmToken DirectiveID) {
4339285181Sdim  StringRef IDVal = DirectiveID.getString();
4340285181Sdim
4341341825Sdim  if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
4342341825Sdim    if (IDVal == ".amdgcn_target")
4343341825Sdim      return ParseDirectiveAMDGCNTarget();
4344285181Sdim
4345341825Sdim    if (IDVal == ".amdhsa_kernel")
4346341825Sdim      return ParseDirectiveAMDHSAKernel();
4347344779Sdim
4348344779Sdim    // TODO: Restructure/combine with PAL metadata directive.
4349344779Sdim    if (IDVal == AMDGPU::HSAMD::V3::AssemblerDirectiveBegin)
4350344779Sdim      return ParseDirectiveHSAMetadata();
4351341825Sdim  } else {
4352341825Sdim    if (IDVal == ".hsa_code_object_version")
4353341825Sdim      return ParseDirectiveHSACodeObjectVersion();
4354285181Sdim
4355341825Sdim    if (IDVal == ".hsa_code_object_isa")
4356341825Sdim      return ParseDirectiveHSACodeObjectISA();
4357285181Sdim
4358341825Sdim    if (IDVal == ".amd_kernel_code_t")
4359341825Sdim      return ParseDirectiveAMDKernelCodeT();
4360296417Sdim
4361341825Sdim    if (IDVal == ".amdgpu_hsa_kernel")
4362341825Sdim      return ParseDirectiveAMDGPUHsaKernel();
4363327952Sdim
4364341825Sdim    if (IDVal == ".amd_amdgpu_isa")
4365341825Sdim      return ParseDirectiveISAVersion();
4366344779Sdim
4367344779Sdim    if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin)
4368344779Sdim      return ParseDirectiveHSAMetadata();
4369341825Sdim  }
4370341825Sdim
4371353358Sdim  if (IDVal == ".amdgpu_lds")
4372353358Sdim    return ParseDirectiveAMDGPULDS();
4373353358Sdim
4374353358Sdim  if (IDVal == PALMD::AssemblerDirectiveBegin)
4375353358Sdim    return ParseDirectivePALMetadataBegin();
4376353358Sdim
4377327952Sdim  if (IDVal == PALMD::AssemblerDirective)
4378327952Sdim    return ParseDirectivePALMetadata();
4379327952Sdim
4380284677Sdim  return true;
4381284677Sdim}
4382284677Sdim
4383296417Sdimbool AMDGPUAsmParser::subtargetHasRegister(const MCRegisterInfo &MRI,
4384296417Sdim                                           unsigned RegNo) const {
4385327952Sdim
4386327952Sdim  for (MCRegAliasIterator R(AMDGPU::TTMP12_TTMP13_TTMP14_TTMP15, &MRI, true);
4387327952Sdim       R.isValid(); ++R) {
4388327952Sdim    if (*R == RegNo)
4389353358Sdim      return isGFX9() || isGFX10();
4390327952Sdim  }
4391327952Sdim
4392353358Sdim  // GFX10 has 2 more SGPRs 104 and 105.
4393353358Sdim  for (MCRegAliasIterator R(AMDGPU::SGPR104_SGPR105, &MRI, true);
4394353358Sdim       R.isValid(); ++R) {
4395353358Sdim    if (*R == RegNo)
4396353358Sdim      return hasSGPR104_SGPR105();
4397353358Sdim  }
4398353358Sdim
4399327952Sdim  switch (RegNo) {
4400353358Sdim  case AMDGPU::SRC_SHARED_BASE:
4401353358Sdim  case AMDGPU::SRC_SHARED_LIMIT:
4402353358Sdim  case AMDGPU::SRC_PRIVATE_BASE:
4403353358Sdim  case AMDGPU::SRC_PRIVATE_LIMIT:
4404353358Sdim  case AMDGPU::SRC_POPS_EXITING_WAVE_ID:
4405353358Sdim    return !isCI() && !isSI() && !isVI();
4406327952Sdim  case AMDGPU::TBA:
4407327952Sdim  case AMDGPU::TBA_LO:
4408327952Sdim  case AMDGPU::TBA_HI:
4409327952Sdim  case AMDGPU::TMA:
4410327952Sdim  case AMDGPU::TMA_LO:
4411327952Sdim  case AMDGPU::TMA_HI:
4412353358Sdim    return !isGFX9() && !isGFX10();
4413341825Sdim  case AMDGPU::XNACK_MASK:
4414341825Sdim  case AMDGPU::XNACK_MASK_LO:
4415341825Sdim  case AMDGPU::XNACK_MASK_HI:
4416353358Sdim    return !isCI() && !isSI() && !isGFX10() && hasXNACK();
4417353358Sdim  case AMDGPU::SGPR_NULL:
4418353358Sdim    return isGFX10();
4419327952Sdim  default:
4420327952Sdim    break;
4421327952Sdim  }
4422327952Sdim
4423296417Sdim  if (isCI())
4424296417Sdim    return true;
4425296417Sdim
4426353358Sdim  if (isSI() || isGFX10()) {
4427353358Sdim    // No flat_scr on SI.
4428353358Sdim    // On GFX10 flat scratch is not a valid register operand and can only be
4429353358Sdim    // accessed with s_setreg/s_getreg.
4430296417Sdim    switch (RegNo) {
4431296417Sdim    case AMDGPU::FLAT_SCR:
4432296417Sdim    case AMDGPU::FLAT_SCR_LO:
4433296417Sdim    case AMDGPU::FLAT_SCR_HI:
4434296417Sdim      return false;
4435296417Sdim    default:
4436296417Sdim      return true;
4437296417Sdim    }
4438296417Sdim  }
4439296417Sdim
4440296417Sdim  // VI only has 102 SGPRs, so make sure we aren't trying to use the 2 more that
4441296417Sdim  // SI/CI have.
4442296417Sdim  for (MCRegAliasIterator R(AMDGPU::SGPR102_SGPR103, &MRI, true);
4443296417Sdim       R.isValid(); ++R) {
4444296417Sdim    if (*R == RegNo)
4445353358Sdim      return hasSGPR102_SGPR103();
4446296417Sdim  }
4447296417Sdim
4448296417Sdim  return true;
4449296417Sdim}
4450296417Sdim
4451314564SdimOperandMatchResultTy
4452353358SdimAMDGPUAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic,
4453353358Sdim                              OperandMode Mode) {
4454284677Sdim  // Try to parse with a custom parser
4455284677Sdim  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4456284677Sdim
4457284677Sdim  // If we successfully parsed the operand or if there as an error parsing,
4458284677Sdim  // we are done.
4459284677Sdim  //
4460284677Sdim  // If we are parsing after we reach EndOfStatement then this means we
4461284677Sdim  // are appending default values to the Operands list.  This is only done
4462284677Sdim  // by custom parser, so we shouldn't continue on to the generic parsing.
4463284677Sdim  if (ResTy == MatchOperand_Success || ResTy == MatchOperand_ParseFail ||
4464284677Sdim      getLexer().is(AsmToken::EndOfStatement))
4465284677Sdim    return ResTy;
4466284677Sdim
4467353358Sdim  if (Mode == OperandMode_NSA && getLexer().is(AsmToken::LBrac)) {
4468353358Sdim    unsigned Prefix = Operands.size();
4469353358Sdim    SMLoc LBraceLoc = getTok().getLoc();
4470353358Sdim    Parser.Lex(); // eat the '['
4471284677Sdim
4472353358Sdim    for (;;) {
4473353358Sdim      ResTy = parseReg(Operands);
4474353358Sdim      if (ResTy != MatchOperand_Success)
4475353358Sdim        return ResTy;
4476284677Sdim
4477353358Sdim      if (getLexer().is(AsmToken::RBrac))
4478353358Sdim        break;
4479284677Sdim
4480353358Sdim      if (getLexer().isNot(AsmToken::Comma))
4481353358Sdim        return MatchOperand_ParseFail;
4482353358Sdim      Parser.Lex();
4483353358Sdim    }
4484327952Sdim
4485353358Sdim    if (Operands.size() - Prefix > 1) {
4486353358Sdim      Operands.insert(Operands.begin() + Prefix,
4487353358Sdim                      AMDGPUOperand::CreateToken(this, "[", LBraceLoc));
4488353358Sdim      Operands.push_back(AMDGPUOperand::CreateToken(this, "]",
4489353358Sdim                                                    getTok().getLoc()));
4490353358Sdim    }
4491353358Sdim
4492353358Sdim    Parser.Lex(); // eat the ']'
4493309124Sdim    return MatchOperand_Success;
4494284677Sdim  }
4495327952Sdim
4496353358Sdim  return parseRegOrImm(Operands);
4497284677Sdim}
4498284677Sdim
4499309124SdimStringRef AMDGPUAsmParser::parseMnemonicSuffix(StringRef Name) {
4500284677Sdim  // Clear any forced encodings from the previous instruction.
4501284677Sdim  setForcedEncodingSize(0);
4502309124Sdim  setForcedDPP(false);
4503309124Sdim  setForcedSDWA(false);
4504284677Sdim
4505309124Sdim  if (Name.endswith("_e64")) {
4506284677Sdim    setForcedEncodingSize(64);
4507309124Sdim    return Name.substr(0, Name.size() - 4);
4508309124Sdim  } else if (Name.endswith("_e32")) {
4509284677Sdim    setForcedEncodingSize(32);
4510309124Sdim    return Name.substr(0, Name.size() - 4);
4511309124Sdim  } else if (Name.endswith("_dpp")) {
4512309124Sdim    setForcedDPP(true);
4513309124Sdim    return Name.substr(0, Name.size() - 4);
4514309124Sdim  } else if (Name.endswith("_sdwa")) {
4515309124Sdim    setForcedSDWA(true);
4516309124Sdim    return Name.substr(0, Name.size() - 5);
4517309124Sdim  }
4518309124Sdim  return Name;
4519309124Sdim}
4520284677Sdim
4521309124Sdimbool AMDGPUAsmParser::ParseInstruction(ParseInstructionInfo &Info,
4522309124Sdim                                       StringRef Name,
4523309124Sdim                                       SMLoc NameLoc, OperandVector &Operands) {
4524284677Sdim  // Add the instruction mnemonic
4525309124Sdim  Name = parseMnemonicSuffix(Name);
4526314564Sdim  Operands.push_back(AMDGPUOperand::CreateToken(this, Name, NameLoc));
4527284677Sdim
4528353358Sdim  bool IsMIMG = Name.startswith("image_");
4529353358Sdim
4530284677Sdim  while (!getLexer().is(AsmToken::EndOfStatement)) {
4531353358Sdim    OperandMode Mode = OperandMode_Default;
4532353358Sdim    if (IsMIMG && isGFX10() && Operands.size() == 2)
4533353358Sdim      Mode = OperandMode_NSA;
4534353358Sdim    OperandMatchResultTy Res = parseOperand(Operands, Name, Mode);
4535284677Sdim
4536284677Sdim    // Eat the comma or space if there is one.
4537284677Sdim    if (getLexer().is(AsmToken::Comma))
4538284677Sdim      Parser.Lex();
4539284677Sdim
4540284677Sdim    switch (Res) {
4541284677Sdim      case MatchOperand_Success: break;
4542309124Sdim      case MatchOperand_ParseFail:
4543353358Sdim        // FIXME: use real operand location rather than the current location.
4544309124Sdim        Error(getLexer().getLoc(), "failed parsing operand.");
4545309124Sdim        while (!getLexer().is(AsmToken::EndOfStatement)) {
4546309124Sdim          Parser.Lex();
4547309124Sdim        }
4548309124Sdim        return true;
4549309124Sdim      case MatchOperand_NoMatch:
4550353358Sdim        // FIXME: use real operand location rather than the current location.
4551309124Sdim        Error(getLexer().getLoc(), "not a valid operand.");
4552309124Sdim        while (!getLexer().is(AsmToken::EndOfStatement)) {
4553309124Sdim          Parser.Lex();
4554309124Sdim        }
4555309124Sdim        return true;
4556284677Sdim    }
4557284677Sdim  }
4558284677Sdim
4559284677Sdim  return false;
4560284677Sdim}
4561284677Sdim
4562284677Sdim//===----------------------------------------------------------------------===//
4563284677Sdim// Utility functions
4564284677Sdim//===----------------------------------------------------------------------===//
4565284677Sdim
4566314564SdimOperandMatchResultTy
4567353358SdimAMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, int64_t &IntVal) {
4568284677Sdim
4569353358Sdim  if (!trySkipId(Prefix, AsmToken::Colon))
4570353358Sdim    return MatchOperand_NoMatch;
4571284677Sdim
4572353358Sdim  return parseExpr(IntVal) ? MatchOperand_Success : MatchOperand_ParseFail;
4573284677Sdim}
4574284677Sdim
4575314564SdimOperandMatchResultTy
4576284677SdimAMDGPUAsmParser::parseIntWithPrefix(const char *Prefix, OperandVector &Operands,
4577321369Sdim                                    AMDGPUOperand::ImmTy ImmTy,
4578309124Sdim                                    bool (*ConvertResult)(int64_t&)) {
4579353358Sdim  SMLoc S = getLoc();
4580309124Sdim  int64_t Value = 0;
4581284677Sdim
4582314564Sdim  OperandMatchResultTy Res = parseIntWithPrefix(Prefix, Value);
4583284677Sdim  if (Res != MatchOperand_Success)
4584284677Sdim    return Res;
4585284677Sdim
4586309124Sdim  if (ConvertResult && !ConvertResult(Value)) {
4587353358Sdim    Error(S, "invalid " + StringRef(Prefix) + " value.");
4588309124Sdim  }
4589309124Sdim
4590314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Value, S, ImmTy));
4591284677Sdim  return MatchOperand_Success;
4592284677Sdim}
4593284677Sdim
4594353358SdimOperandMatchResultTy
4595353358SdimAMDGPUAsmParser::parseOperandArrayWithPrefix(const char *Prefix,
4596353358Sdim                                             OperandVector &Operands,
4597353358Sdim                                             AMDGPUOperand::ImmTy ImmTy,
4598353358Sdim                                             bool (*ConvertResult)(int64_t&)) {
4599353358Sdim  SMLoc S = getLoc();
4600353358Sdim  if (!trySkipId(Prefix, AsmToken::Colon))
4601321369Sdim    return MatchOperand_NoMatch;
4602321369Sdim
4603353358Sdim  if (!skipToken(AsmToken::LBrac, "expected a left square bracket"))
4604321369Sdim    return MatchOperand_ParseFail;
4605321369Sdim
4606321369Sdim  unsigned Val = 0;
4607353358Sdim  const unsigned MaxSize = 4;
4608321369Sdim
4609321369Sdim  // FIXME: How to verify the number of elements matches the number of src
4610321369Sdim  // operands?
4611353358Sdim  for (int I = 0; ; ++I) {
4612353358Sdim    int64_t Op;
4613353358Sdim    SMLoc Loc = getLoc();
4614353358Sdim    if (!parseExpr(Op))
4615353358Sdim      return MatchOperand_ParseFail;
4616321369Sdim
4617353358Sdim    if (Op != 0 && Op != 1) {
4618353358Sdim      Error(Loc, "invalid " + StringRef(Prefix) + " value.");
4619353358Sdim      return MatchOperand_ParseFail;
4620321369Sdim    }
4621321369Sdim
4622353358Sdim    Val |= (Op << I);
4623321369Sdim
4624353358Sdim    if (trySkipToken(AsmToken::RBrac))
4625353358Sdim      break;
4626353358Sdim
4627353358Sdim    if (I + 1 == MaxSize) {
4628353358Sdim      Error(getLoc(), "expected a closing square bracket");
4629321369Sdim      return MatchOperand_ParseFail;
4630353358Sdim    }
4631321369Sdim
4632353358Sdim    if (!skipToken(AsmToken::Comma, "expected a comma"))
4633321369Sdim      return MatchOperand_ParseFail;
4634321369Sdim  }
4635321369Sdim
4636321369Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S, ImmTy));
4637321369Sdim  return MatchOperand_Success;
4638321369Sdim}
4639321369Sdim
4640314564SdimOperandMatchResultTy
4641284677SdimAMDGPUAsmParser::parseNamedBit(const char *Name, OperandVector &Operands,
4642321369Sdim                               AMDGPUOperand::ImmTy ImmTy) {
4643284677Sdim  int64_t Bit = 0;
4644284677Sdim  SMLoc S = Parser.getTok().getLoc();
4645284677Sdim
4646284677Sdim  // We are at the end of the statement, and this is a default argument, so
4647284677Sdim  // use a default value.
4648284677Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
4649284677Sdim    switch(getLexer().getKind()) {
4650284677Sdim      case AsmToken::Identifier: {
4651284677Sdim        StringRef Tok = Parser.getTok().getString();
4652284677Sdim        if (Tok == Name) {
4653344779Sdim          if (Tok == "r128" && isGFX9())
4654344779Sdim            Error(S, "r128 modifier is not supported on this GPU");
4655353358Sdim          if (Tok == "a16" && !isGFX9() && !isGFX10())
4656344779Sdim            Error(S, "a16 modifier is not supported on this GPU");
4657284677Sdim          Bit = 1;
4658284677Sdim          Parser.Lex();
4659284677Sdim        } else if (Tok.startswith("no") && Tok.endswith(Name)) {
4660284677Sdim          Bit = 0;
4661284677Sdim          Parser.Lex();
4662284677Sdim        } else {
4663284677Sdim          return MatchOperand_NoMatch;
4664284677Sdim        }
4665284677Sdim        break;
4666284677Sdim      }
4667284677Sdim      default:
4668284677Sdim        return MatchOperand_NoMatch;
4669284677Sdim    }
4670284677Sdim  }
4671284677Sdim
4672353358Sdim  if (!isGFX10() && ImmTy == AMDGPUOperand::ImmTyDLC)
4673353358Sdim    return MatchOperand_ParseFail;
4674353358Sdim
4675314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Bit, S, ImmTy));
4676284677Sdim  return MatchOperand_Success;
4677284677Sdim}
4678284677Sdim
4679321369Sdimstatic void addOptionalImmOperand(
4680321369Sdim  MCInst& Inst, const OperandVector& Operands,
4681321369Sdim  AMDGPUAsmParser::OptionalImmIndexMap& OptionalIdx,
4682321369Sdim  AMDGPUOperand::ImmTy ImmT,
4683321369Sdim  int64_t Default = 0) {
4684309124Sdim  auto i = OptionalIdx.find(ImmT);
4685309124Sdim  if (i != OptionalIdx.end()) {
4686309124Sdim    unsigned Idx = i->second;
4687309124Sdim    ((AMDGPUOperand &)*Operands[Idx]).addImmOperands(Inst, 1);
4688309124Sdim  } else {
4689309124Sdim    Inst.addOperand(MCOperand::createImm(Default));
4690284677Sdim  }
4691284677Sdim}
4692284677Sdim
4693314564SdimOperandMatchResultTy
4694309124SdimAMDGPUAsmParser::parseStringWithPrefix(StringRef Prefix, StringRef &Value) {
4695309124Sdim  if (getLexer().isNot(AsmToken::Identifier)) {
4696309124Sdim    return MatchOperand_NoMatch;
4697309124Sdim  }
4698309124Sdim  StringRef Tok = Parser.getTok().getString();
4699309124Sdim  if (Tok != Prefix) {
4700309124Sdim    return MatchOperand_NoMatch;
4701309124Sdim  }
4702284677Sdim
4703309124Sdim  Parser.Lex();
4704309124Sdim  if (getLexer().isNot(AsmToken::Colon)) {
4705309124Sdim    return MatchOperand_ParseFail;
4706309124Sdim  }
4707284677Sdim
4708309124Sdim  Parser.Lex();
4709309124Sdim  if (getLexer().isNot(AsmToken::Identifier)) {
4710309124Sdim    return MatchOperand_ParseFail;
4711309124Sdim  }
4712284677Sdim
4713309124Sdim  Value = Parser.getTok().getString();
4714309124Sdim  return MatchOperand_Success;
4715284677Sdim}
4716284677Sdim
4717344779Sdim// dfmt and nfmt (in a tbuffer instruction) are parsed as one to allow their
4718344779Sdim// values to live in a joint format operand in the MCInst encoding.
4719344779SdimOperandMatchResultTy
4720344779SdimAMDGPUAsmParser::parseDfmtNfmt(OperandVector &Operands) {
4721344779Sdim  SMLoc S = Parser.getTok().getLoc();
4722344779Sdim  int64_t Dfmt = 0, Nfmt = 0;
4723344779Sdim  // dfmt and nfmt can appear in either order, and each is optional.
4724344779Sdim  bool GotDfmt = false, GotNfmt = false;
4725344779Sdim  while (!GotDfmt || !GotNfmt) {
4726344779Sdim    if (!GotDfmt) {
4727344779Sdim      auto Res = parseIntWithPrefix("dfmt", Dfmt);
4728344779Sdim      if (Res != MatchOperand_NoMatch) {
4729344779Sdim        if (Res != MatchOperand_Success)
4730344779Sdim          return Res;
4731344779Sdim        if (Dfmt >= 16) {
4732344779Sdim          Error(Parser.getTok().getLoc(), "out of range dfmt");
4733344779Sdim          return MatchOperand_ParseFail;
4734344779Sdim        }
4735344779Sdim        GotDfmt = true;
4736344779Sdim        Parser.Lex();
4737344779Sdim        continue;
4738344779Sdim      }
4739344779Sdim    }
4740344779Sdim    if (!GotNfmt) {
4741344779Sdim      auto Res = parseIntWithPrefix("nfmt", Nfmt);
4742344779Sdim      if (Res != MatchOperand_NoMatch) {
4743344779Sdim        if (Res != MatchOperand_Success)
4744344779Sdim          return Res;
4745344779Sdim        if (Nfmt >= 8) {
4746344779Sdim          Error(Parser.getTok().getLoc(), "out of range nfmt");
4747344779Sdim          return MatchOperand_ParseFail;
4748344779Sdim        }
4749344779Sdim        GotNfmt = true;
4750344779Sdim        Parser.Lex();
4751344779Sdim        continue;
4752344779Sdim      }
4753344779Sdim    }
4754344779Sdim    break;
4755344779Sdim  }
4756344779Sdim  if (!GotDfmt && !GotNfmt)
4757344779Sdim    return MatchOperand_NoMatch;
4758344779Sdim  auto Format = Dfmt | Nfmt << 4;
4759344779Sdim  Operands.push_back(
4760344779Sdim      AMDGPUOperand::CreateImm(this, Format, S, AMDGPUOperand::ImmTyFORMAT));
4761344779Sdim  return MatchOperand_Success;
4762344779Sdim}
4763344779Sdim
4764284677Sdim//===----------------------------------------------------------------------===//
4765284677Sdim// ds
4766284677Sdim//===----------------------------------------------------------------------===//
4767284677Sdim
4768284677Sdimvoid AMDGPUAsmParser::cvtDSOffset01(MCInst &Inst,
4769284677Sdim                                    const OperandVector &Operands) {
4770309124Sdim  OptionalImmIndexMap OptionalIdx;
4771284677Sdim
4772284677Sdim  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4773284677Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4774284677Sdim
4775284677Sdim    // Add the register arguments
4776284677Sdim    if (Op.isReg()) {
4777284677Sdim      Op.addRegOperands(Inst, 1);
4778284677Sdim      continue;
4779284677Sdim    }
4780284677Sdim
4781284677Sdim    // Handle optional arguments
4782284677Sdim    OptionalIdx[Op.getImmTy()] = i;
4783284677Sdim  }
4784284677Sdim
4785309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset0);
4786309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset1);
4787309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
4788284677Sdim
4789284677Sdim  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4790284677Sdim}
4791284677Sdim
4792321369Sdimvoid AMDGPUAsmParser::cvtDSImpl(MCInst &Inst, const OperandVector &Operands,
4793321369Sdim                                bool IsGdsHardcoded) {
4794321369Sdim  OptionalImmIndexMap OptionalIdx;
4795284677Sdim
4796284677Sdim  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4797284677Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4798284677Sdim
4799284677Sdim    // Add the register arguments
4800284677Sdim    if (Op.isReg()) {
4801284677Sdim      Op.addRegOperands(Inst, 1);
4802284677Sdim      continue;
4803284677Sdim    }
4804284677Sdim
4805284677Sdim    if (Op.isToken() && Op.getToken() == "gds") {
4806321369Sdim      IsGdsHardcoded = true;
4807284677Sdim      continue;
4808284677Sdim    }
4809284677Sdim
4810284677Sdim    // Handle optional arguments
4811284677Sdim    OptionalIdx[Op.getImmTy()] = i;
4812284677Sdim  }
4813284677Sdim
4814321369Sdim  AMDGPUOperand::ImmTy OffsetType =
4815353358Sdim    (Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx10 ||
4816353358Sdim     Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_gfx6_gfx7 ||
4817321369Sdim     Inst.getOpcode() == AMDGPU::DS_SWIZZLE_B32_vi) ? AMDGPUOperand::ImmTySwizzle :
4818321369Sdim                                                      AMDGPUOperand::ImmTyOffset;
4819284677Sdim
4820321369Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, OffsetType);
4821321369Sdim
4822321369Sdim  if (!IsGdsHardcoded) {
4823309124Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGDS);
4824284677Sdim  }
4825284677Sdim  Inst.addOperand(MCOperand::createReg(AMDGPU::M0)); // m0
4826284677Sdim}
4827284677Sdim
4828314564Sdimvoid AMDGPUAsmParser::cvtExp(MCInst &Inst, const OperandVector &Operands) {
4829314564Sdim  OptionalImmIndexMap OptionalIdx;
4830284677Sdim
4831321369Sdim  unsigned OperandIdx[4];
4832314564Sdim  unsigned EnMask = 0;
4833314564Sdim  int SrcIdx = 0;
4834314564Sdim
4835314564Sdim  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
4836314564Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
4837314564Sdim
4838314564Sdim    // Add the register arguments
4839314564Sdim    if (Op.isReg()) {
4840321369Sdim      assert(SrcIdx < 4);
4841321369Sdim      OperandIdx[SrcIdx] = Inst.size();
4842314564Sdim      Op.addRegOperands(Inst, 1);
4843314564Sdim      ++SrcIdx;
4844314564Sdim      continue;
4845314564Sdim    }
4846314564Sdim
4847314564Sdim    if (Op.isOff()) {
4848321369Sdim      assert(SrcIdx < 4);
4849321369Sdim      OperandIdx[SrcIdx] = Inst.size();
4850321369Sdim      Inst.addOperand(MCOperand::createReg(AMDGPU::NoRegister));
4851314564Sdim      ++SrcIdx;
4852314564Sdim      continue;
4853314564Sdim    }
4854314564Sdim
4855314564Sdim    if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyExpTgt) {
4856314564Sdim      Op.addImmOperands(Inst, 1);
4857314564Sdim      continue;
4858314564Sdim    }
4859314564Sdim
4860314564Sdim    if (Op.isToken() && Op.getToken() == "done")
4861314564Sdim      continue;
4862314564Sdim
4863314564Sdim    // Handle optional arguments
4864314564Sdim    OptionalIdx[Op.getImmTy()] = i;
4865314564Sdim  }
4866314564Sdim
4867321369Sdim  assert(SrcIdx == 4);
4868321369Sdim
4869321369Sdim  bool Compr = false;
4870321369Sdim  if (OptionalIdx.find(AMDGPUOperand::ImmTyExpCompr) != OptionalIdx.end()) {
4871321369Sdim    Compr = true;
4872321369Sdim    Inst.getOperand(OperandIdx[1]) = Inst.getOperand(OperandIdx[2]);
4873321369Sdim    Inst.getOperand(OperandIdx[2]).setReg(AMDGPU::NoRegister);
4874321369Sdim    Inst.getOperand(OperandIdx[3]).setReg(AMDGPU::NoRegister);
4875321369Sdim  }
4876321369Sdim
4877321369Sdim  for (auto i = 0; i < SrcIdx; ++i) {
4878321369Sdim    if (Inst.getOperand(OperandIdx[i]).getReg() != AMDGPU::NoRegister) {
4879321369Sdim      EnMask |= Compr? (0x3 << i * 2) : (0x1 << i);
4880321369Sdim    }
4881321369Sdim  }
4882321369Sdim
4883314564Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpVM);
4884314564Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyExpCompr);
4885314564Sdim
4886314564Sdim  Inst.addOperand(MCOperand::createImm(EnMask));
4887314564Sdim}
4888314564Sdim
4889284677Sdim//===----------------------------------------------------------------------===//
4890284677Sdim// s_waitcnt
4891284677Sdim//===----------------------------------------------------------------------===//
4892284677Sdim
4893321369Sdimstatic bool
4894321369SdimencodeCnt(
4895344779Sdim  const AMDGPU::IsaVersion ISA,
4896321369Sdim  int64_t &IntVal,
4897321369Sdim  int64_t CntVal,
4898321369Sdim  bool Saturate,
4899344779Sdim  unsigned (*encode)(const IsaVersion &Version, unsigned, unsigned),
4900344779Sdim  unsigned (*decode)(const IsaVersion &Version, unsigned))
4901321369Sdim{
4902321369Sdim  bool Failed = false;
4903321369Sdim
4904321369Sdim  IntVal = encode(ISA, IntVal, CntVal);
4905321369Sdim  if (CntVal != decode(ISA, IntVal)) {
4906321369Sdim    if (Saturate) {
4907321369Sdim      IntVal = encode(ISA, IntVal, -1);
4908321369Sdim    } else {
4909321369Sdim      Failed = true;
4910321369Sdim    }
4911321369Sdim  }
4912321369Sdim  return Failed;
4913321369Sdim}
4914321369Sdim
4915284677Sdimbool AMDGPUAsmParser::parseCnt(int64_t &IntVal) {
4916284677Sdim
4917353358Sdim  SMLoc CntLoc = getLoc();
4918353358Sdim  StringRef CntName = getTokenStr();
4919284677Sdim
4920353358Sdim  if (!skipToken(AsmToken::Identifier, "expected a counter name") ||
4921353358Sdim      !skipToken(AsmToken::LParen, "expected a left parenthesis"))
4922353358Sdim    return false;
4923284677Sdim
4924353358Sdim  int64_t CntVal;
4925353358Sdim  SMLoc ValLoc = getLoc();
4926353358Sdim  if (!parseExpr(CntVal))
4927353358Sdim    return false;
4928284677Sdim
4929344779Sdim  AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
4930321369Sdim
4931321369Sdim  bool Failed = true;
4932321369Sdim  bool Sat = CntName.endswith("_sat");
4933321369Sdim
4934321369Sdim  if (CntName == "vmcnt" || CntName == "vmcnt_sat") {
4935321369Sdim    Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeVmcnt, decodeVmcnt);
4936321369Sdim  } else if (CntName == "expcnt" || CntName == "expcnt_sat") {
4937321369Sdim    Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeExpcnt, decodeExpcnt);
4938321369Sdim  } else if (CntName == "lgkmcnt" || CntName == "lgkmcnt_sat") {
4939321369Sdim    Failed = encodeCnt(ISA, IntVal, CntVal, Sat, encodeLgkmcnt, decodeLgkmcnt);
4940353358Sdim  } else {
4941353358Sdim    Error(CntLoc, "invalid counter name " + CntName);
4942353358Sdim    return false;
4943321369Sdim  }
4944321369Sdim
4945321369Sdim  if (Failed) {
4946321369Sdim    Error(ValLoc, "too large value for " + CntName);
4947353358Sdim    return false;
4948321369Sdim  }
4949284677Sdim
4950353358Sdim  if (!skipToken(AsmToken::RParen, "expected a closing parenthesis"))
4951353358Sdim    return false;
4952321369Sdim
4953353358Sdim  if (trySkipToken(AsmToken::Amp) || trySkipToken(AsmToken::Comma)) {
4954353358Sdim    if (isToken(AsmToken::EndOfStatement)) {
4955353358Sdim      Error(getLoc(), "expected a counter name");
4956353358Sdim      return false;
4957321369Sdim    }
4958321369Sdim  }
4959284677Sdim
4960353358Sdim  return true;
4961284677Sdim}
4962284677Sdim
4963314564SdimOperandMatchResultTy
4964284677SdimAMDGPUAsmParser::parseSWaitCntOps(OperandVector &Operands) {
4965344779Sdim  AMDGPU::IsaVersion ISA = AMDGPU::getIsaVersion(getSTI().getCPU());
4966321369Sdim  int64_t Waitcnt = getWaitcntBitMask(ISA);
4967353358Sdim  SMLoc S = getLoc();
4968284677Sdim
4969353358Sdim  // If parse failed, do not return error code
4970353358Sdim  // to avoid excessive error messages.
4971353358Sdim  if (isToken(AsmToken::Identifier) && peekToken().is(AsmToken::LParen)) {
4972353358Sdim    while (parseCnt(Waitcnt) && !isToken(AsmToken::EndOfStatement));
4973353358Sdim  } else {
4974353358Sdim    parseExpr(Waitcnt);
4975353358Sdim  }
4976284677Sdim
4977314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Waitcnt, S));
4978284677Sdim  return MatchOperand_Success;
4979284677Sdim}
4980284677Sdim
4981353358Sdimbool
4982353358SdimAMDGPUOperand::isSWaitCnt() const {
4983353358Sdim  return isImm();
4984353358Sdim}
4985309124Sdim
4986353358Sdim//===----------------------------------------------------------------------===//
4987353358Sdim// hwreg
4988353358Sdim//===----------------------------------------------------------------------===//
4989309124Sdim
4990353358Sdimbool
4991353358SdimAMDGPUAsmParser::parseHwregBody(OperandInfoTy &HwReg,
4992353358Sdim                                int64_t &Offset,
4993353358Sdim                                int64_t &Width) {
4994353358Sdim  using namespace llvm::AMDGPU::Hwreg;
4995309124Sdim
4996353358Sdim  // The register may be specified by name or using a numeric code
4997353358Sdim  if (isToken(AsmToken::Identifier) &&
4998353358Sdim      (HwReg.Id = getHwregId(getTokenStr())) >= 0) {
4999309124Sdim    HwReg.IsSymbolic = true;
5000353358Sdim    lex(); // skip message name
5001353358Sdim  } else if (!parseExpr(HwReg.Id)) {
5002309124Sdim    return false;
5003309124Sdim  }
5004309124Sdim
5005353358Sdim  if (trySkipToken(AsmToken::RParen))
5006309124Sdim    return true;
5007309124Sdim
5008353358Sdim  // parse optional params
5009353358Sdim  return
5010353358Sdim    skipToken(AsmToken::Comma, "expected a comma or a closing parenthesis") &&
5011353358Sdim    parseExpr(Offset) &&
5012353358Sdim    skipToken(AsmToken::Comma, "expected a comma") &&
5013353358Sdim    parseExpr(Width) &&
5014353358Sdim    skipToken(AsmToken::RParen, "expected a closing parenthesis");
5015353358Sdim}
5016309124Sdim
5017353358Sdimbool
5018353358SdimAMDGPUAsmParser::validateHwreg(const OperandInfoTy &HwReg,
5019353358Sdim                               const int64_t Offset,
5020353358Sdim                               const int64_t Width,
5021353358Sdim                               const SMLoc Loc) {
5022309124Sdim
5023353358Sdim  using namespace llvm::AMDGPU::Hwreg;
5024309124Sdim
5025353358Sdim  if (HwReg.IsSymbolic && !isValidHwreg(HwReg.Id, getSTI())) {
5026353358Sdim    Error(Loc, "specified hardware register is not supported on this GPU");
5027353358Sdim    return false;
5028353358Sdim  } else if (!isValidHwreg(HwReg.Id)) {
5029353358Sdim    Error(Loc, "invalid code of hardware register: only 6-bit values are legal");
5030353358Sdim    return false;
5031353358Sdim  } else if (!isValidHwregOffset(Offset)) {
5032353358Sdim    Error(Loc, "invalid bit offset: only 5-bit values are legal");
5033353358Sdim    return false;
5034353358Sdim  } else if (!isValidHwregWidth(Width)) {
5035353358Sdim    Error(Loc, "invalid bitfield width: only values from 1 to 32 are legal");
5036353358Sdim    return false;
5037353358Sdim  }
5038353358Sdim  return true;
5039309124Sdim}
5040309124Sdim
5041353358SdimOperandMatchResultTy
5042353358SdimAMDGPUAsmParser::parseHwreg(OperandVector &Operands) {
5043309124Sdim  using namespace llvm::AMDGPU::Hwreg;
5044309124Sdim
5045353358Sdim  int64_t ImmVal = 0;
5046353358Sdim  SMLoc Loc = getLoc();
5047309124Sdim
5048353358Sdim  // If parse failed, do not return error code
5049353358Sdim  // to avoid excessive error messages.
5050353358Sdim  if (trySkipId("hwreg", AsmToken::LParen)) {
5051353358Sdim    OperandInfoTy HwReg(ID_UNKNOWN_);
5052353358Sdim    int64_t Offset = OFFSET_DEFAULT_;
5053353358Sdim    int64_t Width = WIDTH_DEFAULT_;
5054353358Sdim    if (parseHwregBody(HwReg, Offset, Width) &&
5055353358Sdim        validateHwreg(HwReg, Offset, Width, Loc)) {
5056353358Sdim      ImmVal = encodeHwreg(HwReg.Id, Offset, Width);
5057353358Sdim    }
5058353358Sdim  } else if (parseExpr(ImmVal)) {
5059353358Sdim    if (ImmVal < 0 || !isUInt<16>(ImmVal))
5060353358Sdim      Error(Loc, "invalid immediate: only 16-bit values are legal");
5061353358Sdim  }
5062309124Sdim
5063353358Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTyHwreg));
5064309124Sdim  return MatchOperand_Success;
5065309124Sdim}
5066309124Sdim
5067309124Sdimbool AMDGPUOperand::isHwreg() const {
5068309124Sdim  return isImmTy(ImmTyHwreg);
5069309124Sdim}
5070309124Sdim
5071353358Sdim//===----------------------------------------------------------------------===//
5072353358Sdim// sendmsg
5073353358Sdim//===----------------------------------------------------------------------===//
5074353358Sdim
5075353358Sdimbool
5076353358SdimAMDGPUAsmParser::parseSendMsgBody(OperandInfoTy &Msg,
5077353358Sdim                                  OperandInfoTy &Op,
5078353358Sdim                                  OperandInfoTy &Stream) {
5079309124Sdim  using namespace llvm::AMDGPU::SendMsg;
5080309124Sdim
5081353358Sdim  if (isToken(AsmToken::Identifier) && (Msg.Id = getMsgId(getTokenStr())) >= 0) {
5082353358Sdim    Msg.IsSymbolic = true;
5083353358Sdim    lex(); // skip message name
5084353358Sdim  } else if (!parseExpr(Msg.Id)) {
5085353358Sdim    return false;
5086353358Sdim  }
5087309124Sdim
5088353358Sdim  if (trySkipToken(AsmToken::Comma)) {
5089353358Sdim    Op.IsDefined = true;
5090353358Sdim    if (isToken(AsmToken::Identifier) &&
5091353358Sdim        (Op.Id = getMsgOpId(Msg.Id, getTokenStr())) >= 0) {
5092353358Sdim      lex(); // skip operation name
5093353358Sdim    } else if (!parseExpr(Op.Id)) {
5094353358Sdim      return false;
5095353358Sdim    }
5096309124Sdim
5097353358Sdim    if (trySkipToken(AsmToken::Comma)) {
5098353358Sdim      Stream.IsDefined = true;
5099353358Sdim      if (!parseExpr(Stream.Id))
5100353358Sdim        return false;
5101309124Sdim    }
5102309124Sdim  }
5103309124Sdim
5104353358Sdim  return skipToken(AsmToken::RParen, "expected a closing parenthesis");
5105353358Sdim}
5106353358Sdim
5107353358Sdimbool
5108353358SdimAMDGPUAsmParser::validateSendMsg(const OperandInfoTy &Msg,
5109353358Sdim                                 const OperandInfoTy &Op,
5110353358Sdim                                 const OperandInfoTy &Stream,
5111353358Sdim                                 const SMLoc S) {
5112353358Sdim  using namespace llvm::AMDGPU::SendMsg;
5113353358Sdim
5114353358Sdim  // Validation strictness depends on whether message is specified
5115353358Sdim  // in a symbolc or in a numeric form. In the latter case
5116353358Sdim  // only encoding possibility is checked.
5117353358Sdim  bool Strict = Msg.IsSymbolic;
5118353358Sdim
5119353358Sdim  if (!isValidMsgId(Msg.Id, getSTI(), Strict)) {
5120353358Sdim    Error(S, "invalid message id");
5121309124Sdim    return false;
5122353358Sdim  } else if (Strict && (msgRequiresOp(Msg.Id) != Op.IsDefined)) {
5123353358Sdim    Error(S, Op.IsDefined ?
5124353358Sdim             "message does not support operations" :
5125353358Sdim             "missing message operation");
5126353358Sdim    return false;
5127353358Sdim  } else if (!isValidMsgOp(Msg.Id, Op.Id, Strict)) {
5128353358Sdim    Error(S, "invalid operation id");
5129353358Sdim    return false;
5130353358Sdim  } else if (Strict && !msgSupportsStream(Msg.Id, Op.Id) && Stream.IsDefined) {
5131353358Sdim    Error(S, "message operation does not support streams");
5132353358Sdim    return false;
5133353358Sdim  } else if (!isValidMsgStream(Msg.Id, Op.Id, Stream.Id, Strict)) {
5134353358Sdim    Error(S, "invalid message stream id");
5135353358Sdim    return false;
5136309124Sdim  }
5137353358Sdim  return true;
5138353358Sdim}
5139309124Sdim
5140353358SdimOperandMatchResultTy
5141353358SdimAMDGPUAsmParser::parseSendMsgOp(OperandVector &Operands) {
5142353358Sdim  using namespace llvm::AMDGPU::SendMsg;
5143309124Sdim
5144353358Sdim  int64_t ImmVal = 0;
5145353358Sdim  SMLoc Loc = getLoc();
5146353358Sdim
5147353358Sdim  // If parse failed, do not return error code
5148353358Sdim  // to avoid excessive error messages.
5149353358Sdim  if (trySkipId("sendmsg", AsmToken::LParen)) {
5150353358Sdim    OperandInfoTy Msg(ID_UNKNOWN_);
5151353358Sdim    OperandInfoTy Op(OP_NONE_);
5152353358Sdim    OperandInfoTy Stream(STREAM_ID_NONE_);
5153353358Sdim    if (parseSendMsgBody(Msg, Op, Stream) &&
5154353358Sdim        validateSendMsg(Msg, Op, Stream, Loc)) {
5155353358Sdim      ImmVal = encodeMsg(Msg.Id, Op.Id, Stream.Id);
5156309124Sdim    }
5157353358Sdim  } else if (parseExpr(ImmVal)) {
5158353358Sdim    if (ImmVal < 0 || !isUInt<16>(ImmVal))
5159353358Sdim      Error(Loc, "invalid immediate: only 16-bit values are legal");
5160309124Sdim  }
5161309124Sdim
5162353358Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, ImmVal, Loc, AMDGPUOperand::ImmTySendMsg));
5163353358Sdim  return MatchOperand_Success;
5164353358Sdim}
5165309124Sdim
5166353358Sdimbool AMDGPUOperand::isSendMsg() const {
5167353358Sdim  return isImmTy(ImmTySendMsg);
5168353358Sdim}
5169309124Sdim
5170353358Sdim//===----------------------------------------------------------------------===//
5171353358Sdim// v_interp
5172353358Sdim//===----------------------------------------------------------------------===//
5173309124Sdim
5174314564SdimOperandMatchResultTy AMDGPUAsmParser::parseInterpSlot(OperandVector &Operands) {
5175314564Sdim  if (getLexer().getKind() != AsmToken::Identifier)
5176314564Sdim    return MatchOperand_NoMatch;
5177314564Sdim
5178314564Sdim  StringRef Str = Parser.getTok().getString();
5179314564Sdim  int Slot = StringSwitch<int>(Str)
5180314564Sdim    .Case("p10", 0)
5181314564Sdim    .Case("p20", 1)
5182314564Sdim    .Case("p0", 2)
5183314564Sdim    .Default(-1);
5184314564Sdim
5185314564Sdim  SMLoc S = Parser.getTok().getLoc();
5186314564Sdim  if (Slot == -1)
5187314564Sdim    return MatchOperand_ParseFail;
5188314564Sdim
5189314564Sdim  Parser.Lex();
5190314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Slot, S,
5191314564Sdim                                              AMDGPUOperand::ImmTyInterpSlot));
5192314564Sdim  return MatchOperand_Success;
5193314564Sdim}
5194314564Sdim
5195314564SdimOperandMatchResultTy AMDGPUAsmParser::parseInterpAttr(OperandVector &Operands) {
5196314564Sdim  if (getLexer().getKind() != AsmToken::Identifier)
5197314564Sdim    return MatchOperand_NoMatch;
5198314564Sdim
5199314564Sdim  StringRef Str = Parser.getTok().getString();
5200314564Sdim  if (!Str.startswith("attr"))
5201314564Sdim    return MatchOperand_NoMatch;
5202314564Sdim
5203314564Sdim  StringRef Chan = Str.take_back(2);
5204314564Sdim  int AttrChan = StringSwitch<int>(Chan)
5205314564Sdim    .Case(".x", 0)
5206314564Sdim    .Case(".y", 1)
5207314564Sdim    .Case(".z", 2)
5208314564Sdim    .Case(".w", 3)
5209314564Sdim    .Default(-1);
5210314564Sdim  if (AttrChan == -1)
5211314564Sdim    return MatchOperand_ParseFail;
5212314564Sdim
5213314564Sdim  Str = Str.drop_back(2).drop_front(4);
5214314564Sdim
5215314564Sdim  uint8_t Attr;
5216314564Sdim  if (Str.getAsInteger(10, Attr))
5217314564Sdim    return MatchOperand_ParseFail;
5218314564Sdim
5219314564Sdim  SMLoc S = Parser.getTok().getLoc();
5220314564Sdim  Parser.Lex();
5221314564Sdim  if (Attr > 63) {
5222314564Sdim    Error(S, "out of bounds attr");
5223314564Sdim    return MatchOperand_Success;
5224314564Sdim  }
5225314564Sdim
5226314564Sdim  SMLoc SChan = SMLoc::getFromPointer(Chan.data());
5227314564Sdim
5228314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Attr, S,
5229314564Sdim                                              AMDGPUOperand::ImmTyInterpAttr));
5230314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, AttrChan, SChan,
5231314564Sdim                                              AMDGPUOperand::ImmTyAttrChan));
5232314564Sdim  return MatchOperand_Success;
5233314564Sdim}
5234314564Sdim
5235353358Sdim//===----------------------------------------------------------------------===//
5236353358Sdim// exp
5237353358Sdim//===----------------------------------------------------------------------===//
5238353358Sdim
5239314564Sdimvoid AMDGPUAsmParser::errorExpTgt() {
5240314564Sdim  Error(Parser.getTok().getLoc(), "invalid exp target");
5241314564Sdim}
5242314564Sdim
5243314564SdimOperandMatchResultTy AMDGPUAsmParser::parseExpTgtImpl(StringRef Str,
5244314564Sdim                                                      uint8_t &Val) {
5245314564Sdim  if (Str == "null") {
5246314564Sdim    Val = 9;
5247314564Sdim    return MatchOperand_Success;
5248314564Sdim  }
5249314564Sdim
5250314564Sdim  if (Str.startswith("mrt")) {
5251314564Sdim    Str = Str.drop_front(3);
5252314564Sdim    if (Str == "z") { // == mrtz
5253314564Sdim      Val = 8;
5254314564Sdim      return MatchOperand_Success;
5255314564Sdim    }
5256314564Sdim
5257314564Sdim    if (Str.getAsInteger(10, Val))
5258314564Sdim      return MatchOperand_ParseFail;
5259314564Sdim
5260314564Sdim    if (Val > 7)
5261314564Sdim      errorExpTgt();
5262314564Sdim
5263314564Sdim    return MatchOperand_Success;
5264314564Sdim  }
5265314564Sdim
5266314564Sdim  if (Str.startswith("pos")) {
5267314564Sdim    Str = Str.drop_front(3);
5268314564Sdim    if (Str.getAsInteger(10, Val))
5269314564Sdim      return MatchOperand_ParseFail;
5270314564Sdim
5271353358Sdim    if (Val > 4 || (Val == 4 && !isGFX10()))
5272314564Sdim      errorExpTgt();
5273314564Sdim
5274314564Sdim    Val += 12;
5275314564Sdim    return MatchOperand_Success;
5276314564Sdim  }
5277314564Sdim
5278353358Sdim  if (isGFX10() && Str == "prim") {
5279353358Sdim    Val = 20;
5280353358Sdim    return MatchOperand_Success;
5281353358Sdim  }
5282353358Sdim
5283314564Sdim  if (Str.startswith("param")) {
5284314564Sdim    Str = Str.drop_front(5);
5285314564Sdim    if (Str.getAsInteger(10, Val))
5286314564Sdim      return MatchOperand_ParseFail;
5287314564Sdim
5288314564Sdim    if (Val >= 32)
5289314564Sdim      errorExpTgt();
5290314564Sdim
5291314564Sdim    Val += 32;
5292314564Sdim    return MatchOperand_Success;
5293314564Sdim  }
5294314564Sdim
5295314564Sdim  if (Str.startswith("invalid_target_")) {
5296314564Sdim    Str = Str.drop_front(15);
5297314564Sdim    if (Str.getAsInteger(10, Val))
5298314564Sdim      return MatchOperand_ParseFail;
5299314564Sdim
5300314564Sdim    errorExpTgt();
5301314564Sdim    return MatchOperand_Success;
5302314564Sdim  }
5303314564Sdim
5304314564Sdim  return MatchOperand_NoMatch;
5305314564Sdim}
5306314564Sdim
5307314564SdimOperandMatchResultTy AMDGPUAsmParser::parseExpTgt(OperandVector &Operands) {
5308314564Sdim  uint8_t Val;
5309314564Sdim  StringRef Str = Parser.getTok().getString();
5310314564Sdim
5311314564Sdim  auto Res = parseExpTgtImpl(Str, Val);
5312314564Sdim  if (Res != MatchOperand_Success)
5313314564Sdim    return Res;
5314314564Sdim
5315314564Sdim  SMLoc S = Parser.getTok().getLoc();
5316314564Sdim  Parser.Lex();
5317314564Sdim
5318314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Val, S,
5319314564Sdim                                              AMDGPUOperand::ImmTyExpTgt));
5320314564Sdim  return MatchOperand_Success;
5321314564Sdim}
5322314564Sdim
5323353358Sdim//===----------------------------------------------------------------------===//
5324353358Sdim// parser helpers
5325353358Sdim//===----------------------------------------------------------------------===//
5326309124Sdim
5327353358Sdimbool
5328353358SdimAMDGPUAsmParser::isId(const AsmToken &Token, const StringRef Id) const {
5329353358Sdim  return Token.is(AsmToken::Identifier) && Token.getString() == Id;
5330353358Sdim}
5331309124Sdim
5332353358Sdimbool
5333353358SdimAMDGPUAsmParser::isId(const StringRef Id) const {
5334353358Sdim  return isId(getToken(), Id);
5335309124Sdim}
5336309124Sdim
5337353358Sdimbool
5338353358SdimAMDGPUAsmParser::isToken(const AsmToken::TokenKind Kind) const {
5339353358Sdim  return getTokenKind() == Kind;
5340309124Sdim}
5341309124Sdim
5342321369Sdimbool
5343321369SdimAMDGPUAsmParser::trySkipId(const StringRef Id) {
5344353358Sdim  if (isId(Id)) {
5345353358Sdim    lex();
5346321369Sdim    return true;
5347321369Sdim  }
5348321369Sdim  return false;
5349321369Sdim}
5350321369Sdim
5351321369Sdimbool
5352353358SdimAMDGPUAsmParser::trySkipId(const StringRef Id, const AsmToken::TokenKind Kind) {
5353353358Sdim  if (isId(Id) && peekToken().is(Kind)) {
5354353358Sdim    lex();
5355353358Sdim    lex();
5356353358Sdim    return true;
5357353358Sdim  }
5358353358Sdim  return false;
5359353358Sdim}
5360353358Sdim
5361353358Sdimbool
5362321369SdimAMDGPUAsmParser::trySkipToken(const AsmToken::TokenKind Kind) {
5363353358Sdim  if (isToken(Kind)) {
5364353358Sdim    lex();
5365321369Sdim    return true;
5366321369Sdim  }
5367321369Sdim  return false;
5368321369Sdim}
5369321369Sdim
5370321369Sdimbool
5371321369SdimAMDGPUAsmParser::skipToken(const AsmToken::TokenKind Kind,
5372321369Sdim                           const StringRef ErrMsg) {
5373321369Sdim  if (!trySkipToken(Kind)) {
5374353358Sdim    Error(getLoc(), ErrMsg);
5375321369Sdim    return false;
5376321369Sdim  }
5377321369Sdim  return true;
5378321369Sdim}
5379321369Sdim
5380321369Sdimbool
5381321369SdimAMDGPUAsmParser::parseExpr(int64_t &Imm) {
5382321369Sdim  return !getParser().parseAbsoluteExpression(Imm);
5383321369Sdim}
5384321369Sdim
5385321369Sdimbool
5386360784SdimAMDGPUAsmParser::parseExpr(OperandVector &Operands) {
5387360784Sdim  SMLoc S = getLoc();
5388360784Sdim
5389360784Sdim  const MCExpr *Expr;
5390360784Sdim  if (Parser.parseExpression(Expr))
5391360784Sdim    return false;
5392360784Sdim
5393360784Sdim  int64_t IntVal;
5394360784Sdim  if (Expr->evaluateAsAbsolute(IntVal)) {
5395360784Sdim    Operands.push_back(AMDGPUOperand::CreateImm(this, IntVal, S));
5396360784Sdim  } else {
5397360784Sdim    Operands.push_back(AMDGPUOperand::CreateExpr(this, Expr, S));
5398360784Sdim  }
5399360784Sdim  return true;
5400360784Sdim}
5401360784Sdim
5402360784Sdimbool
5403321369SdimAMDGPUAsmParser::parseString(StringRef &Val, const StringRef ErrMsg) {
5404353358Sdim  if (isToken(AsmToken::String)) {
5405353358Sdim    Val = getToken().getStringContents();
5406353358Sdim    lex();
5407321369Sdim    return true;
5408321369Sdim  } else {
5409353358Sdim    Error(getLoc(), ErrMsg);
5410321369Sdim    return false;
5411321369Sdim  }
5412321369Sdim}
5413321369Sdim
5414353358SdimAsmToken
5415353358SdimAMDGPUAsmParser::getToken() const {
5416353358Sdim  return Parser.getTok();
5417353358Sdim}
5418353358Sdim
5419353358SdimAsmToken
5420353358SdimAMDGPUAsmParser::peekToken() {
5421353358Sdim  return getLexer().peekTok();
5422353358Sdim}
5423353358Sdim
5424353358Sdimvoid
5425353358SdimAMDGPUAsmParser::peekTokens(MutableArrayRef<AsmToken> Tokens) {
5426353358Sdim  auto TokCount = getLexer().peekTokens(Tokens);
5427353358Sdim
5428353358Sdim  for (auto Idx = TokCount; Idx < Tokens.size(); ++Idx)
5429353358Sdim    Tokens[Idx] = AsmToken(AsmToken::Error, "");
5430353358Sdim}
5431353358Sdim
5432353358SdimAsmToken::TokenKind
5433353358SdimAMDGPUAsmParser::getTokenKind() const {
5434353358Sdim  return getLexer().getKind();
5435353358Sdim}
5436353358Sdim
5437353358SdimSMLoc
5438353358SdimAMDGPUAsmParser::getLoc() const {
5439353358Sdim  return getToken().getLoc();
5440353358Sdim}
5441353358Sdim
5442353358SdimStringRef
5443353358SdimAMDGPUAsmParser::getTokenStr() const {
5444353358Sdim  return getToken().getString();
5445353358Sdim}
5446353358Sdim
5447353358Sdimvoid
5448353358SdimAMDGPUAsmParser::lex() {
5449353358Sdim  Parser.Lex();
5450353358Sdim}
5451353358Sdim
5452321369Sdim//===----------------------------------------------------------------------===//
5453321369Sdim// swizzle
5454321369Sdim//===----------------------------------------------------------------------===//
5455321369Sdim
5456321369SdimLLVM_READNONE
5457321369Sdimstatic unsigned
5458321369SdimencodeBitmaskPerm(const unsigned AndMask,
5459321369Sdim                  const unsigned OrMask,
5460321369Sdim                  const unsigned XorMask) {
5461321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5462321369Sdim
5463321369Sdim  return BITMASK_PERM_ENC |
5464321369Sdim         (AndMask << BITMASK_AND_SHIFT) |
5465321369Sdim         (OrMask  << BITMASK_OR_SHIFT)  |
5466321369Sdim         (XorMask << BITMASK_XOR_SHIFT);
5467321369Sdim}
5468321369Sdim
5469321369Sdimbool
5470321369SdimAMDGPUAsmParser::parseSwizzleOperands(const unsigned OpNum, int64_t* Op,
5471321369Sdim                                      const unsigned MinVal,
5472321369Sdim                                      const unsigned MaxVal,
5473321369Sdim                                      const StringRef ErrMsg) {
5474321369Sdim  for (unsigned i = 0; i < OpNum; ++i) {
5475321369Sdim    if (!skipToken(AsmToken::Comma, "expected a comma")){
5476321369Sdim      return false;
5477321369Sdim    }
5478321369Sdim    SMLoc ExprLoc = Parser.getTok().getLoc();
5479321369Sdim    if (!parseExpr(Op[i])) {
5480321369Sdim      return false;
5481321369Sdim    }
5482321369Sdim    if (Op[i] < MinVal || Op[i] > MaxVal) {
5483321369Sdim      Error(ExprLoc, ErrMsg);
5484321369Sdim      return false;
5485321369Sdim    }
5486321369Sdim  }
5487321369Sdim
5488321369Sdim  return true;
5489321369Sdim}
5490321369Sdim
5491321369Sdimbool
5492321369SdimAMDGPUAsmParser::parseSwizzleQuadPerm(int64_t &Imm) {
5493321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5494321369Sdim
5495321369Sdim  int64_t Lane[LANE_NUM];
5496321369Sdim  if (parseSwizzleOperands(LANE_NUM, Lane, 0, LANE_MAX,
5497321369Sdim                           "expected a 2-bit lane id")) {
5498321369Sdim    Imm = QUAD_PERM_ENC;
5499353358Sdim    for (unsigned I = 0; I < LANE_NUM; ++I) {
5500353358Sdim      Imm |= Lane[I] << (LANE_SHIFT * I);
5501321369Sdim    }
5502321369Sdim    return true;
5503321369Sdim  }
5504321369Sdim  return false;
5505321369Sdim}
5506321369Sdim
5507321369Sdimbool
5508321369SdimAMDGPUAsmParser::parseSwizzleBroadcast(int64_t &Imm) {
5509321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5510321369Sdim
5511321369Sdim  SMLoc S = Parser.getTok().getLoc();
5512321369Sdim  int64_t GroupSize;
5513321369Sdim  int64_t LaneIdx;
5514321369Sdim
5515321369Sdim  if (!parseSwizzleOperands(1, &GroupSize,
5516321369Sdim                            2, 32,
5517321369Sdim                            "group size must be in the interval [2,32]")) {
5518321369Sdim    return false;
5519321369Sdim  }
5520321369Sdim  if (!isPowerOf2_64(GroupSize)) {
5521321369Sdim    Error(S, "group size must be a power of two");
5522321369Sdim    return false;
5523321369Sdim  }
5524321369Sdim  if (parseSwizzleOperands(1, &LaneIdx,
5525321369Sdim                           0, GroupSize - 1,
5526321369Sdim                           "lane id must be in the interval [0,group size - 1]")) {
5527321369Sdim    Imm = encodeBitmaskPerm(BITMASK_MAX - GroupSize + 1, LaneIdx, 0);
5528321369Sdim    return true;
5529321369Sdim  }
5530321369Sdim  return false;
5531321369Sdim}
5532321369Sdim
5533321369Sdimbool
5534321369SdimAMDGPUAsmParser::parseSwizzleReverse(int64_t &Imm) {
5535321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5536321369Sdim
5537321369Sdim  SMLoc S = Parser.getTok().getLoc();
5538321369Sdim  int64_t GroupSize;
5539321369Sdim
5540321369Sdim  if (!parseSwizzleOperands(1, &GroupSize,
5541321369Sdim      2, 32, "group size must be in the interval [2,32]")) {
5542321369Sdim    return false;
5543321369Sdim  }
5544321369Sdim  if (!isPowerOf2_64(GroupSize)) {
5545321369Sdim    Error(S, "group size must be a power of two");
5546321369Sdim    return false;
5547321369Sdim  }
5548321369Sdim
5549321369Sdim  Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize - 1);
5550321369Sdim  return true;
5551321369Sdim}
5552321369Sdim
5553321369Sdimbool
5554321369SdimAMDGPUAsmParser::parseSwizzleSwap(int64_t &Imm) {
5555321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5556321369Sdim
5557321369Sdim  SMLoc S = Parser.getTok().getLoc();
5558321369Sdim  int64_t GroupSize;
5559321369Sdim
5560321369Sdim  if (!parseSwizzleOperands(1, &GroupSize,
5561321369Sdim      1, 16, "group size must be in the interval [1,16]")) {
5562321369Sdim    return false;
5563321369Sdim  }
5564321369Sdim  if (!isPowerOf2_64(GroupSize)) {
5565321369Sdim    Error(S, "group size must be a power of two");
5566321369Sdim    return false;
5567321369Sdim  }
5568321369Sdim
5569321369Sdim  Imm = encodeBitmaskPerm(BITMASK_MAX, 0, GroupSize);
5570321369Sdim  return true;
5571321369Sdim}
5572321369Sdim
5573321369Sdimbool
5574321369SdimAMDGPUAsmParser::parseSwizzleBitmaskPerm(int64_t &Imm) {
5575321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5576321369Sdim
5577321369Sdim  if (!skipToken(AsmToken::Comma, "expected a comma")) {
5578321369Sdim    return false;
5579321369Sdim  }
5580321369Sdim
5581321369Sdim  StringRef Ctl;
5582321369Sdim  SMLoc StrLoc = Parser.getTok().getLoc();
5583321369Sdim  if (!parseString(Ctl)) {
5584321369Sdim    return false;
5585321369Sdim  }
5586321369Sdim  if (Ctl.size() != BITMASK_WIDTH) {
5587321369Sdim    Error(StrLoc, "expected a 5-character mask");
5588321369Sdim    return false;
5589321369Sdim  }
5590321369Sdim
5591321369Sdim  unsigned AndMask = 0;
5592321369Sdim  unsigned OrMask = 0;
5593321369Sdim  unsigned XorMask = 0;
5594321369Sdim
5595321369Sdim  for (size_t i = 0; i < Ctl.size(); ++i) {
5596321369Sdim    unsigned Mask = 1 << (BITMASK_WIDTH - 1 - i);
5597321369Sdim    switch(Ctl[i]) {
5598321369Sdim    default:
5599321369Sdim      Error(StrLoc, "invalid mask");
5600321369Sdim      return false;
5601321369Sdim    case '0':
5602321369Sdim      break;
5603321369Sdim    case '1':
5604321369Sdim      OrMask |= Mask;
5605321369Sdim      break;
5606321369Sdim    case 'p':
5607321369Sdim      AndMask |= Mask;
5608321369Sdim      break;
5609321369Sdim    case 'i':
5610321369Sdim      AndMask |= Mask;
5611321369Sdim      XorMask |= Mask;
5612321369Sdim      break;
5613321369Sdim    }
5614321369Sdim  }
5615321369Sdim
5616321369Sdim  Imm = encodeBitmaskPerm(AndMask, OrMask, XorMask);
5617321369Sdim  return true;
5618321369Sdim}
5619321369Sdim
5620321369Sdimbool
5621321369SdimAMDGPUAsmParser::parseSwizzleOffset(int64_t &Imm) {
5622321369Sdim
5623321369Sdim  SMLoc OffsetLoc = Parser.getTok().getLoc();
5624321369Sdim
5625321369Sdim  if (!parseExpr(Imm)) {
5626321369Sdim    return false;
5627321369Sdim  }
5628321369Sdim  if (!isUInt<16>(Imm)) {
5629321369Sdim    Error(OffsetLoc, "expected a 16-bit offset");
5630321369Sdim    return false;
5631321369Sdim  }
5632321369Sdim  return true;
5633321369Sdim}
5634321369Sdim
5635321369Sdimbool
5636321369SdimAMDGPUAsmParser::parseSwizzleMacro(int64_t &Imm) {
5637321369Sdim  using namespace llvm::AMDGPU::Swizzle;
5638321369Sdim
5639321369Sdim  if (skipToken(AsmToken::LParen, "expected a left parentheses")) {
5640321369Sdim
5641321369Sdim    SMLoc ModeLoc = Parser.getTok().getLoc();
5642321369Sdim    bool Ok = false;
5643321369Sdim
5644321369Sdim    if (trySkipId(IdSymbolic[ID_QUAD_PERM])) {
5645321369Sdim      Ok = parseSwizzleQuadPerm(Imm);
5646321369Sdim    } else if (trySkipId(IdSymbolic[ID_BITMASK_PERM])) {
5647321369Sdim      Ok = parseSwizzleBitmaskPerm(Imm);
5648321369Sdim    } else if (trySkipId(IdSymbolic[ID_BROADCAST])) {
5649321369Sdim      Ok = parseSwizzleBroadcast(Imm);
5650321369Sdim    } else if (trySkipId(IdSymbolic[ID_SWAP])) {
5651321369Sdim      Ok = parseSwizzleSwap(Imm);
5652321369Sdim    } else if (trySkipId(IdSymbolic[ID_REVERSE])) {
5653321369Sdim      Ok = parseSwizzleReverse(Imm);
5654321369Sdim    } else {
5655321369Sdim      Error(ModeLoc, "expected a swizzle mode");
5656321369Sdim    }
5657321369Sdim
5658321369Sdim    return Ok && skipToken(AsmToken::RParen, "expected a closing parentheses");
5659321369Sdim  }
5660321369Sdim
5661321369Sdim  return false;
5662321369Sdim}
5663321369Sdim
5664321369SdimOperandMatchResultTy
5665321369SdimAMDGPUAsmParser::parseSwizzleOp(OperandVector &Operands) {
5666321369Sdim  SMLoc S = Parser.getTok().getLoc();
5667321369Sdim  int64_t Imm = 0;
5668321369Sdim
5669321369Sdim  if (trySkipId("offset")) {
5670321369Sdim
5671321369Sdim    bool Ok = false;
5672321369Sdim    if (skipToken(AsmToken::Colon, "expected a colon")) {
5673321369Sdim      if (trySkipId("swizzle")) {
5674321369Sdim        Ok = parseSwizzleMacro(Imm);
5675321369Sdim      } else {
5676321369Sdim        Ok = parseSwizzleOffset(Imm);
5677321369Sdim      }
5678321369Sdim    }
5679321369Sdim
5680321369Sdim    Operands.push_back(AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTySwizzle));
5681321369Sdim
5682321369Sdim    return Ok? MatchOperand_Success : MatchOperand_ParseFail;
5683321369Sdim  } else {
5684327952Sdim    // Swizzle "offset" operand is optional.
5685327952Sdim    // If it is omitted, try parsing other optional operands.
5686327952Sdim    return parseOptionalOpr(Operands);
5687321369Sdim  }
5688321369Sdim}
5689321369Sdim
5690321369Sdimbool
5691321369SdimAMDGPUOperand::isSwizzle() const {
5692321369Sdim  return isImmTy(ImmTySwizzle);
5693321369Sdim}
5694321369Sdim
5695321369Sdim//===----------------------------------------------------------------------===//
5696353358Sdim// VGPR Index Mode
5697353358Sdim//===----------------------------------------------------------------------===//
5698353358Sdim
5699353358Sdimint64_t AMDGPUAsmParser::parseGPRIdxMacro() {
5700353358Sdim
5701353358Sdim  using namespace llvm::AMDGPU::VGPRIndexMode;
5702353358Sdim
5703353358Sdim  if (trySkipToken(AsmToken::RParen)) {
5704353358Sdim    return OFF;
5705353358Sdim  }
5706353358Sdim
5707353358Sdim  int64_t Imm = 0;
5708353358Sdim
5709353358Sdim  while (true) {
5710353358Sdim    unsigned Mode = 0;
5711353358Sdim    SMLoc S = Parser.getTok().getLoc();
5712353358Sdim
5713353358Sdim    for (unsigned ModeId = ID_MIN; ModeId <= ID_MAX; ++ModeId) {
5714353358Sdim      if (trySkipId(IdSymbolic[ModeId])) {
5715353358Sdim        Mode = 1 << ModeId;
5716353358Sdim        break;
5717353358Sdim      }
5718353358Sdim    }
5719353358Sdim
5720353358Sdim    if (Mode == 0) {
5721353358Sdim      Error(S, (Imm == 0)?
5722353358Sdim               "expected a VGPR index mode or a closing parenthesis" :
5723353358Sdim               "expected a VGPR index mode");
5724353358Sdim      break;
5725353358Sdim    }
5726353358Sdim
5727353358Sdim    if (Imm & Mode) {
5728353358Sdim      Error(S, "duplicate VGPR index mode");
5729353358Sdim      break;
5730353358Sdim    }
5731353358Sdim    Imm |= Mode;
5732353358Sdim
5733353358Sdim    if (trySkipToken(AsmToken::RParen))
5734353358Sdim      break;
5735353358Sdim    if (!skipToken(AsmToken::Comma,
5736353358Sdim                   "expected a comma or a closing parenthesis"))
5737353358Sdim      break;
5738353358Sdim  }
5739353358Sdim
5740353358Sdim  return Imm;
5741353358Sdim}
5742353358Sdim
5743353358SdimOperandMatchResultTy
5744353358SdimAMDGPUAsmParser::parseGPRIdxMode(OperandVector &Operands) {
5745353358Sdim
5746353358Sdim  int64_t Imm = 0;
5747353358Sdim  SMLoc S = Parser.getTok().getLoc();
5748353358Sdim
5749353358Sdim  if (getLexer().getKind() == AsmToken::Identifier &&
5750353358Sdim      Parser.getTok().getString() == "gpr_idx" &&
5751353358Sdim      getLexer().peekTok().is(AsmToken::LParen)) {
5752353358Sdim
5753353358Sdim    Parser.Lex();
5754353358Sdim    Parser.Lex();
5755353358Sdim
5756353358Sdim    // If parse failed, trigger an error but do not return error code
5757353358Sdim    // to avoid excessive error messages.
5758353358Sdim    Imm = parseGPRIdxMacro();
5759353358Sdim
5760353358Sdim  } else {
5761353358Sdim    if (getParser().parseAbsoluteExpression(Imm))
5762353358Sdim      return MatchOperand_NoMatch;
5763353358Sdim    if (Imm < 0 || !isUInt<4>(Imm)) {
5764353358Sdim      Error(S, "invalid immediate: only 4-bit values are legal");
5765353358Sdim    }
5766353358Sdim  }
5767353358Sdim
5768353358Sdim  Operands.push_back(
5769353358Sdim      AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyGprIdxMode));
5770353358Sdim  return MatchOperand_Success;
5771353358Sdim}
5772353358Sdim
5773353358Sdimbool AMDGPUOperand::isGPRIdxMode() const {
5774353358Sdim  return isImmTy(ImmTyGprIdxMode);
5775353358Sdim}
5776353358Sdim
5777353358Sdim//===----------------------------------------------------------------------===//
5778284677Sdim// sopp branch targets
5779284677Sdim//===----------------------------------------------------------------------===//
5780284677Sdim
5781314564SdimOperandMatchResultTy
5782284677SdimAMDGPUAsmParser::parseSOppBrTarget(OperandVector &Operands) {
5783284677Sdim
5784360784Sdim  // Make sure we are not parsing something
5785360784Sdim  // that looks like a label or an expression but is not.
5786360784Sdim  // This will improve error messages.
5787360784Sdim  if (isRegister() || isModifier())
5788360784Sdim    return MatchOperand_NoMatch;
5789360784Sdim
5790360784Sdim  if (parseExpr(Operands)) {
5791360784Sdim
5792360784Sdim    AMDGPUOperand &Opr = ((AMDGPUOperand &)*Operands[Operands.size() - 1]);
5793360784Sdim    assert(Opr.isImm() || Opr.isExpr());
5794360784Sdim    SMLoc Loc = Opr.getStartLoc();
5795360784Sdim
5796360784Sdim    // Currently we do not support arbitrary expressions as branch targets.
5797360784Sdim    // Only labels and absolute expressions are accepted.
5798360784Sdim    if (Opr.isExpr() && !Opr.isSymbolRefExpr()) {
5799360784Sdim      Error(Loc, "expected an absolute expression or a label");
5800360784Sdim    } else if (Opr.isImm() && !Opr.isS16Imm()) {
5801360784Sdim      Error(Loc, "expected a 16-bit signed jump offset");
5802284677Sdim    }
5803360784Sdim  }
5804284677Sdim
5805360784Sdim  return MatchOperand_Success; // avoid excessive error messages
5806284677Sdim}
5807284677Sdim
5808284677Sdim//===----------------------------------------------------------------------===//
5809353358Sdim// Boolean holding registers
5810353358Sdim//===----------------------------------------------------------------------===//
5811353358Sdim
5812353358SdimOperandMatchResultTy
5813353358SdimAMDGPUAsmParser::parseBoolReg(OperandVector &Operands) {
5814353358Sdim  return parseReg(Operands);
5815353358Sdim}
5816353358Sdim
5817353358Sdim//===----------------------------------------------------------------------===//
5818309124Sdim// mubuf
5819284677Sdim//===----------------------------------------------------------------------===//
5820284677Sdim
5821353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultDLC() const {
5822353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDLC);
5823353358Sdim}
5824353358Sdim
5825309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultGLC() const {
5826314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyGLC);
5827309124Sdim}
5828284677Sdim
5829309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSLC() const {
5830314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTySLC);
5831284677Sdim}
5832284677Sdim
5833309124Sdimvoid AMDGPUAsmParser::cvtMubufImpl(MCInst &Inst,
5834309124Sdim                               const OperandVector &Operands,
5835341825Sdim                               bool IsAtomic,
5836341825Sdim                               bool IsAtomicReturn,
5837341825Sdim                               bool IsLds) {
5838341825Sdim  bool IsLdsOpcode = IsLds;
5839341825Sdim  bool HasLdsModifier = false;
5840309124Sdim  OptionalImmIndexMap OptionalIdx;
5841309124Sdim  assert(IsAtomicReturn ? IsAtomic : true);
5842353358Sdim  unsigned FirstOperandIdx = 1;
5843284677Sdim
5844353358Sdim  for (unsigned i = FirstOperandIdx, e = Operands.size(); i != e; ++i) {
5845284677Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5846284677Sdim
5847284677Sdim    // Add the register arguments
5848284677Sdim    if (Op.isReg()) {
5849284677Sdim      Op.addRegOperands(Inst, 1);
5850353358Sdim      // Insert a tied src for atomic return dst.
5851353358Sdim      // This cannot be postponed as subsequent calls to
5852353358Sdim      // addImmOperands rely on correct number of MC operands.
5853353358Sdim      if (IsAtomicReturn && i == FirstOperandIdx)
5854353358Sdim        Op.addRegOperands(Inst, 1);
5855284677Sdim      continue;
5856284677Sdim    }
5857284677Sdim
5858309124Sdim    // Handle the case where soffset is an immediate
5859309124Sdim    if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5860309124Sdim      Op.addImmOperands(Inst, 1);
5861309124Sdim      continue;
5862309124Sdim    }
5863309124Sdim
5864353358Sdim    HasLdsModifier |= Op.isLDS();
5865341825Sdim
5866309124Sdim    // Handle tokens like 'offen' which are sometimes hard-coded into the
5867284677Sdim    // asm string.  There are no MCInst operands for these.
5868309124Sdim    if (Op.isToken()) {
5869284677Sdim      continue;
5870309124Sdim    }
5871309124Sdim    assert(Op.isImm());
5872284677Sdim
5873284677Sdim    // Handle optional arguments
5874284677Sdim    OptionalIdx[Op.getImmTy()] = i;
5875309124Sdim  }
5876284677Sdim
5877341825Sdim  // This is a workaround for an llvm quirk which may result in an
5878341825Sdim  // incorrect instruction selection. Lds and non-lds versions of
5879341825Sdim  // MUBUF instructions are identical except that lds versions
5880341825Sdim  // have mandatory 'lds' modifier. However this modifier follows
5881341825Sdim  // optional modifiers and llvm asm matcher regards this 'lds'
5882341825Sdim  // modifier as an optional one. As a result, an lds version
5883341825Sdim  // of opcode may be selected even if it has no 'lds' modifier.
5884341825Sdim  if (IsLdsOpcode && !HasLdsModifier) {
5885341825Sdim    int NoLdsOpcode = AMDGPU::getMUBUFNoLdsInst(Inst.getOpcode());
5886341825Sdim    if (NoLdsOpcode != -1) { // Got lds version - correct it.
5887341825Sdim      Inst.setOpcode(NoLdsOpcode);
5888341825Sdim      IsLdsOpcode = false;
5889341825Sdim    }
5890341825Sdim  }
5891341825Sdim
5892309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOffset);
5893309124Sdim  if (!IsAtomic) { // glc is hard-coded.
5894309124Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5895284677Sdim  }
5896309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
5897341825Sdim
5898341825Sdim  if (!IsLdsOpcode) { // tfe is not legal with lds opcodes
5899341825Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5900341825Sdim  }
5901353358Sdim
5902353358Sdim  if (isGFX10())
5903353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
5904284677Sdim}
5905284677Sdim
5906321369Sdimvoid AMDGPUAsmParser::cvtMtbuf(MCInst &Inst, const OperandVector &Operands) {
5907309124Sdim  OptionalImmIndexMap OptionalIdx;
5908284677Sdim
5909321369Sdim  for (unsigned i = 1, e = Operands.size(); i != e; ++i) {
5910321369Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[i]);
5911284677Sdim
5912309124Sdim    // Add the register arguments
5913321369Sdim    if (Op.isReg()) {
5914321369Sdim      Op.addRegOperands(Inst, 1);
5915309124Sdim      continue;
5916309124Sdim    }
5917321369Sdim
5918321369Sdim    // Handle the case where soffset is an immediate
5919321369Sdim    if (Op.isImm() && Op.getImmTy() == AMDGPUOperand::ImmTyNone) {
5920321369Sdim      Op.addImmOperands(Inst, 1);
5921321369Sdim      continue;
5922321369Sdim    }
5923321369Sdim
5924321369Sdim    // Handle tokens like 'offen' which are sometimes hard-coded into the
5925321369Sdim    // asm string.  There are no MCInst operands for these.
5926321369Sdim    if (Op.isToken()) {
5927321369Sdim      continue;
5928321369Sdim    }
5929321369Sdim    assert(Op.isImm());
5930321369Sdim
5931321369Sdim    // Handle optional arguments
5932321369Sdim    OptionalIdx[Op.getImmTy()] = i;
5933309124Sdim  }
5934284677Sdim
5935321369Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx,
5936321369Sdim                        AMDGPUOperand::ImmTyOffset);
5937344779Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyFORMAT);
5938309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5939321369Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
5940309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5941353358Sdim
5942353358Sdim  if (isGFX10())
5943353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
5944284677Sdim}
5945284677Sdim
5946321369Sdim//===----------------------------------------------------------------------===//
5947321369Sdim// mimg
5948321369Sdim//===----------------------------------------------------------------------===//
5949321369Sdim
5950321369Sdimvoid AMDGPUAsmParser::cvtMIMG(MCInst &Inst, const OperandVector &Operands,
5951321369Sdim                              bool IsAtomic) {
5952309124Sdim  unsigned I = 1;
5953309124Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
5954309124Sdim  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
5955309124Sdim    ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
5956309124Sdim  }
5957284677Sdim
5958321369Sdim  if (IsAtomic) {
5959321369Sdim    // Add src, same as dst
5960341825Sdim    assert(Desc.getNumDefs() == 1);
5961341825Sdim    ((AMDGPUOperand &)*Operands[I - 1]).addRegOperands(Inst, 1);
5962321369Sdim  }
5963284677Sdim
5964309124Sdim  OptionalImmIndexMap OptionalIdx;
5965284677Sdim
5966309124Sdim  for (unsigned E = Operands.size(); I != E; ++I) {
5967309124Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
5968284677Sdim
5969284677Sdim    // Add the register arguments
5970341825Sdim    if (Op.isReg()) {
5971341825Sdim      Op.addRegOperands(Inst, 1);
5972309124Sdim    } else if (Op.isImmModifier()) {
5973309124Sdim      OptionalIdx[Op.getImmTy()] = I;
5974353358Sdim    } else if (!Op.isToken()) {
5975314564Sdim      llvm_unreachable("unexpected operand type");
5976284677Sdim    }
5977284677Sdim  }
5978284677Sdim
5979353358Sdim  bool IsGFX10 = isGFX10();
5980353358Sdim
5981309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDMask);
5982353358Sdim  if (IsGFX10)
5983353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDim, -1);
5984309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyUNorm);
5985353358Sdim  if (IsGFX10)
5986353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDLC);
5987309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyGLC);
5988341825Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySLC);
5989344779Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyR128A16);
5990309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyTFE);
5991309124Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyLWE);
5992353358Sdim  if (!IsGFX10)
5993353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDA);
5994341825Sdim  addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyD16);
5995309124Sdim}
5996284677Sdim
5997321369Sdimvoid AMDGPUAsmParser::cvtMIMGAtomic(MCInst &Inst, const OperandVector &Operands) {
5998321369Sdim  cvtMIMG(Inst, Operands, true);
5999321369Sdim}
6000321369Sdim
6001284677Sdim//===----------------------------------------------------------------------===//
6002296417Sdim// smrd
6003296417Sdim//===----------------------------------------------------------------------===//
6004296417Sdim
6005314564Sdimbool AMDGPUOperand::isSMRDOffset8() const {
6006296417Sdim  return isImm() && isUInt<8>(getImm());
6007296417Sdim}
6008296417Sdim
6009314564Sdimbool AMDGPUOperand::isSMRDOffset20() const {
6010314564Sdim  return isImm() && isUInt<20>(getImm());
6011314564Sdim}
6012314564Sdim
6013296417Sdimbool AMDGPUOperand::isSMRDLiteralOffset() const {
6014296417Sdim  // 32-bit literals are only supported on CI and we only want to use them
6015296417Sdim  // when the offset is > 8-bits.
6016296417Sdim  return isImm() && !isUInt<8>(getImm()) && isUInt<32>(getImm());
6017296417Sdim}
6018296417Sdim
6019314564SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset8() const {
6020314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
6021309124Sdim}
6022309124Sdim
6023314564SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDOffset20() const {
6024314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
6025314564Sdim}
6026314564Sdim
6027309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultSMRDLiteralOffset() const {
6028314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
6029309124Sdim}
6030309124Sdim
6031353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultFlatOffset() const {
6032321369Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyOffset);
6033321369Sdim}
6034321369Sdim
6035296417Sdim//===----------------------------------------------------------------------===//
6036284677Sdim// vop3
6037284677Sdim//===----------------------------------------------------------------------===//
6038284677Sdim
6039284677Sdimstatic bool ConvertOmodMul(int64_t &Mul) {
6040284677Sdim  if (Mul != 1 && Mul != 2 && Mul != 4)
6041284677Sdim    return false;
6042284677Sdim
6043284677Sdim  Mul >>= 1;
6044284677Sdim  return true;
6045284677Sdim}
6046284677Sdim
6047284677Sdimstatic bool ConvertOmodDiv(int64_t &Div) {
6048284677Sdim  if (Div == 1) {
6049284677Sdim    Div = 0;
6050284677Sdim    return true;
6051284677Sdim  }
6052284677Sdim
6053284677Sdim  if (Div == 2) {
6054284677Sdim    Div = 3;
6055284677Sdim    return true;
6056284677Sdim  }
6057284677Sdim
6058284677Sdim  return false;
6059284677Sdim}
6060284677Sdim
6061309124Sdimstatic bool ConvertBoundCtrl(int64_t &BoundCtrl) {
6062309124Sdim  if (BoundCtrl == 0) {
6063309124Sdim    BoundCtrl = 1;
6064309124Sdim    return true;
6065314564Sdim  }
6066314564Sdim
6067314564Sdim  if (BoundCtrl == -1) {
6068309124Sdim    BoundCtrl = 0;
6069309124Sdim    return true;
6070309124Sdim  }
6071314564Sdim
6072309124Sdim  return false;
6073309124Sdim}
6074309124Sdim
6075309124Sdim// Note: the order in this table matches the order of operands in AsmString.
6076309124Sdimstatic const OptionalOperand AMDGPUOptionalOperandTable[] = {
6077309124Sdim  {"offen",   AMDGPUOperand::ImmTyOffen, true, nullptr},
6078309124Sdim  {"idxen",   AMDGPUOperand::ImmTyIdxen, true, nullptr},
6079309124Sdim  {"addr64",  AMDGPUOperand::ImmTyAddr64, true, nullptr},
6080309124Sdim  {"offset0", AMDGPUOperand::ImmTyOffset0, false, nullptr},
6081309124Sdim  {"offset1", AMDGPUOperand::ImmTyOffset1, false, nullptr},
6082309124Sdim  {"gds",     AMDGPUOperand::ImmTyGDS, true, nullptr},
6083341825Sdim  {"lds",     AMDGPUOperand::ImmTyLDS, true, nullptr},
6084309124Sdim  {"offset",  AMDGPUOperand::ImmTyOffset, false, nullptr},
6085327952Sdim  {"inst_offset", AMDGPUOperand::ImmTyInstOffset, false, nullptr},
6086353358Sdim  {"dlc",     AMDGPUOperand::ImmTyDLC, true, nullptr},
6087353358Sdim  {"format",  AMDGPUOperand::ImmTyFORMAT, false, nullptr},
6088309124Sdim  {"glc",     AMDGPUOperand::ImmTyGLC, true, nullptr},
6089309124Sdim  {"slc",     AMDGPUOperand::ImmTySLC, true, nullptr},
6090360784Sdim  {"swz",     AMDGPUOperand::ImmTySWZ, true, nullptr},
6091309124Sdim  {"tfe",     AMDGPUOperand::ImmTyTFE, true, nullptr},
6092341825Sdim  {"d16",     AMDGPUOperand::ImmTyD16, true, nullptr},
6093327952Sdim  {"high",    AMDGPUOperand::ImmTyHigh, true, nullptr},
6094309124Sdim  {"clamp",   AMDGPUOperand::ImmTyClampSI, true, nullptr},
6095309124Sdim  {"omod",    AMDGPUOperand::ImmTyOModSI, false, ConvertOmodMul},
6096309124Sdim  {"unorm",   AMDGPUOperand::ImmTyUNorm, true, nullptr},
6097309124Sdim  {"da",      AMDGPUOperand::ImmTyDA,    true, nullptr},
6098344779Sdim  {"r128",    AMDGPUOperand::ImmTyR128A16,  true, nullptr},
6099344779Sdim  {"a16",     AMDGPUOperand::ImmTyR128A16,  true, nullptr},
6100309124Sdim  {"lwe",     AMDGPUOperand::ImmTyLWE,   true, nullptr},
6101341825Sdim  {"d16",     AMDGPUOperand::ImmTyD16,   true, nullptr},
6102309124Sdim  {"dmask",   AMDGPUOperand::ImmTyDMask, false, nullptr},
6103353358Sdim  {"dim",     AMDGPUOperand::ImmTyDim,   false, nullptr},
6104309124Sdim  {"row_mask",   AMDGPUOperand::ImmTyDppRowMask, false, nullptr},
6105309124Sdim  {"bank_mask",  AMDGPUOperand::ImmTyDppBankMask, false, nullptr},
6106309124Sdim  {"bound_ctrl", AMDGPUOperand::ImmTyDppBoundCtrl, false, ConvertBoundCtrl},
6107353358Sdim  {"fi",         AMDGPUOperand::ImmTyDppFi, false, nullptr},
6108309124Sdim  {"dst_sel",    AMDGPUOperand::ImmTySdwaDstSel, false, nullptr},
6109309124Sdim  {"src0_sel",   AMDGPUOperand::ImmTySdwaSrc0Sel, false, nullptr},
6110309124Sdim  {"src1_sel",   AMDGPUOperand::ImmTySdwaSrc1Sel, false, nullptr},
6111309124Sdim  {"dst_unused", AMDGPUOperand::ImmTySdwaDstUnused, false, nullptr},
6112321369Sdim  {"compr", AMDGPUOperand::ImmTyExpCompr, true, nullptr },
6113314564Sdim  {"vm", AMDGPUOperand::ImmTyExpVM, true, nullptr},
6114321369Sdim  {"op_sel", AMDGPUOperand::ImmTyOpSel, false, nullptr},
6115321369Sdim  {"op_sel_hi", AMDGPUOperand::ImmTyOpSelHi, false, nullptr},
6116321369Sdim  {"neg_lo", AMDGPUOperand::ImmTyNegLo, false, nullptr},
6117353358Sdim  {"neg_hi", AMDGPUOperand::ImmTyNegHi, false, nullptr},
6118353358Sdim  {"blgp", AMDGPUOperand::ImmTyBLGP, false, nullptr},
6119353358Sdim  {"cbsz", AMDGPUOperand::ImmTyCBSZ, false, nullptr},
6120353358Sdim  {"abid", AMDGPUOperand::ImmTyABID, false, nullptr}
6121284677Sdim};
6122284677Sdim
6123314564SdimOperandMatchResultTy AMDGPUAsmParser::parseOptionalOperand(OperandVector &Operands) {
6124327952Sdim
6125327952Sdim  OperandMatchResultTy res = parseOptionalOpr(Operands);
6126327952Sdim
6127327952Sdim  // This is a hack to enable hardcoded mandatory operands which follow
6128327952Sdim  // optional operands.
6129327952Sdim  //
6130327952Sdim  // Current design assumes that all operands after the first optional operand
6131327952Sdim  // are also optional. However implementation of some instructions violates
6132327952Sdim  // this rule (see e.g. flat/global atomic which have hardcoded 'glc' operands).
6133327952Sdim  //
6134327952Sdim  // To alleviate this problem, we have to (implicitly) parse extra operands
6135327952Sdim  // to make sure autogenerated parser of custom operands never hit hardcoded
6136327952Sdim  // mandatory operands.
6137327952Sdim
6138360784Sdim  for (unsigned i = 0; i < MAX_OPR_LOOKAHEAD; ++i) {
6139360784Sdim    if (res != MatchOperand_Success ||
6140360784Sdim        isToken(AsmToken::EndOfStatement))
6141360784Sdim      break;
6142327952Sdim
6143360784Sdim    trySkipToken(AsmToken::Comma);
6144360784Sdim    res = parseOptionalOpr(Operands);
6145327952Sdim  }
6146327952Sdim
6147327952Sdim  return res;
6148327952Sdim}
6149327952Sdim
6150327952SdimOperandMatchResultTy AMDGPUAsmParser::parseOptionalOpr(OperandVector &Operands) {
6151309124Sdim  OperandMatchResultTy res;
6152309124Sdim  for (const OptionalOperand &Op : AMDGPUOptionalOperandTable) {
6153309124Sdim    // try to parse any optional operand here
6154309124Sdim    if (Op.IsBit) {
6155309124Sdim      res = parseNamedBit(Op.Name, Operands, Op.Type);
6156309124Sdim    } else if (Op.Type == AMDGPUOperand::ImmTyOModSI) {
6157309124Sdim      res = parseOModOperand(Operands);
6158309124Sdim    } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstSel ||
6159309124Sdim               Op.Type == AMDGPUOperand::ImmTySdwaSrc0Sel ||
6160309124Sdim               Op.Type == AMDGPUOperand::ImmTySdwaSrc1Sel) {
6161309124Sdim      res = parseSDWASel(Operands, Op.Name, Op.Type);
6162309124Sdim    } else if (Op.Type == AMDGPUOperand::ImmTySdwaDstUnused) {
6163309124Sdim      res = parseSDWADstUnused(Operands);
6164321369Sdim    } else if (Op.Type == AMDGPUOperand::ImmTyOpSel ||
6165321369Sdim               Op.Type == AMDGPUOperand::ImmTyOpSelHi ||
6166321369Sdim               Op.Type == AMDGPUOperand::ImmTyNegLo ||
6167321369Sdim               Op.Type == AMDGPUOperand::ImmTyNegHi) {
6168321369Sdim      res = parseOperandArrayWithPrefix(Op.Name, Operands, Op.Type,
6169321369Sdim                                        Op.ConvertResult);
6170353358Sdim    } else if (Op.Type == AMDGPUOperand::ImmTyDim) {
6171353358Sdim      res = parseDim(Operands);
6172353358Sdim    } else if (Op.Type == AMDGPUOperand::ImmTyFORMAT && !isGFX10()) {
6173344779Sdim      res = parseDfmtNfmt(Operands);
6174309124Sdim    } else {
6175309124Sdim      res = parseIntWithPrefix(Op.Name, Operands, Op.Type, Op.ConvertResult);
6176309124Sdim    }
6177309124Sdim    if (res != MatchOperand_NoMatch) {
6178309124Sdim      return res;
6179309124Sdim    }
6180309124Sdim  }
6181309124Sdim  return MatchOperand_NoMatch;
6182309124Sdim}
6183284677Sdim
6184314564SdimOperandMatchResultTy AMDGPUAsmParser::parseOModOperand(OperandVector &Operands) {
6185309124Sdim  StringRef Name = Parser.getTok().getString();
6186309124Sdim  if (Name == "mul") {
6187314564Sdim    return parseIntWithPrefix("mul", Operands,
6188314564Sdim                              AMDGPUOperand::ImmTyOModSI, ConvertOmodMul);
6189309124Sdim  }
6190314564Sdim
6191314564Sdim  if (Name == "div") {
6192314564Sdim    return parseIntWithPrefix("div", Operands,
6193314564Sdim                              AMDGPUOperand::ImmTyOModSI, ConvertOmodDiv);
6194314564Sdim  }
6195314564Sdim
6196314564Sdim  return MatchOperand_NoMatch;
6197309124Sdim}
6198284677Sdim
6199327952Sdimvoid AMDGPUAsmParser::cvtVOP3OpSel(MCInst &Inst, const OperandVector &Operands) {
6200327952Sdim  cvtVOP3P(Inst, Operands);
6201327952Sdim
6202327952Sdim  int Opc = Inst.getOpcode();
6203327952Sdim
6204327952Sdim  int SrcNum;
6205327952Sdim  const int Ops[] = { AMDGPU::OpName::src0,
6206327952Sdim                      AMDGPU::OpName::src1,
6207327952Sdim                      AMDGPU::OpName::src2 };
6208327952Sdim  for (SrcNum = 0;
6209327952Sdim       SrcNum < 3 && AMDGPU::getNamedOperandIdx(Opc, Ops[SrcNum]) != -1;
6210327952Sdim       ++SrcNum);
6211327952Sdim  assert(SrcNum > 0);
6212327952Sdim
6213327952Sdim  int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
6214327952Sdim  unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
6215327952Sdim
6216327952Sdim  if ((OpSel & (1 << SrcNum)) != 0) {
6217327952Sdim    int ModIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers);
6218327952Sdim    uint32_t ModVal = Inst.getOperand(ModIdx).getImm();
6219327952Sdim    Inst.getOperand(ModIdx).setImm(ModVal | SISrcMods::DST_OP_SEL);
6220327952Sdim  }
6221327952Sdim}
6222327952Sdim
6223314564Sdimstatic bool isRegOrImmWithInputMods(const MCInstrDesc &Desc, unsigned OpNum) {
6224314564Sdim      // 1. This operand is input modifiers
6225314564Sdim  return Desc.OpInfo[OpNum].OperandType == AMDGPU::OPERAND_INPUT_MODS
6226314564Sdim      // 2. This is not last operand
6227314564Sdim      && Desc.NumOperands > (OpNum + 1)
6228314564Sdim      // 3. Next operand is register class
6229314564Sdim      && Desc.OpInfo[OpNum + 1].RegClass != -1
6230314564Sdim      // 4. Next register is not tied to any other operand
6231314564Sdim      && Desc.getOperandConstraint(OpNum + 1, MCOI::OperandConstraint::TIED_TO) == -1;
6232314564Sdim}
6233314564Sdim
6234327952Sdimvoid AMDGPUAsmParser::cvtVOP3Interp(MCInst &Inst, const OperandVector &Operands)
6235327952Sdim{
6236327952Sdim  OptionalImmIndexMap OptionalIdx;
6237327952Sdim  unsigned Opc = Inst.getOpcode();
6238327952Sdim
6239327952Sdim  unsigned I = 1;
6240327952Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6241327952Sdim  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6242327952Sdim    ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6243327952Sdim  }
6244327952Sdim
6245327952Sdim  for (unsigned E = Operands.size(); I != E; ++I) {
6246327952Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6247327952Sdim    if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6248327952Sdim      Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
6249327952Sdim    } else if (Op.isInterpSlot() ||
6250327952Sdim               Op.isInterpAttr() ||
6251327952Sdim               Op.isAttrChan()) {
6252353358Sdim      Inst.addOperand(MCOperand::createImm(Op.getImm()));
6253327952Sdim    } else if (Op.isImmModifier()) {
6254327952Sdim      OptionalIdx[Op.getImmTy()] = I;
6255327952Sdim    } else {
6256327952Sdim      llvm_unreachable("unhandled operand type");
6257327952Sdim    }
6258327952Sdim  }
6259327952Sdim
6260327952Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::high) != -1) {
6261327952Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyHigh);
6262327952Sdim  }
6263327952Sdim
6264327952Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
6265327952Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
6266327952Sdim  }
6267327952Sdim
6268327952Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
6269327952Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
6270327952Sdim  }
6271327952Sdim}
6272327952Sdim
6273321369Sdimvoid AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands,
6274321369Sdim                              OptionalImmIndexMap &OptionalIdx) {
6275321369Sdim  unsigned Opc = Inst.getOpcode();
6276321369Sdim
6277309124Sdim  unsigned I = 1;
6278309124Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6279309124Sdim  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6280309124Sdim    ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6281284677Sdim  }
6282309124Sdim
6283321369Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) {
6284321369Sdim    // This instruction has src modifiers
6285321369Sdim    for (unsigned E = Operands.size(); I != E; ++I) {
6286321369Sdim      AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6287321369Sdim      if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6288321369Sdim        Op.addRegOrImmWithFPInputModsOperands(Inst, 2);
6289321369Sdim      } else if (Op.isImmModifier()) {
6290321369Sdim        OptionalIdx[Op.getImmTy()] = I;
6291321369Sdim      } else if (Op.isRegOrImm()) {
6292321369Sdim        Op.addRegOrImmOperands(Inst, 1);
6293321369Sdim      } else {
6294321369Sdim        llvm_unreachable("unhandled operand type");
6295321369Sdim      }
6296309124Sdim    }
6297321369Sdim  } else {
6298321369Sdim    // No src modifiers
6299321369Sdim    for (unsigned E = Operands.size(); I != E; ++I) {
6300321369Sdim      AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6301321369Sdim      if (Op.isMod()) {
6302321369Sdim        OptionalIdx[Op.getImmTy()] = I;
6303321369Sdim      } else {
6304321369Sdim        Op.addRegOrImmOperands(Inst, 1);
6305321369Sdim      }
6306321369Sdim    }
6307309124Sdim  }
6308309124Sdim
6309321369Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::clamp) != -1) {
6310321369Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI);
6311321369Sdim  }
6312314564Sdim
6313321369Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::omod) != -1) {
6314321369Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI);
6315321369Sdim  }
6316321369Sdim
6317353358Sdim  // Special case v_mac_{f16, f32} and v_fmac_{f16, f32} (gfx906/gfx10+):
6318314564Sdim  // it has src2 register operand that is tied to dst operand
6319314564Sdim  // we don't allow modifiers for this operand in assembler so src2_modifiers
6320341825Sdim  // should be 0.
6321353358Sdim  if (Opc == AMDGPU::V_MAC_F32_e64_gfx6_gfx7 ||
6322353358Sdim      Opc == AMDGPU::V_MAC_F32_e64_gfx10 ||
6323341825Sdim      Opc == AMDGPU::V_MAC_F32_e64_vi ||
6324341825Sdim      Opc == AMDGPU::V_MAC_F16_e64_vi ||
6325353358Sdim      Opc == AMDGPU::V_FMAC_F32_e64_gfx10 ||
6326353358Sdim      Opc == AMDGPU::V_FMAC_F32_e64_vi ||
6327353358Sdim      Opc == AMDGPU::V_FMAC_F16_e64_gfx10) {
6328314564Sdim    auto it = Inst.begin();
6329321369Sdim    std::advance(it, AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2_modifiers));
6330314564Sdim    it = Inst.insert(it, MCOperand::createImm(0)); // no modifiers for src2
6331314564Sdim    ++it;
6332314564Sdim    Inst.insert(it, Inst.getOperand(0)); // src2 = dst
6333314564Sdim  }
6334309124Sdim}
6335309124Sdim
6336321369Sdimvoid AMDGPUAsmParser::cvtVOP3(MCInst &Inst, const OperandVector &Operands) {
6337321369Sdim  OptionalImmIndexMap OptionalIdx;
6338321369Sdim  cvtVOP3(Inst, Operands, OptionalIdx);
6339321369Sdim}
6340321369Sdim
6341327952Sdimvoid AMDGPUAsmParser::cvtVOP3P(MCInst &Inst,
6342327952Sdim                               const OperandVector &Operands) {
6343321369Sdim  OptionalImmIndexMap OptIdx;
6344327952Sdim  const int Opc = Inst.getOpcode();
6345327952Sdim  const MCInstrDesc &Desc = MII.get(Opc);
6346321369Sdim
6347327952Sdim  const bool IsPacked = (Desc.TSFlags & SIInstrFlags::IsPacked) != 0;
6348327952Sdim
6349321369Sdim  cvtVOP3(Inst, Operands, OptIdx);
6350321369Sdim
6351327952Sdim  if (AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) {
6352327952Sdim    assert(!IsPacked);
6353327952Sdim    Inst.addOperand(Inst.getOperand(0));
6354327952Sdim  }
6355327952Sdim
6356321369Sdim  // FIXME: This is messy. Parse the modifiers as if it was a normal VOP3
6357321369Sdim  // instruction, and then figure out where to actually put the modifiers
6358321369Sdim
6359321369Sdim  addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSel);
6360321369Sdim
6361327952Sdim  int OpSelHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi);
6362327952Sdim  if (OpSelHiIdx != -1) {
6363327952Sdim    int DefaultVal = IsPacked ? -1 : 0;
6364327952Sdim    addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyOpSelHi,
6365327952Sdim                          DefaultVal);
6366327952Sdim  }
6367327952Sdim
6368321369Sdim  int NegLoIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo);
6369321369Sdim  if (NegLoIdx != -1) {
6370327952Sdim    assert(IsPacked);
6371321369Sdim    addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegLo);
6372321369Sdim    addOptionalImmOperand(Inst, Operands, OptIdx, AMDGPUOperand::ImmTyNegHi);
6373321369Sdim  }
6374321369Sdim
6375321369Sdim  const int Ops[] = { AMDGPU::OpName::src0,
6376321369Sdim                      AMDGPU::OpName::src1,
6377321369Sdim                      AMDGPU::OpName::src2 };
6378321369Sdim  const int ModOps[] = { AMDGPU::OpName::src0_modifiers,
6379321369Sdim                         AMDGPU::OpName::src1_modifiers,
6380321369Sdim                         AMDGPU::OpName::src2_modifiers };
6381321369Sdim
6382321369Sdim  int OpSelIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel);
6383321369Sdim
6384321369Sdim  unsigned OpSel = Inst.getOperand(OpSelIdx).getImm();
6385327952Sdim  unsigned OpSelHi = 0;
6386321369Sdim  unsigned NegLo = 0;
6387321369Sdim  unsigned NegHi = 0;
6388321369Sdim
6389327952Sdim  if (OpSelHiIdx != -1) {
6390327952Sdim    OpSelHi = Inst.getOperand(OpSelHiIdx).getImm();
6391327952Sdim  }
6392327952Sdim
6393321369Sdim  if (NegLoIdx != -1) {
6394321369Sdim    int NegHiIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi);
6395321369Sdim    NegLo = Inst.getOperand(NegLoIdx).getImm();
6396321369Sdim    NegHi = Inst.getOperand(NegHiIdx).getImm();
6397321369Sdim  }
6398321369Sdim
6399321369Sdim  for (int J = 0; J < 3; ++J) {
6400321369Sdim    int OpIdx = AMDGPU::getNamedOperandIdx(Opc, Ops[J]);
6401321369Sdim    if (OpIdx == -1)
6402321369Sdim      break;
6403321369Sdim
6404321369Sdim    uint32_t ModVal = 0;
6405321369Sdim
6406321369Sdim    if ((OpSel & (1 << J)) != 0)
6407321369Sdim      ModVal |= SISrcMods::OP_SEL_0;
6408321369Sdim
6409321369Sdim    if ((OpSelHi & (1 << J)) != 0)
6410321369Sdim      ModVal |= SISrcMods::OP_SEL_1;
6411321369Sdim
6412321369Sdim    if ((NegLo & (1 << J)) != 0)
6413321369Sdim      ModVal |= SISrcMods::NEG;
6414321369Sdim
6415321369Sdim    if ((NegHi & (1 << J)) != 0)
6416321369Sdim      ModVal |= SISrcMods::NEG_HI;
6417321369Sdim
6418321369Sdim    int ModIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
6419321369Sdim
6420321369Sdim    Inst.getOperand(ModIdx).setImm(Inst.getOperand(ModIdx).getImm() | ModVal);
6421321369Sdim  }
6422321369Sdim}
6423321369Sdim
6424309124Sdim//===----------------------------------------------------------------------===//
6425309124Sdim// dpp
6426309124Sdim//===----------------------------------------------------------------------===//
6427309124Sdim
6428353358Sdimbool AMDGPUOperand::isDPP8() const {
6429353358Sdim  return isImmTy(ImmTyDPP8);
6430353358Sdim}
6431353358Sdim
6432309124Sdimbool AMDGPUOperand::isDPPCtrl() const {
6433341825Sdim  using namespace AMDGPU::DPP;
6434341825Sdim
6435309124Sdim  bool result = isImm() && getImmTy() == ImmTyDppCtrl && isUInt<9>(getImm());
6436309124Sdim  if (result) {
6437309124Sdim    int64_t Imm = getImm();
6438341825Sdim    return (Imm >= DppCtrl::QUAD_PERM_FIRST && Imm <= DppCtrl::QUAD_PERM_LAST) ||
6439341825Sdim           (Imm >= DppCtrl::ROW_SHL_FIRST && Imm <= DppCtrl::ROW_SHL_LAST) ||
6440341825Sdim           (Imm >= DppCtrl::ROW_SHR_FIRST && Imm <= DppCtrl::ROW_SHR_LAST) ||
6441341825Sdim           (Imm >= DppCtrl::ROW_ROR_FIRST && Imm <= DppCtrl::ROW_ROR_LAST) ||
6442341825Sdim           (Imm == DppCtrl::WAVE_SHL1) ||
6443341825Sdim           (Imm == DppCtrl::WAVE_ROL1) ||
6444341825Sdim           (Imm == DppCtrl::WAVE_SHR1) ||
6445341825Sdim           (Imm == DppCtrl::WAVE_ROR1) ||
6446341825Sdim           (Imm == DppCtrl::ROW_MIRROR) ||
6447341825Sdim           (Imm == DppCtrl::ROW_HALF_MIRROR) ||
6448341825Sdim           (Imm == DppCtrl::BCAST15) ||
6449353358Sdim           (Imm == DppCtrl::BCAST31) ||
6450353358Sdim           (Imm >= DppCtrl::ROW_SHARE_FIRST && Imm <= DppCtrl::ROW_SHARE_LAST) ||
6451353358Sdim           (Imm >= DppCtrl::ROW_XMASK_FIRST && Imm <= DppCtrl::ROW_XMASK_LAST);
6452309124Sdim  }
6453284677Sdim  return false;
6454284677Sdim}
6455284677Sdim
6456353358Sdim//===----------------------------------------------------------------------===//
6457353358Sdim// mAI
6458353358Sdim//===----------------------------------------------------------------------===//
6459353358Sdim
6460353358Sdimbool AMDGPUOperand::isBLGP() const {
6461353358Sdim  return isImm() && getImmTy() == ImmTyBLGP && isUInt<3>(getImm());
6462314564Sdim}
6463314564Sdim
6464353358Sdimbool AMDGPUOperand::isCBSZ() const {
6465353358Sdim  return isImm() && getImmTy() == ImmTyCBSZ && isUInt<3>(getImm());
6466353358Sdim}
6467353358Sdim
6468353358Sdimbool AMDGPUOperand::isABID() const {
6469353358Sdim  return isImm() && getImmTy() == ImmTyABID && isUInt<4>(getImm());
6470353358Sdim}
6471353358Sdim
6472321369Sdimbool AMDGPUOperand::isS16Imm() const {
6473321369Sdim  return isImm() && (isInt<16>(getImm()) || isUInt<16>(getImm()));
6474321369Sdim}
6475321369Sdim
6476321369Sdimbool AMDGPUOperand::isU16Imm() const {
6477321369Sdim  return isImm() && isUInt<16>(getImm());
6478321369Sdim}
6479321369Sdim
6480353358SdimOperandMatchResultTy AMDGPUAsmParser::parseDim(OperandVector &Operands) {
6481353358Sdim  if (!isGFX10())
6482353358Sdim    return MatchOperand_NoMatch;
6483353358Sdim
6484353358Sdim  SMLoc S = Parser.getTok().getLoc();
6485353358Sdim
6486353358Sdim  if (getLexer().isNot(AsmToken::Identifier))
6487353358Sdim    return MatchOperand_NoMatch;
6488353358Sdim  if (getLexer().getTok().getString() != "dim")
6489353358Sdim    return MatchOperand_NoMatch;
6490353358Sdim
6491353358Sdim  Parser.Lex();
6492353358Sdim  if (getLexer().isNot(AsmToken::Colon))
6493353358Sdim    return MatchOperand_ParseFail;
6494353358Sdim
6495353358Sdim  Parser.Lex();
6496353358Sdim
6497353358Sdim  // We want to allow "dim:1D" etc., but the initial 1 is tokenized as an
6498353358Sdim  // integer.
6499353358Sdim  std::string Token;
6500353358Sdim  if (getLexer().is(AsmToken::Integer)) {
6501353358Sdim    SMLoc Loc = getLexer().getTok().getEndLoc();
6502353358Sdim    Token = getLexer().getTok().getString();
6503353358Sdim    Parser.Lex();
6504353358Sdim    if (getLexer().getTok().getLoc() != Loc)
6505353358Sdim      return MatchOperand_ParseFail;
6506353358Sdim  }
6507353358Sdim  if (getLexer().isNot(AsmToken::Identifier))
6508353358Sdim    return MatchOperand_ParseFail;
6509353358Sdim  Token += getLexer().getTok().getString();
6510353358Sdim
6511353358Sdim  StringRef DimId = Token;
6512353358Sdim  if (DimId.startswith("SQ_RSRC_IMG_"))
6513353358Sdim    DimId = DimId.substr(12);
6514353358Sdim
6515353358Sdim  const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfoByAsmSuffix(DimId);
6516353358Sdim  if (!DimInfo)
6517353358Sdim    return MatchOperand_ParseFail;
6518353358Sdim
6519353358Sdim  Parser.Lex();
6520353358Sdim
6521353358Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, DimInfo->Encoding, S,
6522353358Sdim                                              AMDGPUOperand::ImmTyDim));
6523353358Sdim  return MatchOperand_Success;
6524353358Sdim}
6525353358Sdim
6526353358SdimOperandMatchResultTy AMDGPUAsmParser::parseDPP8(OperandVector &Operands) {
6527353358Sdim  SMLoc S = Parser.getTok().getLoc();
6528353358Sdim  StringRef Prefix;
6529353358Sdim
6530353358Sdim  if (getLexer().getKind() == AsmToken::Identifier) {
6531353358Sdim    Prefix = Parser.getTok().getString();
6532353358Sdim  } else {
6533353358Sdim    return MatchOperand_NoMatch;
6534353358Sdim  }
6535353358Sdim
6536353358Sdim  if (Prefix != "dpp8")
6537353358Sdim    return parseDPPCtrl(Operands);
6538353358Sdim  if (!isGFX10())
6539353358Sdim    return MatchOperand_NoMatch;
6540353358Sdim
6541353358Sdim  // dpp8:[%d,%d,%d,%d,%d,%d,%d,%d]
6542353358Sdim
6543353358Sdim  int64_t Sels[8];
6544353358Sdim
6545353358Sdim  Parser.Lex();
6546353358Sdim  if (getLexer().isNot(AsmToken::Colon))
6547353358Sdim    return MatchOperand_ParseFail;
6548353358Sdim
6549353358Sdim  Parser.Lex();
6550353358Sdim  if (getLexer().isNot(AsmToken::LBrac))
6551353358Sdim    return MatchOperand_ParseFail;
6552353358Sdim
6553353358Sdim  Parser.Lex();
6554353358Sdim  if (getParser().parseAbsoluteExpression(Sels[0]))
6555353358Sdim    return MatchOperand_ParseFail;
6556353358Sdim  if (0 > Sels[0] || 7 < Sels[0])
6557353358Sdim    return MatchOperand_ParseFail;
6558353358Sdim
6559353358Sdim  for (size_t i = 1; i < 8; ++i) {
6560353358Sdim    if (getLexer().isNot(AsmToken::Comma))
6561353358Sdim      return MatchOperand_ParseFail;
6562353358Sdim
6563353358Sdim    Parser.Lex();
6564353358Sdim    if (getParser().parseAbsoluteExpression(Sels[i]))
6565353358Sdim      return MatchOperand_ParseFail;
6566353358Sdim    if (0 > Sels[i] || 7 < Sels[i])
6567353358Sdim      return MatchOperand_ParseFail;
6568353358Sdim  }
6569353358Sdim
6570353358Sdim  if (getLexer().isNot(AsmToken::RBrac))
6571353358Sdim    return MatchOperand_ParseFail;
6572353358Sdim  Parser.Lex();
6573353358Sdim
6574353358Sdim  unsigned DPP8 = 0;
6575353358Sdim  for (size_t i = 0; i < 8; ++i)
6576353358Sdim    DPP8 |= (Sels[i] << (i * 3));
6577353358Sdim
6578353358Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, DPP8, S, AMDGPUOperand::ImmTyDPP8));
6579353358Sdim  return MatchOperand_Success;
6580353358Sdim}
6581353358Sdim
6582314564SdimOperandMatchResultTy
6583309124SdimAMDGPUAsmParser::parseDPPCtrl(OperandVector &Operands) {
6584341825Sdim  using namespace AMDGPU::DPP;
6585341825Sdim
6586309124Sdim  SMLoc S = Parser.getTok().getLoc();
6587309124Sdim  StringRef Prefix;
6588309124Sdim  int64_t Int;
6589284677Sdim
6590309124Sdim  if (getLexer().getKind() == AsmToken::Identifier) {
6591309124Sdim    Prefix = Parser.getTok().getString();
6592309124Sdim  } else {
6593309124Sdim    return MatchOperand_NoMatch;
6594309124Sdim  }
6595284677Sdim
6596309124Sdim  if (Prefix == "row_mirror") {
6597341825Sdim    Int = DppCtrl::ROW_MIRROR;
6598314564Sdim    Parser.Lex();
6599309124Sdim  } else if (Prefix == "row_half_mirror") {
6600341825Sdim    Int = DppCtrl::ROW_HALF_MIRROR;
6601314564Sdim    Parser.Lex();
6602309124Sdim  } else {
6603309124Sdim    // Check to prevent parseDPPCtrlOps from eating invalid tokens
6604309124Sdim    if (Prefix != "quad_perm"
6605309124Sdim        && Prefix != "row_shl"
6606309124Sdim        && Prefix != "row_shr"
6607309124Sdim        && Prefix != "row_ror"
6608309124Sdim        && Prefix != "wave_shl"
6609309124Sdim        && Prefix != "wave_rol"
6610309124Sdim        && Prefix != "wave_shr"
6611309124Sdim        && Prefix != "wave_ror"
6612353358Sdim        && Prefix != "row_bcast"
6613353358Sdim        && Prefix != "row_share"
6614353358Sdim        && Prefix != "row_xmask") {
6615309124Sdim      return MatchOperand_NoMatch;
6616309124Sdim    }
6617284677Sdim
6618353358Sdim    if (!isGFX10() && (Prefix == "row_share" || Prefix == "row_xmask"))
6619353358Sdim      return MatchOperand_NoMatch;
6620353358Sdim
6621353358Sdim    if (!isVI() && !isGFX9() &&
6622353358Sdim        (Prefix == "wave_shl" || Prefix == "wave_shr" ||
6623353358Sdim         Prefix == "wave_rol" || Prefix == "wave_ror" ||
6624353358Sdim         Prefix == "row_bcast"))
6625353358Sdim      return MatchOperand_NoMatch;
6626353358Sdim
6627309124Sdim    Parser.Lex();
6628309124Sdim    if (getLexer().isNot(AsmToken::Colon))
6629309124Sdim      return MatchOperand_ParseFail;
6630284677Sdim
6631309124Sdim    if (Prefix == "quad_perm") {
6632309124Sdim      // quad_perm:[%d,%d,%d,%d]
6633309124Sdim      Parser.Lex();
6634309124Sdim      if (getLexer().isNot(AsmToken::LBrac))
6635309124Sdim        return MatchOperand_ParseFail;
6636309124Sdim      Parser.Lex();
6637309124Sdim
6638314564Sdim      if (getParser().parseAbsoluteExpression(Int) || !(0 <= Int && Int <=3))
6639309124Sdim        return MatchOperand_ParseFail;
6640309124Sdim
6641314564Sdim      for (int i = 0; i < 3; ++i) {
6642314564Sdim        if (getLexer().isNot(AsmToken::Comma))
6643314564Sdim          return MatchOperand_ParseFail;
6644314564Sdim        Parser.Lex();
6645309124Sdim
6646314564Sdim        int64_t Temp;
6647314564Sdim        if (getParser().parseAbsoluteExpression(Temp) || !(0 <= Temp && Temp <=3))
6648314564Sdim          return MatchOperand_ParseFail;
6649314564Sdim        const int shift = i*2 + 2;
6650314564Sdim        Int += (Temp << shift);
6651314564Sdim      }
6652309124Sdim
6653309124Sdim      if (getLexer().isNot(AsmToken::RBrac))
6654309124Sdim        return MatchOperand_ParseFail;
6655314564Sdim      Parser.Lex();
6656309124Sdim    } else {
6657309124Sdim      // sel:%d
6658309124Sdim      Parser.Lex();
6659314564Sdim      if (getParser().parseAbsoluteExpression(Int))
6660309124Sdim        return MatchOperand_ParseFail;
6661309124Sdim
6662314564Sdim      if (Prefix == "row_shl" && 1 <= Int && Int <= 15) {
6663341825Sdim        Int |= DppCtrl::ROW_SHL0;
6664314564Sdim      } else if (Prefix == "row_shr" && 1 <= Int && Int <= 15) {
6665341825Sdim        Int |= DppCtrl::ROW_SHR0;
6666314564Sdim      } else if (Prefix == "row_ror" && 1 <= Int && Int <= 15) {
6667341825Sdim        Int |= DppCtrl::ROW_ROR0;
6668314564Sdim      } else if (Prefix == "wave_shl" && 1 == Int) {
6669341825Sdim        Int = DppCtrl::WAVE_SHL1;
6670314564Sdim      } else if (Prefix == "wave_rol" && 1 == Int) {
6671341825Sdim        Int = DppCtrl::WAVE_ROL1;
6672314564Sdim      } else if (Prefix == "wave_shr" && 1 == Int) {
6673341825Sdim        Int = DppCtrl::WAVE_SHR1;
6674314564Sdim      } else if (Prefix == "wave_ror" && 1 == Int) {
6675341825Sdim        Int = DppCtrl::WAVE_ROR1;
6676309124Sdim      } else if (Prefix == "row_bcast") {
6677309124Sdim        if (Int == 15) {
6678341825Sdim          Int = DppCtrl::BCAST15;
6679309124Sdim        } else if (Int == 31) {
6680341825Sdim          Int = DppCtrl::BCAST31;
6681309124Sdim        } else {
6682309124Sdim          return MatchOperand_ParseFail;
6683309124Sdim        }
6684353358Sdim      } else if (Prefix == "row_share" && 0 <= Int && Int <= 15) {
6685353358Sdim        Int |= DppCtrl::ROW_SHARE_FIRST;
6686353358Sdim      } else if (Prefix == "row_xmask" && 0 <= Int && Int <= 15) {
6687353358Sdim        Int |= DppCtrl::ROW_XMASK_FIRST;
6688309124Sdim      } else {
6689309124Sdim        return MatchOperand_ParseFail;
6690284677Sdim      }
6691284677Sdim    }
6692284677Sdim  }
6693309124Sdim
6694314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTyDppCtrl));
6695309124Sdim  return MatchOperand_Success;
6696284677Sdim}
6697284677Sdim
6698309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultRowMask() const {
6699314564Sdim  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppRowMask);
6700309124Sdim}
6701284677Sdim
6702353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultEndpgmImmOperands() const {
6703353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyEndpgm);
6704353358Sdim}
6705353358Sdim
6706309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBankMask() const {
6707314564Sdim  return AMDGPUOperand::CreateImm(this, 0xf, SMLoc(), AMDGPUOperand::ImmTyDppBankMask);
6708309124Sdim}
6709309124Sdim
6710309124SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBoundCtrl() const {
6711314564Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppBoundCtrl);
6712309124Sdim}
6713309124Sdim
6714353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultFI() const {
6715353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyDppFi);
6716353358Sdim}
6717353358Sdim
6718353358Sdimvoid AMDGPUAsmParser::cvtDPP(MCInst &Inst, const OperandVector &Operands, bool IsDPP8) {
6719309124Sdim  OptionalImmIndexMap OptionalIdx;
6720309124Sdim
6721309124Sdim  unsigned I = 1;
6722296417Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6723309124Sdim  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6724309124Sdim    ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6725296417Sdim  }
6726296417Sdim
6727353358Sdim  int Fi = 0;
6728309124Sdim  for (unsigned E = Operands.size(); I != E; ++I) {
6729344779Sdim    auto TiedTo = Desc.getOperandConstraint(Inst.getNumOperands(),
6730344779Sdim                                            MCOI::TIED_TO);
6731344779Sdim    if (TiedTo != -1) {
6732344779Sdim      assert((unsigned)TiedTo < Inst.getNumOperands());
6733344779Sdim      // handle tied old or src2 for MAC instructions
6734344779Sdim      Inst.addOperand(Inst.getOperand(TiedTo));
6735344779Sdim    }
6736309124Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6737309124Sdim    // Add the register arguments
6738353358Sdim    if (Op.isReg() && validateVccOperand(Op.getReg())) {
6739321369Sdim      // VOP2b (v_add_u32, v_sub_u32 ...) dpp use "vcc" token.
6740314564Sdim      // Skip it.
6741314564Sdim      continue;
6742353358Sdim    }
6743353358Sdim
6744353358Sdim    if (IsDPP8) {
6745353358Sdim      if (Op.isDPP8()) {
6746353358Sdim        Op.addImmOperands(Inst, 1);
6747353358Sdim      } else if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6748353358Sdim        Op.addRegWithFPInputModsOperands(Inst, 2);
6749353358Sdim      } else if (Op.isFI()) {
6750353358Sdim        Fi = Op.getImm();
6751353358Sdim      } else if (Op.isReg()) {
6752353358Sdim        Op.addRegOperands(Inst, 1);
6753353358Sdim      } else {
6754353358Sdim        llvm_unreachable("Invalid operand type");
6755353358Sdim      }
6756309124Sdim    } else {
6757353358Sdim      if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6758353358Sdim        Op.addRegWithFPInputModsOperands(Inst, 2);
6759353358Sdim      } else if (Op.isDPPCtrl()) {
6760353358Sdim        Op.addImmOperands(Inst, 1);
6761353358Sdim      } else if (Op.isImm()) {
6762353358Sdim        // Handle optional arguments
6763353358Sdim        OptionalIdx[Op.getImmTy()] = I;
6764353358Sdim      } else {
6765353358Sdim        llvm_unreachable("Invalid operand type");
6766353358Sdim      }
6767309124Sdim    }
6768309124Sdim  }
6769284677Sdim
6770353358Sdim  if (IsDPP8) {
6771353358Sdim    using namespace llvm::AMDGPU::DPP;
6772353358Sdim    Inst.addOperand(MCOperand::createImm(Fi? DPP8_FI_1 : DPP8_FI_0));
6773353358Sdim  } else {
6774353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppRowMask, 0xf);
6775353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBankMask, 0xf);
6776353358Sdim    addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppBoundCtrl);
6777353358Sdim    if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::fi) != -1) {
6778353358Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyDppFi);
6779353358Sdim    }
6780353358Sdim  }
6781309124Sdim}
6782284677Sdim
6783309124Sdim//===----------------------------------------------------------------------===//
6784309124Sdim// sdwa
6785309124Sdim//===----------------------------------------------------------------------===//
6786284677Sdim
6787314564SdimOperandMatchResultTy
6788309124SdimAMDGPUAsmParser::parseSDWASel(OperandVector &Operands, StringRef Prefix,
6789309124Sdim                              AMDGPUOperand::ImmTy Type) {
6790314564Sdim  using namespace llvm::AMDGPU::SDWA;
6791314564Sdim
6792309124Sdim  SMLoc S = Parser.getTok().getLoc();
6793309124Sdim  StringRef Value;
6794314564Sdim  OperandMatchResultTy res;
6795284677Sdim
6796309124Sdim  res = parseStringWithPrefix(Prefix, Value);
6797309124Sdim  if (res != MatchOperand_Success) {
6798309124Sdim    return res;
6799284677Sdim  }
6800309124Sdim
6801309124Sdim  int64_t Int;
6802309124Sdim  Int = StringSwitch<int64_t>(Value)
6803314564Sdim        .Case("BYTE_0", SdwaSel::BYTE_0)
6804314564Sdim        .Case("BYTE_1", SdwaSel::BYTE_1)
6805314564Sdim        .Case("BYTE_2", SdwaSel::BYTE_2)
6806314564Sdim        .Case("BYTE_3", SdwaSel::BYTE_3)
6807314564Sdim        .Case("WORD_0", SdwaSel::WORD_0)
6808314564Sdim        .Case("WORD_1", SdwaSel::WORD_1)
6809314564Sdim        .Case("DWORD", SdwaSel::DWORD)
6810309124Sdim        .Default(0xffffffff);
6811309124Sdim  Parser.Lex(); // eat last token
6812309124Sdim
6813309124Sdim  if (Int == 0xffffffff) {
6814309124Sdim    return MatchOperand_ParseFail;
6815309124Sdim  }
6816309124Sdim
6817314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, Type));
6818309124Sdim  return MatchOperand_Success;
6819284677Sdim}
6820284677Sdim
6821314564SdimOperandMatchResultTy
6822309124SdimAMDGPUAsmParser::parseSDWADstUnused(OperandVector &Operands) {
6823314564Sdim  using namespace llvm::AMDGPU::SDWA;
6824314564Sdim
6825309124Sdim  SMLoc S = Parser.getTok().getLoc();
6826309124Sdim  StringRef Value;
6827314564Sdim  OperandMatchResultTy res;
6828309124Sdim
6829309124Sdim  res = parseStringWithPrefix("dst_unused", Value);
6830309124Sdim  if (res != MatchOperand_Success) {
6831309124Sdim    return res;
6832309124Sdim  }
6833309124Sdim
6834309124Sdim  int64_t Int;
6835309124Sdim  Int = StringSwitch<int64_t>(Value)
6836314564Sdim        .Case("UNUSED_PAD", DstUnused::UNUSED_PAD)
6837314564Sdim        .Case("UNUSED_SEXT", DstUnused::UNUSED_SEXT)
6838314564Sdim        .Case("UNUSED_PRESERVE", DstUnused::UNUSED_PRESERVE)
6839309124Sdim        .Default(0xffffffff);
6840309124Sdim  Parser.Lex(); // eat last token
6841309124Sdim
6842309124Sdim  if (Int == 0xffffffff) {
6843309124Sdim    return MatchOperand_ParseFail;
6844309124Sdim  }
6845309124Sdim
6846314564Sdim  Operands.push_back(AMDGPUOperand::CreateImm(this, Int, S, AMDGPUOperand::ImmTySdwaDstUnused));
6847309124Sdim  return MatchOperand_Success;
6848309124Sdim}
6849309124Sdim
6850309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOP1(MCInst &Inst, const OperandVector &Operands) {
6851309124Sdim  cvtSDWA(Inst, Operands, SIInstrFlags::VOP1);
6852309124Sdim}
6853309124Sdim
6854309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2(MCInst &Inst, const OperandVector &Operands) {
6855309124Sdim  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2);
6856309124Sdim}
6857309124Sdim
6858321369Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2b(MCInst &Inst, const OperandVector &Operands) {
6859360784Sdim  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, true, true);
6860321369Sdim}
6861321369Sdim
6862360784Sdimvoid AMDGPUAsmParser::cvtSdwaVOP2e(MCInst &Inst, const OperandVector &Operands) {
6863360784Sdim  cvtSDWA(Inst, Operands, SIInstrFlags::VOP2, false, true);
6864360784Sdim}
6865360784Sdim
6866309124Sdimvoid AMDGPUAsmParser::cvtSdwaVOPC(MCInst &Inst, const OperandVector &Operands) {
6867321369Sdim  cvtSDWA(Inst, Operands, SIInstrFlags::VOPC, isVI());
6868309124Sdim}
6869309124Sdim
6870309124Sdimvoid AMDGPUAsmParser::cvtSDWA(MCInst &Inst, const OperandVector &Operands,
6871360784Sdim                              uint64_t BasicInstType,
6872360784Sdim                              bool SkipDstVcc,
6873360784Sdim                              bool SkipSrcVcc) {
6874321369Sdim  using namespace llvm::AMDGPU::SDWA;
6875327952Sdim
6876309124Sdim  OptionalImmIndexMap OptionalIdx;
6877360784Sdim  bool SkipVcc = SkipDstVcc || SkipSrcVcc;
6878360784Sdim  bool SkippedVcc = false;
6879309124Sdim
6880309124Sdim  unsigned I = 1;
6881309124Sdim  const MCInstrDesc &Desc = MII.get(Inst.getOpcode());
6882309124Sdim  for (unsigned J = 0; J < Desc.getNumDefs(); ++J) {
6883309124Sdim    ((AMDGPUOperand &)*Operands[I++]).addRegOperands(Inst, 1);
6884309124Sdim  }
6885309124Sdim
6886309124Sdim  for (unsigned E = Operands.size(); I != E; ++I) {
6887309124Sdim    AMDGPUOperand &Op = ((AMDGPUOperand &)*Operands[I]);
6888360784Sdim    if (SkipVcc && !SkippedVcc && Op.isReg() &&
6889353358Sdim        (Op.getReg() == AMDGPU::VCC || Op.getReg() == AMDGPU::VCC_LO)) {
6890321369Sdim      // VOP2b (v_add_u32, v_sub_u32 ...) sdwa use "vcc" token as dst.
6891321369Sdim      // Skip it if it's 2nd (e.g. v_add_i32_sdwa v1, vcc, v2, v3)
6892321369Sdim      // or 4th (v_addc_u32_sdwa v1, vcc, v2, v3, vcc) operand.
6893321369Sdim      // Skip VCC only if we didn't skip it on previous iteration.
6894360784Sdim      // Note that src0 and src1 occupy 2 slots each because of modifiers.
6895321369Sdim      if (BasicInstType == SIInstrFlags::VOP2 &&
6896360784Sdim          ((SkipDstVcc && Inst.getNumOperands() == 1) ||
6897360784Sdim           (SkipSrcVcc && Inst.getNumOperands() == 5))) {
6898360784Sdim        SkippedVcc = true;
6899321369Sdim        continue;
6900321369Sdim      } else if (BasicInstType == SIInstrFlags::VOPC &&
6901321369Sdim                 Inst.getNumOperands() == 0) {
6902360784Sdim        SkippedVcc = true;
6903321369Sdim        continue;
6904321369Sdim      }
6905321369Sdim    }
6906321369Sdim    if (isRegOrImmWithInputMods(Desc, Inst.getNumOperands())) {
6907341825Sdim      Op.addRegOrImmWithInputModsOperands(Inst, 2);
6908309124Sdim    } else if (Op.isImm()) {
6909309124Sdim      // Handle optional arguments
6910309124Sdim      OptionalIdx[Op.getImmTy()] = I;
6911309124Sdim    } else {
6912309124Sdim      llvm_unreachable("Invalid operand type");
6913309124Sdim    }
6914360784Sdim    SkippedVcc = false;
6915309124Sdim  }
6916309124Sdim
6917353358Sdim  if (Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx10 &&
6918353358Sdim      Inst.getOpcode() != AMDGPU::V_NOP_sdwa_gfx9 &&
6919321369Sdim      Inst.getOpcode() != AMDGPU::V_NOP_sdwa_vi) {
6920321369Sdim    // v_nop_sdwa_sdwa_vi/gfx9 has no optional sdwa arguments
6921314564Sdim    switch (BasicInstType) {
6922314564Sdim    case SIInstrFlags::VOP1:
6923321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
6924321369Sdim      if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
6925321369Sdim        addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6926321369Sdim      }
6927321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6928321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6929321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6930314564Sdim      break;
6931314564Sdim
6932314564Sdim    case SIInstrFlags::VOP2:
6933321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
6934321369Sdim      if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::omod) != -1) {
6935321369Sdim        addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyOModSI, 0);
6936321369Sdim      }
6937321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstSel, SdwaSel::DWORD);
6938321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaDstUnused, DstUnused::UNUSED_PRESERVE);
6939321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6940321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
6941314564Sdim      break;
6942314564Sdim
6943314564Sdim    case SIInstrFlags::VOPC:
6944353358Sdim      if (AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::clamp) != -1)
6945353358Sdim        addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTyClampSI, 0);
6946321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc0Sel, SdwaSel::DWORD);
6947321369Sdim      addOptionalImmOperand(Inst, Operands, OptionalIdx, AMDGPUOperand::ImmTySdwaSrc1Sel, SdwaSel::DWORD);
6948314564Sdim      break;
6949314564Sdim
6950314564Sdim    default:
6951314564Sdim      llvm_unreachable("Invalid instruction type. Only VOP1, VOP2 and VOPC allowed");
6952314564Sdim    }
6953309124Sdim  }
6954314564Sdim
6955314564Sdim  // special case v_mac_{f16, f32}:
6956314564Sdim  // it has src2 register operand that is tied to dst operand
6957314564Sdim  if (Inst.getOpcode() == AMDGPU::V_MAC_F32_sdwa_vi ||
6958314564Sdim      Inst.getOpcode() == AMDGPU::V_MAC_F16_sdwa_vi)  {
6959314564Sdim    auto it = Inst.begin();
6960314564Sdim    std::advance(
6961321369Sdim      it, AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::src2));
6962314564Sdim    Inst.insert(it, Inst.getOperand(0)); // src2 = dst
6963309124Sdim  }
6964309124Sdim}
6965309124Sdim
6966353358Sdim//===----------------------------------------------------------------------===//
6967353358Sdim// mAI
6968353358Sdim//===----------------------------------------------------------------------===//
6969353358Sdim
6970353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultBLGP() const {
6971353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyBLGP);
6972353358Sdim}
6973353358Sdim
6974353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultCBSZ() const {
6975353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyCBSZ);
6976353358Sdim}
6977353358Sdim
6978353358SdimAMDGPUOperand::Ptr AMDGPUAsmParser::defaultABID() const {
6979353358Sdim  return AMDGPUOperand::CreateImm(this, 0, SMLoc(), AMDGPUOperand::ImmTyABID);
6980353358Sdim}
6981353358Sdim
6982284677Sdim/// Force static initialization.
6983360784Sdimextern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUAsmParser() {
6984314564Sdim  RegisterMCAsmParser<AMDGPUAsmParser> A(getTheAMDGPUTarget());
6985314564Sdim  RegisterMCAsmParser<AMDGPUAsmParser> B(getTheGCNTarget());
6986284677Sdim}
6987284677Sdim
6988284677Sdim#define GET_REGISTER_MATCHER
6989284677Sdim#define GET_MATCHER_IMPLEMENTATION
6990327952Sdim#define GET_MNEMONIC_SPELL_CHECKER
6991284677Sdim#include "AMDGPUGenAsmMatcher.inc"
6992284677Sdim
6993309124Sdim// This fuction should be defined after auto-generated include so that we have
6994309124Sdim// MatchClassKind enum defined
6995309124Sdimunsigned AMDGPUAsmParser::validateTargetOperandClass(MCParsedAsmOperand &Op,
6996309124Sdim                                                     unsigned Kind) {
6997309124Sdim  // Tokens like "glc" would be parsed as immediate operands in ParseOperand().
6998309124Sdim  // But MatchInstructionImpl() expects to meet token and fails to validate
6999309124Sdim  // operand. This method checks if we are given immediate operand but expect to
7000309124Sdim  // get corresponding token.
7001309124Sdim  AMDGPUOperand &Operand = (AMDGPUOperand&)Op;
7002309124Sdim  switch (Kind) {
7003309124Sdim  case MCK_addr64:
7004309124Sdim    return Operand.isAddr64() ? Match_Success : Match_InvalidOperand;
7005309124Sdim  case MCK_gds:
7006309124Sdim    return Operand.isGDS() ? Match_Success : Match_InvalidOperand;
7007341825Sdim  case MCK_lds:
7008341825Sdim    return Operand.isLDS() ? Match_Success : Match_InvalidOperand;
7009309124Sdim  case MCK_glc:
7010309124Sdim    return Operand.isGLC() ? Match_Success : Match_InvalidOperand;
7011309124Sdim  case MCK_idxen:
7012309124Sdim    return Operand.isIdxen() ? Match_Success : Match_InvalidOperand;
7013309124Sdim  case MCK_offen:
7014309124Sdim    return Operand.isOffen() ? Match_Success : Match_InvalidOperand;
7015314564Sdim  case MCK_SSrcB32:
7016309124Sdim    // When operands have expression values, they will return true for isToken,
7017309124Sdim    // because it is not possible to distinguish between a token and an
7018309124Sdim    // expression at parse time. MatchInstructionImpl() will always try to
7019309124Sdim    // match an operand as a token, when isToken returns true, and when the
7020309124Sdim    // name of the expression is not a valid token, the match will fail,
7021309124Sdim    // so we need to handle it here.
7022314564Sdim    return Operand.isSSrcB32() ? Match_Success : Match_InvalidOperand;
7023314564Sdim  case MCK_SSrcF32:
7024314564Sdim    return Operand.isSSrcF32() ? Match_Success : Match_InvalidOperand;
7025309124Sdim  case MCK_SoppBrTarget:
7026309124Sdim    return Operand.isSoppBrTarget() ? Match_Success : Match_InvalidOperand;
7027314564Sdim  case MCK_VReg32OrOff:
7028314564Sdim    return Operand.isVReg32OrOff() ? Match_Success : Match_InvalidOperand;
7029314564Sdim  case MCK_InterpSlot:
7030314564Sdim    return Operand.isInterpSlot() ? Match_Success : Match_InvalidOperand;
7031314564Sdim  case MCK_Attr:
7032314564Sdim    return Operand.isInterpAttr() ? Match_Success : Match_InvalidOperand;
7033314564Sdim  case MCK_AttrChan:
7034314564Sdim    return Operand.isAttrChan() ? Match_Success : Match_InvalidOperand;
7035360784Sdim  case MCK_SReg_64:
7036360784Sdim  case MCK_SReg_64_XEXEC:
7037360784Sdim    // Null is defined as a 32-bit register but
7038360784Sdim    // it should also be enabled with 64-bit operands.
7039360784Sdim    // The following code enables it for SReg_64 operands
7040360784Sdim    // used as source and destination. Remaining source
7041360784Sdim    // operands are handled in isInlinableImm.
7042360784Sdim    return Operand.isNull() ? Match_Success : Match_InvalidOperand;
7043314564Sdim  default:
7044314564Sdim    return Match_InvalidOperand;
7045309124Sdim  }
7046309124Sdim}
7047353358Sdim
7048353358Sdim//===----------------------------------------------------------------------===//
7049353358Sdim// endpgm
7050353358Sdim//===----------------------------------------------------------------------===//
7051353358Sdim
7052353358SdimOperandMatchResultTy AMDGPUAsmParser::parseEndpgmOp(OperandVector &Operands) {
7053353358Sdim  SMLoc S = Parser.getTok().getLoc();
7054353358Sdim  int64_t Imm = 0;
7055353358Sdim
7056353358Sdim  if (!parseExpr(Imm)) {
7057353358Sdim    // The operand is optional, if not present default to 0
7058353358Sdim    Imm = 0;
7059353358Sdim  }
7060353358Sdim
7061353358Sdim  if (!isUInt<16>(Imm)) {
7062353358Sdim    Error(S, "expected a 16-bit value");
7063353358Sdim    return MatchOperand_ParseFail;
7064353358Sdim  }
7065353358Sdim
7066353358Sdim  Operands.push_back(
7067353358Sdim      AMDGPUOperand::CreateImm(this, Imm, S, AMDGPUOperand::ImmTyEndpgm));
7068353358Sdim  return MatchOperand_Success;
7069353358Sdim}
7070353358Sdim
7071353358Sdimbool AMDGPUOperand::isEndpgm() const { return isImmTy(ImmTyEndpgm); }
7072