xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA ---------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric /// \file
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric /// This file contains definition for AMDGPU ISA disassembler
140b57cec5SDimitry Andric //
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric // ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)?
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "Disassembler/AMDGPUDisassembler.h"
200b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
2181ad6265SDimitry Andric #include "SIDefines.h"
2281ad6265SDimitry Andric #include "SIRegisterInfo.h"
230b57cec5SDimitry Andric #include "TargetInfo/AMDGPUTargetInfo.h"
24*0fca6ea1SDimitry Andric #include "Utils/AMDGPUAsmUtils.h"
250b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
26e8d8bef9SDimitry Andric #include "llvm-c/DisassemblerTypes.h"
2781ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
3081ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
32349cc55cSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
3381ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
3481ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
3581ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
36e8d8bef9SDimitry Andric #include "llvm/Support/AMDHSAKernelDescriptor.h"
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric using namespace llvm;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-disassembler"
410b57cec5SDimitry Andric 
42e8d8bef9SDimitry Andric #define SGPR_MAX                                                               \
43e8d8bef9SDimitry Andric   (isGFX10Plus() ? AMDGPU::EncValues::SGPR_MAX_GFX10                           \
440b57cec5SDimitry Andric                  : AMDGPU::EncValues::SGPR_MAX_SI)
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric using DecodeStatus = llvm::MCDisassembler::DecodeStatus;
470b57cec5SDimitry Andric 
48*0fca6ea1SDimitry Andric static const MCSubtargetInfo &addDefaultWaveSize(const MCSubtargetInfo &STI,
49*0fca6ea1SDimitry Andric                                                  MCContext &Ctx) {
50*0fca6ea1SDimitry Andric   if (!STI.hasFeature(AMDGPU::FeatureWavefrontSize64) &&
51*0fca6ea1SDimitry Andric       !STI.hasFeature(AMDGPU::FeatureWavefrontSize32)) {
52*0fca6ea1SDimitry Andric     MCSubtargetInfo &STICopy = Ctx.getSubtargetCopy(STI);
53*0fca6ea1SDimitry Andric     // If there is no default wave size it must be a generation before gfx10,
54*0fca6ea1SDimitry Andric     // these have FeatureWavefrontSize64 in their definition already. For gfx10+
55*0fca6ea1SDimitry Andric     // set wave32 as a default.
56*0fca6ea1SDimitry Andric     STICopy.ToggleFeature(AMDGPU::FeatureWavefrontSize32);
57*0fca6ea1SDimitry Andric     return STICopy;
58*0fca6ea1SDimitry Andric   }
59*0fca6ea1SDimitry Andric 
60*0fca6ea1SDimitry Andric   return STI;
61*0fca6ea1SDimitry Andric }
62*0fca6ea1SDimitry Andric 
630b57cec5SDimitry Andric AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
6406c3fb27SDimitry Andric                                        MCContext &Ctx, MCInstrInfo const *MCII)
65*0fca6ea1SDimitry Andric     : MCDisassembler(addDefaultWaveSize(STI, Ctx), Ctx), MCII(MCII),
66*0fca6ea1SDimitry Andric       MRI(*Ctx.getRegisterInfo()), MAI(*Ctx.getAsmInfo()),
67*0fca6ea1SDimitry Andric       TargetMaxInstBytes(MAI.getMaxInstLength(&STI)),
68*0fca6ea1SDimitry Andric       CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) {
690b57cec5SDimitry Andric   // ToDo: AMDGPUDisassembler supports only VI ISA.
7006c3fb27SDimitry Andric   if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
710b57cec5SDimitry Andric     report_fatal_error("Disassembly not yet supported for subtarget");
72*0fca6ea1SDimitry Andric 
73*0fca6ea1SDimitry Andric   for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
74*0fca6ea1SDimitry Andric     createConstantSymbolExpr(Symbol, Code);
75*0fca6ea1SDimitry Andric 
76*0fca6ea1SDimitry Andric   UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000);
77*0fca6ea1SDimitry Andric   UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000);
78*0fca6ea1SDimitry Andric   UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000);
79*0fca6ea1SDimitry Andric }
80*0fca6ea1SDimitry Andric 
81*0fca6ea1SDimitry Andric void AMDGPUDisassembler::setABIVersion(unsigned Version) {
82*0fca6ea1SDimitry Andric   CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(Version);
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric inline static MCDisassembler::DecodeStatus
860b57cec5SDimitry Andric addOperand(MCInst &Inst, const MCOperand& Opnd) {
870b57cec5SDimitry Andric   Inst.addOperand(Opnd);
880b57cec5SDimitry Andric   return Opnd.isValid() ?
890b57cec5SDimitry Andric     MCDisassembler::Success :
90480093f4SDimitry Andric     MCDisassembler::Fail;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,
940b57cec5SDimitry Andric                                 uint16_t NameIdx) {
950b57cec5SDimitry Andric   int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), NameIdx);
960b57cec5SDimitry Andric   if (OpIdx != -1) {
970b57cec5SDimitry Andric     auto I = MI.begin();
980b57cec5SDimitry Andric     std::advance(I, OpIdx);
990b57cec5SDimitry Andric     MI.insert(I, Op);
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   return OpIdx;
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
10406c3fb27SDimitry Andric static DecodeStatus decodeSOPPBrTarget(MCInst &Inst, unsigned Imm,
10581ad6265SDimitry Andric                                        uint64_t Addr,
10681ad6265SDimitry Andric                                        const MCDisassembler *Decoder) {
1070b57cec5SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   // Our branches take a simm16, but we need two extra bits to account for the
1100b57cec5SDimitry Andric   // factor of 4.
1110b57cec5SDimitry Andric   APInt SignedOffset(18, Imm * 4, true);
1120b57cec5SDimitry Andric   int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
1130b57cec5SDimitry Andric 
11481ad6265SDimitry Andric   if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2, 0))
1150b57cec5SDimitry Andric     return MCDisassembler::Success;
1160b57cec5SDimitry Andric   return addOperand(Inst, MCOperand::createImm(Imm));
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
11981ad6265SDimitry Andric static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, uint64_t Addr,
12081ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
1215ffd83dbSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
1225ffd83dbSDimitry Andric   int64_t Offset;
1235f757f3fSDimitry Andric   if (DAsm->isGFX12Plus()) { // GFX12 supports 24-bit signed offsets.
1245f757f3fSDimitry Andric     Offset = SignExtend64<24>(Imm);
1255f757f3fSDimitry Andric   } else if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets.
1265ffd83dbSDimitry Andric     Offset = Imm & 0xFFFFF;
1275ffd83dbSDimitry Andric   } else { // GFX9+ supports 21-bit signed offsets.
1285ffd83dbSDimitry Andric     Offset = SignExtend64<21>(Imm);
1295ffd83dbSDimitry Andric   }
1305ffd83dbSDimitry Andric   return addOperand(Inst, MCOperand::createImm(Offset));
1315ffd83dbSDimitry Andric }
1325ffd83dbSDimitry Andric 
13381ad6265SDimitry Andric static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, uint64_t Addr,
13481ad6265SDimitry Andric                                   const MCDisassembler *Decoder) {
1350b57cec5SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
1360b57cec5SDimitry Andric   return addOperand(Inst, DAsm->decodeBoolReg(Val));
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
1395f757f3fSDimitry Andric static DecodeStatus decodeSplitBarrier(MCInst &Inst, unsigned Val,
1405f757f3fSDimitry Andric                                        uint64_t Addr,
1415f757f3fSDimitry Andric                                        const MCDisassembler *Decoder) {
1425f757f3fSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
1435f757f3fSDimitry Andric   return addOperand(Inst, DAsm->decodeSplitBarrier(Val));
1445f757f3fSDimitry Andric }
1455f757f3fSDimitry Andric 
146*0fca6ea1SDimitry Andric static DecodeStatus decodeDpp8FI(MCInst &Inst, unsigned Val, uint64_t Addr,
147*0fca6ea1SDimitry Andric                                  const MCDisassembler *Decoder) {
148*0fca6ea1SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
149*0fca6ea1SDimitry Andric   return addOperand(Inst, DAsm->decodeDpp8FI(Val));
150*0fca6ea1SDimitry Andric }
151*0fca6ea1SDimitry Andric 
1520b57cec5SDimitry Andric #define DECODE_OPERAND(StaticDecoderName, DecoderName)                         \
15381ad6265SDimitry Andric   static DecodeStatus StaticDecoderName(MCInst &Inst, unsigned Imm,            \
1540b57cec5SDimitry Andric                                         uint64_t /*Addr*/,                     \
15581ad6265SDimitry Andric                                         const MCDisassembler *Decoder) {       \
1560b57cec5SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
1570b57cec5SDimitry Andric     return addOperand(Inst, DAsm->DecoderName(Imm));                           \
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric 
16006c3fb27SDimitry Andric // Decoder for registers, decode directly using RegClassID. Imm(8-bit) is
16106c3fb27SDimitry Andric // number of register. Used by VGPR only and AGPR only operands.
16206c3fb27SDimitry Andric #define DECODE_OPERAND_REG_8(RegClass)                                         \
16306c3fb27SDimitry Andric   static DecodeStatus Decode##RegClass##RegisterClass(                         \
16406c3fb27SDimitry Andric       MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,                           \
16506c3fb27SDimitry Andric       const MCDisassembler *Decoder) {                                         \
16606c3fb27SDimitry Andric     assert(Imm < (1 << 8) && "8-bit encoding");                                \
16706c3fb27SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
16806c3fb27SDimitry Andric     return addOperand(                                                         \
16906c3fb27SDimitry Andric         Inst, DAsm->createRegOperand(AMDGPU::RegClass##RegClassID, Imm));      \
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
17206c3fb27SDimitry Andric #define DECODE_SrcOp(Name, EncSize, OpWidth, EncImm, MandatoryLiteral,         \
17306c3fb27SDimitry Andric                      ImmWidth)                                                 \
17406c3fb27SDimitry Andric   static DecodeStatus Name(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,      \
17506c3fb27SDimitry Andric                            const MCDisassembler *Decoder) {                    \
17606c3fb27SDimitry Andric     assert(Imm < (1 << EncSize) && #EncSize "-bit encoding");                  \
17706c3fb27SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
17806c3fb27SDimitry Andric     return addOperand(Inst,                                                    \
17906c3fb27SDimitry Andric                       DAsm->decodeSrcOp(AMDGPUDisassembler::OpWidth, EncImm,   \
18006c3fb27SDimitry Andric                                         MandatoryLiteral, ImmWidth));          \
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
183*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcOp(MCInst &Inst, unsigned EncSize,
184*0fca6ea1SDimitry Andric                                 AMDGPUDisassembler::OpWidthTy OpWidth,
185*0fca6ea1SDimitry Andric                                 unsigned Imm, unsigned EncImm,
186*0fca6ea1SDimitry Andric                                 bool MandatoryLiteral, unsigned ImmWidth,
187*0fca6ea1SDimitry Andric                                 AMDGPU::OperandSemantics Sema,
188*0fca6ea1SDimitry Andric                                 const MCDisassembler *Decoder) {
189*0fca6ea1SDimitry Andric   assert(Imm < (1U << EncSize) && "Operand doesn't fit encoding!");
190*0fca6ea1SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
191*0fca6ea1SDimitry Andric   return addOperand(Inst, DAsm->decodeSrcOp(OpWidth, EncImm, MandatoryLiteral,
192*0fca6ea1SDimitry Andric                                             ImmWidth, Sema));
193*0fca6ea1SDimitry Andric }
194*0fca6ea1SDimitry Andric 
19506c3fb27SDimitry Andric // Decoder for registers. Imm(7-bit) is number of register, uses decodeSrcOp to
19606c3fb27SDimitry Andric // get register class. Used by SGPR only operands.
19706c3fb27SDimitry Andric #define DECODE_OPERAND_REG_7(RegClass, OpWidth)                                \
19806c3fb27SDimitry Andric   DECODE_SrcOp(Decode##RegClass##RegisterClass, 7, OpWidth, Imm, false, 0)
199fe6060f1SDimitry Andric 
20006c3fb27SDimitry Andric // Decoder for registers. Imm(10-bit): Imm{7-0} is number of register,
20106c3fb27SDimitry Andric // Imm{9} is acc(agpr or vgpr) Imm{8} should be 0 (see VOP3Pe_SMFMAC).
20206c3fb27SDimitry Andric // Set Imm{8} to 1 (IS_VGPR) to decode using 'enum10' from decodeSrcOp.
20306c3fb27SDimitry Andric // Used by AV_ register classes (AGPR or VGPR only register operands).
204*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth>
205*0fca6ea1SDimitry Andric static DecodeStatus decodeAV10(MCInst &Inst, unsigned Imm, uint64_t /* Addr */,
206*0fca6ea1SDimitry Andric                                const MCDisassembler *Decoder) {
207*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm | AMDGPU::EncValues::IS_VGPR,
208*0fca6ea1SDimitry Andric                      false, 0, AMDGPU::OperandSemantics::INT, Decoder);
209*0fca6ea1SDimitry Andric }
2100b57cec5SDimitry Andric 
21106c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) registers only.
212*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth>
213*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcReg9(MCInst &Inst, unsigned Imm,
214*0fca6ea1SDimitry Andric                                   uint64_t /* Addr */,
215*0fca6ea1SDimitry Andric                                   const MCDisassembler *Decoder) {
216*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, false, 0,
217*0fca6ea1SDimitry Andric                      AMDGPU::OperandSemantics::INT, Decoder);
218*0fca6ea1SDimitry Andric }
2190b57cec5SDimitry Andric 
22006c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) AGPR, register number encoded in 9bits, set
22106c3fb27SDimitry Andric // Imm{9} to 1 (set acc) and decode using 'enum10' from decodeSrcOp, registers
22206c3fb27SDimitry Andric // only.
223*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth>
224*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcA9(MCInst &Inst, unsigned Imm, uint64_t /* Addr */,
225*0fca6ea1SDimitry Andric                                 const MCDisassembler *Decoder) {
226*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, false, 0,
227*0fca6ea1SDimitry Andric                      AMDGPU::OperandSemantics::INT, Decoder);
228*0fca6ea1SDimitry Andric }
229fe6060f1SDimitry Andric 
23006c3fb27SDimitry Andric // Decoder for 'enum10' from decodeSrcOp, Imm{0-8} is 9-bit Src encoding
23106c3fb27SDimitry Andric // Imm{9} is acc, registers only.
232*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth>
233*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcAV10(MCInst &Inst, unsigned Imm,
234*0fca6ea1SDimitry Andric                                   uint64_t /* Addr */,
235*0fca6ea1SDimitry Andric                                   const MCDisassembler *Decoder) {
236*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm, false, 0,
237*0fca6ea1SDimitry Andric                      AMDGPU::OperandSemantics::INT, Decoder);
238*0fca6ea1SDimitry Andric }
2390b57cec5SDimitry Andric 
24006c3fb27SDimitry Andric // Decoder for RegisterOperands using 9-bit Src encoding. Operand can be
24106c3fb27SDimitry Andric // register from RegClass or immediate. Registers that don't belong to RegClass
24206c3fb27SDimitry Andric // will be decoded and InstPrinter will report warning. Immediate will be
24306c3fb27SDimitry Andric // decoded into constant of size ImmWidth, should match width of immediate used
24406c3fb27SDimitry Andric // by OperandType (important for floating point types).
245*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth,
246*0fca6ea1SDimitry Andric           unsigned OperandSemantics>
247*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImm9(MCInst &Inst, unsigned Imm,
248*0fca6ea1SDimitry Andric                                        uint64_t /* Addr */,
249*0fca6ea1SDimitry Andric                                        const MCDisassembler *Decoder) {
250*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, false, ImmWidth,
251*0fca6ea1SDimitry Andric                      (AMDGPU::OperandSemantics)OperandSemantics, Decoder);
252*0fca6ea1SDimitry Andric }
2531db9f3b2SDimitry Andric 
25406c3fb27SDimitry Andric // Decoder for Src(9-bit encoding) AGPR or immediate. Set Imm{9} to 1 (set acc)
25506c3fb27SDimitry Andric // and decode using 'enum10' from decodeSrcOp.
256*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth,
257*0fca6ea1SDimitry Andric           unsigned OperandSemantics>
258*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImmA9(MCInst &Inst, unsigned Imm,
259*0fca6ea1SDimitry Andric                                         uint64_t /* Addr */,
260*0fca6ea1SDimitry Andric                                         const MCDisassembler *Decoder) {
261*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, false, ImmWidth,
262*0fca6ea1SDimitry Andric                      (AMDGPU::OperandSemantics)OperandSemantics, Decoder);
263*0fca6ea1SDimitry Andric }
2640b57cec5SDimitry Andric 
265*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy OpWidth, unsigned ImmWidth,
266*0fca6ea1SDimitry Andric           unsigned OperandSemantics>
267*0fca6ea1SDimitry Andric static DecodeStatus decodeSrcRegOrImmDeferred9(MCInst &Inst, unsigned Imm,
268*0fca6ea1SDimitry Andric                                                uint64_t /* Addr */,
269*0fca6ea1SDimitry Andric                                                const MCDisassembler *Decoder) {
270*0fca6ea1SDimitry Andric   return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, true, ImmWidth,
271*0fca6ea1SDimitry Andric                      (AMDGPU::OperandSemantics)OperandSemantics, Decoder);
272*0fca6ea1SDimitry Andric }
2730b57cec5SDimitry Andric 
27406c3fb27SDimitry Andric // Default decoders generated by tablegen: 'Decode<RegClass>RegisterClass'
27506c3fb27SDimitry Andric // when RegisterClass is used as an operand. Most often used for destination
27606c3fb27SDimitry Andric // operands.
277fe6060f1SDimitry Andric 
27806c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32)
27906c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32_Lo128)
28006c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_64)
28106c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_96)
28206c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_128)
28306c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_256)
28406c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_288)
28506c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_352)
28606c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_384)
28706c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_512)
28806c3fb27SDimitry Andric DECODE_OPERAND_REG_8(VReg_1024)
289fe6060f1SDimitry Andric 
29006c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32, OPW32)
2915f757f3fSDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC, OPW32)
29206c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XM0_XEXEC, OPW32)
29306c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC_HI, OPW32)
29406c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_64, OPW64)
29506c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_64_XEXEC, OPW64)
2965f757f3fSDimitry Andric DECODE_OPERAND_REG_7(SReg_96, OPW96)
29706c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_128, OPW128)
29806c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_256, OPW256)
29906c3fb27SDimitry Andric DECODE_OPERAND_REG_7(SReg_512, OPW512)
300fe6060f1SDimitry Andric 
30106c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AGPR_32)
30206c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_64)
30306c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_128)
30406c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_256)
30506c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_512)
30606c3fb27SDimitry Andric DECODE_OPERAND_REG_8(AReg_1024)
307fe6060f1SDimitry Andric 
3085f757f3fSDimitry Andric static DecodeStatus DecodeVGPR_16RegisterClass(MCInst &Inst, unsigned Imm,
3095f757f3fSDimitry Andric                                                uint64_t /*Addr*/,
3105f757f3fSDimitry Andric                                                const MCDisassembler *Decoder) {
3115f757f3fSDimitry Andric   assert(isUInt<10>(Imm) && "10-bit encoding expected");
3125f757f3fSDimitry Andric   assert((Imm & (1 << 8)) == 0 && "Imm{8} should not be used");
3135f757f3fSDimitry Andric 
3145f757f3fSDimitry Andric   bool IsHi = Imm & (1 << 9);
3155f757f3fSDimitry Andric   unsigned RegIdx = Imm & 0xff;
3165f757f3fSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
3175f757f3fSDimitry Andric   return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
3185f757f3fSDimitry Andric }
3195f757f3fSDimitry Andric 
3205f757f3fSDimitry Andric static DecodeStatus
3215f757f3fSDimitry Andric DecodeVGPR_16_Lo128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,
3225f757f3fSDimitry Andric                                  const MCDisassembler *Decoder) {
3235f757f3fSDimitry Andric   assert(isUInt<8>(Imm) && "8-bit encoding expected");
3245f757f3fSDimitry Andric 
3255f757f3fSDimitry Andric   bool IsHi = Imm & (1 << 7);
3265f757f3fSDimitry Andric   unsigned RegIdx = Imm & 0x7f;
3275f757f3fSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
3285f757f3fSDimitry Andric   return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
3295f757f3fSDimitry Andric }
3305f757f3fSDimitry Andric 
3315f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrcT16_Lo128(MCInst &Inst, unsigned Imm,
3325f757f3fSDimitry Andric                                                 uint64_t /*Addr*/,
3335f757f3fSDimitry Andric                                                 const MCDisassembler *Decoder) {
3345f757f3fSDimitry Andric   assert(isUInt<9>(Imm) && "9-bit encoding expected");
3355f757f3fSDimitry Andric 
3365f757f3fSDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
3375f757f3fSDimitry Andric   bool IsVGPR = Imm & (1 << 8);
3385f757f3fSDimitry Andric   if (IsVGPR) {
3395f757f3fSDimitry Andric     bool IsHi = Imm & (1 << 7);
3405f757f3fSDimitry Andric     unsigned RegIdx = Imm & 0x7f;
3415f757f3fSDimitry Andric     return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
3425f757f3fSDimitry Andric   }
3435f757f3fSDimitry Andric   return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16,
3445f757f3fSDimitry Andric                                                    Imm & 0xFF, false, 16));
3455f757f3fSDimitry Andric }
3465f757f3fSDimitry Andric 
3475f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrcT16(MCInst &Inst, unsigned Imm,
3485f757f3fSDimitry Andric                                           uint64_t /*Addr*/,
3495f757f3fSDimitry Andric                                           const MCDisassembler *Decoder) {
3505f757f3fSDimitry Andric   assert(isUInt<10>(Imm) && "10-bit encoding expected");
3515f757f3fSDimitry Andric 
3525f757f3fSDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
3535f757f3fSDimitry Andric   bool IsVGPR = Imm & (1 << 8);
3545f757f3fSDimitry Andric   if (IsVGPR) {
3555f757f3fSDimitry Andric     bool IsHi = Imm & (1 << 9);
3565f757f3fSDimitry Andric     unsigned RegIdx = Imm & 0xff;
3575f757f3fSDimitry Andric     return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
3585f757f3fSDimitry Andric   }
3595f757f3fSDimitry Andric   return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16,
3605f757f3fSDimitry Andric                                                    Imm & 0xFF, false, 16));
3615f757f3fSDimitry Andric }
36206c3fb27SDimitry Andric 
36306c3fb27SDimitry Andric static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, unsigned Imm,
36481ad6265SDimitry Andric                                          uint64_t Addr,
36581ad6265SDimitry Andric                                          const MCDisassembler *Decoder) {
366349cc55cSDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
367349cc55cSDimitry Andric   return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm));
368349cc55cSDimitry Andric }
369349cc55cSDimitry Andric 
37081ad6265SDimitry Andric static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val,
37181ad6265SDimitry Andric                                           uint64_t Addr, const void *Decoder) {
37281ad6265SDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
37381ad6265SDimitry Andric   return addOperand(Inst, DAsm->decodeVOPDDstYOp(Inst, Val));
37481ad6265SDimitry Andric }
37581ad6265SDimitry Andric 
376fe6060f1SDimitry Andric static bool IsAGPROperand(const MCInst &Inst, int OpIdx,
377fe6060f1SDimitry Andric                           const MCRegisterInfo *MRI) {
378fe6060f1SDimitry Andric   if (OpIdx < 0)
379fe6060f1SDimitry Andric     return false;
380fe6060f1SDimitry Andric 
381fe6060f1SDimitry Andric   const MCOperand &Op = Inst.getOperand(OpIdx);
382fe6060f1SDimitry Andric   if (!Op.isReg())
383fe6060f1SDimitry Andric     return false;
384fe6060f1SDimitry Andric 
385fe6060f1SDimitry Andric   unsigned Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0);
386fe6060f1SDimitry Andric   auto Reg = Sub ? Sub : Op.getReg();
387fe6060f1SDimitry Andric   return Reg >= AMDGPU::AGPR0 && Reg <= AMDGPU::AGPR255;
388fe6060f1SDimitry Andric }
389fe6060f1SDimitry Andric 
390*0fca6ea1SDimitry Andric static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm,
391fe6060f1SDimitry Andric                                  AMDGPUDisassembler::OpWidthTy Opw,
39281ad6265SDimitry Andric                                  const MCDisassembler *Decoder) {
393fe6060f1SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
394fe6060f1SDimitry Andric   if (!DAsm->isGFX90A()) {
395fe6060f1SDimitry Andric     Imm &= 511;
396fe6060f1SDimitry Andric   } else {
397fe6060f1SDimitry Andric     // If atomic has both vdata and vdst their register classes are tied.
398fe6060f1SDimitry Andric     // The bit is decoded along with the vdst, first operand. We need to
399fe6060f1SDimitry Andric     // change register class to AGPR if vdst was AGPR.
400fe6060f1SDimitry Andric     // If a DS instruction has both data0 and data1 their register classes
401fe6060f1SDimitry Andric     // are also tied.
402fe6060f1SDimitry Andric     unsigned Opc = Inst.getOpcode();
403fe6060f1SDimitry Andric     uint64_t TSFlags = DAsm->getMCII()->get(Opc).TSFlags;
404fe6060f1SDimitry Andric     uint16_t DataNameIdx = (TSFlags & SIInstrFlags::DS) ? AMDGPU::OpName::data0
405fe6060f1SDimitry Andric                                                         : AMDGPU::OpName::vdata;
406fe6060f1SDimitry Andric     const MCRegisterInfo *MRI = DAsm->getContext().getRegisterInfo();
407fe6060f1SDimitry Andric     int DataIdx = AMDGPU::getNamedOperandIdx(Opc, DataNameIdx);
408fe6060f1SDimitry Andric     if ((int)Inst.getNumOperands() == DataIdx) {
409fe6060f1SDimitry Andric       int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
410fe6060f1SDimitry Andric       if (IsAGPROperand(Inst, DstIdx, MRI))
411fe6060f1SDimitry Andric         Imm |= 512;
412fe6060f1SDimitry Andric     }
413fe6060f1SDimitry Andric 
414fe6060f1SDimitry Andric     if (TSFlags & SIInstrFlags::DS) {
415fe6060f1SDimitry Andric       int Data2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
416fe6060f1SDimitry Andric       if ((int)Inst.getNumOperands() == Data2Idx &&
417fe6060f1SDimitry Andric           IsAGPROperand(Inst, DataIdx, MRI))
418fe6060f1SDimitry Andric         Imm |= 512;
419fe6060f1SDimitry Andric     }
420fe6060f1SDimitry Andric   }
421fe6060f1SDimitry Andric   return addOperand(Inst, DAsm->decodeSrcOp(Opw, Imm | 256));
422fe6060f1SDimitry Andric }
423fe6060f1SDimitry Andric 
424*0fca6ea1SDimitry Andric template <AMDGPUDisassembler::OpWidthTy Opw>
425*0fca6ea1SDimitry Andric static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm,
426*0fca6ea1SDimitry Andric                                  uint64_t /* Addr */,
427*0fca6ea1SDimitry Andric                                  const MCDisassembler *Decoder) {
428*0fca6ea1SDimitry Andric   return decodeAVLdSt(Inst, Imm, Opw, Decoder);
429*0fca6ea1SDimitry Andric }
430*0fca6ea1SDimitry Andric 
4315f757f3fSDimitry Andric static DecodeStatus decodeOperand_VSrc_f64(MCInst &Inst, unsigned Imm,
4325f757f3fSDimitry Andric                                            uint64_t Addr,
4335f757f3fSDimitry Andric                                            const MCDisassembler *Decoder) {
4345f757f3fSDimitry Andric   assert(Imm < (1 << 9) && "9-bit encoding");
4355f757f3fSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
436*0fca6ea1SDimitry Andric   return addOperand(Inst,
437*0fca6ea1SDimitry Andric                     DAsm->decodeSrcOp(AMDGPUDisassembler::OPW64, Imm, false, 64,
438*0fca6ea1SDimitry Andric                                       AMDGPU::OperandSemantics::FP64));
439bdd1243dSDimitry Andric }
440bdd1243dSDimitry Andric 
4410b57cec5SDimitry Andric #define DECODE_SDWA(DecName) \
4420b57cec5SDimitry Andric DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric DECODE_SDWA(Src32)
4450b57cec5SDimitry Andric DECODE_SDWA(Src16)
4460b57cec5SDimitry Andric DECODE_SDWA(VopcDst)
4470b57cec5SDimitry Andric 
448*0fca6ea1SDimitry Andric static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm,
449*0fca6ea1SDimitry Andric                                      uint64_t /* Addr */,
450*0fca6ea1SDimitry Andric                                      const MCDisassembler *Decoder) {
451*0fca6ea1SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
452*0fca6ea1SDimitry Andric   return addOperand(Inst, DAsm->decodeVersionImm(Imm));
453*0fca6ea1SDimitry Andric }
454*0fca6ea1SDimitry Andric 
4550b57cec5SDimitry Andric #include "AMDGPUGenDisassemblerTables.inc"
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4580b57cec5SDimitry Andric //
4590b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
4620b57cec5SDimitry Andric   assert(Bytes.size() >= sizeof(T));
4635f757f3fSDimitry Andric   const auto Res =
4645f757f3fSDimitry Andric       support::endian::read<T, llvm::endianness::little>(Bytes.data());
4650b57cec5SDimitry Andric   Bytes = Bytes.slice(sizeof(T));
4660b57cec5SDimitry Andric   return Res;
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric 
46981ad6265SDimitry Andric static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) {
47081ad6265SDimitry Andric   assert(Bytes.size() >= 12);
4715f757f3fSDimitry Andric   uint64_t Lo =
4725f757f3fSDimitry Andric       support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
47381ad6265SDimitry Andric   Bytes = Bytes.slice(8);
4745f757f3fSDimitry Andric   uint64_t Hi =
4755f757f3fSDimitry Andric       support::endian::read<uint32_t, llvm::endianness::little>(Bytes.data());
47681ad6265SDimitry Andric   Bytes = Bytes.slice(4);
47781ad6265SDimitry Andric   return DecoderUInt128(Lo, Hi);
4780b57cec5SDimitry Andric }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
4810b57cec5SDimitry Andric                                                 ArrayRef<uint8_t> Bytes_,
4820b57cec5SDimitry Andric                                                 uint64_t Address,
4830b57cec5SDimitry Andric                                                 raw_ostream &CS) const {
4840b57cec5SDimitry Andric   unsigned MaxInstBytesNum = std::min((size_t)TargetMaxInstBytes, Bytes_.size());
4850b57cec5SDimitry Andric   Bytes = Bytes_.slice(0, MaxInstBytesNum);
4860b57cec5SDimitry Andric 
487*0fca6ea1SDimitry Andric   // In case the opcode is not recognized we'll assume a Size of 4 bytes (unless
488*0fca6ea1SDimitry Andric   // there are fewer bytes left). This will be overridden on success.
489*0fca6ea1SDimitry Andric   Size = std::min((size_t)4, Bytes_.size());
490*0fca6ea1SDimitry Andric 
4910b57cec5SDimitry Andric   do {
4920b57cec5SDimitry Andric     // ToDo: better to switch encoding length using some bit predicate
4930b57cec5SDimitry Andric     // but it is unknown yet, so try all we can
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric     // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
4960b57cec5SDimitry Andric     // encodings
49781ad6265SDimitry Andric     if (isGFX11Plus() && Bytes.size() >= 12 ) {
49881ad6265SDimitry Andric       DecoderUInt128 DecW = eat12Bytes(Bytes);
4995f757f3fSDimitry Andric 
500*0fca6ea1SDimitry Andric       if (isGFX11() &&
501*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1196, DecoderTableGFX11_FAKE1696, MI,
502*0fca6ea1SDimitry Andric                         DecW, Address, CS))
50381ad6265SDimitry Andric         break;
5045f757f3fSDimitry Andric 
505*0fca6ea1SDimitry Andric       if (isGFX12() &&
506*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1296, DecoderTableGFX12_FAKE1696, MI,
507*0fca6ea1SDimitry Andric                         DecW, Address, CS))
5085f757f3fSDimitry Andric         break;
5097a6dacacSDimitry Andric 
510*0fca6ea1SDimitry Andric       if (isGFX12() &&
511*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX12W6496, MI, DecW, Address, CS))
5127a6dacacSDimitry Andric         break;
513*0fca6ea1SDimitry Andric 
51481ad6265SDimitry Andric       // Reinitialize Bytes
51581ad6265SDimitry Andric       Bytes = Bytes_.slice(0, MaxInstBytesNum);
516*0fca6ea1SDimitry Andric     }
51781ad6265SDimitry Andric 
5180b57cec5SDimitry Andric     if (Bytes.size() >= 8) {
5190b57cec5SDimitry Andric       const uint64_t QW = eatBytes<uint64_t>(Bytes);
5200b57cec5SDimitry Andric 
521*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) &&
522*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX10_B64, MI, QW, Address, CS))
5235ffd83dbSDimitry Andric         break;
524*0fca6ea1SDimitry Andric 
525*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) &&
526*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address, CS))
5275ffd83dbSDimitry Andric         break;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric       // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and
5300b57cec5SDimitry Andric       // v_mad_mixhi_f16 for FMA variants. Try to decode using this special
5310b57cec5SDimitry Andric       // table first so we print the correct name.
532*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureFmaMixInsts) &&
533*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address, CS))
5340b57cec5SDimitry Andric         break;
5350b57cec5SDimitry Andric 
536*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX940Insts) &&
537*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX94064, MI, QW, Address, CS))
538*0fca6ea1SDimitry Andric         break;
539*0fca6ea1SDimitry Andric 
540*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) &&
541*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX90A64, MI, QW, Address, CS))
542*0fca6ea1SDimitry Andric         break;
543*0fca6ea1SDimitry Andric 
544*0fca6ea1SDimitry Andric       if ((isVI() || isGFX9()) &&
545*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX864, MI, QW, Address, CS))
546*0fca6ea1SDimitry Andric         break;
547*0fca6ea1SDimitry Andric 
548*0fca6ea1SDimitry Andric       if (isGFX9() && tryDecodeInst(DecoderTableGFX964, MI, QW, Address, CS))
549*0fca6ea1SDimitry Andric         break;
550*0fca6ea1SDimitry Andric 
551*0fca6ea1SDimitry Andric       if (isGFX10() && tryDecodeInst(DecoderTableGFX1064, MI, QW, Address, CS))
552*0fca6ea1SDimitry Andric         break;
553*0fca6ea1SDimitry Andric 
554*0fca6ea1SDimitry Andric       if (isGFX12() &&
555*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1264, DecoderTableGFX12_FAKE1664, MI, QW,
556*0fca6ea1SDimitry Andric                         Address, CS))
557*0fca6ea1SDimitry Andric         break;
558*0fca6ea1SDimitry Andric 
559*0fca6ea1SDimitry Andric       if (isGFX11() &&
560*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1164, DecoderTableGFX11_FAKE1664, MI, QW,
561*0fca6ea1SDimitry Andric                         Address, CS))
562*0fca6ea1SDimitry Andric         break;
563*0fca6ea1SDimitry Andric 
564*0fca6ea1SDimitry Andric       if (isGFX11() &&
565*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX11W6464, MI, QW, Address, CS))
566*0fca6ea1SDimitry Andric         break;
567*0fca6ea1SDimitry Andric 
568*0fca6ea1SDimitry Andric       if (isGFX12() &&
569*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX12W6464, MI, QW, Address, CS))
570*0fca6ea1SDimitry Andric         break;
571*0fca6ea1SDimitry Andric 
572*0fca6ea1SDimitry Andric       // Reinitialize Bytes
5730b57cec5SDimitry Andric       Bytes = Bytes_.slice(0, MaxInstBytesNum);
574*0fca6ea1SDimitry Andric     }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric     // Try decode 32-bit instruction
577*0fca6ea1SDimitry Andric     if (Bytes.size() >= 4) {
5780b57cec5SDimitry Andric       const uint32_t DW = eatBytes<uint32_t>(Bytes);
5790b57cec5SDimitry Andric 
580*0fca6ea1SDimitry Andric       if ((isVI() || isGFX9()) &&
581*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX832, MI, DW, Address, CS))
582*0fca6ea1SDimitry Andric         break;
5830b57cec5SDimitry Andric 
584*0fca6ea1SDimitry Andric       if (tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address, CS))
585*0fca6ea1SDimitry Andric         break;
5860b57cec5SDimitry Andric 
587*0fca6ea1SDimitry Andric       if (isGFX9() && tryDecodeInst(DecoderTableGFX932, MI, DW, Address, CS))
588*0fca6ea1SDimitry Andric         break;
589*0fca6ea1SDimitry Andric 
590*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) &&
591*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX90A32, MI, DW, Address, CS))
592*0fca6ea1SDimitry Andric         break;
593*0fca6ea1SDimitry Andric 
594*0fca6ea1SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) &&
595*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX10_B32, MI, DW, Address, CS))
596*0fca6ea1SDimitry Andric         break;
597*0fca6ea1SDimitry Andric 
598*0fca6ea1SDimitry Andric       if (isGFX10() && tryDecodeInst(DecoderTableGFX1032, MI, DW, Address, CS))
599*0fca6ea1SDimitry Andric         break;
600*0fca6ea1SDimitry Andric 
601*0fca6ea1SDimitry Andric       if (isGFX11() &&
602*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1132, DecoderTableGFX11_FAKE1632, MI, DW,
603*0fca6ea1SDimitry Andric                         Address, CS))
604*0fca6ea1SDimitry Andric         break;
605*0fca6ea1SDimitry Andric 
606*0fca6ea1SDimitry Andric       if (isGFX12() &&
607*0fca6ea1SDimitry Andric           tryDecodeInst(DecoderTableGFX1232, DecoderTableGFX12_FAKE1632, MI, DW,
608*0fca6ea1SDimitry Andric                         Address, CS))
609fe6060f1SDimitry Andric         break;
610fe6060f1SDimitry Andric     }
611fe6060f1SDimitry Andric 
612*0fca6ea1SDimitry Andric     return MCDisassembler::Fail;
6130b57cec5SDimitry Andric   } while (false);
6140b57cec5SDimitry Andric 
615*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DPP) {
616*0fca6ea1SDimitry Andric     if (isMacDPP(MI))
617*0fca6ea1SDimitry Andric       convertMacDPPInst(MI);
618*0fca6ea1SDimitry Andric 
619*0fca6ea1SDimitry Andric     if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3P)
620*0fca6ea1SDimitry Andric       convertVOP3PDPPInst(MI);
621*0fca6ea1SDimitry Andric     else if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC) ||
622*0fca6ea1SDimitry Andric              AMDGPU::isVOPC64DPP(MI.getOpcode()))
623*0fca6ea1SDimitry Andric       convertVOPCDPPInst(MI); // Special VOP3 case
624*0fca6ea1SDimitry Andric     else if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dpp8) !=
625*0fca6ea1SDimitry Andric              -1)
626*0fca6ea1SDimitry Andric       convertDPP8Inst(MI);
627*0fca6ea1SDimitry Andric     else if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3)
628*0fca6ea1SDimitry Andric       convertVOP3DPPInst(MI); // Regular VOP3 case
629*0fca6ea1SDimitry Andric   }
630*0fca6ea1SDimitry Andric 
631*0fca6ea1SDimitry Andric   if (AMDGPU::isMAC(MI.getOpcode())) {
6320b57cec5SDimitry Andric     // Insert dummy unused src2_modifiers.
6330b57cec5SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
6340b57cec5SDimitry Andric                          AMDGPU::OpName::src2_modifiers);
6350b57cec5SDimitry Andric   }
6360b57cec5SDimitry Andric 
637*0fca6ea1SDimitry Andric   if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp ||
638*0fca6ea1SDimitry Andric       MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp) {
639b3edf446SDimitry Andric     // Insert dummy unused src2_modifiers.
640b3edf446SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
641b3edf446SDimitry Andric                          AMDGPU::OpName::src2_modifiers);
642b3edf446SDimitry Andric   }
643b3edf446SDimitry Andric 
644*0fca6ea1SDimitry Andric   if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DS) &&
645cb14a3feSDimitry Andric       !AMDGPU::hasGDS(STI)) {
646cb14a3feSDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::gds);
647cb14a3feSDimitry Andric   }
648cb14a3feSDimitry Andric 
649*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags &
650*0fca6ea1SDimitry Andric       (SIInstrFlags::MUBUF | SIInstrFlags::FLAT | SIInstrFlags::SMRD)) {
651fe6060f1SDimitry Andric     int CPolPos = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
652fe6060f1SDimitry Andric                                              AMDGPU::OpName::cpol);
653fe6060f1SDimitry Andric     if (CPolPos != -1) {
654fe6060f1SDimitry Andric       unsigned CPol =
655fe6060f1SDimitry Andric           (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsAtomicRet) ?
656fe6060f1SDimitry Andric               AMDGPU::CPol::GLC : 0;
657fe6060f1SDimitry Andric       if (MI.getNumOperands() <= (unsigned)CPolPos) {
658fe6060f1SDimitry Andric         insertNamedMCOperand(MI, MCOperand::createImm(CPol),
659fe6060f1SDimitry Andric                              AMDGPU::OpName::cpol);
660fe6060f1SDimitry Andric       } else if (CPol) {
661fe6060f1SDimitry Andric         MI.getOperand(CPolPos).setImm(MI.getOperand(CPolPos).getImm() | CPol);
662fe6060f1SDimitry Andric       }
663fe6060f1SDimitry Andric     }
664fe6060f1SDimitry Andric   }
665fe6060f1SDimitry Andric 
666*0fca6ea1SDimitry Andric   if ((MCII->get(MI.getOpcode()).TSFlags &
667fe6060f1SDimitry Andric        (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) &&
66806c3fb27SDimitry Andric       (STI.hasFeature(AMDGPU::FeatureGFX90AInsts))) {
669fe6060f1SDimitry Andric     // GFX90A lost TFE, its place is occupied by ACC.
670fe6060f1SDimitry Andric     int TFEOpIdx =
671fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe);
672fe6060f1SDimitry Andric     if (TFEOpIdx != -1) {
673fe6060f1SDimitry Andric       auto TFEIter = MI.begin();
674fe6060f1SDimitry Andric       std::advance(TFEIter, TFEOpIdx);
675fe6060f1SDimitry Andric       MI.insert(TFEIter, MCOperand::createImm(0));
676fe6060f1SDimitry Andric     }
677fe6060f1SDimitry Andric   }
678fe6060f1SDimitry Andric 
679*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags &
680*0fca6ea1SDimitry Andric       (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) {
681fe6060f1SDimitry Andric     int SWZOpIdx =
682fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::swz);
683fe6060f1SDimitry Andric     if (SWZOpIdx != -1) {
684fe6060f1SDimitry Andric       auto SWZIter = MI.begin();
685fe6060f1SDimitry Andric       std::advance(SWZIter, SWZOpIdx);
686fe6060f1SDimitry Andric       MI.insert(SWZIter, MCOperand::createImm(0));
687fe6060f1SDimitry Andric     }
688e8d8bef9SDimitry Andric   }
689e8d8bef9SDimitry Andric 
690*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG) {
6910b57cec5SDimitry Andric     int VAddr0Idx =
6920b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
6930b57cec5SDimitry Andric     int RsrcIdx =
6940b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
6950b57cec5SDimitry Andric     unsigned NSAArgs = RsrcIdx - VAddr0Idx - 1;
6960b57cec5SDimitry Andric     if (VAddr0Idx >= 0 && NSAArgs > 0) {
6970b57cec5SDimitry Andric       unsigned NSAWords = (NSAArgs + 3) / 4;
698*0fca6ea1SDimitry Andric       if (Bytes.size() < 4 * NSAWords)
699*0fca6ea1SDimitry Andric         return MCDisassembler::Fail;
7000b57cec5SDimitry Andric       for (unsigned i = 0; i < NSAArgs; ++i) {
70181ad6265SDimitry Andric         const unsigned VAddrIdx = VAddr0Idx + 1 + i;
702bdd1243dSDimitry Andric         auto VAddrRCID =
703bdd1243dSDimitry Andric             MCII->get(MI.getOpcode()).operands()[VAddrIdx].RegClass;
704*0fca6ea1SDimitry Andric         MI.insert(MI.begin() + VAddrIdx, createRegOperand(VAddrRCID, Bytes[i]));
7050b57cec5SDimitry Andric       }
7060b57cec5SDimitry Andric       Bytes = Bytes.slice(4 * NSAWords);
7070b57cec5SDimitry Andric     }
708*0fca6ea1SDimitry Andric 
709*0fca6ea1SDimitry Andric     convertMIMGInst(MI);
7100b57cec5SDimitry Andric   }
7110b57cec5SDimitry Andric 
712*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags &
713*0fca6ea1SDimitry Andric       (SIInstrFlags::VIMAGE | SIInstrFlags::VSAMPLE))
714*0fca6ea1SDimitry Andric     convertMIMGInst(MI);
7150b57cec5SDimitry Andric 
716*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::EXP)
717*0fca6ea1SDimitry Andric     convertEXPInst(MI);
7185f757f3fSDimitry Andric 
719*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VINTERP)
720*0fca6ea1SDimitry Andric     convertVINTERPInst(MI);
72181ad6265SDimitry Andric 
722*0fca6ea1SDimitry Andric   if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SDWA)
723*0fca6ea1SDimitry Andric     convertSDWAInst(MI);
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric   int VDstIn_Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
7260b57cec5SDimitry Andric                                               AMDGPU::OpName::vdst_in);
7270b57cec5SDimitry Andric   if (VDstIn_Idx != -1) {
7280b57cec5SDimitry Andric     int Tied = MCII->get(MI.getOpcode()).getOperandConstraint(VDstIn_Idx,
7290b57cec5SDimitry Andric                            MCOI::OperandConstraint::TIED_TO);
7300b57cec5SDimitry Andric     if (Tied != -1 && (MI.getNumOperands() <= (unsigned)VDstIn_Idx ||
7310b57cec5SDimitry Andric          !MI.getOperand(VDstIn_Idx).isReg() ||
7320b57cec5SDimitry Andric          MI.getOperand(VDstIn_Idx).getReg() != MI.getOperand(Tied).getReg())) {
7330b57cec5SDimitry Andric       if (MI.getNumOperands() > (unsigned)VDstIn_Idx)
7340b57cec5SDimitry Andric         MI.erase(&MI.getOperand(VDstIn_Idx));
7350b57cec5SDimitry Andric       insertNamedMCOperand(MI,
7360b57cec5SDimitry Andric         MCOperand::createReg(MI.getOperand(Tied).getReg()),
7370b57cec5SDimitry Andric         AMDGPU::OpName::vdst_in);
7380b57cec5SDimitry Andric     }
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric 
741349cc55cSDimitry Andric   int ImmLitIdx =
742349cc55cSDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::imm);
743bdd1243dSDimitry Andric   bool IsSOPK = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SOPK;
744*0fca6ea1SDimitry Andric   if (ImmLitIdx != -1 && !IsSOPK)
745*0fca6ea1SDimitry Andric     convertFMAanyK(MI, ImmLitIdx);
746349cc55cSDimitry Andric 
747*0fca6ea1SDimitry Andric   Size = MaxInstBytesNum - Bytes.size();
748*0fca6ea1SDimitry Andric   return MCDisassembler::Success;
7490b57cec5SDimitry Andric }
7500b57cec5SDimitry Andric 
751*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertEXPInst(MCInst &MI) const {
7525f757f3fSDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX11Insts)) {
75381ad6265SDimitry Andric     // The MCInst still has these fields even though they are no longer encoded
75481ad6265SDimitry Andric     // in the GFX11 instruction.
75581ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vm);
75681ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::compr);
75781ad6265SDimitry Andric   }
75881ad6265SDimitry Andric }
75981ad6265SDimitry Andric 
760*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const {
76181ad6265SDimitry Andric   if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx11 ||
7625f757f3fSDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx12 ||
76381ad6265SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx11 ||
7645f757f3fSDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx12 ||
76581ad6265SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx11 ||
7665f757f3fSDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx12 ||
7675f757f3fSDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx11 ||
7685f757f3fSDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx12) {
76981ad6265SDimitry Andric     // The MCInst has this field that is not directly encoded in the
77081ad6265SDimitry Andric     // instruction.
77181ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::op_sel);
77281ad6265SDimitry Andric   }
77381ad6265SDimitry Andric }
77481ad6265SDimitry Andric 
775*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
77606c3fb27SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX9) ||
77706c3fb27SDimitry Andric       STI.hasFeature(AMDGPU::FeatureGFX10)) {
778bdd1243dSDimitry Andric     if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::sdst))
7790b57cec5SDimitry Andric       // VOPC - insert clamp
7800b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);
78106c3fb27SDimitry Andric   } else if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) {
7820b57cec5SDimitry Andric     int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);
7830b57cec5SDimitry Andric     if (SDst != -1) {
7840b57cec5SDimitry Andric       // VOPC - insert VCC register as sdst
7850b57cec5SDimitry Andric       insertNamedMCOperand(MI, createRegOperand(AMDGPU::VCC),
7860b57cec5SDimitry Andric                            AMDGPU::OpName::sdst);
7870b57cec5SDimitry Andric     } else {
7880b57cec5SDimitry Andric       // VOP1/2 - insert omod if present in instruction
7890b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);
7900b57cec5SDimitry Andric     }
7910b57cec5SDimitry Andric   }
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
794fcaf7f86SDimitry Andric struct VOPModifiers {
795fcaf7f86SDimitry Andric   unsigned OpSel = 0;
796fcaf7f86SDimitry Andric   unsigned OpSelHi = 0;
797fcaf7f86SDimitry Andric   unsigned NegLo = 0;
798fcaf7f86SDimitry Andric   unsigned NegHi = 0;
799fcaf7f86SDimitry Andric };
800fcaf7f86SDimitry Andric 
801fcaf7f86SDimitry Andric // Reconstruct values of VOP3/VOP3P operands such as op_sel.
802fcaf7f86SDimitry Andric // Note that these values do not affect disassembler output,
803fcaf7f86SDimitry Andric // so this is only necessary for consistency with src_modifiers.
804fcaf7f86SDimitry Andric static VOPModifiers collectVOPModifiers(const MCInst &MI,
805fcaf7f86SDimitry Andric                                         bool IsVOP3P = false) {
806fcaf7f86SDimitry Andric   VOPModifiers Modifiers;
807fcaf7f86SDimitry Andric   unsigned Opc = MI.getOpcode();
808fcaf7f86SDimitry Andric   const int ModOps[] = {AMDGPU::OpName::src0_modifiers,
809fcaf7f86SDimitry Andric                         AMDGPU::OpName::src1_modifiers,
810fcaf7f86SDimitry Andric                         AMDGPU::OpName::src2_modifiers};
811fcaf7f86SDimitry Andric   for (int J = 0; J < 3; ++J) {
812fcaf7f86SDimitry Andric     int OpIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
813fcaf7f86SDimitry Andric     if (OpIdx == -1)
814fcaf7f86SDimitry Andric       continue;
815fcaf7f86SDimitry Andric 
816fcaf7f86SDimitry Andric     unsigned Val = MI.getOperand(OpIdx).getImm();
817fcaf7f86SDimitry Andric 
818fcaf7f86SDimitry Andric     Modifiers.OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J;
819fcaf7f86SDimitry Andric     if (IsVOP3P) {
820fcaf7f86SDimitry Andric       Modifiers.OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J;
821fcaf7f86SDimitry Andric       Modifiers.NegLo |= !!(Val & SISrcMods::NEG) << J;
822fcaf7f86SDimitry Andric       Modifiers.NegHi |= !!(Val & SISrcMods::NEG_HI) << J;
823fcaf7f86SDimitry Andric     } else if (J == 0) {
824fcaf7f86SDimitry Andric       Modifiers.OpSel |= !!(Val & SISrcMods::DST_OP_SEL) << 3;
825fcaf7f86SDimitry Andric     }
826fcaf7f86SDimitry Andric   }
827fcaf7f86SDimitry Andric 
828fcaf7f86SDimitry Andric   return Modifiers;
829fcaf7f86SDimitry Andric }
830fcaf7f86SDimitry Andric 
831*0fca6ea1SDimitry Andric // Instructions decode the op_sel/suffix bits into the src_modifier
832*0fca6ea1SDimitry Andric // operands. Copy those bits into the src operands for true16 VGPRs.
833*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertTrue16OpSel(MCInst &MI) const {
834*0fca6ea1SDimitry Andric   const unsigned Opc = MI.getOpcode();
835*0fca6ea1SDimitry Andric   const MCRegisterClass &ConversionRC =
836*0fca6ea1SDimitry Andric       MRI.getRegClass(AMDGPU::VGPR_16RegClassID);
837*0fca6ea1SDimitry Andric   constexpr std::array<std::tuple<int, int, unsigned>, 4> OpAndOpMods = {
838*0fca6ea1SDimitry Andric       {{AMDGPU::OpName::src0, AMDGPU::OpName::src0_modifiers,
839*0fca6ea1SDimitry Andric         SISrcMods::OP_SEL_0},
840*0fca6ea1SDimitry Andric        {AMDGPU::OpName::src1, AMDGPU::OpName::src1_modifiers,
841*0fca6ea1SDimitry Andric         SISrcMods::OP_SEL_0},
842*0fca6ea1SDimitry Andric        {AMDGPU::OpName::src2, AMDGPU::OpName::src2_modifiers,
843*0fca6ea1SDimitry Andric         SISrcMods::OP_SEL_0},
844*0fca6ea1SDimitry Andric        {AMDGPU::OpName::vdst, AMDGPU::OpName::src0_modifiers,
845*0fca6ea1SDimitry Andric         SISrcMods::DST_OP_SEL}}};
846*0fca6ea1SDimitry Andric   for (const auto &[OpName, OpModsName, OpSelMask] : OpAndOpMods) {
847*0fca6ea1SDimitry Andric     int OpIdx = AMDGPU::getNamedOperandIdx(Opc, OpName);
848*0fca6ea1SDimitry Andric     int OpModsIdx = AMDGPU::getNamedOperandIdx(Opc, OpModsName);
849*0fca6ea1SDimitry Andric     if (OpIdx == -1 || OpModsIdx == -1)
850*0fca6ea1SDimitry Andric       continue;
851*0fca6ea1SDimitry Andric     MCOperand &Op = MI.getOperand(OpIdx);
852*0fca6ea1SDimitry Andric     if (!Op.isReg())
853*0fca6ea1SDimitry Andric       continue;
854*0fca6ea1SDimitry Andric     if (!ConversionRC.contains(Op.getReg()))
855*0fca6ea1SDimitry Andric       continue;
856*0fca6ea1SDimitry Andric     unsigned OpEnc = MRI.getEncodingValue(Op.getReg());
857*0fca6ea1SDimitry Andric     const MCOperand &OpMods = MI.getOperand(OpModsIdx);
858*0fca6ea1SDimitry Andric     unsigned ModVal = OpMods.getImm();
859*0fca6ea1SDimitry Andric     if (ModVal & OpSelMask) { // isHi
860*0fca6ea1SDimitry Andric       unsigned RegIdx = OpEnc & AMDGPU::HWEncoding::REG_IDX_MASK;
861*0fca6ea1SDimitry Andric       Op.setReg(ConversionRC.getRegister(RegIdx * 2 + 1));
862*0fca6ea1SDimitry Andric     }
863*0fca6ea1SDimitry Andric   }
864*0fca6ea1SDimitry Andric }
865*0fca6ea1SDimitry Andric 
866bdd1243dSDimitry Andric // MAC opcodes have special old and src2 operands.
867bdd1243dSDimitry Andric // src2 is tied to dst, while old is not tied (but assumed to be).
868bdd1243dSDimitry Andric bool AMDGPUDisassembler::isMacDPP(MCInst &MI) const {
869bdd1243dSDimitry Andric   constexpr int DST_IDX = 0;
870bdd1243dSDimitry Andric   auto Opcode = MI.getOpcode();
871bdd1243dSDimitry Andric   const auto &Desc = MCII->get(Opcode);
872bdd1243dSDimitry Andric   auto OldIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::old);
873bdd1243dSDimitry Andric 
874bdd1243dSDimitry Andric   if (OldIdx != -1 && Desc.getOperandConstraint(
875bdd1243dSDimitry Andric                           OldIdx, MCOI::OperandConstraint::TIED_TO) == -1) {
876bdd1243dSDimitry Andric     assert(AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2));
877bdd1243dSDimitry Andric     assert(Desc.getOperandConstraint(
878bdd1243dSDimitry Andric                AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2),
879bdd1243dSDimitry Andric                MCOI::OperandConstraint::TIED_TO) == DST_IDX);
880bdd1243dSDimitry Andric     (void)DST_IDX;
881bdd1243dSDimitry Andric     return true;
882bdd1243dSDimitry Andric   }
883bdd1243dSDimitry Andric 
884bdd1243dSDimitry Andric   return false;
885bdd1243dSDimitry Andric }
886bdd1243dSDimitry Andric 
887bdd1243dSDimitry Andric // Create dummy old operand and insert dummy unused src2_modifiers
888bdd1243dSDimitry Andric void AMDGPUDisassembler::convertMacDPPInst(MCInst &MI) const {
889bdd1243dSDimitry Andric   assert(MI.getNumOperands() + 1 < MCII->get(MI.getOpcode()).getNumOperands());
890bdd1243dSDimitry Andric   insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);
891bdd1243dSDimitry Andric   insertNamedMCOperand(MI, MCOperand::createImm(0),
892bdd1243dSDimitry Andric                        AMDGPU::OpName::src2_modifiers);
893bdd1243dSDimitry Andric }
894bdd1243dSDimitry Andric 
895*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const {
8960b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
897b3edf446SDimitry Andric 
898b3edf446SDimitry Andric   int VDstInIdx =
899b3edf446SDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);
900b3edf446SDimitry Andric   if (VDstInIdx != -1)
901b3edf446SDimitry Andric     insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);
902b3edf446SDimitry Andric 
903bdd1243dSDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
904bdd1243dSDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
905bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
906*0fca6ea1SDimitry Andric     convertTrue16OpSel(MI);
907fcaf7f86SDimitry Andric     auto Mods = collectVOPModifiers(MI);
908fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
909fcaf7f86SDimitry Andric                          AMDGPU::OpName::op_sel);
91081ad6265SDimitry Andric   } else {
9110b57cec5SDimitry Andric     // Insert dummy unused src modifiers.
9120b57cec5SDimitry Andric     if (MI.getNumOperands() < DescNumOps &&
913bdd1243dSDimitry Andric         AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))
9140b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0),
9150b57cec5SDimitry Andric                            AMDGPU::OpName::src0_modifiers);
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric     if (MI.getNumOperands() < DescNumOps &&
918bdd1243dSDimitry Andric         AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))
9190b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0),
9200b57cec5SDimitry Andric                            AMDGPU::OpName::src1_modifiers);
92181ad6265SDimitry Andric   }
922bdd1243dSDimitry Andric }
9230b57cec5SDimitry Andric 
924*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOP3DPPInst(MCInst &MI) const {
925*0fca6ea1SDimitry Andric   convertTrue16OpSel(MI);
926bdd1243dSDimitry Andric 
927b3edf446SDimitry Andric   int VDstInIdx =
928b3edf446SDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);
929b3edf446SDimitry Andric   if (VDstInIdx != -1)
930b3edf446SDimitry Andric     insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);
931b3edf446SDimitry Andric 
932fcaf7f86SDimitry Andric   unsigned Opc = MI.getOpcode();
933fcaf7f86SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
934fcaf7f86SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
935bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
936fcaf7f86SDimitry Andric     auto Mods = collectVOPModifiers(MI);
937fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
938fcaf7f86SDimitry Andric                          AMDGPU::OpName::op_sel);
939fcaf7f86SDimitry Andric   }
940fcaf7f86SDimitry Andric }
941fcaf7f86SDimitry Andric 
9420b57cec5SDimitry Andric // Note that before gfx10, the MIMG encoding provided no information about
9430b57cec5SDimitry Andric // VADDR size. Consequently, decoded instructions always show address as if it
9440b57cec5SDimitry Andric // has 1 dword, which could be not really so.
945*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
9465f757f3fSDimitry Andric   auto TSFlags = MCII->get(MI.getOpcode()).TSFlags;
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
9490b57cec5SDimitry Andric                                            AMDGPU::OpName::vdst);
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric   int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
9520b57cec5SDimitry Andric                                             AMDGPU::OpName::vdata);
9530b57cec5SDimitry Andric   int VAddr0Idx =
9540b57cec5SDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
955*0fca6ea1SDimitry Andric   int RsrcOpName = (TSFlags & SIInstrFlags::MIMG) ? AMDGPU::OpName::srsrc
9565f757f3fSDimitry Andric                                                   : AMDGPU::OpName::rsrc;
9575f757f3fSDimitry Andric   int RsrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), RsrcOpName);
9580b57cec5SDimitry Andric   int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
9590b57cec5SDimitry Andric                                             AMDGPU::OpName::dmask);
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric   int TFEIdx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
9620b57cec5SDimitry Andric                                             AMDGPU::OpName::tfe);
9630b57cec5SDimitry Andric   int D16Idx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
9640b57cec5SDimitry Andric                                             AMDGPU::OpName::d16);
9650b57cec5SDimitry Andric 
966349cc55cSDimitry Andric   const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
967349cc55cSDimitry Andric   const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
968349cc55cSDimitry Andric       AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
969349cc55cSDimitry Andric 
9700b57cec5SDimitry Andric   assert(VDataIdx != -1);
971349cc55cSDimitry Andric   if (BaseOpcode->BVH) {
972349cc55cSDimitry Andric     // Add A16 operand for intersect_ray instructions
97306c3fb27SDimitry Andric     addOperand(MI, MCOperand::createImm(BaseOpcode->A16));
974*0fca6ea1SDimitry Andric     return;
975e8d8bef9SDimitry Andric   }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   bool IsAtomic = (VDstIdx != -1);
9785f757f3fSDimitry Andric   bool IsGather4 = TSFlags & SIInstrFlags::Gather4;
9795f757f3fSDimitry Andric   bool IsVSample = TSFlags & SIInstrFlags::VSAMPLE;
9800b57cec5SDimitry Andric   bool IsNSA = false;
98106c3fb27SDimitry Andric   bool IsPartialNSA = false;
9820b57cec5SDimitry Andric   unsigned AddrSize = Info->VAddrDwords;
9830b57cec5SDimitry Andric 
98481ad6265SDimitry Andric   if (isGFX10Plus()) {
9850b57cec5SDimitry Andric     unsigned DimIdx =
9860b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dim);
987fe6060f1SDimitry Andric     int A16Idx =
988fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::a16);
9890b57cec5SDimitry Andric     const AMDGPU::MIMGDimInfo *Dim =
9900b57cec5SDimitry Andric         AMDGPU::getMIMGDimInfoByEncoding(MI.getOperand(DimIdx).getImm());
991fe6060f1SDimitry Andric     const bool IsA16 = (A16Idx != -1 && MI.getOperand(A16Idx).getImm());
9920b57cec5SDimitry Andric 
993fe6060f1SDimitry Andric     AddrSize =
994fe6060f1SDimitry Andric         AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, AMDGPU::hasG16(STI));
995fe6060f1SDimitry Andric 
9965f757f3fSDimitry Andric     // VSAMPLE insts that do not use vaddr3 behave the same as NSA forms.
9975f757f3fSDimitry Andric     // VIMAGE insts other than BVH never use vaddr4.
99881ad6265SDimitry Andric     IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA ||
9995f757f3fSDimitry Andric             Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA ||
10005f757f3fSDimitry Andric             Info->MIMGEncoding == AMDGPU::MIMGEncGfx12;
10010b57cec5SDimitry Andric     if (!IsNSA) {
10025f757f3fSDimitry Andric       if (!IsVSample && AddrSize > 12)
10030b57cec5SDimitry Andric         AddrSize = 16;
10040b57cec5SDimitry Andric     } else {
10050b57cec5SDimitry Andric       if (AddrSize > Info->VAddrDwords) {
100606c3fb27SDimitry Andric         if (!STI.hasFeature(AMDGPU::FeaturePartialNSAEncoding)) {
100706c3fb27SDimitry Andric           // The NSA encoding does not contain enough operands for the
100806c3fb27SDimitry Andric           // combination of base opcode / dimension. Should this be an error?
1009*0fca6ea1SDimitry Andric           return;
10100b57cec5SDimitry Andric         }
101106c3fb27SDimitry Andric         IsPartialNSA = true;
101206c3fb27SDimitry Andric       }
10130b57cec5SDimitry Andric     }
10140b57cec5SDimitry Andric   }
10150b57cec5SDimitry Andric 
10160b57cec5SDimitry Andric   unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;
1017bdd1243dSDimitry Andric   unsigned DstSize = IsGather4 ? 4 : std::max(llvm::popcount(DMask), 1);
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm();
10200b57cec5SDimitry Andric   if (D16 && AMDGPU::hasPackedD16(STI)) {
10210b57cec5SDimitry Andric     DstSize = (DstSize + 1) / 2;
10220b57cec5SDimitry Andric   }
10230b57cec5SDimitry Andric 
1024fe6060f1SDimitry Andric   if (TFEIdx != -1 && MI.getOperand(TFEIdx).getImm())
1025e8d8bef9SDimitry Andric     DstSize += 1;
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   if (DstSize == Info->VDataDwords && AddrSize == Info->VAddrDwords)
1028*0fca6ea1SDimitry Andric     return;
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   int NewOpcode =
10310b57cec5SDimitry Andric       AMDGPU::getMIMGOpcode(Info->BaseOpcode, Info->MIMGEncoding, DstSize, AddrSize);
10320b57cec5SDimitry Andric   if (NewOpcode == -1)
1033*0fca6ea1SDimitry Andric     return;
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   // Widen the register to the correct number of enabled channels.
10360b57cec5SDimitry Andric   unsigned NewVdata = AMDGPU::NoRegister;
10370b57cec5SDimitry Andric   if (DstSize != Info->VDataDwords) {
1038bdd1243dSDimitry Andric     auto DataRCID = MCII->get(NewOpcode).operands()[VDataIdx].RegClass;
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric     // Get first subregister of VData
10410b57cec5SDimitry Andric     unsigned Vdata0 = MI.getOperand(VDataIdx).getReg();
10420b57cec5SDimitry Andric     unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0);
10430b57cec5SDimitry Andric     Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric     NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,
10460b57cec5SDimitry Andric                                        &MRI.getRegClass(DataRCID));
10470b57cec5SDimitry Andric     if (NewVdata == AMDGPU::NoRegister) {
10480b57cec5SDimitry Andric       // It's possible to encode this such that the low register + enabled
10490b57cec5SDimitry Andric       // components exceeds the register count.
1050*0fca6ea1SDimitry Andric       return;
10510b57cec5SDimitry Andric     }
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric 
105406c3fb27SDimitry Andric   // If not using NSA on GFX10+, widen vaddr0 address register to correct size.
105506c3fb27SDimitry Andric   // If using partial NSA on GFX11+ widen last address register.
105606c3fb27SDimitry Andric   int VAddrSAIdx = IsPartialNSA ? (RsrcIdx - 1) : VAddr0Idx;
105706c3fb27SDimitry Andric   unsigned NewVAddrSA = AMDGPU::NoRegister;
105806c3fb27SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureNSAEncoding) && (!IsNSA || IsPartialNSA) &&
105906c3fb27SDimitry Andric       AddrSize != Info->VAddrDwords) {
106006c3fb27SDimitry Andric     unsigned VAddrSA = MI.getOperand(VAddrSAIdx).getReg();
106106c3fb27SDimitry Andric     unsigned VAddrSubSA = MRI.getSubReg(VAddrSA, AMDGPU::sub0);
106206c3fb27SDimitry Andric     VAddrSA = VAddrSubSA ? VAddrSubSA : VAddrSA;
10630b57cec5SDimitry Andric 
106406c3fb27SDimitry Andric     auto AddrRCID = MCII->get(NewOpcode).operands()[VAddrSAIdx].RegClass;
106506c3fb27SDimitry Andric     NewVAddrSA = MRI.getMatchingSuperReg(VAddrSA, AMDGPU::sub0,
10660b57cec5SDimitry Andric                                         &MRI.getRegClass(AddrRCID));
106706c3fb27SDimitry Andric     if (!NewVAddrSA)
1068*0fca6ea1SDimitry Andric       return;
10690b57cec5SDimitry Andric   }
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   MI.setOpcode(NewOpcode);
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric   if (NewVdata != AMDGPU::NoRegister) {
10740b57cec5SDimitry Andric     MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric     if (IsAtomic) {
10770b57cec5SDimitry Andric       // Atomic operations have an additional operand (a copy of data)
10780b57cec5SDimitry Andric       MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata);
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric   }
10810b57cec5SDimitry Andric 
108206c3fb27SDimitry Andric   if (NewVAddrSA) {
108306c3fb27SDimitry Andric     MI.getOperand(VAddrSAIdx) = MCOperand::createReg(NewVAddrSA);
10840b57cec5SDimitry Andric   } else if (IsNSA) {
10850b57cec5SDimitry Andric     assert(AddrSize <= Info->VAddrDwords);
10860b57cec5SDimitry Andric     MI.erase(MI.begin() + VAddr0Idx + AddrSize,
10870b57cec5SDimitry Andric              MI.begin() + VAddr0Idx + Info->VAddrDwords);
10880b57cec5SDimitry Andric   }
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
109181ad6265SDimitry Andric // Opsel and neg bits are used in src_modifiers and standalone operands. Autogen
109281ad6265SDimitry Andric // decoder only adds to src_modifiers, so manually add the bits to the other
109381ad6265SDimitry Andric // operands.
1094*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const {
109581ad6265SDimitry Andric   unsigned Opc = MI.getOpcode();
109681ad6265SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
1097fcaf7f86SDimitry Andric   auto Mods = collectVOPModifiers(MI, true);
109881ad6265SDimitry Andric 
109981ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1100bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
110181ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vdst_in);
110281ad6265SDimitry Andric 
110381ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1104bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel))
1105fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
110681ad6265SDimitry Andric                          AMDGPU::OpName::op_sel);
110781ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1108bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel_hi))
1109fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSelHi),
111081ad6265SDimitry Andric                          AMDGPU::OpName::op_sel_hi);
111181ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1112bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_lo))
1113fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegLo),
111481ad6265SDimitry Andric                          AMDGPU::OpName::neg_lo);
111581ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1116bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_hi))
1117fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegHi),
111881ad6265SDimitry Andric                          AMDGPU::OpName::neg_hi);
111981ad6265SDimitry Andric }
112081ad6265SDimitry Andric 
112181ad6265SDimitry Andric // Create dummy old operand and insert optional operands
1122*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const {
112381ad6265SDimitry Andric   unsigned Opc = MI.getOpcode();
112481ad6265SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
112581ad6265SDimitry Andric 
112681ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1127bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::old))
112881ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);
112981ad6265SDimitry Andric 
113081ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1131bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))
113281ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
113381ad6265SDimitry Andric                          AMDGPU::OpName::src0_modifiers);
113481ad6265SDimitry Andric 
113581ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1136bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))
113781ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
113881ad6265SDimitry Andric                          AMDGPU::OpName::src1_modifiers);
113981ad6265SDimitry Andric }
114081ad6265SDimitry Andric 
1141*0fca6ea1SDimitry Andric void AMDGPUDisassembler::convertFMAanyK(MCInst &MI, int ImmLitIdx) const {
1142349cc55cSDimitry Andric   assert(HasLiteral && "Should have decoded a literal");
1143349cc55cSDimitry Andric   const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
1144349cc55cSDimitry Andric   unsigned DescNumOps = Desc.getNumOperands();
114581ad6265SDimitry Andric   insertNamedMCOperand(MI, MCOperand::createImm(Literal),
114681ad6265SDimitry Andric                        AMDGPU::OpName::immDeferred);
1147349cc55cSDimitry Andric   assert(DescNumOps == MI.getNumOperands());
1148349cc55cSDimitry Andric   for (unsigned I = 0; I < DescNumOps; ++I) {
1149349cc55cSDimitry Andric     auto &Op = MI.getOperand(I);
1150bdd1243dSDimitry Andric     auto OpType = Desc.operands()[I].OperandType;
1151349cc55cSDimitry Andric     bool IsDeferredOp = (OpType == AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED ||
1152349cc55cSDimitry Andric                          OpType == AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED);
1153349cc55cSDimitry Andric     if (Op.isImm() && Op.getImm() == AMDGPU::EncValues::LITERAL_CONST &&
1154349cc55cSDimitry Andric         IsDeferredOp)
1155349cc55cSDimitry Andric       Op.setImm(Literal);
1156349cc55cSDimitry Andric   }
1157349cc55cSDimitry Andric }
1158349cc55cSDimitry Andric 
11590b57cec5SDimitry Andric const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
11600b57cec5SDimitry Andric   return getContext().getRegisterInfo()->
11610b57cec5SDimitry Andric     getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
11620b57cec5SDimitry Andric }
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric inline
11650b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::errOperand(unsigned V,
11660b57cec5SDimitry Andric                                          const Twine& ErrMsg) const {
11670b57cec5SDimitry Andric   *CommentStream << "Error: " + ErrMsg;
11680b57cec5SDimitry Andric 
11690b57cec5SDimitry Andric   // ToDo: add support for error operands to MCInst.h
11700b57cec5SDimitry Andric   // return MCOperand::createError(V);
11710b57cec5SDimitry Andric   return MCOperand();
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric inline
11750b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
11760b57cec5SDimitry Andric   return MCOperand::createReg(AMDGPU::getMCReg(RegId, STI));
11770b57cec5SDimitry Andric }
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric inline
11800b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
11810b57cec5SDimitry Andric                                                unsigned Val) const {
11820b57cec5SDimitry Andric   const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
11830b57cec5SDimitry Andric   if (Val >= RegCl.getNumRegs())
11840b57cec5SDimitry Andric     return errOperand(Val, Twine(getRegClassName(RegClassID)) +
11850b57cec5SDimitry Andric                            ": unknown register " + Twine(Val));
11860b57cec5SDimitry Andric   return createRegOperand(RegCl.getRegister(Val));
11870b57cec5SDimitry Andric }
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric inline
11900b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
11910b57cec5SDimitry Andric                                                 unsigned Val) const {
11920b57cec5SDimitry Andric   // ToDo: SI/CI have 104 SGPRs, VI - 102
11930b57cec5SDimitry Andric   // Valery: here we accepting as much as we can, let assembler sort it out
11940b57cec5SDimitry Andric   int shift = 0;
11950b57cec5SDimitry Andric   switch (SRegClassID) {
11960b57cec5SDimitry Andric   case AMDGPU::SGPR_32RegClassID:
11970b57cec5SDimitry Andric   case AMDGPU::TTMP_32RegClassID:
11980b57cec5SDimitry Andric     break;
11990b57cec5SDimitry Andric   case AMDGPU::SGPR_64RegClassID:
12000b57cec5SDimitry Andric   case AMDGPU::TTMP_64RegClassID:
12010b57cec5SDimitry Andric     shift = 1;
12020b57cec5SDimitry Andric     break;
12035f757f3fSDimitry Andric   case AMDGPU::SGPR_96RegClassID:
12045f757f3fSDimitry Andric   case AMDGPU::TTMP_96RegClassID:
12050b57cec5SDimitry Andric   case AMDGPU::SGPR_128RegClassID:
12060b57cec5SDimitry Andric   case AMDGPU::TTMP_128RegClassID:
12070b57cec5SDimitry Andric   // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
12080b57cec5SDimitry Andric   // this bundle?
12090b57cec5SDimitry Andric   case AMDGPU::SGPR_256RegClassID:
12100b57cec5SDimitry Andric   case AMDGPU::TTMP_256RegClassID:
12110b57cec5SDimitry Andric     // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
12120b57cec5SDimitry Andric   // this bundle?
1213bdd1243dSDimitry Andric   case AMDGPU::SGPR_288RegClassID:
1214bdd1243dSDimitry Andric   case AMDGPU::TTMP_288RegClassID:
1215bdd1243dSDimitry Andric   case AMDGPU::SGPR_320RegClassID:
1216bdd1243dSDimitry Andric   case AMDGPU::TTMP_320RegClassID:
1217bdd1243dSDimitry Andric   case AMDGPU::SGPR_352RegClassID:
1218bdd1243dSDimitry Andric   case AMDGPU::TTMP_352RegClassID:
1219bdd1243dSDimitry Andric   case AMDGPU::SGPR_384RegClassID:
1220bdd1243dSDimitry Andric   case AMDGPU::TTMP_384RegClassID:
12210b57cec5SDimitry Andric   case AMDGPU::SGPR_512RegClassID:
12220b57cec5SDimitry Andric   case AMDGPU::TTMP_512RegClassID:
12230b57cec5SDimitry Andric     shift = 2;
12240b57cec5SDimitry Andric     break;
12250b57cec5SDimitry Andric   // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
12260b57cec5SDimitry Andric   // this bundle?
12270b57cec5SDimitry Andric   default:
12280b57cec5SDimitry Andric     llvm_unreachable("unhandled register class");
12290b57cec5SDimitry Andric   }
12300b57cec5SDimitry Andric 
12310b57cec5SDimitry Andric   if (Val % (1 << shift)) {
12320b57cec5SDimitry Andric     *CommentStream << "Warning: " << getRegClassName(SRegClassID)
12330b57cec5SDimitry Andric                    << ": scalar reg isn't aligned " << Val;
12340b57cec5SDimitry Andric   }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   return createRegOperand(SRegClassID, Val >> shift);
12370b57cec5SDimitry Andric }
12380b57cec5SDimitry Andric 
12395f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::createVGPR16Operand(unsigned RegIdx,
12405f757f3fSDimitry Andric                                                   bool IsHi) const {
1241647cbc5dSDimitry Andric   unsigned RegIdxInVGPR16 = RegIdx * 2 + (IsHi ? 1 : 0);
1242647cbc5dSDimitry Andric   return createRegOperand(AMDGPU::VGPR_16RegClassID, RegIdxInVGPR16);
12435f757f3fSDimitry Andric }
12445f757f3fSDimitry Andric 
1245349cc55cSDimitry Andric // Decode Literals for insts which always have a literal in the encoding
1246349cc55cSDimitry Andric MCOperand
1247349cc55cSDimitry Andric AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const {
1248349cc55cSDimitry Andric   if (HasLiteral) {
124981ad6265SDimitry Andric     assert(
125081ad6265SDimitry Andric         AMDGPU::hasVOPD(STI) &&
125181ad6265SDimitry Andric         "Should only decode multiple kimm with VOPD, check VSrc operand types");
1252349cc55cSDimitry Andric     if (Literal != Val)
1253349cc55cSDimitry Andric       return errOperand(Val, "More than one unique literal is illegal");
1254349cc55cSDimitry Andric   }
1255349cc55cSDimitry Andric   HasLiteral = true;
1256349cc55cSDimitry Andric   Literal = Val;
1257349cc55cSDimitry Andric   return MCOperand::createImm(Literal);
1258349cc55cSDimitry Andric }
1259349cc55cSDimitry Andric 
12605f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::decodeLiteralConstant(bool ExtendFP64) const {
12610b57cec5SDimitry Andric   // For now all literal constants are supposed to be unsigned integer
12620b57cec5SDimitry Andric   // ToDo: deal with signed/unsigned 64-bit integer constants
12630b57cec5SDimitry Andric   // ToDo: deal with float/double constants
12640b57cec5SDimitry Andric   if (!HasLiteral) {
12650b57cec5SDimitry Andric     if (Bytes.size() < 4) {
12660b57cec5SDimitry Andric       return errOperand(0, "cannot read literal, inst bytes left " +
12670b57cec5SDimitry Andric                         Twine(Bytes.size()));
12680b57cec5SDimitry Andric     }
12690b57cec5SDimitry Andric     HasLiteral = true;
12705f757f3fSDimitry Andric     Literal = Literal64 = eatBytes<uint32_t>(Bytes);
12715f757f3fSDimitry Andric     if (ExtendFP64)
12725f757f3fSDimitry Andric       Literal64 <<= 32;
12730b57cec5SDimitry Andric   }
12745f757f3fSDimitry Andric   return MCOperand::createImm(ExtendFP64 ? Literal64 : Literal);
12750b57cec5SDimitry Andric }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
12780b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric   assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
12810b57cec5SDimitry Andric   return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
12820b57cec5SDimitry Andric     (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
12830b57cec5SDimitry Andric     (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
12840b57cec5SDimitry Andric       // Cast prevents negative overflow.
12850b57cec5SDimitry Andric }
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric static int64_t getInlineImmVal32(unsigned Imm) {
12880b57cec5SDimitry Andric   switch (Imm) {
12890b57cec5SDimitry Andric   case 240:
129006c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(0.5f);
12910b57cec5SDimitry Andric   case 241:
129206c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(-0.5f);
12930b57cec5SDimitry Andric   case 242:
129406c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(1.0f);
12950b57cec5SDimitry Andric   case 243:
129606c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(-1.0f);
12970b57cec5SDimitry Andric   case 244:
129806c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(2.0f);
12990b57cec5SDimitry Andric   case 245:
130006c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(-2.0f);
13010b57cec5SDimitry Andric   case 246:
130206c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(4.0f);
13030b57cec5SDimitry Andric   case 247:
130406c3fb27SDimitry Andric     return llvm::bit_cast<uint32_t>(-4.0f);
13050b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
13060b57cec5SDimitry Andric     return 0x3e22f983;
13070b57cec5SDimitry Andric   default:
13080b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
13090b57cec5SDimitry Andric   }
13100b57cec5SDimitry Andric }
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric static int64_t getInlineImmVal64(unsigned Imm) {
13130b57cec5SDimitry Andric   switch (Imm) {
13140b57cec5SDimitry Andric   case 240:
131506c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(0.5);
13160b57cec5SDimitry Andric   case 241:
131706c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(-0.5);
13180b57cec5SDimitry Andric   case 242:
131906c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(1.0);
13200b57cec5SDimitry Andric   case 243:
132106c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(-1.0);
13220b57cec5SDimitry Andric   case 244:
132306c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(2.0);
13240b57cec5SDimitry Andric   case 245:
132506c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(-2.0);
13260b57cec5SDimitry Andric   case 246:
132706c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(4.0);
13280b57cec5SDimitry Andric   case 247:
132906c3fb27SDimitry Andric     return llvm::bit_cast<uint64_t>(-4.0);
13300b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
13310b57cec5SDimitry Andric     return 0x3fc45f306dc9c882;
13320b57cec5SDimitry Andric   default:
13330b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
13340b57cec5SDimitry Andric   }
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric 
1337*0fca6ea1SDimitry Andric static int64_t getInlineImmValF16(unsigned Imm) {
13380b57cec5SDimitry Andric   switch (Imm) {
13390b57cec5SDimitry Andric   case 240:
13400b57cec5SDimitry Andric     return 0x3800;
13410b57cec5SDimitry Andric   case 241:
13420b57cec5SDimitry Andric     return 0xB800;
13430b57cec5SDimitry Andric   case 242:
13440b57cec5SDimitry Andric     return 0x3C00;
13450b57cec5SDimitry Andric   case 243:
13460b57cec5SDimitry Andric     return 0xBC00;
13470b57cec5SDimitry Andric   case 244:
13480b57cec5SDimitry Andric     return 0x4000;
13490b57cec5SDimitry Andric   case 245:
13500b57cec5SDimitry Andric     return 0xC000;
13510b57cec5SDimitry Andric   case 246:
13520b57cec5SDimitry Andric     return 0x4400;
13530b57cec5SDimitry Andric   case 247:
13540b57cec5SDimitry Andric     return 0xC400;
13550b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
13560b57cec5SDimitry Andric     return 0x3118;
13570b57cec5SDimitry Andric   default:
13580b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric }
13610b57cec5SDimitry Andric 
1362*0fca6ea1SDimitry Andric static int64_t getInlineImmValBF16(unsigned Imm) {
1363*0fca6ea1SDimitry Andric   switch (Imm) {
1364*0fca6ea1SDimitry Andric   case 240:
1365*0fca6ea1SDimitry Andric     return 0x3F00;
1366*0fca6ea1SDimitry Andric   case 241:
1367*0fca6ea1SDimitry Andric     return 0xBF00;
1368*0fca6ea1SDimitry Andric   case 242:
1369*0fca6ea1SDimitry Andric     return 0x3F80;
1370*0fca6ea1SDimitry Andric   case 243:
1371*0fca6ea1SDimitry Andric     return 0xBF80;
1372*0fca6ea1SDimitry Andric   case 244:
1373*0fca6ea1SDimitry Andric     return 0x4000;
1374*0fca6ea1SDimitry Andric   case 245:
1375*0fca6ea1SDimitry Andric     return 0xC000;
1376*0fca6ea1SDimitry Andric   case 246:
1377*0fca6ea1SDimitry Andric     return 0x4080;
1378*0fca6ea1SDimitry Andric   case 247:
1379*0fca6ea1SDimitry Andric     return 0xC080;
1380*0fca6ea1SDimitry Andric   case 248: // 1 / (2 * PI)
1381*0fca6ea1SDimitry Andric     return 0x3E22;
1382*0fca6ea1SDimitry Andric   default:
1383*0fca6ea1SDimitry Andric     llvm_unreachable("invalid fp inline imm");
1384*0fca6ea1SDimitry Andric   }
1385*0fca6ea1SDimitry Andric }
1386*0fca6ea1SDimitry Andric 
1387*0fca6ea1SDimitry Andric static int64_t getInlineImmVal16(unsigned Imm, AMDGPU::OperandSemantics Sema) {
1388*0fca6ea1SDimitry Andric   return (Sema == AMDGPU::OperandSemantics::BF16) ? getInlineImmValBF16(Imm)
1389*0fca6ea1SDimitry Andric                                                   : getInlineImmValF16(Imm);
1390*0fca6ea1SDimitry Andric }
1391*0fca6ea1SDimitry Andric 
1392*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeFPImmed(unsigned ImmWidth, unsigned Imm,
1393*0fca6ea1SDimitry Andric                                             AMDGPU::OperandSemantics Sema) {
1394*0fca6ea1SDimitry Andric   assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN &&
1395*0fca6ea1SDimitry Andric          Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
13960b57cec5SDimitry Andric 
13970b57cec5SDimitry Andric   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
139806c3fb27SDimitry Andric   // ImmWidth 0 is a default case where operand should not allow immediates.
139906c3fb27SDimitry Andric   // Imm value is still decoded into 32 bit immediate operand, inst printer will
140006c3fb27SDimitry Andric   // use it to print verbose error message.
140106c3fb27SDimitry Andric   switch (ImmWidth) {
140206c3fb27SDimitry Andric   case 0:
140306c3fb27SDimitry Andric   case 32:
14040b57cec5SDimitry Andric     return MCOperand::createImm(getInlineImmVal32(Imm));
140506c3fb27SDimitry Andric   case 64:
14060b57cec5SDimitry Andric     return MCOperand::createImm(getInlineImmVal64(Imm));
140706c3fb27SDimitry Andric   case 16:
1408*0fca6ea1SDimitry Andric     return MCOperand::createImm(getInlineImmVal16(Imm, Sema));
14090b57cec5SDimitry Andric   default:
14100b57cec5SDimitry Andric     llvm_unreachable("implement me");
14110b57cec5SDimitry Andric   }
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
14150b57cec5SDimitry Andric   using namespace AMDGPU;
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
14180b57cec5SDimitry Andric   switch (Width) {
14190b57cec5SDimitry Andric   default: // fall
14200b57cec5SDimitry Andric   case OPW32:
14210b57cec5SDimitry Andric   case OPW16:
14220b57cec5SDimitry Andric   case OPWV216:
14230b57cec5SDimitry Andric     return VGPR_32RegClassID;
1424fe6060f1SDimitry Andric   case OPW64:
1425fe6060f1SDimitry Andric   case OPWV232: return VReg_64RegClassID;
1426fe6060f1SDimitry Andric   case OPW96: return VReg_96RegClassID;
14270b57cec5SDimitry Andric   case OPW128: return VReg_128RegClassID;
1428fe6060f1SDimitry Andric   case OPW160: return VReg_160RegClassID;
1429fe6060f1SDimitry Andric   case OPW256: return VReg_256RegClassID;
1430bdd1243dSDimitry Andric   case OPW288: return VReg_288RegClassID;
1431bdd1243dSDimitry Andric   case OPW320: return VReg_320RegClassID;
1432bdd1243dSDimitry Andric   case OPW352: return VReg_352RegClassID;
1433bdd1243dSDimitry Andric   case OPW384: return VReg_384RegClassID;
1434fe6060f1SDimitry Andric   case OPW512: return VReg_512RegClassID;
1435fe6060f1SDimitry Andric   case OPW1024: return VReg_1024RegClassID;
14360b57cec5SDimitry Andric   }
14370b57cec5SDimitry Andric }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getAgprClassId(const OpWidthTy Width) const {
14400b57cec5SDimitry Andric   using namespace AMDGPU;
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
14430b57cec5SDimitry Andric   switch (Width) {
14440b57cec5SDimitry Andric   default: // fall
14450b57cec5SDimitry Andric   case OPW32:
14460b57cec5SDimitry Andric   case OPW16:
14470b57cec5SDimitry Andric   case OPWV216:
14480b57cec5SDimitry Andric     return AGPR_32RegClassID;
1449fe6060f1SDimitry Andric   case OPW64:
1450fe6060f1SDimitry Andric   case OPWV232: return AReg_64RegClassID;
1451fe6060f1SDimitry Andric   case OPW96: return AReg_96RegClassID;
14520b57cec5SDimitry Andric   case OPW128: return AReg_128RegClassID;
1453fe6060f1SDimitry Andric   case OPW160: return AReg_160RegClassID;
14545ffd83dbSDimitry Andric   case OPW256: return AReg_256RegClassID;
1455bdd1243dSDimitry Andric   case OPW288: return AReg_288RegClassID;
1456bdd1243dSDimitry Andric   case OPW320: return AReg_320RegClassID;
1457bdd1243dSDimitry Andric   case OPW352: return AReg_352RegClassID;
1458bdd1243dSDimitry Andric   case OPW384: return AReg_384RegClassID;
14590b57cec5SDimitry Andric   case OPW512: return AReg_512RegClassID;
14600b57cec5SDimitry Andric   case OPW1024: return AReg_1024RegClassID;
14610b57cec5SDimitry Andric   }
14620b57cec5SDimitry Andric }
14630b57cec5SDimitry Andric 
14640b57cec5SDimitry Andric 
14650b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
14660b57cec5SDimitry Andric   using namespace AMDGPU;
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
14690b57cec5SDimitry Andric   switch (Width) {
14700b57cec5SDimitry Andric   default: // fall
14710b57cec5SDimitry Andric   case OPW32:
14720b57cec5SDimitry Andric   case OPW16:
14730b57cec5SDimitry Andric   case OPWV216:
14740b57cec5SDimitry Andric     return SGPR_32RegClassID;
1475fe6060f1SDimitry Andric   case OPW64:
1476fe6060f1SDimitry Andric   case OPWV232: return SGPR_64RegClassID;
1477fe6060f1SDimitry Andric   case OPW96: return SGPR_96RegClassID;
14780b57cec5SDimitry Andric   case OPW128: return SGPR_128RegClassID;
1479fe6060f1SDimitry Andric   case OPW160: return SGPR_160RegClassID;
14800b57cec5SDimitry Andric   case OPW256: return SGPR_256RegClassID;
1481bdd1243dSDimitry Andric   case OPW288: return SGPR_288RegClassID;
1482bdd1243dSDimitry Andric   case OPW320: return SGPR_320RegClassID;
1483bdd1243dSDimitry Andric   case OPW352: return SGPR_352RegClassID;
1484bdd1243dSDimitry Andric   case OPW384: return SGPR_384RegClassID;
14850b57cec5SDimitry Andric   case OPW512: return SGPR_512RegClassID;
14860b57cec5SDimitry Andric   }
14870b57cec5SDimitry Andric }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
14900b57cec5SDimitry Andric   using namespace AMDGPU;
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
14930b57cec5SDimitry Andric   switch (Width) {
14940b57cec5SDimitry Andric   default: // fall
14950b57cec5SDimitry Andric   case OPW32:
14960b57cec5SDimitry Andric   case OPW16:
14970b57cec5SDimitry Andric   case OPWV216:
14980b57cec5SDimitry Andric     return TTMP_32RegClassID;
1499fe6060f1SDimitry Andric   case OPW64:
1500fe6060f1SDimitry Andric   case OPWV232: return TTMP_64RegClassID;
15010b57cec5SDimitry Andric   case OPW128: return TTMP_128RegClassID;
15020b57cec5SDimitry Andric   case OPW256: return TTMP_256RegClassID;
1503bdd1243dSDimitry Andric   case OPW288: return TTMP_288RegClassID;
1504bdd1243dSDimitry Andric   case OPW320: return TTMP_320RegClassID;
1505bdd1243dSDimitry Andric   case OPW352: return TTMP_352RegClassID;
1506bdd1243dSDimitry Andric   case OPW384: return TTMP_384RegClassID;
15070b57cec5SDimitry Andric   case OPW512: return TTMP_512RegClassID;
15080b57cec5SDimitry Andric   }
15090b57cec5SDimitry Andric }
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const {
15120b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
15130b57cec5SDimitry Andric 
1514e8d8bef9SDimitry Andric   unsigned TTmpMin = isGFX9Plus() ? TTMP_GFX9PLUS_MIN : TTMP_VI_MIN;
1515e8d8bef9SDimitry Andric   unsigned TTmpMax = isGFX9Plus() ? TTMP_GFX9PLUS_MAX : TTMP_VI_MAX;
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric   return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1;
15180b57cec5SDimitry Andric }
15190b57cec5SDimitry Andric 
1520349cc55cSDimitry Andric MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val,
152106c3fb27SDimitry Andric                                           bool MandatoryLiteral,
1522*0fca6ea1SDimitry Andric                                           unsigned ImmWidth,
1523*0fca6ea1SDimitry Andric                                           AMDGPU::OperandSemantics Sema) const {
15240b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric   assert(Val < 1024); // enum10
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric   bool IsAGPR = Val & 512;
15290b57cec5SDimitry Andric   Val &= 511;
15300b57cec5SDimitry Andric 
15310b57cec5SDimitry Andric   if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
15320b57cec5SDimitry Andric     return createRegOperand(IsAGPR ? getAgprClassId(Width)
15330b57cec5SDimitry Andric                                    : getVgprClassId(Width), Val - VGPR_MIN);
15340b57cec5SDimitry Andric   }
15355f757f3fSDimitry Andric   return decodeNonVGPRSrcOp(Width, Val & 0xFF, MandatoryLiteral, ImmWidth,
1536*0fca6ea1SDimitry Andric                             Sema);
15375f757f3fSDimitry Andric }
15385f757f3fSDimitry Andric 
1539*0fca6ea1SDimitry Andric MCOperand
1540*0fca6ea1SDimitry Andric AMDGPUDisassembler::decodeNonVGPRSrcOp(const OpWidthTy Width, unsigned Val,
1541*0fca6ea1SDimitry Andric                                        bool MandatoryLiteral, unsigned ImmWidth,
1542*0fca6ea1SDimitry Andric                                        AMDGPU::OperandSemantics Sema) const {
15435f757f3fSDimitry Andric   // Cases when Val{8} is 1 (vgpr, agpr or true 16 vgpr) should have been
15445f757f3fSDimitry Andric   // decoded earlier.
15455f757f3fSDimitry Andric   assert(Val < (1 << 8) && "9-bit Src encoding when Val{8} is 0");
15465f757f3fSDimitry Andric   using namespace AMDGPU::EncValues;
15475f757f3fSDimitry Andric 
15480b57cec5SDimitry Andric   if (Val <= SGPR_MAX) {
1549e8d8bef9SDimitry Andric     // "SGPR_MIN <= Val" is always true and causes compilation warning.
1550bdd1243dSDimitry Andric     static_assert(SGPR_MIN == 0);
15510b57cec5SDimitry Andric     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
15520b57cec5SDimitry Andric   }
15530b57cec5SDimitry Andric 
15540b57cec5SDimitry Andric   int TTmpIdx = getTTmpIdx(Val);
15550b57cec5SDimitry Andric   if (TTmpIdx >= 0) {
15560b57cec5SDimitry Andric     return createSRegOperand(getTtmpClassId(Width), TTmpIdx);
15570b57cec5SDimitry Andric   }
15580b57cec5SDimitry Andric 
15590b57cec5SDimitry Andric   if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
15600b57cec5SDimitry Andric     return decodeIntImmed(Val);
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric   if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
1563*0fca6ea1SDimitry Andric     return decodeFPImmed(ImmWidth, Val, Sema);
15640b57cec5SDimitry Andric 
1565349cc55cSDimitry Andric   if (Val == LITERAL_CONST) {
1566349cc55cSDimitry Andric     if (MandatoryLiteral)
1567349cc55cSDimitry Andric       // Keep a sentinel value for deferred setting
1568349cc55cSDimitry Andric       return MCOperand::createImm(LITERAL_CONST);
1569*0fca6ea1SDimitry Andric     return decodeLiteralConstant(Sema == AMDGPU::OperandSemantics::FP64);
1570349cc55cSDimitry Andric   }
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric   switch (Width) {
15730b57cec5SDimitry Andric   case OPW32:
15740b57cec5SDimitry Andric   case OPW16:
15750b57cec5SDimitry Andric   case OPWV216:
15760b57cec5SDimitry Andric     return decodeSpecialReg32(Val);
15770b57cec5SDimitry Andric   case OPW64:
1578fe6060f1SDimitry Andric   case OPWV232:
15790b57cec5SDimitry Andric     return decodeSpecialReg64(Val);
15800b57cec5SDimitry Andric   default:
15810b57cec5SDimitry Andric     llvm_unreachable("unexpected immediate type");
15820b57cec5SDimitry Andric   }
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric 
158581ad6265SDimitry Andric // Bit 0 of DstY isn't stored in the instruction, because it's always the
158681ad6265SDimitry Andric // opposite of bit 0 of DstX.
158781ad6265SDimitry Andric MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst,
158881ad6265SDimitry Andric                                                unsigned Val) const {
158981ad6265SDimitry Andric   int VDstXInd =
159081ad6265SDimitry Andric       AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::vdstX);
159181ad6265SDimitry Andric   assert(VDstXInd != -1);
159281ad6265SDimitry Andric   assert(Inst.getOperand(VDstXInd).isReg());
159381ad6265SDimitry Andric   unsigned XDstReg = MRI.getEncodingValue(Inst.getOperand(VDstXInd).getReg());
159481ad6265SDimitry Andric   Val |= ~XDstReg & 1;
159581ad6265SDimitry Andric   auto Width = llvm::AMDGPUDisassembler::OPW32;
159681ad6265SDimitry Andric   return createRegOperand(getVgprClassId(Width), Val);
159781ad6265SDimitry Andric }
159881ad6265SDimitry Andric 
15990b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
16000b57cec5SDimitry Andric   using namespace AMDGPU;
16010b57cec5SDimitry Andric 
16020b57cec5SDimitry Andric   switch (Val) {
1603bdd1243dSDimitry Andric   // clang-format off
16040b57cec5SDimitry Andric   case 102: return createRegOperand(FLAT_SCR_LO);
16050b57cec5SDimitry Andric   case 103: return createRegOperand(FLAT_SCR_HI);
16060b57cec5SDimitry Andric   case 104: return createRegOperand(XNACK_MASK_LO);
16070b57cec5SDimitry Andric   case 105: return createRegOperand(XNACK_MASK_HI);
16080b57cec5SDimitry Andric   case 106: return createRegOperand(VCC_LO);
16090b57cec5SDimitry Andric   case 107: return createRegOperand(VCC_HI);
16100b57cec5SDimitry Andric   case 108: return createRegOperand(TBA_LO);
16110b57cec5SDimitry Andric   case 109: return createRegOperand(TBA_HI);
16120b57cec5SDimitry Andric   case 110: return createRegOperand(TMA_LO);
16130b57cec5SDimitry Andric   case 111: return createRegOperand(TMA_HI);
161481ad6265SDimitry Andric   case 124:
161581ad6265SDimitry Andric     return isGFX11Plus() ? createRegOperand(SGPR_NULL) : createRegOperand(M0);
161681ad6265SDimitry Andric   case 125:
161781ad6265SDimitry Andric     return isGFX11Plus() ? createRegOperand(M0) : createRegOperand(SGPR_NULL);
16180b57cec5SDimitry Andric   case 126: return createRegOperand(EXEC_LO);
16190b57cec5SDimitry Andric   case 127: return createRegOperand(EXEC_HI);
1620bdd1243dSDimitry Andric   case 235: return createRegOperand(SRC_SHARED_BASE_LO);
1621bdd1243dSDimitry Andric   case 236: return createRegOperand(SRC_SHARED_LIMIT_LO);
1622bdd1243dSDimitry Andric   case 237: return createRegOperand(SRC_PRIVATE_BASE_LO);
1623bdd1243dSDimitry Andric   case 238: return createRegOperand(SRC_PRIVATE_LIMIT_LO);
16240b57cec5SDimitry Andric   case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);
16250b57cec5SDimitry Andric   case 251: return createRegOperand(SRC_VCCZ);
16260b57cec5SDimitry Andric   case 252: return createRegOperand(SRC_EXECZ);
16270b57cec5SDimitry Andric   case 253: return createRegOperand(SRC_SCC);
16280b57cec5SDimitry Andric   case 254: return createRegOperand(LDS_DIRECT);
16290b57cec5SDimitry Andric   default: break;
1630bdd1243dSDimitry Andric     // clang-format on
16310b57cec5SDimitry Andric   }
16320b57cec5SDimitry Andric   return errOperand(Val, "unknown operand encoding " + Twine(Val));
16330b57cec5SDimitry Andric }
16340b57cec5SDimitry Andric 
16350b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
16360b57cec5SDimitry Andric   using namespace AMDGPU;
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric   switch (Val) {
16390b57cec5SDimitry Andric   case 102: return createRegOperand(FLAT_SCR);
16400b57cec5SDimitry Andric   case 104: return createRegOperand(XNACK_MASK);
16410b57cec5SDimitry Andric   case 106: return createRegOperand(VCC);
16420b57cec5SDimitry Andric   case 108: return createRegOperand(TBA);
16430b57cec5SDimitry Andric   case 110: return createRegOperand(TMA);
164481ad6265SDimitry Andric   case 124:
164581ad6265SDimitry Andric     if (isGFX11Plus())
164681ad6265SDimitry Andric       return createRegOperand(SGPR_NULL);
164781ad6265SDimitry Andric     break;
164881ad6265SDimitry Andric   case 125:
164981ad6265SDimitry Andric     if (!isGFX11Plus())
165081ad6265SDimitry Andric       return createRegOperand(SGPR_NULL);
165181ad6265SDimitry Andric     break;
16520b57cec5SDimitry Andric   case 126: return createRegOperand(EXEC);
16530b57cec5SDimitry Andric   case 235: return createRegOperand(SRC_SHARED_BASE);
16540b57cec5SDimitry Andric   case 236: return createRegOperand(SRC_SHARED_LIMIT);
16550b57cec5SDimitry Andric   case 237: return createRegOperand(SRC_PRIVATE_BASE);
16560b57cec5SDimitry Andric   case 238: return createRegOperand(SRC_PRIVATE_LIMIT);
16570b57cec5SDimitry Andric   case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);
16580b57cec5SDimitry Andric   case 251: return createRegOperand(SRC_VCCZ);
16590b57cec5SDimitry Andric   case 252: return createRegOperand(SRC_EXECZ);
16600b57cec5SDimitry Andric   case 253: return createRegOperand(SRC_SCC);
16610b57cec5SDimitry Andric   default: break;
16620b57cec5SDimitry Andric   }
16630b57cec5SDimitry Andric   return errOperand(Val, "unknown operand encoding " + Twine(Val));
16640b57cec5SDimitry Andric }
16650b57cec5SDimitry Andric 
1666*0fca6ea1SDimitry Andric MCOperand
1667*0fca6ea1SDimitry Andric AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width, const unsigned Val,
1668*0fca6ea1SDimitry Andric                                   unsigned ImmWidth,
1669*0fca6ea1SDimitry Andric                                   AMDGPU::OperandSemantics Sema) const {
16700b57cec5SDimitry Andric   using namespace AMDGPU::SDWA;
16710b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
16720b57cec5SDimitry Andric 
167306c3fb27SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX9) ||
167406c3fb27SDimitry Andric       STI.hasFeature(AMDGPU::FeatureGFX10)) {
16750b57cec5SDimitry Andric     // XXX: cast to int is needed to avoid stupid warning:
16760b57cec5SDimitry Andric     // compare with unsigned is always true
16770b57cec5SDimitry Andric     if (int(SDWA9EncValues::SRC_VGPR_MIN) <= int(Val) &&
16780b57cec5SDimitry Andric         Val <= SDWA9EncValues::SRC_VGPR_MAX) {
16790b57cec5SDimitry Andric       return createRegOperand(getVgprClassId(Width),
16800b57cec5SDimitry Andric                               Val - SDWA9EncValues::SRC_VGPR_MIN);
16810b57cec5SDimitry Andric     }
16820b57cec5SDimitry Andric     if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
1683e8d8bef9SDimitry Andric         Val <= (isGFX10Plus() ? SDWA9EncValues::SRC_SGPR_MAX_GFX10
16840b57cec5SDimitry Andric                               : SDWA9EncValues::SRC_SGPR_MAX_SI)) {
16850b57cec5SDimitry Andric       return createSRegOperand(getSgprClassId(Width),
16860b57cec5SDimitry Andric                                Val - SDWA9EncValues::SRC_SGPR_MIN);
16870b57cec5SDimitry Andric     }
16880b57cec5SDimitry Andric     if (SDWA9EncValues::SRC_TTMP_MIN <= Val &&
16890b57cec5SDimitry Andric         Val <= SDWA9EncValues::SRC_TTMP_MAX) {
16900b57cec5SDimitry Andric       return createSRegOperand(getTtmpClassId(Width),
16910b57cec5SDimitry Andric                                Val - SDWA9EncValues::SRC_TTMP_MIN);
16920b57cec5SDimitry Andric     }
16930b57cec5SDimitry Andric 
16940b57cec5SDimitry Andric     const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric     if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX)
16970b57cec5SDimitry Andric       return decodeIntImmed(SVal);
16980b57cec5SDimitry Andric 
16990b57cec5SDimitry Andric     if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX)
1700*0fca6ea1SDimitry Andric       return decodeFPImmed(ImmWidth, SVal, Sema);
17010b57cec5SDimitry Andric 
17020b57cec5SDimitry Andric     return decodeSpecialReg32(SVal);
17030b57cec5SDimitry Andric   }
1704*0fca6ea1SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands))
1705*0fca6ea1SDimitry Andric     return createRegOperand(getVgprClassId(Width), Val);
17060b57cec5SDimitry Andric   llvm_unreachable("unsupported target");
17070b57cec5SDimitry Andric }
17080b57cec5SDimitry Andric 
17090b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
1710*0fca6ea1SDimitry Andric   return decodeSDWASrc(OPW16, Val, 16, AMDGPU::OperandSemantics::FP16);
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
1714*0fca6ea1SDimitry Andric   return decodeSDWASrc(OPW32, Val, 32, AMDGPU::OperandSemantics::FP32);
17150b57cec5SDimitry Andric }
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
17180b57cec5SDimitry Andric   using namespace AMDGPU::SDWA;
17190b57cec5SDimitry Andric 
172006c3fb27SDimitry Andric   assert((STI.hasFeature(AMDGPU::FeatureGFX9) ||
172106c3fb27SDimitry Andric           STI.hasFeature(AMDGPU::FeatureGFX10)) &&
17220b57cec5SDimitry Andric          "SDWAVopcDst should be present only on GFX9+");
17230b57cec5SDimitry Andric 
172406c3fb27SDimitry Andric   bool IsWave64 = STI.hasFeature(AMDGPU::FeatureWavefrontSize64);
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric   if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
17270b57cec5SDimitry Andric     Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric     int TTmpIdx = getTTmpIdx(Val);
17300b57cec5SDimitry Andric     if (TTmpIdx >= 0) {
17318bcb0991SDimitry Andric       auto TTmpClsId = getTtmpClassId(IsWave64 ? OPW64 : OPW32);
17328bcb0991SDimitry Andric       return createSRegOperand(TTmpClsId, TTmpIdx);
1733*0fca6ea1SDimitry Andric     }
1734*0fca6ea1SDimitry Andric     if (Val > SGPR_MAX) {
1735*0fca6ea1SDimitry Andric       return IsWave64 ? decodeSpecialReg64(Val) : decodeSpecialReg32(Val);
1736*0fca6ea1SDimitry Andric     }
17370b57cec5SDimitry Andric     return createSRegOperand(getSgprClassId(IsWave64 ? OPW64 : OPW32), Val);
17380b57cec5SDimitry Andric   }
17390b57cec5SDimitry Andric   return createRegOperand(IsWave64 ? AMDGPU::VCC : AMDGPU::VCC_LO);
17400b57cec5SDimitry Andric }
17410b57cec5SDimitry Andric 
17420b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeBoolReg(unsigned Val) const {
174306c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureWavefrontSize64)
174406c3fb27SDimitry Andric              ? decodeSrcOp(OPW64, Val)
174506c3fb27SDimitry Andric              : decodeSrcOp(OPW32, Val);
17460b57cec5SDimitry Andric }
17470b57cec5SDimitry Andric 
17485f757f3fSDimitry Andric MCOperand AMDGPUDisassembler::decodeSplitBarrier(unsigned Val) const {
17495f757f3fSDimitry Andric   return decodeSrcOp(OPW32, Val);
17505f757f3fSDimitry Andric }
17515f757f3fSDimitry Andric 
1752*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {
1753*0fca6ea1SDimitry Andric   if (Val != AMDGPU::DPP::DPP8_FI_0 && Val != AMDGPU::DPP::DPP8_FI_1)
1754*0fca6ea1SDimitry Andric     return MCOperand();
1755*0fca6ea1SDimitry Andric   return MCOperand::createImm(Val);
1756*0fca6ea1SDimitry Andric }
1757*0fca6ea1SDimitry Andric 
1758*0fca6ea1SDimitry Andric MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {
1759*0fca6ea1SDimitry Andric   using VersionField = AMDGPU::EncodingField<7, 0>;
1760*0fca6ea1SDimitry Andric   using W64Bit = AMDGPU::EncodingBit<13>;
1761*0fca6ea1SDimitry Andric   using W32Bit = AMDGPU::EncodingBit<14>;
1762*0fca6ea1SDimitry Andric   using MDPBit = AMDGPU::EncodingBit<15>;
1763*0fca6ea1SDimitry Andric   using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;
1764*0fca6ea1SDimitry Andric 
1765*0fca6ea1SDimitry Andric   auto [Version, W64, W32, MDP] = Encoding::decode(Imm);
1766*0fca6ea1SDimitry Andric 
1767*0fca6ea1SDimitry Andric   // Decode into a plain immediate if any unused bits are raised.
1768*0fca6ea1SDimitry Andric   if (Encoding::encode(Version, W64, W32, MDP) != Imm)
1769*0fca6ea1SDimitry Andric     return MCOperand::createImm(Imm);
1770*0fca6ea1SDimitry Andric 
1771*0fca6ea1SDimitry Andric   const auto &Versions = AMDGPU::UCVersion::getGFXVersions();
1772*0fca6ea1SDimitry Andric   auto I = find_if(Versions,
1773*0fca6ea1SDimitry Andric                    [Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {
1774*0fca6ea1SDimitry Andric                      return V.Code == Version;
1775*0fca6ea1SDimitry Andric                    });
1776*0fca6ea1SDimitry Andric   MCContext &Ctx = getContext();
1777*0fca6ea1SDimitry Andric   const MCExpr *E;
1778*0fca6ea1SDimitry Andric   if (I == Versions.end())
1779*0fca6ea1SDimitry Andric     E = MCConstantExpr::create(Version, Ctx);
1780*0fca6ea1SDimitry Andric   else
1781*0fca6ea1SDimitry Andric     E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx);
1782*0fca6ea1SDimitry Andric 
1783*0fca6ea1SDimitry Andric   if (W64)
1784*0fca6ea1SDimitry Andric     E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx);
1785*0fca6ea1SDimitry Andric   if (W32)
1786*0fca6ea1SDimitry Andric     E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx);
1787*0fca6ea1SDimitry Andric   if (MDP)
1788*0fca6ea1SDimitry Andric     E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx);
1789*0fca6ea1SDimitry Andric 
1790*0fca6ea1SDimitry Andric   return MCOperand::createExpr(E);
1791*0fca6ea1SDimitry Andric }
1792*0fca6ea1SDimitry Andric 
17930b57cec5SDimitry Andric bool AMDGPUDisassembler::isVI() const {
179406c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
17950b57cec5SDimitry Andric }
17960b57cec5SDimitry Andric 
1797e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9() const { return AMDGPU::isGFX9(STI); }
1798e8d8bef9SDimitry Andric 
1799fe6060f1SDimitry Andric bool AMDGPUDisassembler::isGFX90A() const {
180006c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX90AInsts);
1801fe6060f1SDimitry Andric }
1802fe6060f1SDimitry Andric 
1803e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9Plus() const { return AMDGPU::isGFX9Plus(STI); }
1804e8d8bef9SDimitry Andric 
1805e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10() const { return AMDGPU::isGFX10(STI); }
1806e8d8bef9SDimitry Andric 
1807e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10Plus() const {
1808e8d8bef9SDimitry Andric   return AMDGPU::isGFX10Plus(STI);
18090b57cec5SDimitry Andric }
18100b57cec5SDimitry Andric 
181181ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11() const {
181206c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX11);
181381ad6265SDimitry Andric }
181481ad6265SDimitry Andric 
181581ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11Plus() const {
181681ad6265SDimitry Andric   return AMDGPU::isGFX11Plus(STI);
181781ad6265SDimitry Andric }
181881ad6265SDimitry Andric 
1819*0fca6ea1SDimitry Andric bool AMDGPUDisassembler::isGFX12() const {
1820*0fca6ea1SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX12);
1821*0fca6ea1SDimitry Andric }
1822*0fca6ea1SDimitry Andric 
18235f757f3fSDimitry Andric bool AMDGPUDisassembler::isGFX12Plus() const {
18245f757f3fSDimitry Andric   return AMDGPU::isGFX12Plus(STI);
18255f757f3fSDimitry Andric }
182681ad6265SDimitry Andric 
1827fe6060f1SDimitry Andric bool AMDGPUDisassembler::hasArchitectedFlatScratch() const {
182806c3fb27SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch);
1829fe6060f1SDimitry Andric }
1830fe6060f1SDimitry Andric 
18315f757f3fSDimitry Andric bool AMDGPUDisassembler::hasKernargPreload() const {
18325f757f3fSDimitry Andric   return AMDGPU::hasKernargPreload(STI);
18335f757f3fSDimitry Andric }
18345f757f3fSDimitry Andric 
1835e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1836e8d8bef9SDimitry Andric // AMDGPU specific symbol handling
1837e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1838*0fca6ea1SDimitry Andric 
1839*0fca6ea1SDimitry Andric /// Print a string describing the reserved bit range specified by Mask with
1840*0fca6ea1SDimitry Andric /// offset BaseBytes for use in error comments. Mask is a single continuous
1841*0fca6ea1SDimitry Andric /// range of 1s surrounded by zeros. The format here is meant to align with the
1842*0fca6ea1SDimitry Andric /// tables that describe these bits in llvm.org/docs/AMDGPUUsage.html.
1843*0fca6ea1SDimitry Andric static SmallString<32> getBitRangeFromMask(uint32_t Mask, unsigned BaseBytes) {
1844*0fca6ea1SDimitry Andric   SmallString<32> Result;
1845*0fca6ea1SDimitry Andric   raw_svector_ostream S(Result);
1846*0fca6ea1SDimitry Andric 
1847*0fca6ea1SDimitry Andric   int TrailingZeros = llvm::countr_zero(Mask);
1848*0fca6ea1SDimitry Andric   int PopCount = llvm::popcount(Mask);
1849*0fca6ea1SDimitry Andric 
1850*0fca6ea1SDimitry Andric   if (PopCount == 1) {
1851*0fca6ea1SDimitry Andric     S << "bit (" << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';
1852*0fca6ea1SDimitry Andric   } else {
1853*0fca6ea1SDimitry Andric     S << "bits in range ("
1854*0fca6ea1SDimitry Andric       << (TrailingZeros + PopCount - 1 + BaseBytes * CHAR_BIT) << ':'
1855*0fca6ea1SDimitry Andric       << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';
1856*0fca6ea1SDimitry Andric   }
1857*0fca6ea1SDimitry Andric 
1858*0fca6ea1SDimitry Andric   return Result;
1859*0fca6ea1SDimitry Andric }
1860*0fca6ea1SDimitry Andric 
186106c3fb27SDimitry Andric #define GET_FIELD(MASK) (AMDHSA_BITS_GET(FourByteBuffer, MASK))
1862e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK)                                       \
1863e8d8bef9SDimitry Andric   do {                                                                         \
186406c3fb27SDimitry Andric     KdStream << Indent << DIRECTIVE " " << GET_FIELD(MASK) << '\n';            \
186506c3fb27SDimitry Andric   } while (0)
186606c3fb27SDimitry Andric #define PRINT_PSEUDO_DIRECTIVE_COMMENT(DIRECTIVE, MASK)                        \
186706c3fb27SDimitry Andric   do {                                                                         \
186806c3fb27SDimitry Andric     KdStream << Indent << MAI.getCommentString() << ' ' << DIRECTIVE " "       \
186906c3fb27SDimitry Andric              << GET_FIELD(MASK) << '\n';                                       \
1870e8d8bef9SDimitry Andric   } while (0)
1871e8d8bef9SDimitry Andric 
1872*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_IMPL(MASK, DESC, MSG)                              \
1873*0fca6ea1SDimitry Andric   do {                                                                         \
1874*0fca6ea1SDimitry Andric     if (FourByteBuffer & (MASK)) {                                             \
1875*0fca6ea1SDimitry Andric       return createStringError(std::errc::invalid_argument,                    \
1876*0fca6ea1SDimitry Andric                                "kernel descriptor " DESC                       \
1877*0fca6ea1SDimitry Andric                                " reserved %s set" MSG,                         \
1878*0fca6ea1SDimitry Andric                                getBitRangeFromMask((MASK), 0).c_str());        \
1879*0fca6ea1SDimitry Andric     }                                                                          \
1880*0fca6ea1SDimitry Andric   } while (0)
1881*0fca6ea1SDimitry Andric 
1882*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS(MASK) CHECK_RESERVED_BITS_IMPL(MASK, #MASK, "")
1883*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_MSG(MASK, MSG)                                     \
1884*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS_IMPL(MASK, #MASK, ", " MSG)
1885*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_DESC(MASK, DESC)                                   \
1886*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS_IMPL(MASK, DESC, "")
1887*0fca6ea1SDimitry Andric #define CHECK_RESERVED_BITS_DESC_MSG(MASK, DESC, MSG)                          \
1888*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS_IMPL(MASK, DESC, ", " MSG)
1889*0fca6ea1SDimitry Andric 
1890e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
1891*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1(
1892e8d8bef9SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
1893e8d8bef9SDimitry Andric   using namespace amdhsa;
1894e8d8bef9SDimitry Andric   StringRef Indent = "\t";
1895e8d8bef9SDimitry Andric 
1896e8d8bef9SDimitry Andric   // We cannot accurately backward compute #VGPRs used from
1897e8d8bef9SDimitry Andric   // GRANULATED_WORKITEM_VGPR_COUNT. But we are concerned with getting the same
1898e8d8bef9SDimitry Andric   // value of GRANULATED_WORKITEM_VGPR_COUNT in the reassembled binary. So we
1899e8d8bef9SDimitry Andric   // simply calculate the inverse of what the assembler does.
1900e8d8bef9SDimitry Andric 
1901e8d8bef9SDimitry Andric   uint32_t GranulatedWorkitemVGPRCount =
190206c3fb27SDimitry Andric       GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT);
1903e8d8bef9SDimitry Andric 
190406c3fb27SDimitry Andric   uint32_t NextFreeVGPR =
190506c3fb27SDimitry Andric       (GranulatedWorkitemVGPRCount + 1) *
190606c3fb27SDimitry Andric       AMDGPU::IsaInfo::getVGPREncodingGranule(&STI, EnableWavefrontSize32);
1907e8d8bef9SDimitry Andric 
1908e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_next_free_vgpr " << NextFreeVGPR << '\n';
1909e8d8bef9SDimitry Andric 
1910e8d8bef9SDimitry Andric   // We cannot backward compute values used to calculate
1911e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT. Hence the original values for following
1912e8d8bef9SDimitry Andric   // directives can't be computed:
1913e8d8bef9SDimitry Andric   // .amdhsa_reserve_vcc
1914e8d8bef9SDimitry Andric   // .amdhsa_reserve_flat_scratch
1915e8d8bef9SDimitry Andric   // .amdhsa_reserve_xnack_mask
1916e8d8bef9SDimitry Andric   // They take their respective default values if not specified in the assembly.
1917e8d8bef9SDimitry Andric   //
1918e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT
1919e8d8bef9SDimitry Andric   //    = f(NEXT_FREE_SGPR + VCC + FLAT_SCRATCH + XNACK_MASK)
1920e8d8bef9SDimitry Andric   //
1921e8d8bef9SDimitry Andric   // We compute the inverse as though all directives apart from NEXT_FREE_SGPR
1922e8d8bef9SDimitry Andric   // are set to 0. So while disassembling we consider that:
1923e8d8bef9SDimitry Andric   //
1924e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT
1925e8d8bef9SDimitry Andric   //    = f(NEXT_FREE_SGPR + 0 + 0 + 0)
1926e8d8bef9SDimitry Andric   //
1927e8d8bef9SDimitry Andric   // The disassembler cannot recover the original values of those 3 directives.
1928e8d8bef9SDimitry Andric 
1929e8d8bef9SDimitry Andric   uint32_t GranulatedWavefrontSGPRCount =
193006c3fb27SDimitry Andric       GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT);
1931e8d8bef9SDimitry Andric 
1932*0fca6ea1SDimitry Andric   if (isGFX10Plus())
1933*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_MSG(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
1934*0fca6ea1SDimitry Andric                             "must be zero on gfx10+");
1935e8d8bef9SDimitry Andric 
1936e8d8bef9SDimitry Andric   uint32_t NextFreeSGPR = (GranulatedWavefrontSGPRCount + 1) *
1937e8d8bef9SDimitry Andric                           AMDGPU::IsaInfo::getSGPREncodingGranule(&STI);
1938e8d8bef9SDimitry Andric 
1939e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_reserve_vcc " << 0 << '\n';
1940fe6060f1SDimitry Andric   if (!hasArchitectedFlatScratch())
1941e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_reserve_flat_scratch " << 0 << '\n';
1942e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_reserve_xnack_mask " << 0 << '\n';
1943e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_next_free_sgpr " << NextFreeSGPR << "\n";
1944e8d8bef9SDimitry Andric 
1945*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIORITY);
1946e8d8bef9SDimitry Andric 
1947e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_round_mode_32",
1948e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32);
1949e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_round_mode_16_64",
1950e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64);
1951e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_32",
1952e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32);
1953e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_16_64",
1954e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64);
1955e8d8bef9SDimitry Andric 
1956*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIV);
1957e8d8bef9SDimitry Andric 
19585f757f3fSDimitry Andric   if (!isGFX12Plus())
19595f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_dx10_clamp",
19605f757f3fSDimitry Andric                     COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP);
1961e8d8bef9SDimitry Andric 
1962*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_DEBUG_MODE);
1963e8d8bef9SDimitry Andric 
19645f757f3fSDimitry Andric   if (!isGFX12Plus())
19655f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_ieee_mode",
19665f757f3fSDimitry Andric                     COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE);
1967e8d8bef9SDimitry Andric 
1968*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_BULKY);
1969*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_CDBG_USER);
1970e8d8bef9SDimitry Andric 
19715f757f3fSDimitry Andric   if (isGFX9Plus())
19725f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_fp16_overflow", COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL);
1973e8d8bef9SDimitry Andric 
19745f757f3fSDimitry Andric   if (!isGFX9Plus())
1975*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX8_RESERVED0,
1976*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC1", "must be zero pre-gfx9");
1977*0fca6ea1SDimitry Andric 
1978*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_RESERVED1, "COMPUTE_PGM_RSRC1");
1979*0fca6ea1SDimitry Andric 
19805f757f3fSDimitry Andric   if (!isGFX10Plus())
1981*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX9_RESERVED2,
1982*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC1", "must be zero pre-gfx10");
1983e8d8bef9SDimitry Andric 
1984e8d8bef9SDimitry Andric   if (isGFX10Plus()) {
1985e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_workgroup_processor_mode",
19865f757f3fSDimitry Andric                     COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE);
19875f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_memory_ordered", COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED);
19885f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_forward_progress", COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS);
1989e8d8bef9SDimitry Andric   }
19905f757f3fSDimitry Andric 
19915f757f3fSDimitry Andric   if (isGFX12Plus())
19925f757f3fSDimitry Andric     PRINT_DIRECTIVE(".amdhsa_round_robin_scheduling",
19935f757f3fSDimitry Andric                     COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN);
19945f757f3fSDimitry Andric 
1995*0fca6ea1SDimitry Andric   return true;
1996e8d8bef9SDimitry Andric }
1997e8d8bef9SDimitry Andric 
1998e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
1999*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC2(
2000e8d8bef9SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
2001e8d8bef9SDimitry Andric   using namespace amdhsa;
2002e8d8bef9SDimitry Andric   StringRef Indent = "\t";
2003fe6060f1SDimitry Andric   if (hasArchitectedFlatScratch())
2004fe6060f1SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_enable_private_segment",
2005fe6060f1SDimitry Andric                     COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
2006fe6060f1SDimitry Andric   else
2007fe6060f1SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_system_sgpr_private_segment_wavefront_offset",
2008e8d8bef9SDimitry Andric                     COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
2009e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_x",
2010e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X);
2011e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_y",
2012e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y);
2013e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_z",
2014e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z);
2015e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_info",
2016e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO);
2017e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_vgpr_workitem_id",
2018e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID);
2019e8d8bef9SDimitry Andric 
2020*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_ADDRESS_WATCH);
2021*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_MEMORY);
2022*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_GRANULATED_LDS_SIZE);
2023e8d8bef9SDimitry Andric 
2024e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(
2025e8d8bef9SDimitry Andric       ".amdhsa_exception_fp_ieee_invalid_op",
2026e8d8bef9SDimitry Andric       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION);
2027e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_denorm_src",
2028e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE);
2029e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(
2030e8d8bef9SDimitry Andric       ".amdhsa_exception_fp_ieee_div_zero",
2031e8d8bef9SDimitry Andric       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO);
2032e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_overflow",
2033e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW);
2034e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_underflow",
2035e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW);
2036e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_inexact",
2037e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT);
2038e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_int_div_zero",
2039e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO);
2040e8d8bef9SDimitry Andric 
2041*0fca6ea1SDimitry Andric   CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC2_RESERVED0, "COMPUTE_PGM_RSRC2");
2042e8d8bef9SDimitry Andric 
2043*0fca6ea1SDimitry Andric   return true;
2044e8d8bef9SDimitry Andric }
2045e8d8bef9SDimitry Andric 
204606c3fb27SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
2047*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3(
204806c3fb27SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
204906c3fb27SDimitry Andric   using namespace amdhsa;
205006c3fb27SDimitry Andric   StringRef Indent = "\t";
205106c3fb27SDimitry Andric   if (isGFX90A()) {
205206c3fb27SDimitry Andric     KdStream << Indent << ".amdhsa_accum_offset "
205306c3fb27SDimitry Andric              << (GET_FIELD(COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4
205406c3fb27SDimitry Andric              << '\n';
2055*0fca6ea1SDimitry Andric 
205606c3fb27SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_tg_split", COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT);
2057*0fca6ea1SDimitry Andric 
2058*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED0,
2059*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");
2060*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED1,
2061*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");
206206c3fb27SDimitry Andric   } else if (isGFX10Plus()) {
2063647cbc5dSDimitry Andric     // Bits [0-3].
2064647cbc5dSDimitry Andric     if (!isGFX12Plus()) {
206506c3fb27SDimitry Andric       if (!EnableWavefrontSize32 || !*EnableWavefrontSize32) {
206606c3fb27SDimitry Andric         PRINT_DIRECTIVE(".amdhsa_shared_vgpr_count",
2067647cbc5dSDimitry Andric                         COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
206806c3fb27SDimitry Andric       } else {
206906c3fb27SDimitry Andric         PRINT_PSEUDO_DIRECTIVE_COMMENT(
2070647cbc5dSDimitry Andric             "SHARED_VGPR_COUNT",
2071647cbc5dSDimitry Andric             COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
207206c3fb27SDimitry Andric       }
20735f757f3fSDimitry Andric     } else {
2074*0fca6ea1SDimitry Andric       CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX12_PLUS_RESERVED0,
2075*0fca6ea1SDimitry Andric                                    "COMPUTE_PGM_RSRC3",
2076*0fca6ea1SDimitry Andric                                    "must be zero on gfx12+");
20775f757f3fSDimitry Andric     }
20785f757f3fSDimitry Andric 
2079647cbc5dSDimitry Andric     // Bits [4-11].
2080647cbc5dSDimitry Andric     if (isGFX11()) {
2081647cbc5dSDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("INST_PREF_SIZE",
2082647cbc5dSDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE);
2083647cbc5dSDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START",
2084647cbc5dSDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START);
2085647cbc5dSDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END",
2086647cbc5dSDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END);
2087647cbc5dSDimitry Andric     } else if (isGFX12Plus()) {
2088647cbc5dSDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT(
2089647cbc5dSDimitry Andric           "INST_PREF_SIZE", COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE);
2090647cbc5dSDimitry Andric     } else {
2091*0fca6ea1SDimitry Andric       CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED1,
2092*0fca6ea1SDimitry Andric                                    "COMPUTE_PGM_RSRC3",
2093*0fca6ea1SDimitry Andric                                    "must be zero on gfx10");
2094647cbc5dSDimitry Andric     }
2095647cbc5dSDimitry Andric 
2096647cbc5dSDimitry Andric     // Bits [12].
2097*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED2,
2098*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");
20995f757f3fSDimitry Andric 
2100647cbc5dSDimitry Andric     // Bits [13].
2101647cbc5dSDimitry Andric     if (isGFX12Plus()) {
2102647cbc5dSDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("GLG_EN",
2103647cbc5dSDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX12_PLUS_GLG_EN);
2104647cbc5dSDimitry Andric     } else {
2105*0fca6ea1SDimitry Andric       CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX11_RESERVED3,
2106*0fca6ea1SDimitry Andric                                    "COMPUTE_PGM_RSRC3",
2107*0fca6ea1SDimitry Andric                                    "must be zero on gfx10 or gfx11");
2108647cbc5dSDimitry Andric     }
2109647cbc5dSDimitry Andric 
2110647cbc5dSDimitry Andric     // Bits [14-30].
2111*0fca6ea1SDimitry Andric     CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED4,
2112*0fca6ea1SDimitry Andric                                  "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");
2113647cbc5dSDimitry Andric 
2114647cbc5dSDimitry Andric     // Bits [31].
21155f757f3fSDimitry Andric     if (isGFX11Plus()) {
211606c3fb27SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("IMAGE_OP",
2117647cbc5dSDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_PLUS_IMAGE_OP);
21185f757f3fSDimitry Andric     } else {
2119*0fca6ea1SDimitry Andric       CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED5,
2120*0fca6ea1SDimitry Andric                                    "COMPUTE_PGM_RSRC3",
2121*0fca6ea1SDimitry Andric                                    "must be zero on gfx10");
21225f757f3fSDimitry Andric     }
212306c3fb27SDimitry Andric   } else if (FourByteBuffer) {
2124*0fca6ea1SDimitry Andric     return createStringError(
2125*0fca6ea1SDimitry Andric         std::errc::invalid_argument,
2126*0fca6ea1SDimitry Andric         "kernel descriptor COMPUTE_PGM_RSRC3 must be all zero before gfx9");
212706c3fb27SDimitry Andric   }
2128*0fca6ea1SDimitry Andric   return true;
212906c3fb27SDimitry Andric }
213006c3fb27SDimitry Andric #undef PRINT_PSEUDO_DIRECTIVE_COMMENT
2131e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE
213206c3fb27SDimitry Andric #undef GET_FIELD
2133*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_IMPL
2134*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS
2135*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_MSG
2136*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_DESC
2137*0fca6ea1SDimitry Andric #undef CHECK_RESERVED_BITS_DESC_MSG
2138e8d8bef9SDimitry Andric 
2139*0fca6ea1SDimitry Andric /// Create an error object to return from onSymbolStart for reserved kernel
2140*0fca6ea1SDimitry Andric /// descriptor bits being set.
2141*0fca6ea1SDimitry Andric static Error createReservedKDBitsError(uint32_t Mask, unsigned BaseBytes,
2142*0fca6ea1SDimitry Andric                                        const char *Msg = "") {
2143*0fca6ea1SDimitry Andric   return createStringError(
2144*0fca6ea1SDimitry Andric       std::errc::invalid_argument, "kernel descriptor reserved %s set%s%s",
2145*0fca6ea1SDimitry Andric       getBitRangeFromMask(Mask, BaseBytes).c_str(), *Msg ? ", " : "", Msg);
2146*0fca6ea1SDimitry Andric }
2147*0fca6ea1SDimitry Andric 
2148*0fca6ea1SDimitry Andric /// Create an error object to return from onSymbolStart for reserved kernel
2149*0fca6ea1SDimitry Andric /// descriptor bytes being set.
2150*0fca6ea1SDimitry Andric static Error createReservedKDBytesError(unsigned BaseInBytes,
2151*0fca6ea1SDimitry Andric                                         unsigned WidthInBytes) {
2152*0fca6ea1SDimitry Andric   // Create an error comment in the same format as the "Kernel Descriptor"
2153*0fca6ea1SDimitry Andric   // table here: https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor .
2154*0fca6ea1SDimitry Andric   return createStringError(
2155*0fca6ea1SDimitry Andric       std::errc::invalid_argument,
2156*0fca6ea1SDimitry Andric       "kernel descriptor reserved bits in range (%u:%u) set",
2157*0fca6ea1SDimitry Andric       (BaseInBytes + WidthInBytes) * CHAR_BIT - 1, BaseInBytes * CHAR_BIT);
2158*0fca6ea1SDimitry Andric }
2159*0fca6ea1SDimitry Andric 
2160*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeKernelDescriptorDirective(
2161e8d8bef9SDimitry Andric     DataExtractor::Cursor &Cursor, ArrayRef<uint8_t> Bytes,
2162e8d8bef9SDimitry Andric     raw_string_ostream &KdStream) const {
2163e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK)                                       \
2164e8d8bef9SDimitry Andric   do {                                                                         \
2165e8d8bef9SDimitry Andric     KdStream << Indent << DIRECTIVE " "                                        \
2166e8d8bef9SDimitry Andric              << ((TwoByteBuffer & MASK) >> (MASK##_SHIFT)) << '\n';            \
2167e8d8bef9SDimitry Andric   } while (0)
2168e8d8bef9SDimitry Andric 
2169e8d8bef9SDimitry Andric   uint16_t TwoByteBuffer = 0;
2170e8d8bef9SDimitry Andric   uint32_t FourByteBuffer = 0;
2171e8d8bef9SDimitry Andric 
2172e8d8bef9SDimitry Andric   StringRef ReservedBytes;
2173e8d8bef9SDimitry Andric   StringRef Indent = "\t";
2174e8d8bef9SDimitry Andric 
2175e8d8bef9SDimitry Andric   assert(Bytes.size() == 64);
2176e8d8bef9SDimitry Andric   DataExtractor DE(Bytes, /*IsLittleEndian=*/true, /*AddressSize=*/8);
2177e8d8bef9SDimitry Andric 
2178e8d8bef9SDimitry Andric   switch (Cursor.tell()) {
2179e8d8bef9SDimitry Andric   case amdhsa::GROUP_SEGMENT_FIXED_SIZE_OFFSET:
2180e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2181e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_group_segment_fixed_size " << FourByteBuffer
2182e8d8bef9SDimitry Andric              << '\n';
2183*0fca6ea1SDimitry Andric     return true;
2184e8d8bef9SDimitry Andric 
2185e8d8bef9SDimitry Andric   case amdhsa::PRIVATE_SEGMENT_FIXED_SIZE_OFFSET:
2186e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2187e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_private_segment_fixed_size "
2188e8d8bef9SDimitry Andric              << FourByteBuffer << '\n';
2189*0fca6ea1SDimitry Andric     return true;
2190e8d8bef9SDimitry Andric 
2191fe6060f1SDimitry Andric   case amdhsa::KERNARG_SIZE_OFFSET:
2192fe6060f1SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2193fe6060f1SDimitry Andric     KdStream << Indent << ".amdhsa_kernarg_size "
2194fe6060f1SDimitry Andric              << FourByteBuffer << '\n';
2195*0fca6ea1SDimitry Andric     return true;
2196fe6060f1SDimitry Andric 
2197e8d8bef9SDimitry Andric   case amdhsa::RESERVED0_OFFSET:
2198fe6060f1SDimitry Andric     // 4 reserved bytes, must be 0.
2199fe6060f1SDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 4);
2200fe6060f1SDimitry Andric     for (int I = 0; I < 4; ++I) {
2201*0fca6ea1SDimitry Andric       if (ReservedBytes[I] != 0)
2202*0fca6ea1SDimitry Andric         return createReservedKDBytesError(amdhsa::RESERVED0_OFFSET, 4);
2203e8d8bef9SDimitry Andric     }
2204*0fca6ea1SDimitry Andric     return true;
2205e8d8bef9SDimitry Andric 
2206e8d8bef9SDimitry Andric   case amdhsa::KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET:
2207e8d8bef9SDimitry Andric     // KERNEL_CODE_ENTRY_BYTE_OFFSET
2208e8d8bef9SDimitry Andric     // So far no directive controls this for Code Object V3, so simply skip for
2209e8d8bef9SDimitry Andric     // disassembly.
2210e8d8bef9SDimitry Andric     DE.skip(Cursor, 8);
2211*0fca6ea1SDimitry Andric     return true;
2212e8d8bef9SDimitry Andric 
2213e8d8bef9SDimitry Andric   case amdhsa::RESERVED1_OFFSET:
2214e8d8bef9SDimitry Andric     // 20 reserved bytes, must be 0.
2215e8d8bef9SDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 20);
2216e8d8bef9SDimitry Andric     for (int I = 0; I < 20; ++I) {
2217*0fca6ea1SDimitry Andric       if (ReservedBytes[I] != 0)
2218*0fca6ea1SDimitry Andric         return createReservedKDBytesError(amdhsa::RESERVED1_OFFSET, 20);
2219e8d8bef9SDimitry Andric     }
2220*0fca6ea1SDimitry Andric     return true;
2221e8d8bef9SDimitry Andric 
2222e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC3_OFFSET:
2223e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
222406c3fb27SDimitry Andric     return decodeCOMPUTE_PGM_RSRC3(FourByteBuffer, KdStream);
2225e8d8bef9SDimitry Andric 
2226e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC1_OFFSET:
2227e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
222806c3fb27SDimitry Andric     return decodeCOMPUTE_PGM_RSRC1(FourByteBuffer, KdStream);
2229e8d8bef9SDimitry Andric 
2230e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC2_OFFSET:
2231e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
223206c3fb27SDimitry Andric     return decodeCOMPUTE_PGM_RSRC2(FourByteBuffer, KdStream);
2233e8d8bef9SDimitry Andric 
2234e8d8bef9SDimitry Andric   case amdhsa::KERNEL_CODE_PROPERTIES_OFFSET:
2235e8d8bef9SDimitry Andric     using namespace amdhsa;
2236e8d8bef9SDimitry Andric     TwoByteBuffer = DE.getU16(Cursor);
2237e8d8bef9SDimitry Andric 
2238fe6060f1SDimitry Andric     if (!hasArchitectedFlatScratch())
2239e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_buffer",
2240e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER);
2241e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_ptr",
2242e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR);
2243e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_queue_ptr",
2244e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR);
2245e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_segment_ptr",
2246e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR);
2247e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_id",
2248e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID);
2249fe6060f1SDimitry Andric     if (!hasArchitectedFlatScratch())
2250e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_flat_scratch_init",
2251e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT);
2252e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_size",
2253e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE);
2254e8d8bef9SDimitry Andric 
2255e8d8bef9SDimitry Andric     if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED0)
2256*0fca6ea1SDimitry Andric       return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED0,
2257*0fca6ea1SDimitry Andric                                        amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);
2258e8d8bef9SDimitry Andric 
2259e8d8bef9SDimitry Andric     // Reserved for GFX9
2260e8d8bef9SDimitry Andric     if (isGFX9() &&
2261e8d8bef9SDimitry Andric         (TwoByteBuffer & KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32)) {
2262*0fca6ea1SDimitry Andric       return createReservedKDBitsError(
2263*0fca6ea1SDimitry Andric           KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32,
2264*0fca6ea1SDimitry Andric           amdhsa::KERNEL_CODE_PROPERTIES_OFFSET, "must be zero on gfx9");
2265*0fca6ea1SDimitry Andric     }
2266*0fca6ea1SDimitry Andric     if (isGFX10Plus()) {
2267e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_wavefront_size32",
2268e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
2269e8d8bef9SDimitry Andric     }
2270e8d8bef9SDimitry Andric 
2271*0fca6ea1SDimitry Andric     if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5)
2272fcaf7f86SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_uses_dynamic_stack",
2273fcaf7f86SDimitry Andric                       KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK);
2274fcaf7f86SDimitry Andric 
2275*0fca6ea1SDimitry Andric     if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED1) {
2276*0fca6ea1SDimitry Andric       return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED1,
2277*0fca6ea1SDimitry Andric                                        amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);
2278*0fca6ea1SDimitry Andric     }
2279e8d8bef9SDimitry Andric 
2280*0fca6ea1SDimitry Andric     return true;
2281e8d8bef9SDimitry Andric 
22825f757f3fSDimitry Andric   case amdhsa::KERNARG_PRELOAD_OFFSET:
22835f757f3fSDimitry Andric     using namespace amdhsa;
22845f757f3fSDimitry Andric     TwoByteBuffer = DE.getU16(Cursor);
22855f757f3fSDimitry Andric     if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_LENGTH) {
22865f757f3fSDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_length",
22875f757f3fSDimitry Andric                       KERNARG_PRELOAD_SPEC_LENGTH);
22885f757f3fSDimitry Andric     }
22895f757f3fSDimitry Andric 
22905f757f3fSDimitry Andric     if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_OFFSET) {
22915f757f3fSDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_offset",
22925f757f3fSDimitry Andric                       KERNARG_PRELOAD_SPEC_OFFSET);
22935f757f3fSDimitry Andric     }
2294*0fca6ea1SDimitry Andric     return true;
22955f757f3fSDimitry Andric 
22965f757f3fSDimitry Andric   case amdhsa::RESERVED3_OFFSET:
22975f757f3fSDimitry Andric     // 4 bytes from here are reserved, must be 0.
22985f757f3fSDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 4);
22995f757f3fSDimitry Andric     for (int I = 0; I < 4; ++I) {
2300e8d8bef9SDimitry Andric       if (ReservedBytes[I] != 0)
2301*0fca6ea1SDimitry Andric         return createReservedKDBytesError(amdhsa::RESERVED3_OFFSET, 4);
2302e8d8bef9SDimitry Andric     }
2303*0fca6ea1SDimitry Andric     return true;
2304e8d8bef9SDimitry Andric 
2305e8d8bef9SDimitry Andric   default:
2306e8d8bef9SDimitry Andric     llvm_unreachable("Unhandled index. Case statements cover everything.");
2307*0fca6ea1SDimitry Andric     return true;
2308e8d8bef9SDimitry Andric   }
2309e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE
2310e8d8bef9SDimitry Andric }
2311e8d8bef9SDimitry Andric 
2312*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::decodeKernelDescriptor(
2313e8d8bef9SDimitry Andric     StringRef KdName, ArrayRef<uint8_t> Bytes, uint64_t KdAddress) const {
2314*0fca6ea1SDimitry Andric 
2315e8d8bef9SDimitry Andric   // CP microcode requires the kernel descriptor to be 64 aligned.
2316e8d8bef9SDimitry Andric   if (Bytes.size() != 64 || KdAddress % 64 != 0)
2317*0fca6ea1SDimitry Andric     return createStringError(std::errc::invalid_argument,
2318*0fca6ea1SDimitry Andric                              "kernel descriptor must be 64-byte aligned");
2319e8d8bef9SDimitry Andric 
232006c3fb27SDimitry Andric   // FIXME: We can't actually decode "in order" as is done below, as e.g. GFX10
232106c3fb27SDimitry Andric   // requires us to know the setting of .amdhsa_wavefront_size32 in order to
232206c3fb27SDimitry Andric   // accurately produce .amdhsa_next_free_vgpr, and they appear in the wrong
232306c3fb27SDimitry Andric   // order. Workaround this by first looking up .amdhsa_wavefront_size32 here
232406c3fb27SDimitry Andric   // when required.
232506c3fb27SDimitry Andric   if (isGFX10Plus()) {
232606c3fb27SDimitry Andric     uint16_t KernelCodeProperties =
232706c3fb27SDimitry Andric         support::endian::read16(&Bytes[amdhsa::KERNEL_CODE_PROPERTIES_OFFSET],
23285f757f3fSDimitry Andric                                 llvm::endianness::little);
232906c3fb27SDimitry Andric     EnableWavefrontSize32 =
233006c3fb27SDimitry Andric         AMDHSA_BITS_GET(KernelCodeProperties,
233106c3fb27SDimitry Andric                         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
233206c3fb27SDimitry Andric   }
233306c3fb27SDimitry Andric 
2334e8d8bef9SDimitry Andric   std::string Kd;
2335e8d8bef9SDimitry Andric   raw_string_ostream KdStream(Kd);
2336e8d8bef9SDimitry Andric   KdStream << ".amdhsa_kernel " << KdName << '\n';
2337e8d8bef9SDimitry Andric 
2338e8d8bef9SDimitry Andric   DataExtractor::Cursor C(0);
2339e8d8bef9SDimitry Andric   while (C && C.tell() < Bytes.size()) {
2340*0fca6ea1SDimitry Andric     Expected<bool> Res = decodeKernelDescriptorDirective(C, Bytes, KdStream);
2341e8d8bef9SDimitry Andric 
2342e8d8bef9SDimitry Andric     cantFail(C.takeError());
2343e8d8bef9SDimitry Andric 
2344*0fca6ea1SDimitry Andric     if (!Res)
2345*0fca6ea1SDimitry Andric       return Res;
2346e8d8bef9SDimitry Andric   }
2347e8d8bef9SDimitry Andric   KdStream << ".end_amdhsa_kernel\n";
2348e8d8bef9SDimitry Andric   outs() << KdStream.str();
2349*0fca6ea1SDimitry Andric   return true;
2350e8d8bef9SDimitry Andric }
2351e8d8bef9SDimitry Andric 
2352*0fca6ea1SDimitry Andric Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,
2353*0fca6ea1SDimitry Andric                                                  uint64_t &Size,
2354*0fca6ea1SDimitry Andric                                                  ArrayRef<uint8_t> Bytes,
2355*0fca6ea1SDimitry Andric                                                  uint64_t Address) const {
2356e8d8bef9SDimitry Andric   // Right now only kernel descriptor needs to be handled.
2357e8d8bef9SDimitry Andric   // We ignore all other symbols for target specific handling.
2358e8d8bef9SDimitry Andric   // TODO:
2359e8d8bef9SDimitry Andric   // Fix the spurious symbol issue for AMDGPU kernels. Exists for both Code
2360e8d8bef9SDimitry Andric   // Object V2 and V3 when symbols are marked protected.
2361e8d8bef9SDimitry Andric 
2362e8d8bef9SDimitry Andric   // amd_kernel_code_t for Code Object V2.
2363e8d8bef9SDimitry Andric   if (Symbol.Type == ELF::STT_AMDGPU_HSA_KERNEL) {
2364e8d8bef9SDimitry Andric     Size = 256;
2365*0fca6ea1SDimitry Andric     return createStringError(std::errc::invalid_argument,
2366*0fca6ea1SDimitry Andric                              "code object v2 is not supported");
2367e8d8bef9SDimitry Andric   }
2368e8d8bef9SDimitry Andric 
2369e8d8bef9SDimitry Andric   // Code Object V3 kernel descriptors.
2370e8d8bef9SDimitry Andric   StringRef Name = Symbol.Name;
23715f757f3fSDimitry Andric   if (Symbol.Type == ELF::STT_OBJECT && Name.ends_with(StringRef(".kd"))) {
2372e8d8bef9SDimitry Andric     Size = 64; // Size = 64 regardless of success or failure.
2373e8d8bef9SDimitry Andric     return decodeKernelDescriptor(Name.drop_back(3), Bytes, Address);
2374e8d8bef9SDimitry Andric   }
2375*0fca6ea1SDimitry Andric 
2376*0fca6ea1SDimitry Andric   return false;
2377*0fca6ea1SDimitry Andric }
2378*0fca6ea1SDimitry Andric 
2379*0fca6ea1SDimitry Andric const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
2380*0fca6ea1SDimitry Andric                                                            int64_t Val) {
2381*0fca6ea1SDimitry Andric   MCContext &Ctx = getContext();
2382*0fca6ea1SDimitry Andric   MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
2383*0fca6ea1SDimitry Andric   // Note: only set value to Val on a new symbol in case an dissassembler
2384*0fca6ea1SDimitry Andric   // has already been initialized in this context.
2385*0fca6ea1SDimitry Andric   if (!Sym->isVariable()) {
2386*0fca6ea1SDimitry Andric     Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
2387*0fca6ea1SDimitry Andric   } else {
2388*0fca6ea1SDimitry Andric     int64_t Res = ~Val;
2389*0fca6ea1SDimitry Andric     bool Valid = Sym->getVariableValue()->evaluateAsAbsolute(Res);
2390*0fca6ea1SDimitry Andric     if (!Valid || Res != Val)
2391*0fca6ea1SDimitry Andric       Ctx.reportWarning(SMLoc(), "unsupported redefinition of " + Id);
2392*0fca6ea1SDimitry Andric   }
2393*0fca6ea1SDimitry Andric   return MCSymbolRefExpr::create(Sym, Ctx);
23940b57cec5SDimitry Andric }
23950b57cec5SDimitry Andric 
23960b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23970b57cec5SDimitry Andric // AMDGPUSymbolizer
23980b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23990b57cec5SDimitry Andric 
24000b57cec5SDimitry Andric // Try to find symbol name for specified label
240181ad6265SDimitry Andric bool AMDGPUSymbolizer::tryAddingSymbolicOperand(
240281ad6265SDimitry Andric     MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value,
240381ad6265SDimitry Andric     uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/,
240481ad6265SDimitry Andric     uint64_t /*OpSize*/, uint64_t /*InstSize*/) {
24050b57cec5SDimitry Andric 
24060b57cec5SDimitry Andric   if (!IsBranch) {
24070b57cec5SDimitry Andric     return false;
24080b57cec5SDimitry Andric   }
24090b57cec5SDimitry Andric 
24100b57cec5SDimitry Andric   auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
24110b57cec5SDimitry Andric   if (!Symbols)
24120b57cec5SDimitry Andric     return false;
24130b57cec5SDimitry Andric 
2414e8d8bef9SDimitry Andric   auto Result = llvm::find_if(*Symbols, [Value](const SymbolInfoTy &Val) {
2415e8d8bef9SDimitry Andric     return Val.Addr == static_cast<uint64_t>(Value) &&
2416e8d8bef9SDimitry Andric            Val.Type == ELF::STT_NOTYPE;
24170b57cec5SDimitry Andric   });
24180b57cec5SDimitry Andric   if (Result != Symbols->end()) {
24195ffd83dbSDimitry Andric     auto *Sym = Ctx.getOrCreateSymbol(Result->Name);
24200b57cec5SDimitry Andric     const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
24210b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Add));
24220b57cec5SDimitry Andric     return true;
24230b57cec5SDimitry Andric   }
2424fe6060f1SDimitry Andric   // Add to list of referenced addresses, so caller can synthesize a label.
2425fe6060f1SDimitry Andric   ReferencedAddresses.push_back(static_cast<uint64_t>(Value));
24260b57cec5SDimitry Andric   return false;
24270b57cec5SDimitry Andric }
24280b57cec5SDimitry Andric 
24290b57cec5SDimitry Andric void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
24300b57cec5SDimitry Andric                                                        int64_t Value,
24310b57cec5SDimitry Andric                                                        uint64_t Address) {
24320b57cec5SDimitry Andric   llvm_unreachable("unimplemented");
24330b57cec5SDimitry Andric }
24340b57cec5SDimitry Andric 
24350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
24360b57cec5SDimitry Andric // Initialization
24370b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
24380b57cec5SDimitry Andric 
24390b57cec5SDimitry Andric static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
24400b57cec5SDimitry Andric                               LLVMOpInfoCallback /*GetOpInfo*/,
24410b57cec5SDimitry Andric                               LLVMSymbolLookupCallback /*SymbolLookUp*/,
24420b57cec5SDimitry Andric                               void *DisInfo,
24430b57cec5SDimitry Andric                               MCContext *Ctx,
24440b57cec5SDimitry Andric                               std::unique_ptr<MCRelocationInfo> &&RelInfo) {
24450b57cec5SDimitry Andric   return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
24460b57cec5SDimitry Andric }
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric static MCDisassembler *createAMDGPUDisassembler(const Target &T,
24490b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
24500b57cec5SDimitry Andric                                                 MCContext &Ctx) {
24510b57cec5SDimitry Andric   return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());
24520b57cec5SDimitry Andric }
24530b57cec5SDimitry Andric 
2454480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUDisassembler() {
24550b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
24560b57cec5SDimitry Andric                                          createAMDGPUDisassembler);
24570b57cec5SDimitry Andric   TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
24580b57cec5SDimitry Andric                                        createAMDGPUSymbolizer);
24590b57cec5SDimitry Andric }
2460