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"
240b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
25e8d8bef9SDimitry Andric #include "llvm-c/DisassemblerTypes.h"
2681ad6265SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
2981ad6265SDimitry Andric #include "llvm/MC/MCDecoderOps.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
31349cc55cSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
3281ad6265SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
3381ad6265SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
3481ad6265SDimitry Andric #include "llvm/MC/TargetRegistry.h"
35e8d8bef9SDimitry Andric #include "llvm/Support/AMDHSAKernelDescriptor.h"
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric using namespace llvm;
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #define DEBUG_TYPE "amdgpu-disassembler"
400b57cec5SDimitry Andric 
41e8d8bef9SDimitry Andric #define SGPR_MAX                                                               \
42e8d8bef9SDimitry Andric   (isGFX10Plus() ? AMDGPU::EncValues::SGPR_MAX_GFX10                           \
430b57cec5SDimitry Andric                  : AMDGPU::EncValues::SGPR_MAX_SI)
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric using DecodeStatus = llvm::MCDisassembler::DecodeStatus;
460b57cec5SDimitry Andric 
AMDGPUDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)470b57cec5SDimitry Andric AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
48fe013be4SDimitry Andric                                        MCContext &Ctx, MCInstrInfo const *MCII)
49fe013be4SDimitry Andric     : MCDisassembler(STI, Ctx), MCII(MCII), MRI(*Ctx.getRegisterInfo()),
50fe013be4SDimitry Andric       MAI(*Ctx.getAsmInfo()), TargetMaxInstBytes(MAI.getMaxInstLength(&STI)) {
510b57cec5SDimitry Andric   // ToDo: AMDGPUDisassembler supports only VI ISA.
52fe013be4SDimitry Andric   if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
530b57cec5SDimitry Andric     report_fatal_error("Disassembly not yet supported for subtarget");
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric inline static MCDisassembler::DecodeStatus
addOperand(MCInst & Inst,const MCOperand & Opnd)570b57cec5SDimitry Andric addOperand(MCInst &Inst, const MCOperand& Opnd) {
580b57cec5SDimitry Andric   Inst.addOperand(Opnd);
590b57cec5SDimitry Andric   return Opnd.isValid() ?
600b57cec5SDimitry Andric     MCDisassembler::Success :
61480093f4SDimitry Andric     MCDisassembler::Fail;
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
insertNamedMCOperand(MCInst & MI,const MCOperand & Op,uint16_t NameIdx)640b57cec5SDimitry Andric static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,
650b57cec5SDimitry Andric                                 uint16_t NameIdx) {
660b57cec5SDimitry Andric   int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), NameIdx);
670b57cec5SDimitry Andric   if (OpIdx != -1) {
680b57cec5SDimitry Andric     auto I = MI.begin();
690b57cec5SDimitry Andric     std::advance(I, OpIdx);
700b57cec5SDimitry Andric     MI.insert(I, Op);
710b57cec5SDimitry Andric   }
720b57cec5SDimitry Andric   return OpIdx;
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
decodeSOPPBrTarget(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)75fe013be4SDimitry Andric static DecodeStatus decodeSOPPBrTarget(MCInst &Inst, unsigned Imm,
7681ad6265SDimitry Andric                                        uint64_t Addr,
7781ad6265SDimitry Andric                                        const MCDisassembler *Decoder) {
780b57cec5SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   // Our branches take a simm16, but we need two extra bits to account for the
810b57cec5SDimitry Andric   // factor of 4.
820b57cec5SDimitry Andric   APInt SignedOffset(18, Imm * 4, true);
830b57cec5SDimitry Andric   int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue();
840b57cec5SDimitry Andric 
8581ad6265SDimitry Andric   if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2, 0))
860b57cec5SDimitry Andric     return MCDisassembler::Success;
870b57cec5SDimitry Andric   return addOperand(Inst, MCOperand::createImm(Imm));
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
decodeSMEMOffset(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)9081ad6265SDimitry Andric static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, uint64_t Addr,
9181ad6265SDimitry Andric                                      const MCDisassembler *Decoder) {
925ffd83dbSDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
935ffd83dbSDimitry Andric   int64_t Offset;
94c9157d92SDimitry Andric   if (DAsm->isGFX12Plus()) { // GFX12 supports 24-bit signed offsets.
95c9157d92SDimitry Andric     Offset = SignExtend64<24>(Imm);
96c9157d92SDimitry Andric   } else if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets.
975ffd83dbSDimitry Andric     Offset = Imm & 0xFFFFF;
985ffd83dbSDimitry Andric   } else { // GFX9+ supports 21-bit signed offsets.
995ffd83dbSDimitry Andric     Offset = SignExtend64<21>(Imm);
1005ffd83dbSDimitry Andric   }
1015ffd83dbSDimitry Andric   return addOperand(Inst, MCOperand::createImm(Offset));
1025ffd83dbSDimitry Andric }
1035ffd83dbSDimitry Andric 
decodeBoolReg(MCInst & Inst,unsigned Val,uint64_t Addr,const MCDisassembler * Decoder)10481ad6265SDimitry Andric static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, uint64_t Addr,
10581ad6265SDimitry Andric                                   const MCDisassembler *Decoder) {
1060b57cec5SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
1070b57cec5SDimitry Andric   return addOperand(Inst, DAsm->decodeBoolReg(Val));
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
decodeSplitBarrier(MCInst & Inst,unsigned Val,uint64_t Addr,const MCDisassembler * Decoder)110c9157d92SDimitry Andric static DecodeStatus decodeSplitBarrier(MCInst &Inst, unsigned Val,
111c9157d92SDimitry Andric                                        uint64_t Addr,
112c9157d92SDimitry Andric                                        const MCDisassembler *Decoder) {
113c9157d92SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
114c9157d92SDimitry Andric   return addOperand(Inst, DAsm->decodeSplitBarrier(Val));
115c9157d92SDimitry Andric }
116c9157d92SDimitry Andric 
1170b57cec5SDimitry Andric #define DECODE_OPERAND(StaticDecoderName, DecoderName)                         \
11881ad6265SDimitry Andric   static DecodeStatus StaticDecoderName(MCInst &Inst, unsigned Imm,            \
1190b57cec5SDimitry Andric                                         uint64_t /*Addr*/,                     \
12081ad6265SDimitry Andric                                         const MCDisassembler *Decoder) {       \
1210b57cec5SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
1220b57cec5SDimitry Andric     return addOperand(Inst, DAsm->DecoderName(Imm));                           \
1230b57cec5SDimitry Andric   }
1240b57cec5SDimitry Andric 
125fe013be4SDimitry Andric // Decoder for registers, decode directly using RegClassID. Imm(8-bit) is
126fe013be4SDimitry Andric // number of register. Used by VGPR only and AGPR only operands.
127fe013be4SDimitry Andric #define DECODE_OPERAND_REG_8(RegClass)                                         \
128fe013be4SDimitry Andric   static DecodeStatus Decode##RegClass##RegisterClass(                         \
129fe013be4SDimitry Andric       MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,                           \
130fe013be4SDimitry Andric       const MCDisassembler *Decoder) {                                         \
131fe013be4SDimitry Andric     assert(Imm < (1 << 8) && "8-bit encoding");                                \
132fe013be4SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
133fe013be4SDimitry Andric     return addOperand(                                                         \
134fe013be4SDimitry Andric         Inst, DAsm->createRegOperand(AMDGPU::RegClass##RegClassID, Imm));      \
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
137fe013be4SDimitry Andric #define DECODE_SrcOp(Name, EncSize, OpWidth, EncImm, MandatoryLiteral,         \
138fe013be4SDimitry Andric                      ImmWidth)                                                 \
139fe013be4SDimitry Andric   static DecodeStatus Name(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,      \
140fe013be4SDimitry Andric                            const MCDisassembler *Decoder) {                    \
141fe013be4SDimitry Andric     assert(Imm < (1 << EncSize) && #EncSize "-bit encoding");                  \
142fe013be4SDimitry Andric     auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);              \
143fe013be4SDimitry Andric     return addOperand(Inst,                                                    \
144fe013be4SDimitry Andric                       DAsm->decodeSrcOp(AMDGPUDisassembler::OpWidth, EncImm,   \
145fe013be4SDimitry Andric                                         MandatoryLiteral, ImmWidth));          \
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
148fe013be4SDimitry Andric // Decoder for registers. Imm(7-bit) is number of register, uses decodeSrcOp to
149fe013be4SDimitry Andric // get register class. Used by SGPR only operands.
150fe013be4SDimitry Andric #define DECODE_OPERAND_REG_7(RegClass, OpWidth)                                \
151fe013be4SDimitry Andric   DECODE_SrcOp(Decode##RegClass##RegisterClass, 7, OpWidth, Imm, false, 0)
152fe6060f1SDimitry Andric 
153fe013be4SDimitry Andric // Decoder for registers. Imm(10-bit): Imm{7-0} is number of register,
154fe013be4SDimitry Andric // Imm{9} is acc(agpr or vgpr) Imm{8} should be 0 (see VOP3Pe_SMFMAC).
155fe013be4SDimitry Andric // Set Imm{8} to 1 (IS_VGPR) to decode using 'enum10' from decodeSrcOp.
156fe013be4SDimitry Andric // Used by AV_ register classes (AGPR or VGPR only register operands).
157fe013be4SDimitry Andric #define DECODE_OPERAND_REG_AV10(RegClass, OpWidth)                             \
158fe013be4SDimitry Andric   DECODE_SrcOp(Decode##RegClass##RegisterClass, 10, OpWidth,                   \
159fe013be4SDimitry Andric                Imm | AMDGPU::EncValues::IS_VGPR, false, 0)
1600b57cec5SDimitry Andric 
161fe013be4SDimitry Andric // Decoder for Src(9-bit encoding) registers only.
162fe013be4SDimitry Andric #define DECODE_OPERAND_SRC_REG_9(RegClass, OpWidth)                            \
163fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass, 9, OpWidth, Imm, false, 0)
1640b57cec5SDimitry Andric 
165fe013be4SDimitry Andric // Decoder for Src(9-bit encoding) AGPR, register number encoded in 9bits, set
166fe013be4SDimitry Andric // Imm{9} to 1 (set acc) and decode using 'enum10' from decodeSrcOp, registers
167fe013be4SDimitry Andric // only.
168fe013be4SDimitry Andric #define DECODE_OPERAND_SRC_REG_A9(RegClass, OpWidth)                           \
169fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass, 9, OpWidth, Imm | 512, false, 0)
170fe6060f1SDimitry Andric 
171fe013be4SDimitry Andric // Decoder for 'enum10' from decodeSrcOp, Imm{0-8} is 9-bit Src encoding
172fe013be4SDimitry Andric // Imm{9} is acc, registers only.
173fe013be4SDimitry Andric #define DECODE_SRC_OPERAND_REG_AV10(RegClass, OpWidth)                         \
174fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass, 10, OpWidth, Imm, false, 0)
1750b57cec5SDimitry Andric 
176fe013be4SDimitry Andric // Decoder for RegisterOperands using 9-bit Src encoding. Operand can be
177fe013be4SDimitry Andric // register from RegClass or immediate. Registers that don't belong to RegClass
178fe013be4SDimitry Andric // will be decoded and InstPrinter will report warning. Immediate will be
179fe013be4SDimitry Andric // decoded into constant of size ImmWidth, should match width of immediate used
180fe013be4SDimitry Andric // by OperandType (important for floating point types).
181fe013be4SDimitry Andric #define DECODE_OPERAND_SRC_REG_OR_IMM_9(RegClass, OpWidth, ImmWidth)           \
182fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass##_Imm##ImmWidth, 9, OpWidth, Imm,      \
183fe013be4SDimitry Andric                false, ImmWidth)
184fe6060f1SDimitry Andric 
185cdc20ff6SDimitry Andric #define DECODE_OPERAND_SRC_REG_OR_IMM_9_TYPED(Name, OpWidth, ImmWidth)         \
186cdc20ff6SDimitry Andric   DECODE_SrcOp(decodeOperand_##Name, 9, OpWidth, Imm, false, ImmWidth)
187cdc20ff6SDimitry Andric 
188fe013be4SDimitry Andric // Decoder for Src(9-bit encoding) AGPR or immediate. Set Imm{9} to 1 (set acc)
189fe013be4SDimitry Andric // and decode using 'enum10' from decodeSrcOp.
190fe013be4SDimitry Andric #define DECODE_OPERAND_SRC_REG_OR_IMM_A9(RegClass, OpWidth, ImmWidth)          \
191fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass##_Imm##ImmWidth, 9, OpWidth,           \
192fe013be4SDimitry Andric                Imm | 512, false, ImmWidth)
1930b57cec5SDimitry Andric 
194fe013be4SDimitry Andric #define DECODE_OPERAND_SRC_REG_OR_IMM_DEFERRED_9(RegClass, OpWidth, ImmWidth)  \
195fe013be4SDimitry Andric   DECODE_SrcOp(decodeOperand_##RegClass##_Deferred##_Imm##ImmWidth, 9,         \
196fe013be4SDimitry Andric                OpWidth, Imm, true, ImmWidth)
1970b57cec5SDimitry Andric 
198fe013be4SDimitry Andric // Default decoders generated by tablegen: 'Decode<RegClass>RegisterClass'
199fe013be4SDimitry Andric // when RegisterClass is used as an operand. Most often used for destination
200fe013be4SDimitry Andric // operands.
201fe6060f1SDimitry Andric 
202fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32)
DECODE_OPERAND_REG_8(VGPR_32_Lo128)203fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VGPR_32_Lo128)
204fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_64)
205fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_96)
206fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_128)
207fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_256)
208fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_288)
209fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_352)
210fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_384)
211fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_512)
212fe013be4SDimitry Andric DECODE_OPERAND_REG_8(VReg_1024)
213fe6060f1SDimitry Andric 
214fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_32, OPW32)
215c9157d92SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC, OPW32)
216fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XM0_XEXEC, OPW32)
217fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_32_XEXEC_HI, OPW32)
218fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_64, OPW64)
219fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_64_XEXEC, OPW64)
220c9157d92SDimitry Andric DECODE_OPERAND_REG_7(SReg_96, OPW96)
221fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_128, OPW128)
222fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_256, OPW256)
223fe013be4SDimitry Andric DECODE_OPERAND_REG_7(SReg_512, OPW512)
224fe6060f1SDimitry Andric 
225fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AGPR_32)
226fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AReg_64)
227fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AReg_128)
228fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AReg_256)
229fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AReg_512)
230fe013be4SDimitry Andric DECODE_OPERAND_REG_8(AReg_1024)
231fe6060f1SDimitry Andric 
232fe013be4SDimitry Andric DECODE_OPERAND_REG_AV10(AVDst_128, OPW128)
233fe013be4SDimitry Andric DECODE_OPERAND_REG_AV10(AVDst_512, OPW512)
234fe6060f1SDimitry Andric 
235fe013be4SDimitry Andric // Decoders for register only source RegisterOperands that use use 9-bit Src
236fe013be4SDimitry Andric // encoding: 'decodeOperand_<RegClass>'.
237fe013be4SDimitry Andric 
238fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_9(VGPR_32, OPW32)
239fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_9(VReg_64, OPW64)
240fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_9(VReg_128, OPW128)
241fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_9(VReg_256, OPW256)
242fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_9(VRegOrLds_32, OPW32)
243fe013be4SDimitry Andric 
244fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_A9(AGPR_32, OPW32)
245fe013be4SDimitry Andric 
246fe013be4SDimitry Andric DECODE_SRC_OPERAND_REG_AV10(AV_32, OPW32)
247fe013be4SDimitry Andric DECODE_SRC_OPERAND_REG_AV10(AV_64, OPW64)
248fe013be4SDimitry Andric DECODE_SRC_OPERAND_REG_AV10(AV_128, OPW128)
249fe013be4SDimitry Andric 
250fe013be4SDimitry Andric // Decoders for register or immediate RegisterOperands that use 9-bit Src
251fe013be4SDimitry Andric // encoding: 'decodeOperand_<RegClass>_Imm<ImmWidth>'.
252fe013be4SDimitry Andric 
253fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(SReg_64, OPW64, 64)
254fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(SReg_32, OPW32, 32)
255c9157d92SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(SReg_32, OPW32, 16)
256fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(SRegOrLds_32, OPW32, 32)
257fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VS_32_Lo128, OPW16, 16)
258fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VS_32, OPW32, 16)
259fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VS_32, OPW32, 32)
260fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VS_64, OPW64, 64)
261fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VS_64, OPW64, 32)
262fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_64, OPW64, 64)
263*b9d9368bSDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_64, OPW64, 32)
264*b9d9368bSDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_64, OPW64, 16)
265fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_128, OPW128, 32)
266*b9d9368bSDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_128, OPW128, 16)
267fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_256, OPW256, 64)
268*b9d9368bSDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_256, OPW256, 32)
269fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_512, OPW512, 32)
270fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9(VReg_1024, OPW1024, 32)
271fe013be4SDimitry Andric 
272cdc20ff6SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9_TYPED(VS_32_ImmV2I16, OPW32, 32)
273cdc20ff6SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_9_TYPED(VS_32_ImmV2F16, OPW32, 16)
274cdc20ff6SDimitry Andric 
275fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_A9(AReg_64, OPW64, 64)
276fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_A9(AReg_128, OPW128, 32)
277fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_A9(AReg_256, OPW256, 64)
278fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_A9(AReg_512, OPW512, 32)
279fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_A9(AReg_1024, OPW1024, 32)
280fe013be4SDimitry Andric 
281fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_DEFERRED_9(VS_32_Lo128, OPW16, 16)
282fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_DEFERRED_9(VS_32, OPW16, 16)
283fe013be4SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_DEFERRED_9(VS_32, OPW32, 32)
284c9157d92SDimitry Andric DECODE_OPERAND_SRC_REG_OR_IMM_DEFERRED_9(SReg_32, OPW32, 32)
285c9157d92SDimitry Andric 
286c9157d92SDimitry Andric static DecodeStatus DecodeVGPR_16RegisterClass(MCInst &Inst, unsigned Imm,
287c9157d92SDimitry Andric                                                uint64_t /*Addr*/,
288c9157d92SDimitry Andric                                                const MCDisassembler *Decoder) {
289c9157d92SDimitry Andric   assert(isUInt<10>(Imm) && "10-bit encoding expected");
290c9157d92SDimitry Andric   assert((Imm & (1 << 8)) == 0 && "Imm{8} should not be used");
291c9157d92SDimitry Andric 
292c9157d92SDimitry Andric   bool IsHi = Imm & (1 << 9);
293c9157d92SDimitry Andric   unsigned RegIdx = Imm & 0xff;
294c9157d92SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
295c9157d92SDimitry Andric   return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
296c9157d92SDimitry Andric }
297c9157d92SDimitry Andric 
298c9157d92SDimitry Andric static DecodeStatus
DecodeVGPR_16_Lo128RegisterClass(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler * Decoder)299c9157d92SDimitry Andric DecodeVGPR_16_Lo128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,
300c9157d92SDimitry Andric                                  const MCDisassembler *Decoder) {
301c9157d92SDimitry Andric   assert(isUInt<8>(Imm) && "8-bit encoding expected");
302c9157d92SDimitry Andric 
303c9157d92SDimitry Andric   bool IsHi = Imm & (1 << 7);
304c9157d92SDimitry Andric   unsigned RegIdx = Imm & 0x7f;
305c9157d92SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
306c9157d92SDimitry Andric   return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
307c9157d92SDimitry Andric }
308c9157d92SDimitry Andric 
decodeOperand_VSrcT16_Lo128(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler * Decoder)309c9157d92SDimitry Andric static DecodeStatus decodeOperand_VSrcT16_Lo128(MCInst &Inst, unsigned Imm,
310c9157d92SDimitry Andric                                                 uint64_t /*Addr*/,
311c9157d92SDimitry Andric                                                 const MCDisassembler *Decoder) {
312c9157d92SDimitry Andric   assert(isUInt<9>(Imm) && "9-bit encoding expected");
313c9157d92SDimitry Andric 
314c9157d92SDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
315c9157d92SDimitry Andric   bool IsVGPR = Imm & (1 << 8);
316c9157d92SDimitry Andric   if (IsVGPR) {
317c9157d92SDimitry Andric     bool IsHi = Imm & (1 << 7);
318c9157d92SDimitry Andric     unsigned RegIdx = Imm & 0x7f;
319c9157d92SDimitry Andric     return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
320c9157d92SDimitry Andric   }
321c9157d92SDimitry Andric   return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16,
322c9157d92SDimitry Andric                                                    Imm & 0xFF, false, 16));
323c9157d92SDimitry Andric }
324c9157d92SDimitry Andric 
decodeOperand_VSrcT16(MCInst & Inst,unsigned Imm,uint64_t,const MCDisassembler * Decoder)325c9157d92SDimitry Andric static DecodeStatus decodeOperand_VSrcT16(MCInst &Inst, unsigned Imm,
326c9157d92SDimitry Andric                                           uint64_t /*Addr*/,
327c9157d92SDimitry Andric                                           const MCDisassembler *Decoder) {
328c9157d92SDimitry Andric   assert(isUInt<10>(Imm) && "10-bit encoding expected");
329c9157d92SDimitry Andric 
330c9157d92SDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
331c9157d92SDimitry Andric   bool IsVGPR = Imm & (1 << 8);
332c9157d92SDimitry Andric   if (IsVGPR) {
333c9157d92SDimitry Andric     bool IsHi = Imm & (1 << 9);
334c9157d92SDimitry Andric     unsigned RegIdx = Imm & 0xff;
335c9157d92SDimitry Andric     return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));
336c9157d92SDimitry Andric   }
337c9157d92SDimitry Andric   return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(AMDGPUDisassembler::OPW16,
338c9157d92SDimitry Andric                                                    Imm & 0xFF, false, 16));
339c9157d92SDimitry Andric }
340fe013be4SDimitry Andric 
decodeOperand_KImmFP(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)341fe013be4SDimitry Andric static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, unsigned Imm,
34281ad6265SDimitry Andric                                          uint64_t Addr,
34381ad6265SDimitry Andric                                          const MCDisassembler *Decoder) {
344349cc55cSDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
345349cc55cSDimitry Andric   return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm));
346349cc55cSDimitry Andric }
347349cc55cSDimitry Andric 
decodeOperandVOPDDstY(MCInst & Inst,unsigned Val,uint64_t Addr,const void * Decoder)34881ad6265SDimitry Andric static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val,
34981ad6265SDimitry Andric                                           uint64_t Addr, const void *Decoder) {
35081ad6265SDimitry Andric   const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
35181ad6265SDimitry Andric   return addOperand(Inst, DAsm->decodeVOPDDstYOp(Inst, Val));
35281ad6265SDimitry Andric }
35381ad6265SDimitry Andric 
IsAGPROperand(const MCInst & Inst,int OpIdx,const MCRegisterInfo * MRI)354fe6060f1SDimitry Andric static bool IsAGPROperand(const MCInst &Inst, int OpIdx,
355fe6060f1SDimitry Andric                           const MCRegisterInfo *MRI) {
356fe6060f1SDimitry Andric   if (OpIdx < 0)
357fe6060f1SDimitry Andric     return false;
358fe6060f1SDimitry Andric 
359fe6060f1SDimitry Andric   const MCOperand &Op = Inst.getOperand(OpIdx);
360fe6060f1SDimitry Andric   if (!Op.isReg())
361fe6060f1SDimitry Andric     return false;
362fe6060f1SDimitry Andric 
363fe6060f1SDimitry Andric   unsigned Sub = MRI->getSubReg(Op.getReg(), AMDGPU::sub0);
364fe6060f1SDimitry Andric   auto Reg = Sub ? Sub : Op.getReg();
365fe6060f1SDimitry Andric   return Reg >= AMDGPU::AGPR0 && Reg <= AMDGPU::AGPR255;
366fe6060f1SDimitry Andric }
367fe6060f1SDimitry Andric 
decodeOperand_AVLdSt_Any(MCInst & Inst,unsigned Imm,AMDGPUDisassembler::OpWidthTy Opw,const MCDisassembler * Decoder)36881ad6265SDimitry Andric static DecodeStatus decodeOperand_AVLdSt_Any(MCInst &Inst, unsigned Imm,
369fe6060f1SDimitry Andric                                              AMDGPUDisassembler::OpWidthTy Opw,
37081ad6265SDimitry Andric                                              const MCDisassembler *Decoder) {
371fe6060f1SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder);
372fe6060f1SDimitry Andric   if (!DAsm->isGFX90A()) {
373fe6060f1SDimitry Andric     Imm &= 511;
374fe6060f1SDimitry Andric   } else {
375fe6060f1SDimitry Andric     // If atomic has both vdata and vdst their register classes are tied.
376fe6060f1SDimitry Andric     // The bit is decoded along with the vdst, first operand. We need to
377fe6060f1SDimitry Andric     // change register class to AGPR if vdst was AGPR.
378fe6060f1SDimitry Andric     // If a DS instruction has both data0 and data1 their register classes
379fe6060f1SDimitry Andric     // are also tied.
380fe6060f1SDimitry Andric     unsigned Opc = Inst.getOpcode();
381fe6060f1SDimitry Andric     uint64_t TSFlags = DAsm->getMCII()->get(Opc).TSFlags;
382fe6060f1SDimitry Andric     uint16_t DataNameIdx = (TSFlags & SIInstrFlags::DS) ? AMDGPU::OpName::data0
383fe6060f1SDimitry Andric                                                         : AMDGPU::OpName::vdata;
384fe6060f1SDimitry Andric     const MCRegisterInfo *MRI = DAsm->getContext().getRegisterInfo();
385fe6060f1SDimitry Andric     int DataIdx = AMDGPU::getNamedOperandIdx(Opc, DataNameIdx);
386fe6060f1SDimitry Andric     if ((int)Inst.getNumOperands() == DataIdx) {
387fe6060f1SDimitry Andric       int DstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
388fe6060f1SDimitry Andric       if (IsAGPROperand(Inst, DstIdx, MRI))
389fe6060f1SDimitry Andric         Imm |= 512;
390fe6060f1SDimitry Andric     }
391fe6060f1SDimitry Andric 
392fe6060f1SDimitry Andric     if (TSFlags & SIInstrFlags::DS) {
393fe6060f1SDimitry Andric       int Data2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
394fe6060f1SDimitry Andric       if ((int)Inst.getNumOperands() == Data2Idx &&
395fe6060f1SDimitry Andric           IsAGPROperand(Inst, DataIdx, MRI))
396fe6060f1SDimitry Andric         Imm |= 512;
397fe6060f1SDimitry Andric     }
398fe6060f1SDimitry Andric   }
399fe6060f1SDimitry Andric   return addOperand(Inst, DAsm->decodeSrcOp(Opw, Imm | 256));
400fe6060f1SDimitry Andric }
401fe6060f1SDimitry Andric 
decodeOperand_VSrc_f64(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)402c9157d92SDimitry Andric static DecodeStatus decodeOperand_VSrc_f64(MCInst &Inst, unsigned Imm,
403c9157d92SDimitry Andric                                            uint64_t Addr,
404c9157d92SDimitry Andric                                            const MCDisassembler *Decoder) {
405c9157d92SDimitry Andric   assert(Imm < (1 << 9) && "9-bit encoding");
406c9157d92SDimitry Andric   auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
407c9157d92SDimitry Andric   return addOperand(
408c9157d92SDimitry Andric       Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW64, Imm, false, 64, true));
409c9157d92SDimitry Andric }
410c9157d92SDimitry Andric 
41181ad6265SDimitry Andric static DecodeStatus
DecodeAVLdSt_32RegisterClass(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)41281ad6265SDimitry Andric DecodeAVLdSt_32RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr,
41381ad6265SDimitry Andric                              const MCDisassembler *Decoder) {
414fe6060f1SDimitry Andric   return decodeOperand_AVLdSt_Any(Inst, Imm,
415fe6060f1SDimitry Andric                                   AMDGPUDisassembler::OPW32, Decoder);
416fe6060f1SDimitry Andric }
417fe6060f1SDimitry Andric 
41881ad6265SDimitry Andric static DecodeStatus
DecodeAVLdSt_64RegisterClass(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)41981ad6265SDimitry Andric DecodeAVLdSt_64RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr,
42081ad6265SDimitry Andric                              const MCDisassembler *Decoder) {
421fe6060f1SDimitry Andric   return decodeOperand_AVLdSt_Any(Inst, Imm,
422fe6060f1SDimitry Andric                                   AMDGPUDisassembler::OPW64, Decoder);
423fe6060f1SDimitry Andric }
424fe6060f1SDimitry Andric 
42581ad6265SDimitry Andric static DecodeStatus
DecodeAVLdSt_96RegisterClass(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)42681ad6265SDimitry Andric DecodeAVLdSt_96RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr,
42781ad6265SDimitry Andric                              const MCDisassembler *Decoder) {
428fe6060f1SDimitry Andric   return decodeOperand_AVLdSt_Any(Inst, Imm,
429fe6060f1SDimitry Andric                                   AMDGPUDisassembler::OPW96, Decoder);
430fe6060f1SDimitry Andric }
431fe6060f1SDimitry Andric 
43281ad6265SDimitry Andric static DecodeStatus
DecodeAVLdSt_128RegisterClass(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)43381ad6265SDimitry Andric DecodeAVLdSt_128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr,
43481ad6265SDimitry Andric                               const MCDisassembler *Decoder) {
435fe6060f1SDimitry Andric   return decodeOperand_AVLdSt_Any(Inst, Imm,
436fe6060f1SDimitry Andric                                   AMDGPUDisassembler::OPW128, Decoder);
437fe6060f1SDimitry Andric }
438fe6060f1SDimitry Andric 
439bdd1243dSDimitry Andric static DecodeStatus
DecodeAVLdSt_160RegisterClass(MCInst & Inst,unsigned Imm,uint64_t Addr,const MCDisassembler * Decoder)440bdd1243dSDimitry Andric DecodeAVLdSt_160RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr,
441bdd1243dSDimitry Andric                               const MCDisassembler *Decoder) {
442bdd1243dSDimitry Andric   return decodeOperand_AVLdSt_Any(Inst, Imm, AMDGPUDisassembler::OPW160,
443bdd1243dSDimitry Andric                                   Decoder);
444bdd1243dSDimitry Andric }
445bdd1243dSDimitry Andric 
4460b57cec5SDimitry Andric #define DECODE_SDWA(DecName) \
4470b57cec5SDimitry Andric DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric DECODE_SDWA(Src32)
DECODE_SDWA(Src16)4500b57cec5SDimitry Andric DECODE_SDWA(Src16)
4510b57cec5SDimitry Andric DECODE_SDWA(VopcDst)
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric #include "AMDGPUGenDisassemblerTables.inc"
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4560b57cec5SDimitry Andric //
4570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
4600b57cec5SDimitry Andric   assert(Bytes.size() >= sizeof(T));
461c9157d92SDimitry Andric   const auto Res =
462c9157d92SDimitry Andric       support::endian::read<T, llvm::endianness::little>(Bytes.data());
4630b57cec5SDimitry Andric   Bytes = Bytes.slice(sizeof(T));
4640b57cec5SDimitry Andric   return Res;
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
eat12Bytes(ArrayRef<uint8_t> & Bytes)46781ad6265SDimitry Andric static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) {
46881ad6265SDimitry Andric   assert(Bytes.size() >= 12);
469c9157d92SDimitry Andric   uint64_t Lo =
470c9157d92SDimitry Andric       support::endian::read<uint64_t, llvm::endianness::little>(Bytes.data());
47181ad6265SDimitry Andric   Bytes = Bytes.slice(8);
472c9157d92SDimitry Andric   uint64_t Hi =
473c9157d92SDimitry Andric       support::endian::read<uint32_t, llvm::endianness::little>(Bytes.data());
47481ad6265SDimitry Andric   Bytes = Bytes.slice(4);
47581ad6265SDimitry Andric   return DecoderUInt128(Lo, Hi);
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
478fe6060f1SDimitry Andric // The disassembler is greedy, so we need to check FI operand value to
479fe6060f1SDimitry Andric // not parse a dpp if the correct literal is not set. For dpp16 the
480fe6060f1SDimitry Andric // autogenerated decoder checks the dpp literal
isValidDPP8(const MCInst & MI)4810b57cec5SDimitry Andric static bool isValidDPP8(const MCInst &MI) {
4820b57cec5SDimitry Andric   using namespace llvm::AMDGPU::DPP;
4830b57cec5SDimitry Andric   int FiIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::fi);
4840b57cec5SDimitry Andric   assert(FiIdx != -1);
4850b57cec5SDimitry Andric   if ((unsigned)FiIdx >= MI.getNumOperands())
4860b57cec5SDimitry Andric     return false;
4870b57cec5SDimitry Andric   unsigned Fi = MI.getOperand(FiIdx).getImm();
4880b57cec5SDimitry Andric   return Fi == DPP8_FI_0 || Fi == DPP8_FI_1;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes_,uint64_t Address,raw_ostream & CS) const4910b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
4920b57cec5SDimitry Andric                                                 ArrayRef<uint8_t> Bytes_,
4930b57cec5SDimitry Andric                                                 uint64_t Address,
4940b57cec5SDimitry Andric                                                 raw_ostream &CS) const {
4950b57cec5SDimitry Andric   bool IsSDWA = false;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   unsigned MaxInstBytesNum = std::min((size_t)TargetMaxInstBytes, Bytes_.size());
4980b57cec5SDimitry Andric   Bytes = Bytes_.slice(0, MaxInstBytesNum);
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   DecodeStatus Res = MCDisassembler::Fail;
5010b57cec5SDimitry Andric   do {
5020b57cec5SDimitry Andric     // ToDo: better to switch encoding length using some bit predicate
5030b57cec5SDimitry Andric     // but it is unknown yet, so try all we can
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric     // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
5060b57cec5SDimitry Andric     // encodings
50781ad6265SDimitry Andric     if (isGFX11Plus() && Bytes.size() >= 12 ) {
50881ad6265SDimitry Andric       DecoderUInt128 DecW = eat12Bytes(Bytes);
509c9157d92SDimitry Andric       Res =
510c9157d92SDimitry Andric           tryDecodeInst(DecoderTableDPP8GFX1196, DecoderTableDPP8GFX11_FAKE1696,
511c9157d92SDimitry Andric                         MI, DecW, Address, CS);
51281ad6265SDimitry Andric       if (Res && convertDPP8Inst(MI) == MCDisassembler::Success)
51381ad6265SDimitry Andric         break;
51481ad6265SDimitry Andric       MI = MCInst(); // clear
515c9157d92SDimitry Andric       Res =
516c9157d92SDimitry Andric           tryDecodeInst(DecoderTableDPP8GFX1296, DecoderTableDPP8GFX12_FAKE1696,
517c9157d92SDimitry Andric                         MI, DecW, Address, CS);
518c9157d92SDimitry Andric       if (Res && convertDPP8Inst(MI) == MCDisassembler::Success)
519c9157d92SDimitry Andric         break;
520c9157d92SDimitry Andric       MI = MCInst(); // clear
521c9157d92SDimitry Andric 
522c9157d92SDimitry Andric       const auto convertVOPDPP = [&]() {
523c9157d92SDimitry Andric         if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3P) {
52481ad6265SDimitry Andric           convertVOP3PDPPInst(MI);
525c9157d92SDimitry Andric         } else if (AMDGPU::isVOPC64DPP(MI.getOpcode())) {
526fcaf7f86SDimitry Andric           convertVOPCDPPInst(MI); // Special VOP3 case
527c9157d92SDimitry Andric         } else {
528fcaf7f86SDimitry Andric           assert(MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3);
529fcaf7f86SDimitry Andric           convertVOP3DPPInst(MI); // Regular VOP3 case
530fcaf7f86SDimitry Andric         }
531c9157d92SDimitry Andric       };
532c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPPGFX1196, DecoderTableDPPGFX11_FAKE1696,
533c9157d92SDimitry Andric                           MI, DecW, Address, CS);
534c9157d92SDimitry Andric       if (Res) {
535c9157d92SDimitry Andric         convertVOPDPP();
536c9157d92SDimitry Andric         break;
537c9157d92SDimitry Andric       }
538c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPPGFX1296, DecoderTableDPPGFX12_FAKE1696,
539c9157d92SDimitry Andric                           MI, DecW, Address, CS);
540c9157d92SDimitry Andric       if (Res) {
541c9157d92SDimitry Andric         convertVOPDPP();
54281ad6265SDimitry Andric         break;
54381ad6265SDimitry Andric       }
544fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX1196, MI, DecW, Address, CS);
54581ad6265SDimitry Andric       if (Res)
54681ad6265SDimitry Andric         break;
547c9157d92SDimitry Andric 
548c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX1296, MI, DecW, Address, CS);
549c9157d92SDimitry Andric       if (Res)
550c9157d92SDimitry Andric         break;
551a58f00eaSDimitry Andric 
552a58f00eaSDimitry Andric       Res = tryDecodeInst(DecoderTableGFX12W6496, MI, DecW, Address, CS);
553a58f00eaSDimitry Andric       if (Res)
554a58f00eaSDimitry Andric         break;
55581ad6265SDimitry Andric     }
55681ad6265SDimitry Andric     // Reinitialize Bytes
55781ad6265SDimitry Andric     Bytes = Bytes_.slice(0, MaxInstBytesNum);
55881ad6265SDimitry Andric 
5590b57cec5SDimitry Andric     if (Bytes.size() >= 8) {
5600b57cec5SDimitry Andric       const uint64_t QW = eatBytes<uint64_t>(Bytes);
5610b57cec5SDimitry Andric 
562fe013be4SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding)) {
563fe013be4SDimitry Andric         Res = tryDecodeInst(DecoderTableGFX10_B64, MI, QW, Address, CS);
5645ffd83dbSDimitry Andric         if (Res) {
5655ffd83dbSDimitry Andric           if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dpp8)
5665ffd83dbSDimitry Andric               == -1)
5675ffd83dbSDimitry Andric             break;
5685ffd83dbSDimitry Andric           if (convertDPP8Inst(MI) == MCDisassembler::Success)
5695ffd83dbSDimitry Andric             break;
5705ffd83dbSDimitry Andric           MI = MCInst(); // clear
5715ffd83dbSDimitry Andric         }
5725ffd83dbSDimitry Andric       }
5735ffd83dbSDimitry Andric 
574fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableDPP864, MI, QW, Address, CS);
5750b57cec5SDimitry Andric       if (Res && convertDPP8Inst(MI) == MCDisassembler::Success)
5760b57cec5SDimitry Andric         break;
57781ad6265SDimitry Andric       MI = MCInst(); // clear
5780b57cec5SDimitry Andric 
579c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPP8GFX1164,
580c9157d92SDimitry Andric                           DecoderTableDPP8GFX11_FAKE1664, MI, QW, Address, CS);
581c9157d92SDimitry Andric       if (Res && convertDPP8Inst(MI) == MCDisassembler::Success)
582c9157d92SDimitry Andric         break;
583c9157d92SDimitry Andric       MI = MCInst(); // clear
584c9157d92SDimitry Andric 
585c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPP8GFX1264,
586c9157d92SDimitry Andric                           DecoderTableDPP8GFX12_FAKE1664, MI, QW, Address, CS);
58781ad6265SDimitry Andric       if (Res && convertDPP8Inst(MI) == MCDisassembler::Success)
58881ad6265SDimitry Andric         break;
5890b57cec5SDimitry Andric       MI = MCInst(); // clear
5900b57cec5SDimitry Andric 
591fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address, CS);
5920b57cec5SDimitry Andric       if (Res) break;
5930b57cec5SDimitry Andric 
594c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPPGFX1164, DecoderTableDPPGFX11_FAKE1664,
595c9157d92SDimitry Andric                           MI, QW, Address, CS);
596c9157d92SDimitry Andric       if (Res) {
597c9157d92SDimitry Andric         if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC)
598c9157d92SDimitry Andric           convertVOPCDPPInst(MI);
599c9157d92SDimitry Andric         break;
600c9157d92SDimitry Andric       }
601c9157d92SDimitry Andric 
602c9157d92SDimitry Andric       Res = tryDecodeInst(DecoderTableDPPGFX1264, DecoderTableDPPGFX12_FAKE1664,
603c9157d92SDimitry Andric                           MI, QW, Address, CS);
60481ad6265SDimitry Andric       if (Res) {
60581ad6265SDimitry Andric         if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC)
60681ad6265SDimitry Andric           convertVOPCDPPInst(MI);
60781ad6265SDimitry Andric         break;
60881ad6265SDimitry Andric       }
60981ad6265SDimitry Andric 
610fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address, CS);
6110b57cec5SDimitry Andric       if (Res) { IsSDWA = true;  break; }
6120b57cec5SDimitry Andric 
613fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableSDWA964, MI, QW, Address, CS);
6140b57cec5SDimitry Andric       if (Res) { IsSDWA = true;  break; }
6150b57cec5SDimitry Andric 
616fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableSDWA1064, MI, QW, Address, CS);
6170b57cec5SDimitry Andric       if (Res) { IsSDWA = true;  break; }
6180b57cec5SDimitry Andric 
619fe013be4SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem)) {
620fe013be4SDimitry Andric         Res = tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address, CS);
6210b57cec5SDimitry Andric         if (Res)
6220b57cec5SDimitry Andric           break;
6230b57cec5SDimitry Andric       }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric       // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and
6260b57cec5SDimitry Andric       // v_mad_mixhi_f16 for FMA variants. Try to decode using this special
6270b57cec5SDimitry Andric       // table first so we print the correct name.
628fe013be4SDimitry Andric       if (STI.hasFeature(AMDGPU::FeatureFmaMixInsts)) {
629fe013be4SDimitry Andric         Res = tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address, CS);
6300b57cec5SDimitry Andric         if (Res)
6310b57cec5SDimitry Andric           break;
6320b57cec5SDimitry Andric       }
6330b57cec5SDimitry Andric     }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     // Reinitialize Bytes as DPP64 could have eaten too much
6360b57cec5SDimitry Andric     Bytes = Bytes_.slice(0, MaxInstBytesNum);
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric     // Try decode 32-bit instruction
6390b57cec5SDimitry Andric     if (Bytes.size() < 4) break;
6400b57cec5SDimitry Andric     const uint32_t DW = eatBytes<uint32_t>(Bytes);
641fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX832, MI, DW, Address, CS);
6420b57cec5SDimitry Andric     if (Res) break;
6430b57cec5SDimitry Andric 
644fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address, CS);
6450b57cec5SDimitry Andric     if (Res) break;
6460b57cec5SDimitry Andric 
647fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX932, MI, DW, Address, CS);
6480b57cec5SDimitry Andric     if (Res) break;
6490b57cec5SDimitry Andric 
650fe013be4SDimitry Andric     if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts)) {
651fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX90A32, MI, DW, Address, CS);
652fe6060f1SDimitry Andric       if (Res)
653fe6060f1SDimitry Andric         break;
654fe6060f1SDimitry Andric     }
655fe6060f1SDimitry Andric 
656fe013be4SDimitry Andric     if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding)) {
657fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX10_B32, MI, DW, Address, CS);
6585ffd83dbSDimitry Andric       if (Res) break;
6595ffd83dbSDimitry Andric     }
6605ffd83dbSDimitry Andric 
661fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1032, MI, DW, Address, CS);
6620b57cec5SDimitry Andric     if (Res) break;
6630b57cec5SDimitry Andric 
664c9157d92SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1132, DecoderTableGFX11_FAKE1632, MI, DW,
665c9157d92SDimitry Andric                         Address, CS);
66681ad6265SDimitry Andric     if (Res) break;
66781ad6265SDimitry Andric 
668c9157d92SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1232, DecoderTableGFX12_FAKE1632, MI, DW,
669c9157d92SDimitry Andric                         Address, CS);
670c9157d92SDimitry Andric     if (Res)
671c9157d92SDimitry Andric       break;
672c9157d92SDimitry Andric 
6730b57cec5SDimitry Andric     if (Bytes.size() < 4) break;
6740b57cec5SDimitry Andric     const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW;
675fe6060f1SDimitry Andric 
676fe013be4SDimitry Andric     if (STI.hasFeature(AMDGPU::FeatureGFX940Insts)) {
677fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX94064, MI, QW, Address, CS);
678bdd1243dSDimitry Andric       if (Res)
679bdd1243dSDimitry Andric         break;
680bdd1243dSDimitry Andric     }
681bdd1243dSDimitry Andric 
682fe013be4SDimitry Andric     if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts)) {
683fe013be4SDimitry Andric       Res = tryDecodeInst(DecoderTableGFX90A64, MI, QW, Address, CS);
684fe6060f1SDimitry Andric       if (Res)
685fe6060f1SDimitry Andric         break;
686fe6060f1SDimitry Andric     }
687fe6060f1SDimitry Andric 
688fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX864, MI, QW, Address, CS);
6890b57cec5SDimitry Andric     if (Res) break;
6900b57cec5SDimitry Andric 
691fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableAMDGPU64, MI, QW, Address, CS);
6920b57cec5SDimitry Andric     if (Res) break;
6930b57cec5SDimitry Andric 
694fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX964, MI, QW, Address, CS);
6950b57cec5SDimitry Andric     if (Res) break;
6960b57cec5SDimitry Andric 
697fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1064, MI, QW, Address, CS);
69881ad6265SDimitry Andric     if (Res) break;
69981ad6265SDimitry Andric 
700c9157d92SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1264, DecoderTableGFX12_FAKE1664, MI, QW,
701c9157d92SDimitry Andric                         Address, CS);
702c9157d92SDimitry Andric     if (Res)
703c9157d92SDimitry Andric       break;
704c9157d92SDimitry Andric 
705c9157d92SDimitry Andric     Res = tryDecodeInst(DecoderTableGFX1164, DecoderTableGFX11_FAKE1664, MI, QW,
706c9157d92SDimitry Andric                         Address, CS);
70781ad6265SDimitry Andric     if (Res)
70881ad6265SDimitry Andric       break;
70981ad6265SDimitry Andric 
710fe013be4SDimitry Andric     Res = tryDecodeInst(DecoderTableWMMAGFX1164, MI, QW, Address, CS);
711*b9d9368bSDimitry Andric     if (Res)
712*b9d9368bSDimitry Andric       break;
713*b9d9368bSDimitry Andric 
714*b9d9368bSDimitry Andric     Res = tryDecodeInst(DecoderTableWMMAGFX1264, MI, QW, Address, CS);
7150b57cec5SDimitry Andric   } while (false);
7160b57cec5SDimitry Andric 
717bdd1243dSDimitry Andric   if (Res && AMDGPU::isMAC(MI.getOpcode())) {
7180b57cec5SDimitry Andric     // Insert dummy unused src2_modifiers.
7190b57cec5SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
7200b57cec5SDimitry Andric                          AMDGPU::OpName::src2_modifiers);
7210b57cec5SDimitry Andric   }
7220b57cec5SDimitry Andric 
723*b9d9368bSDimitry Andric   if (Res && (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp ||
724*b9d9368bSDimitry Andric               MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp)) {
725*b9d9368bSDimitry Andric     // Insert dummy unused src2_modifiers.
726*b9d9368bSDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
727*b9d9368bSDimitry Andric                          AMDGPU::OpName::src2_modifiers);
728*b9d9368bSDimitry Andric   }
729*b9d9368bSDimitry Andric 
730e710425bSDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DS) &&
731e710425bSDimitry Andric       !AMDGPU::hasGDS(STI)) {
732e710425bSDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::gds);
733e710425bSDimitry Andric   }
734e710425bSDimitry Andric 
735e8d8bef9SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags &
736fe6060f1SDimitry Andric           (SIInstrFlags::MUBUF | SIInstrFlags::FLAT | SIInstrFlags::SMRD))) {
737fe6060f1SDimitry Andric     int CPolPos = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
738fe6060f1SDimitry Andric                                              AMDGPU::OpName::cpol);
739fe6060f1SDimitry Andric     if (CPolPos != -1) {
740fe6060f1SDimitry Andric       unsigned CPol =
741fe6060f1SDimitry Andric           (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsAtomicRet) ?
742fe6060f1SDimitry Andric               AMDGPU::CPol::GLC : 0;
743fe6060f1SDimitry Andric       if (MI.getNumOperands() <= (unsigned)CPolPos) {
744fe6060f1SDimitry Andric         insertNamedMCOperand(MI, MCOperand::createImm(CPol),
745fe6060f1SDimitry Andric                              AMDGPU::OpName::cpol);
746fe6060f1SDimitry Andric       } else if (CPol) {
747fe6060f1SDimitry Andric         MI.getOperand(CPolPos).setImm(MI.getOperand(CPolPos).getImm() | CPol);
748fe6060f1SDimitry Andric       }
749fe6060f1SDimitry Andric     }
750fe6060f1SDimitry Andric   }
751fe6060f1SDimitry Andric 
752fe6060f1SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags &
753fe6060f1SDimitry Andric               (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) &&
754fe013be4SDimitry Andric              (STI.hasFeature(AMDGPU::FeatureGFX90AInsts))) {
755fe6060f1SDimitry Andric     // GFX90A lost TFE, its place is occupied by ACC.
756fe6060f1SDimitry Andric     int TFEOpIdx =
757fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe);
758fe6060f1SDimitry Andric     if (TFEOpIdx != -1) {
759fe6060f1SDimitry Andric       auto TFEIter = MI.begin();
760fe6060f1SDimitry Andric       std::advance(TFEIter, TFEOpIdx);
761fe6060f1SDimitry Andric       MI.insert(TFEIter, MCOperand::createImm(0));
762fe6060f1SDimitry Andric     }
763fe6060f1SDimitry Andric   }
764fe6060f1SDimitry Andric 
765fe6060f1SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags &
766fe6060f1SDimitry Andric               (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF))) {
767fe6060f1SDimitry Andric     int SWZOpIdx =
768fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::swz);
769fe6060f1SDimitry Andric     if (SWZOpIdx != -1) {
770fe6060f1SDimitry Andric       auto SWZIter = MI.begin();
771fe6060f1SDimitry Andric       std::advance(SWZIter, SWZOpIdx);
772fe6060f1SDimitry Andric       MI.insert(SWZIter, MCOperand::createImm(0));
773fe6060f1SDimitry Andric     }
774e8d8bef9SDimitry Andric   }
775e8d8bef9SDimitry Andric 
7760b57cec5SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::MIMG)) {
7770b57cec5SDimitry Andric     int VAddr0Idx =
7780b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
7790b57cec5SDimitry Andric     int RsrcIdx =
7800b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
7810b57cec5SDimitry Andric     unsigned NSAArgs = RsrcIdx - VAddr0Idx - 1;
7820b57cec5SDimitry Andric     if (VAddr0Idx >= 0 && NSAArgs > 0) {
7830b57cec5SDimitry Andric       unsigned NSAWords = (NSAArgs + 3) / 4;
7840b57cec5SDimitry Andric       if (Bytes.size() < 4 * NSAWords) {
7850b57cec5SDimitry Andric         Res = MCDisassembler::Fail;
7860b57cec5SDimitry Andric       } else {
7870b57cec5SDimitry Andric         for (unsigned i = 0; i < NSAArgs; ++i) {
78881ad6265SDimitry Andric           const unsigned VAddrIdx = VAddr0Idx + 1 + i;
789bdd1243dSDimitry Andric           auto VAddrRCID =
790bdd1243dSDimitry Andric               MCII->get(MI.getOpcode()).operands()[VAddrIdx].RegClass;
79181ad6265SDimitry Andric           MI.insert(MI.begin() + VAddrIdx,
79281ad6265SDimitry Andric                     createRegOperand(VAddrRCID, Bytes[i]));
7930b57cec5SDimitry Andric         }
7940b57cec5SDimitry Andric         Bytes = Bytes.slice(4 * NSAWords);
7950b57cec5SDimitry Andric       }
7960b57cec5SDimitry Andric     }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric     if (Res)
7990b57cec5SDimitry Andric       Res = convertMIMGInst(MI);
8000b57cec5SDimitry Andric   }
8010b57cec5SDimitry Andric 
802c9157d92SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags &
803c9157d92SDimitry Andric               (SIInstrFlags::VIMAGE | SIInstrFlags::VSAMPLE)))
804c9157d92SDimitry Andric     Res = convertMIMGInst(MI);
805c9157d92SDimitry Andric 
80681ad6265SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::EXP))
80781ad6265SDimitry Andric     Res = convertEXPInst(MI);
80881ad6265SDimitry Andric 
80981ad6265SDimitry Andric   if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VINTERP))
81081ad6265SDimitry Andric     Res = convertVINTERPInst(MI);
81181ad6265SDimitry Andric 
8120b57cec5SDimitry Andric   if (Res && IsSDWA)
8130b57cec5SDimitry Andric     Res = convertSDWAInst(MI);
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric   int VDstIn_Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
8160b57cec5SDimitry Andric                                               AMDGPU::OpName::vdst_in);
8170b57cec5SDimitry Andric   if (VDstIn_Idx != -1) {
8180b57cec5SDimitry Andric     int Tied = MCII->get(MI.getOpcode()).getOperandConstraint(VDstIn_Idx,
8190b57cec5SDimitry Andric                            MCOI::OperandConstraint::TIED_TO);
8200b57cec5SDimitry Andric     if (Tied != -1 && (MI.getNumOperands() <= (unsigned)VDstIn_Idx ||
8210b57cec5SDimitry Andric          !MI.getOperand(VDstIn_Idx).isReg() ||
8220b57cec5SDimitry Andric          MI.getOperand(VDstIn_Idx).getReg() != MI.getOperand(Tied).getReg())) {
8230b57cec5SDimitry Andric       if (MI.getNumOperands() > (unsigned)VDstIn_Idx)
8240b57cec5SDimitry Andric         MI.erase(&MI.getOperand(VDstIn_Idx));
8250b57cec5SDimitry Andric       insertNamedMCOperand(MI,
8260b57cec5SDimitry Andric         MCOperand::createReg(MI.getOperand(Tied).getReg()),
8270b57cec5SDimitry Andric         AMDGPU::OpName::vdst_in);
8280b57cec5SDimitry Andric     }
8290b57cec5SDimitry Andric   }
8300b57cec5SDimitry Andric 
831349cc55cSDimitry Andric   int ImmLitIdx =
832349cc55cSDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::imm);
833bdd1243dSDimitry Andric   bool IsSOPK = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SOPK;
834bdd1243dSDimitry Andric   if (Res && ImmLitIdx != -1 && !IsSOPK)
835349cc55cSDimitry Andric     Res = convertFMAanyK(MI, ImmLitIdx);
836349cc55cSDimitry Andric 
8370b57cec5SDimitry Andric   // if the opcode was not recognized we'll assume a Size of 4 bytes
8380b57cec5SDimitry Andric   // (unless there are fewer bytes left)
8390b57cec5SDimitry Andric   Size = Res ? (MaxInstBytesNum - Bytes.size())
8400b57cec5SDimitry Andric              : std::min((size_t)4, Bytes_.size());
8410b57cec5SDimitry Andric   return Res;
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric 
convertEXPInst(MCInst & MI) const84481ad6265SDimitry Andric DecodeStatus AMDGPUDisassembler::convertEXPInst(MCInst &MI) const {
845c9157d92SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX11Insts)) {
84681ad6265SDimitry Andric     // The MCInst still has these fields even though they are no longer encoded
84781ad6265SDimitry Andric     // in the GFX11 instruction.
84881ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vm);
84981ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::compr);
85081ad6265SDimitry Andric   }
85181ad6265SDimitry Andric   return MCDisassembler::Success;
85281ad6265SDimitry Andric }
85381ad6265SDimitry Andric 
convertVINTERPInst(MCInst & MI) const85481ad6265SDimitry Andric DecodeStatus AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const {
85581ad6265SDimitry Andric   if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx11 ||
856c9157d92SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx12 ||
85781ad6265SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx11 ||
858c9157d92SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx12 ||
85981ad6265SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx11 ||
860c9157d92SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx12 ||
861c9157d92SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx11 ||
862c9157d92SDimitry Andric       MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx12) {
86381ad6265SDimitry Andric     // The MCInst has this field that is not directly encoded in the
86481ad6265SDimitry Andric     // instruction.
86581ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::op_sel);
86681ad6265SDimitry Andric   }
86781ad6265SDimitry Andric   return MCDisassembler::Success;
86881ad6265SDimitry Andric }
86981ad6265SDimitry Andric 
convertSDWAInst(MCInst & MI) const8700b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
871fe013be4SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX9) ||
872fe013be4SDimitry Andric       STI.hasFeature(AMDGPU::FeatureGFX10)) {
873bdd1243dSDimitry Andric     if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::sdst))
8740b57cec5SDimitry Andric       // VOPC - insert clamp
8750b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);
876fe013be4SDimitry Andric   } else if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) {
8770b57cec5SDimitry Andric     int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);
8780b57cec5SDimitry Andric     if (SDst != -1) {
8790b57cec5SDimitry Andric       // VOPC - insert VCC register as sdst
8800b57cec5SDimitry Andric       insertNamedMCOperand(MI, createRegOperand(AMDGPU::VCC),
8810b57cec5SDimitry Andric                            AMDGPU::OpName::sdst);
8820b57cec5SDimitry Andric     } else {
8830b57cec5SDimitry Andric       // VOP1/2 - insert omod if present in instruction
8840b57cec5SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);
8850b57cec5SDimitry Andric     }
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric   return MCDisassembler::Success;
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
890fcaf7f86SDimitry Andric struct VOPModifiers {
891fcaf7f86SDimitry Andric   unsigned OpSel = 0;
892fcaf7f86SDimitry Andric   unsigned OpSelHi = 0;
893fcaf7f86SDimitry Andric   unsigned NegLo = 0;
894fcaf7f86SDimitry Andric   unsigned NegHi = 0;
895fcaf7f86SDimitry Andric };
896fcaf7f86SDimitry Andric 
897fcaf7f86SDimitry Andric // Reconstruct values of VOP3/VOP3P operands such as op_sel.
898fcaf7f86SDimitry Andric // Note that these values do not affect disassembler output,
899fcaf7f86SDimitry Andric // so this is only necessary for consistency with src_modifiers.
collectVOPModifiers(const MCInst & MI,bool IsVOP3P=false)900fcaf7f86SDimitry Andric static VOPModifiers collectVOPModifiers(const MCInst &MI,
901fcaf7f86SDimitry Andric                                         bool IsVOP3P = false) {
902fcaf7f86SDimitry Andric   VOPModifiers Modifiers;
903fcaf7f86SDimitry Andric   unsigned Opc = MI.getOpcode();
904fcaf7f86SDimitry Andric   const int ModOps[] = {AMDGPU::OpName::src0_modifiers,
905fcaf7f86SDimitry Andric                         AMDGPU::OpName::src1_modifiers,
906fcaf7f86SDimitry Andric                         AMDGPU::OpName::src2_modifiers};
907fcaf7f86SDimitry Andric   for (int J = 0; J < 3; ++J) {
908fcaf7f86SDimitry Andric     int OpIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);
909fcaf7f86SDimitry Andric     if (OpIdx == -1)
910fcaf7f86SDimitry Andric       continue;
911fcaf7f86SDimitry Andric 
912fcaf7f86SDimitry Andric     unsigned Val = MI.getOperand(OpIdx).getImm();
913fcaf7f86SDimitry Andric 
914fcaf7f86SDimitry Andric     Modifiers.OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J;
915fcaf7f86SDimitry Andric     if (IsVOP3P) {
916fcaf7f86SDimitry Andric       Modifiers.OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J;
917fcaf7f86SDimitry Andric       Modifiers.NegLo |= !!(Val & SISrcMods::NEG) << J;
918fcaf7f86SDimitry Andric       Modifiers.NegHi |= !!(Val & SISrcMods::NEG_HI) << J;
919fcaf7f86SDimitry Andric     } else if (J == 0) {
920fcaf7f86SDimitry Andric       Modifiers.OpSel |= !!(Val & SISrcMods::DST_OP_SEL) << 3;
921fcaf7f86SDimitry Andric     }
922fcaf7f86SDimitry Andric   }
923fcaf7f86SDimitry Andric 
924fcaf7f86SDimitry Andric   return Modifiers;
925fcaf7f86SDimitry Andric }
926fcaf7f86SDimitry Andric 
927bdd1243dSDimitry Andric // MAC opcodes have special old and src2 operands.
928bdd1243dSDimitry Andric // src2 is tied to dst, while old is not tied (but assumed to be).
isMacDPP(MCInst & MI) const929bdd1243dSDimitry Andric bool AMDGPUDisassembler::isMacDPP(MCInst &MI) const {
930bdd1243dSDimitry Andric   constexpr int DST_IDX = 0;
931bdd1243dSDimitry Andric   auto Opcode = MI.getOpcode();
932bdd1243dSDimitry Andric   const auto &Desc = MCII->get(Opcode);
933bdd1243dSDimitry Andric   auto OldIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::old);
934bdd1243dSDimitry Andric 
935bdd1243dSDimitry Andric   if (OldIdx != -1 && Desc.getOperandConstraint(
936bdd1243dSDimitry Andric                           OldIdx, MCOI::OperandConstraint::TIED_TO) == -1) {
937bdd1243dSDimitry Andric     assert(AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2));
938bdd1243dSDimitry Andric     assert(Desc.getOperandConstraint(
939bdd1243dSDimitry Andric                AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2),
940bdd1243dSDimitry Andric                MCOI::OperandConstraint::TIED_TO) == DST_IDX);
941bdd1243dSDimitry Andric     (void)DST_IDX;
942bdd1243dSDimitry Andric     return true;
943bdd1243dSDimitry Andric   }
944bdd1243dSDimitry Andric 
945bdd1243dSDimitry Andric   return false;
946bdd1243dSDimitry Andric }
947bdd1243dSDimitry Andric 
948bdd1243dSDimitry Andric // Create dummy old operand and insert dummy unused src2_modifiers
convertMacDPPInst(MCInst & MI) const949bdd1243dSDimitry Andric void AMDGPUDisassembler::convertMacDPPInst(MCInst &MI) const {
950bdd1243dSDimitry Andric   assert(MI.getNumOperands() + 1 < MCII->get(MI.getOpcode()).getNumOperands());
951bdd1243dSDimitry Andric   insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);
952bdd1243dSDimitry Andric   insertNamedMCOperand(MI, MCOperand::createImm(0),
953bdd1243dSDimitry Andric                        AMDGPU::OpName::src2_modifiers);
954bdd1243dSDimitry Andric }
955bdd1243dSDimitry Andric 
956fe6060f1SDimitry Andric // We must check FI == literal to reject not genuine dpp8 insts, and we must
957fe6060f1SDimitry Andric // first add optional MI operands to check FI
convertDPP8Inst(MCInst & MI) const9580b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const {
9590b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
960*b9d9368bSDimitry Andric 
96181ad6265SDimitry Andric   if (MCII->get(Opc).TSFlags & SIInstrFlags::VOP3P) {
96281ad6265SDimitry Andric     convertVOP3PDPPInst(MI);
96381ad6265SDimitry Andric   } else if ((MCII->get(Opc).TSFlags & SIInstrFlags::VOPC) ||
96481ad6265SDimitry Andric              AMDGPU::isVOPC64DPP(Opc)) {
96581ad6265SDimitry Andric     convertVOPCDPPInst(MI);
966bdd1243dSDimitry Andric   } else {
967bdd1243dSDimitry Andric     if (isMacDPP(MI))
968bdd1243dSDimitry Andric       convertMacDPPInst(MI);
969bdd1243dSDimitry Andric 
970*b9d9368bSDimitry Andric     int VDstInIdx =
971*b9d9368bSDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);
972*b9d9368bSDimitry Andric     if (VDstInIdx != -1)
973*b9d9368bSDimitry Andric       insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);
974*b9d9368bSDimitry Andric 
975*b9d9368bSDimitry Andric     if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp8_gfx12 ||
976*b9d9368bSDimitry Andric         MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp8_gfx12)
977*b9d9368bSDimitry Andric       insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::src2);
978*b9d9368bSDimitry Andric 
979bdd1243dSDimitry Andric     unsigned DescNumOps = MCII->get(Opc).getNumOperands();
980bdd1243dSDimitry Andric     if (MI.getNumOperands() < DescNumOps &&
981bdd1243dSDimitry Andric         AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
982fcaf7f86SDimitry Andric       auto Mods = collectVOPModifiers(MI);
983fcaf7f86SDimitry Andric       insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
984fcaf7f86SDimitry Andric                            AMDGPU::OpName::op_sel);
98581ad6265SDimitry Andric     } else {
9860b57cec5SDimitry Andric       // Insert dummy unused src modifiers.
9870b57cec5SDimitry Andric       if (MI.getNumOperands() < DescNumOps &&
988bdd1243dSDimitry Andric           AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))
9890b57cec5SDimitry Andric         insertNamedMCOperand(MI, MCOperand::createImm(0),
9900b57cec5SDimitry Andric                              AMDGPU::OpName::src0_modifiers);
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric       if (MI.getNumOperands() < DescNumOps &&
993bdd1243dSDimitry Andric           AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))
9940b57cec5SDimitry Andric         insertNamedMCOperand(MI, MCOperand::createImm(0),
9950b57cec5SDimitry Andric                              AMDGPU::OpName::src1_modifiers);
99681ad6265SDimitry Andric     }
997bdd1243dSDimitry Andric   }
9980b57cec5SDimitry Andric   return isValidDPP8(MI) ? MCDisassembler::Success : MCDisassembler::SoftFail;
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric 
convertVOP3DPPInst(MCInst & MI) const1001fcaf7f86SDimitry Andric DecodeStatus AMDGPUDisassembler::convertVOP3DPPInst(MCInst &MI) const {
1002bdd1243dSDimitry Andric   if (isMacDPP(MI))
1003bdd1243dSDimitry Andric     convertMacDPPInst(MI);
1004bdd1243dSDimitry Andric 
1005*b9d9368bSDimitry Andric   int VDstInIdx =
1006*b9d9368bSDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);
1007*b9d9368bSDimitry Andric   if (VDstInIdx != -1)
1008*b9d9368bSDimitry Andric     insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);
1009*b9d9368bSDimitry Andric 
1010*b9d9368bSDimitry Andric   if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp_gfx12 ||
1011*b9d9368bSDimitry Andric       MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp_gfx12)
1012*b9d9368bSDimitry Andric     insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::src2);
1013*b9d9368bSDimitry Andric 
1014fcaf7f86SDimitry Andric   unsigned Opc = MI.getOpcode();
1015fcaf7f86SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
1016fcaf7f86SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1017bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {
1018fcaf7f86SDimitry Andric     auto Mods = collectVOPModifiers(MI);
1019fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
1020fcaf7f86SDimitry Andric                          AMDGPU::OpName::op_sel);
1021fcaf7f86SDimitry Andric   }
1022fcaf7f86SDimitry Andric   return MCDisassembler::Success;
1023fcaf7f86SDimitry Andric }
1024fcaf7f86SDimitry Andric 
10250b57cec5SDimitry Andric // Note that before gfx10, the MIMG encoding provided no information about
10260b57cec5SDimitry Andric // VADDR size. Consequently, decoded instructions always show address as if it
10270b57cec5SDimitry Andric // has 1 dword, which could be not really so.
convertMIMGInst(MCInst & MI) const10280b57cec5SDimitry Andric DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
1029c9157d92SDimitry Andric   auto TSFlags = MCII->get(MI.getOpcode()).TSFlags;
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric   int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
10320b57cec5SDimitry Andric                                            AMDGPU::OpName::vdst);
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
10350b57cec5SDimitry Andric                                             AMDGPU::OpName::vdata);
10360b57cec5SDimitry Andric   int VAddr0Idx =
10370b57cec5SDimitry Andric       AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);
1038c9157d92SDimitry Andric   int RsrcOpName = TSFlags & SIInstrFlags::MIMG ? AMDGPU::OpName::srsrc
1039c9157d92SDimitry Andric                                                 : AMDGPU::OpName::rsrc;
1040c9157d92SDimitry Andric   int RsrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), RsrcOpName);
10410b57cec5SDimitry Andric   int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
10420b57cec5SDimitry Andric                                             AMDGPU::OpName::dmask);
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   int TFEIdx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
10450b57cec5SDimitry Andric                                             AMDGPU::OpName::tfe);
10460b57cec5SDimitry Andric   int D16Idx   = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
10470b57cec5SDimitry Andric                                             AMDGPU::OpName::d16);
10480b57cec5SDimitry Andric 
1049349cc55cSDimitry Andric   const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());
1050349cc55cSDimitry Andric   const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
1051349cc55cSDimitry Andric       AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
1052349cc55cSDimitry Andric 
10530b57cec5SDimitry Andric   assert(VDataIdx != -1);
1054349cc55cSDimitry Andric   if (BaseOpcode->BVH) {
1055349cc55cSDimitry Andric     // Add A16 operand for intersect_ray instructions
1056fe013be4SDimitry Andric     addOperand(MI, MCOperand::createImm(BaseOpcode->A16));
1057e8d8bef9SDimitry Andric     return MCDisassembler::Success;
1058e8d8bef9SDimitry Andric   }
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric   bool IsAtomic = (VDstIdx != -1);
1061c9157d92SDimitry Andric   bool IsGather4 = TSFlags & SIInstrFlags::Gather4;
1062c9157d92SDimitry Andric   bool IsVSample = TSFlags & SIInstrFlags::VSAMPLE;
10630b57cec5SDimitry Andric   bool IsNSA = false;
1064fe013be4SDimitry Andric   bool IsPartialNSA = false;
10650b57cec5SDimitry Andric   unsigned AddrSize = Info->VAddrDwords;
10660b57cec5SDimitry Andric 
106781ad6265SDimitry Andric   if (isGFX10Plus()) {
10680b57cec5SDimitry Andric     unsigned DimIdx =
10690b57cec5SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dim);
1070fe6060f1SDimitry Andric     int A16Idx =
1071fe6060f1SDimitry Andric         AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::a16);
10720b57cec5SDimitry Andric     const AMDGPU::MIMGDimInfo *Dim =
10730b57cec5SDimitry Andric         AMDGPU::getMIMGDimInfoByEncoding(MI.getOperand(DimIdx).getImm());
1074fe6060f1SDimitry Andric     const bool IsA16 = (A16Idx != -1 && MI.getOperand(A16Idx).getImm());
10750b57cec5SDimitry Andric 
1076fe6060f1SDimitry Andric     AddrSize =
1077fe6060f1SDimitry Andric         AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, AMDGPU::hasG16(STI));
1078fe6060f1SDimitry Andric 
1079c9157d92SDimitry Andric     // VSAMPLE insts that do not use vaddr3 behave the same as NSA forms.
1080c9157d92SDimitry Andric     // VIMAGE insts other than BVH never use vaddr4.
108181ad6265SDimitry Andric     IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA ||
1082c9157d92SDimitry Andric             Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA ||
1083c9157d92SDimitry Andric             Info->MIMGEncoding == AMDGPU::MIMGEncGfx12;
10840b57cec5SDimitry Andric     if (!IsNSA) {
1085c9157d92SDimitry Andric       if (!IsVSample && AddrSize > 12)
10860b57cec5SDimitry Andric         AddrSize = 16;
10870b57cec5SDimitry Andric     } else {
10880b57cec5SDimitry Andric       if (AddrSize > Info->VAddrDwords) {
1089fe013be4SDimitry Andric         if (!STI.hasFeature(AMDGPU::FeaturePartialNSAEncoding)) {
1090fe013be4SDimitry Andric           // The NSA encoding does not contain enough operands for the
1091fe013be4SDimitry Andric           // combination of base opcode / dimension. Should this be an error?
10920b57cec5SDimitry Andric           return MCDisassembler::Success;
10930b57cec5SDimitry Andric         }
1094fe013be4SDimitry Andric         IsPartialNSA = true;
1095fe013be4SDimitry Andric       }
10960b57cec5SDimitry Andric     }
10970b57cec5SDimitry Andric   }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;
1100bdd1243dSDimitry Andric   unsigned DstSize = IsGather4 ? 4 : std::max(llvm::popcount(DMask), 1);
11010b57cec5SDimitry Andric 
11020b57cec5SDimitry Andric   bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm();
11030b57cec5SDimitry Andric   if (D16 && AMDGPU::hasPackedD16(STI)) {
11040b57cec5SDimitry Andric     DstSize = (DstSize + 1) / 2;
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
1107fe6060f1SDimitry Andric   if (TFEIdx != -1 && MI.getOperand(TFEIdx).getImm())
1108e8d8bef9SDimitry Andric     DstSize += 1;
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   if (DstSize == Info->VDataDwords && AddrSize == Info->VAddrDwords)
11110b57cec5SDimitry Andric     return MCDisassembler::Success;
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric   int NewOpcode =
11140b57cec5SDimitry Andric       AMDGPU::getMIMGOpcode(Info->BaseOpcode, Info->MIMGEncoding, DstSize, AddrSize);
11150b57cec5SDimitry Andric   if (NewOpcode == -1)
11160b57cec5SDimitry Andric     return MCDisassembler::Success;
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric   // Widen the register to the correct number of enabled channels.
11190b57cec5SDimitry Andric   unsigned NewVdata = AMDGPU::NoRegister;
11200b57cec5SDimitry Andric   if (DstSize != Info->VDataDwords) {
1121bdd1243dSDimitry Andric     auto DataRCID = MCII->get(NewOpcode).operands()[VDataIdx].RegClass;
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric     // Get first subregister of VData
11240b57cec5SDimitry Andric     unsigned Vdata0 = MI.getOperand(VDataIdx).getReg();
11250b57cec5SDimitry Andric     unsigned VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0);
11260b57cec5SDimitry Andric     Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric     NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0,
11290b57cec5SDimitry Andric                                        &MRI.getRegClass(DataRCID));
11300b57cec5SDimitry Andric     if (NewVdata == AMDGPU::NoRegister) {
11310b57cec5SDimitry Andric       // It's possible to encode this such that the low register + enabled
11320b57cec5SDimitry Andric       // components exceeds the register count.
11330b57cec5SDimitry Andric       return MCDisassembler::Success;
11340b57cec5SDimitry Andric     }
11350b57cec5SDimitry Andric   }
11360b57cec5SDimitry Andric 
1137fe013be4SDimitry Andric   // If not using NSA on GFX10+, widen vaddr0 address register to correct size.
1138fe013be4SDimitry Andric   // If using partial NSA on GFX11+ widen last address register.
1139fe013be4SDimitry Andric   int VAddrSAIdx = IsPartialNSA ? (RsrcIdx - 1) : VAddr0Idx;
1140fe013be4SDimitry Andric   unsigned NewVAddrSA = AMDGPU::NoRegister;
1141fe013be4SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureNSAEncoding) && (!IsNSA || IsPartialNSA) &&
1142fe013be4SDimitry Andric       AddrSize != Info->VAddrDwords) {
1143fe013be4SDimitry Andric     unsigned VAddrSA = MI.getOperand(VAddrSAIdx).getReg();
1144fe013be4SDimitry Andric     unsigned VAddrSubSA = MRI.getSubReg(VAddrSA, AMDGPU::sub0);
1145fe013be4SDimitry Andric     VAddrSA = VAddrSubSA ? VAddrSubSA : VAddrSA;
11460b57cec5SDimitry Andric 
1147fe013be4SDimitry Andric     auto AddrRCID = MCII->get(NewOpcode).operands()[VAddrSAIdx].RegClass;
1148fe013be4SDimitry Andric     NewVAddrSA = MRI.getMatchingSuperReg(VAddrSA, AMDGPU::sub0,
11490b57cec5SDimitry Andric                                         &MRI.getRegClass(AddrRCID));
1150fe013be4SDimitry Andric     if (!NewVAddrSA)
11510b57cec5SDimitry Andric       return MCDisassembler::Success;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   MI.setOpcode(NewOpcode);
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   if (NewVdata != AMDGPU::NoRegister) {
11570b57cec5SDimitry Andric     MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric     if (IsAtomic) {
11600b57cec5SDimitry Andric       // Atomic operations have an additional operand (a copy of data)
11610b57cec5SDimitry Andric       MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata);
11620b57cec5SDimitry Andric     }
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric 
1165fe013be4SDimitry Andric   if (NewVAddrSA) {
1166fe013be4SDimitry Andric     MI.getOperand(VAddrSAIdx) = MCOperand::createReg(NewVAddrSA);
11670b57cec5SDimitry Andric   } else if (IsNSA) {
11680b57cec5SDimitry Andric     assert(AddrSize <= Info->VAddrDwords);
11690b57cec5SDimitry Andric     MI.erase(MI.begin() + VAddr0Idx + AddrSize,
11700b57cec5SDimitry Andric              MI.begin() + VAddr0Idx + Info->VAddrDwords);
11710b57cec5SDimitry Andric   }
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric   return MCDisassembler::Success;
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric 
117681ad6265SDimitry Andric // Opsel and neg bits are used in src_modifiers and standalone operands. Autogen
117781ad6265SDimitry Andric // decoder only adds to src_modifiers, so manually add the bits to the other
117881ad6265SDimitry Andric // operands.
convertVOP3PDPPInst(MCInst & MI) const117981ad6265SDimitry Andric DecodeStatus AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const {
118081ad6265SDimitry Andric   unsigned Opc = MI.getOpcode();
118181ad6265SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
1182fcaf7f86SDimitry Andric   auto Mods = collectVOPModifiers(MI, true);
118381ad6265SDimitry Andric 
118481ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1185bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))
118681ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vdst_in);
118781ad6265SDimitry Andric 
118881ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1189bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel))
1190fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),
119181ad6265SDimitry Andric                          AMDGPU::OpName::op_sel);
119281ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1193bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel_hi))
1194fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSelHi),
119581ad6265SDimitry Andric                          AMDGPU::OpName::op_sel_hi);
119681ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1197bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_lo))
1198fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegLo),
119981ad6265SDimitry Andric                          AMDGPU::OpName::neg_lo);
120081ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1201bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_hi))
1202fcaf7f86SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegHi),
120381ad6265SDimitry Andric                          AMDGPU::OpName::neg_hi);
120481ad6265SDimitry Andric 
120581ad6265SDimitry Andric   return MCDisassembler::Success;
120681ad6265SDimitry Andric }
120781ad6265SDimitry Andric 
120881ad6265SDimitry Andric // Create dummy old operand and insert optional operands
convertVOPCDPPInst(MCInst & MI) const120981ad6265SDimitry Andric DecodeStatus AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const {
121081ad6265SDimitry Andric   unsigned Opc = MI.getOpcode();
121181ad6265SDimitry Andric   unsigned DescNumOps = MCII->get(Opc).getNumOperands();
121281ad6265SDimitry Andric 
121381ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1214bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::old))
121581ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);
121681ad6265SDimitry Andric 
121781ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1218bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))
121981ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
122081ad6265SDimitry Andric                          AMDGPU::OpName::src0_modifiers);
122181ad6265SDimitry Andric 
122281ad6265SDimitry Andric   if (MI.getNumOperands() < DescNumOps &&
1223bdd1243dSDimitry Andric       AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))
122481ad6265SDimitry Andric     insertNamedMCOperand(MI, MCOperand::createImm(0),
122581ad6265SDimitry Andric                          AMDGPU::OpName::src1_modifiers);
122681ad6265SDimitry Andric   return MCDisassembler::Success;
122781ad6265SDimitry Andric }
122881ad6265SDimitry Andric 
convertFMAanyK(MCInst & MI,int ImmLitIdx) const1229349cc55cSDimitry Andric DecodeStatus AMDGPUDisassembler::convertFMAanyK(MCInst &MI,
1230349cc55cSDimitry Andric                                                 int ImmLitIdx) const {
1231349cc55cSDimitry Andric   assert(HasLiteral && "Should have decoded a literal");
1232349cc55cSDimitry Andric   const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
1233349cc55cSDimitry Andric   unsigned DescNumOps = Desc.getNumOperands();
123481ad6265SDimitry Andric   insertNamedMCOperand(MI, MCOperand::createImm(Literal),
123581ad6265SDimitry Andric                        AMDGPU::OpName::immDeferred);
1236349cc55cSDimitry Andric   assert(DescNumOps == MI.getNumOperands());
1237349cc55cSDimitry Andric   for (unsigned I = 0; I < DescNumOps; ++I) {
1238349cc55cSDimitry Andric     auto &Op = MI.getOperand(I);
1239bdd1243dSDimitry Andric     auto OpType = Desc.operands()[I].OperandType;
1240349cc55cSDimitry Andric     bool IsDeferredOp = (OpType == AMDGPU::OPERAND_REG_IMM_FP32_DEFERRED ||
1241349cc55cSDimitry Andric                          OpType == AMDGPU::OPERAND_REG_IMM_FP16_DEFERRED);
1242349cc55cSDimitry Andric     if (Op.isImm() && Op.getImm() == AMDGPU::EncValues::LITERAL_CONST &&
1243349cc55cSDimitry Andric         IsDeferredOp)
1244349cc55cSDimitry Andric       Op.setImm(Literal);
1245349cc55cSDimitry Andric   }
1246349cc55cSDimitry Andric   return MCDisassembler::Success;
1247349cc55cSDimitry Andric }
1248349cc55cSDimitry Andric 
getRegClassName(unsigned RegClassID) const12490b57cec5SDimitry Andric const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
12500b57cec5SDimitry Andric   return getContext().getRegisterInfo()->
12510b57cec5SDimitry Andric     getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);
12520b57cec5SDimitry Andric }
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric inline
errOperand(unsigned V,const Twine & ErrMsg) const12550b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::errOperand(unsigned V,
12560b57cec5SDimitry Andric                                          const Twine& ErrMsg) const {
12570b57cec5SDimitry Andric   *CommentStream << "Error: " + ErrMsg;
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric   // ToDo: add support for error operands to MCInst.h
12600b57cec5SDimitry Andric   // return MCOperand::createError(V);
12610b57cec5SDimitry Andric   return MCOperand();
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric 
12640b57cec5SDimitry Andric inline
createRegOperand(unsigned int RegId) const12650b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned int RegId) const {
12660b57cec5SDimitry Andric   return MCOperand::createReg(AMDGPU::getMCReg(RegId, STI));
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric inline
createRegOperand(unsigned RegClassID,unsigned Val) const12700b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
12710b57cec5SDimitry Andric                                                unsigned Val) const {
12720b57cec5SDimitry Andric   const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];
12730b57cec5SDimitry Andric   if (Val >= RegCl.getNumRegs())
12740b57cec5SDimitry Andric     return errOperand(Val, Twine(getRegClassName(RegClassID)) +
12750b57cec5SDimitry Andric                            ": unknown register " + Twine(Val));
12760b57cec5SDimitry Andric   return createRegOperand(RegCl.getRegister(Val));
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
12790b57cec5SDimitry Andric inline
createSRegOperand(unsigned SRegClassID,unsigned Val) const12800b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
12810b57cec5SDimitry Andric                                                 unsigned Val) const {
12820b57cec5SDimitry Andric   // ToDo: SI/CI have 104 SGPRs, VI - 102
12830b57cec5SDimitry Andric   // Valery: here we accepting as much as we can, let assembler sort it out
12840b57cec5SDimitry Andric   int shift = 0;
12850b57cec5SDimitry Andric   switch (SRegClassID) {
12860b57cec5SDimitry Andric   case AMDGPU::SGPR_32RegClassID:
12870b57cec5SDimitry Andric   case AMDGPU::TTMP_32RegClassID:
12880b57cec5SDimitry Andric     break;
12890b57cec5SDimitry Andric   case AMDGPU::SGPR_64RegClassID:
12900b57cec5SDimitry Andric   case AMDGPU::TTMP_64RegClassID:
12910b57cec5SDimitry Andric     shift = 1;
12920b57cec5SDimitry Andric     break;
1293c9157d92SDimitry Andric   case AMDGPU::SGPR_96RegClassID:
1294c9157d92SDimitry Andric   case AMDGPU::TTMP_96RegClassID:
12950b57cec5SDimitry Andric   case AMDGPU::SGPR_128RegClassID:
12960b57cec5SDimitry Andric   case AMDGPU::TTMP_128RegClassID:
12970b57cec5SDimitry Andric   // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
12980b57cec5SDimitry Andric   // this bundle?
12990b57cec5SDimitry Andric   case AMDGPU::SGPR_256RegClassID:
13000b57cec5SDimitry Andric   case AMDGPU::TTMP_256RegClassID:
13010b57cec5SDimitry Andric     // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
13020b57cec5SDimitry Andric   // this bundle?
1303bdd1243dSDimitry Andric   case AMDGPU::SGPR_288RegClassID:
1304bdd1243dSDimitry Andric   case AMDGPU::TTMP_288RegClassID:
1305bdd1243dSDimitry Andric   case AMDGPU::SGPR_320RegClassID:
1306bdd1243dSDimitry Andric   case AMDGPU::TTMP_320RegClassID:
1307bdd1243dSDimitry Andric   case AMDGPU::SGPR_352RegClassID:
1308bdd1243dSDimitry Andric   case AMDGPU::TTMP_352RegClassID:
1309bdd1243dSDimitry Andric   case AMDGPU::SGPR_384RegClassID:
1310bdd1243dSDimitry Andric   case AMDGPU::TTMP_384RegClassID:
13110b57cec5SDimitry Andric   case AMDGPU::SGPR_512RegClassID:
13120b57cec5SDimitry Andric   case AMDGPU::TTMP_512RegClassID:
13130b57cec5SDimitry Andric     shift = 2;
13140b57cec5SDimitry Andric     break;
13150b57cec5SDimitry Andric   // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
13160b57cec5SDimitry Andric   // this bundle?
13170b57cec5SDimitry Andric   default:
13180b57cec5SDimitry Andric     llvm_unreachable("unhandled register class");
13190b57cec5SDimitry Andric   }
13200b57cec5SDimitry Andric 
13210b57cec5SDimitry Andric   if (Val % (1 << shift)) {
13220b57cec5SDimitry Andric     *CommentStream << "Warning: " << getRegClassName(SRegClassID)
13230b57cec5SDimitry Andric                    << ": scalar reg isn't aligned " << Val;
13240b57cec5SDimitry Andric   }
13250b57cec5SDimitry Andric 
13260b57cec5SDimitry Andric   return createRegOperand(SRegClassID, Val >> shift);
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric 
createVGPR16Operand(unsigned RegIdx,bool IsHi) const1329c9157d92SDimitry Andric MCOperand AMDGPUDisassembler::createVGPR16Operand(unsigned RegIdx,
1330c9157d92SDimitry Andric                                                   bool IsHi) const {
1331de8261c4SDimitry Andric   unsigned RegIdxInVGPR16 = RegIdx * 2 + (IsHi ? 1 : 0);
1332de8261c4SDimitry Andric   return createRegOperand(AMDGPU::VGPR_16RegClassID, RegIdxInVGPR16);
1333c9157d92SDimitry Andric }
1334c9157d92SDimitry Andric 
1335349cc55cSDimitry Andric // Decode Literals for insts which always have a literal in the encoding
1336349cc55cSDimitry Andric MCOperand
decodeMandatoryLiteralConstant(unsigned Val) const1337349cc55cSDimitry Andric AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const {
1338349cc55cSDimitry Andric   if (HasLiteral) {
133981ad6265SDimitry Andric     assert(
134081ad6265SDimitry Andric         AMDGPU::hasVOPD(STI) &&
134181ad6265SDimitry Andric         "Should only decode multiple kimm with VOPD, check VSrc operand types");
1342349cc55cSDimitry Andric     if (Literal != Val)
1343349cc55cSDimitry Andric       return errOperand(Val, "More than one unique literal is illegal");
1344349cc55cSDimitry Andric   }
1345349cc55cSDimitry Andric   HasLiteral = true;
1346349cc55cSDimitry Andric   Literal = Val;
1347349cc55cSDimitry Andric   return MCOperand::createImm(Literal);
1348349cc55cSDimitry Andric }
1349349cc55cSDimitry Andric 
decodeLiteralConstant(bool ExtendFP64) const1350c9157d92SDimitry Andric MCOperand AMDGPUDisassembler::decodeLiteralConstant(bool ExtendFP64) const {
13510b57cec5SDimitry Andric   // For now all literal constants are supposed to be unsigned integer
13520b57cec5SDimitry Andric   // ToDo: deal with signed/unsigned 64-bit integer constants
13530b57cec5SDimitry Andric   // ToDo: deal with float/double constants
13540b57cec5SDimitry Andric   if (!HasLiteral) {
13550b57cec5SDimitry Andric     if (Bytes.size() < 4) {
13560b57cec5SDimitry Andric       return errOperand(0, "cannot read literal, inst bytes left " +
13570b57cec5SDimitry Andric                         Twine(Bytes.size()));
13580b57cec5SDimitry Andric     }
13590b57cec5SDimitry Andric     HasLiteral = true;
1360c9157d92SDimitry Andric     Literal = Literal64 = eatBytes<uint32_t>(Bytes);
1361c9157d92SDimitry Andric     if (ExtendFP64)
1362c9157d92SDimitry Andric       Literal64 <<= 32;
13630b57cec5SDimitry Andric   }
1364c9157d92SDimitry Andric   return MCOperand::createImm(ExtendFP64 ? Literal64 : Literal);
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric 
decodeIntImmed(unsigned Imm)13670b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
13680b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric   assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
13710b57cec5SDimitry Andric   return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
13720b57cec5SDimitry Andric     (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
13730b57cec5SDimitry Andric     (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
13740b57cec5SDimitry Andric       // Cast prevents negative overflow.
13750b57cec5SDimitry Andric }
13760b57cec5SDimitry Andric 
getInlineImmVal32(unsigned Imm)13770b57cec5SDimitry Andric static int64_t getInlineImmVal32(unsigned Imm) {
13780b57cec5SDimitry Andric   switch (Imm) {
13790b57cec5SDimitry Andric   case 240:
1380fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(0.5f);
13810b57cec5SDimitry Andric   case 241:
1382fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(-0.5f);
13830b57cec5SDimitry Andric   case 242:
1384fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(1.0f);
13850b57cec5SDimitry Andric   case 243:
1386fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(-1.0f);
13870b57cec5SDimitry Andric   case 244:
1388fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(2.0f);
13890b57cec5SDimitry Andric   case 245:
1390fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(-2.0f);
13910b57cec5SDimitry Andric   case 246:
1392fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(4.0f);
13930b57cec5SDimitry Andric   case 247:
1394fe013be4SDimitry Andric     return llvm::bit_cast<uint32_t>(-4.0f);
13950b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
13960b57cec5SDimitry Andric     return 0x3e22f983;
13970b57cec5SDimitry Andric   default:
13980b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
13990b57cec5SDimitry Andric   }
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric 
getInlineImmVal64(unsigned Imm)14020b57cec5SDimitry Andric static int64_t getInlineImmVal64(unsigned Imm) {
14030b57cec5SDimitry Andric   switch (Imm) {
14040b57cec5SDimitry Andric   case 240:
1405fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(0.5);
14060b57cec5SDimitry Andric   case 241:
1407fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(-0.5);
14080b57cec5SDimitry Andric   case 242:
1409fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(1.0);
14100b57cec5SDimitry Andric   case 243:
1411fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(-1.0);
14120b57cec5SDimitry Andric   case 244:
1413fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(2.0);
14140b57cec5SDimitry Andric   case 245:
1415fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(-2.0);
14160b57cec5SDimitry Andric   case 246:
1417fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(4.0);
14180b57cec5SDimitry Andric   case 247:
1419fe013be4SDimitry Andric     return llvm::bit_cast<uint64_t>(-4.0);
14200b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
14210b57cec5SDimitry Andric     return 0x3fc45f306dc9c882;
14220b57cec5SDimitry Andric   default:
14230b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
14240b57cec5SDimitry Andric   }
14250b57cec5SDimitry Andric }
14260b57cec5SDimitry Andric 
getInlineImmVal16(unsigned Imm)14270b57cec5SDimitry Andric static int64_t getInlineImmVal16(unsigned Imm) {
14280b57cec5SDimitry Andric   switch (Imm) {
14290b57cec5SDimitry Andric   case 240:
14300b57cec5SDimitry Andric     return 0x3800;
14310b57cec5SDimitry Andric   case 241:
14320b57cec5SDimitry Andric     return 0xB800;
14330b57cec5SDimitry Andric   case 242:
14340b57cec5SDimitry Andric     return 0x3C00;
14350b57cec5SDimitry Andric   case 243:
14360b57cec5SDimitry Andric     return 0xBC00;
14370b57cec5SDimitry Andric   case 244:
14380b57cec5SDimitry Andric     return 0x4000;
14390b57cec5SDimitry Andric   case 245:
14400b57cec5SDimitry Andric     return 0xC000;
14410b57cec5SDimitry Andric   case 246:
14420b57cec5SDimitry Andric     return 0x4400;
14430b57cec5SDimitry Andric   case 247:
14440b57cec5SDimitry Andric     return 0xC400;
14450b57cec5SDimitry Andric   case 248: // 1 / (2 * PI)
14460b57cec5SDimitry Andric     return 0x3118;
14470b57cec5SDimitry Andric   default:
14480b57cec5SDimitry Andric     llvm_unreachable("invalid fp inline imm");
14490b57cec5SDimitry Andric   }
14500b57cec5SDimitry Andric }
14510b57cec5SDimitry Andric 
decodeFPImmed(unsigned ImmWidth,unsigned Imm)1452fe013be4SDimitry Andric MCOperand AMDGPUDisassembler::decodeFPImmed(unsigned ImmWidth, unsigned Imm) {
14530b57cec5SDimitry Andric   assert(Imm >= AMDGPU::EncValues::INLINE_FLOATING_C_MIN
14540b57cec5SDimitry Andric       && Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX);
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric   // ToDo: case 248: 1/(2*PI) - is allowed only on VI
1457fe013be4SDimitry Andric   // ImmWidth 0 is a default case where operand should not allow immediates.
1458fe013be4SDimitry Andric   // Imm value is still decoded into 32 bit immediate operand, inst printer will
1459fe013be4SDimitry Andric   // use it to print verbose error message.
1460fe013be4SDimitry Andric   switch (ImmWidth) {
1461fe013be4SDimitry Andric   case 0:
1462fe013be4SDimitry Andric   case 32:
14630b57cec5SDimitry Andric     return MCOperand::createImm(getInlineImmVal32(Imm));
1464fe013be4SDimitry Andric   case 64:
14650b57cec5SDimitry Andric     return MCOperand::createImm(getInlineImmVal64(Imm));
1466fe013be4SDimitry Andric   case 16:
14670b57cec5SDimitry Andric     return MCOperand::createImm(getInlineImmVal16(Imm));
14680b57cec5SDimitry Andric   default:
14690b57cec5SDimitry Andric     llvm_unreachable("implement me");
14700b57cec5SDimitry Andric   }
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric 
getVgprClassId(const OpWidthTy Width) const14730b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getVgprClassId(const OpWidthTy Width) const {
14740b57cec5SDimitry Andric   using namespace AMDGPU;
14750b57cec5SDimitry Andric 
14760b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
14770b57cec5SDimitry Andric   switch (Width) {
14780b57cec5SDimitry Andric   default: // fall
14790b57cec5SDimitry Andric   case OPW32:
14800b57cec5SDimitry Andric   case OPW16:
14810b57cec5SDimitry Andric   case OPWV216:
14820b57cec5SDimitry Andric     return VGPR_32RegClassID;
1483fe6060f1SDimitry Andric   case OPW64:
1484fe6060f1SDimitry Andric   case OPWV232: return VReg_64RegClassID;
1485fe6060f1SDimitry Andric   case OPW96: return VReg_96RegClassID;
14860b57cec5SDimitry Andric   case OPW128: return VReg_128RegClassID;
1487fe6060f1SDimitry Andric   case OPW160: return VReg_160RegClassID;
1488fe6060f1SDimitry Andric   case OPW256: return VReg_256RegClassID;
1489bdd1243dSDimitry Andric   case OPW288: return VReg_288RegClassID;
1490bdd1243dSDimitry Andric   case OPW320: return VReg_320RegClassID;
1491bdd1243dSDimitry Andric   case OPW352: return VReg_352RegClassID;
1492bdd1243dSDimitry Andric   case OPW384: return VReg_384RegClassID;
1493fe6060f1SDimitry Andric   case OPW512: return VReg_512RegClassID;
1494fe6060f1SDimitry Andric   case OPW1024: return VReg_1024RegClassID;
14950b57cec5SDimitry Andric   }
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric 
getAgprClassId(const OpWidthTy Width) const14980b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getAgprClassId(const OpWidthTy Width) const {
14990b57cec5SDimitry Andric   using namespace AMDGPU;
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
15020b57cec5SDimitry Andric   switch (Width) {
15030b57cec5SDimitry Andric   default: // fall
15040b57cec5SDimitry Andric   case OPW32:
15050b57cec5SDimitry Andric   case OPW16:
15060b57cec5SDimitry Andric   case OPWV216:
15070b57cec5SDimitry Andric     return AGPR_32RegClassID;
1508fe6060f1SDimitry Andric   case OPW64:
1509fe6060f1SDimitry Andric   case OPWV232: return AReg_64RegClassID;
1510fe6060f1SDimitry Andric   case OPW96: return AReg_96RegClassID;
15110b57cec5SDimitry Andric   case OPW128: return AReg_128RegClassID;
1512fe6060f1SDimitry Andric   case OPW160: return AReg_160RegClassID;
15135ffd83dbSDimitry Andric   case OPW256: return AReg_256RegClassID;
1514bdd1243dSDimitry Andric   case OPW288: return AReg_288RegClassID;
1515bdd1243dSDimitry Andric   case OPW320: return AReg_320RegClassID;
1516bdd1243dSDimitry Andric   case OPW352: return AReg_352RegClassID;
1517bdd1243dSDimitry Andric   case OPW384: return AReg_384RegClassID;
15180b57cec5SDimitry Andric   case OPW512: return AReg_512RegClassID;
15190b57cec5SDimitry Andric   case OPW1024: return AReg_1024RegClassID;
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric }
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric 
getSgprClassId(const OpWidthTy Width) const15240b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getSgprClassId(const OpWidthTy Width) const {
15250b57cec5SDimitry Andric   using namespace AMDGPU;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
15280b57cec5SDimitry Andric   switch (Width) {
15290b57cec5SDimitry Andric   default: // fall
15300b57cec5SDimitry Andric   case OPW32:
15310b57cec5SDimitry Andric   case OPW16:
15320b57cec5SDimitry Andric   case OPWV216:
15330b57cec5SDimitry Andric     return SGPR_32RegClassID;
1534fe6060f1SDimitry Andric   case OPW64:
1535fe6060f1SDimitry Andric   case OPWV232: return SGPR_64RegClassID;
1536fe6060f1SDimitry Andric   case OPW96: return SGPR_96RegClassID;
15370b57cec5SDimitry Andric   case OPW128: return SGPR_128RegClassID;
1538fe6060f1SDimitry Andric   case OPW160: return SGPR_160RegClassID;
15390b57cec5SDimitry Andric   case OPW256: return SGPR_256RegClassID;
1540bdd1243dSDimitry Andric   case OPW288: return SGPR_288RegClassID;
1541bdd1243dSDimitry Andric   case OPW320: return SGPR_320RegClassID;
1542bdd1243dSDimitry Andric   case OPW352: return SGPR_352RegClassID;
1543bdd1243dSDimitry Andric   case OPW384: return SGPR_384RegClassID;
15440b57cec5SDimitry Andric   case OPW512: return SGPR_512RegClassID;
15450b57cec5SDimitry Andric   }
15460b57cec5SDimitry Andric }
15470b57cec5SDimitry Andric 
getTtmpClassId(const OpWidthTy Width) const15480b57cec5SDimitry Andric unsigned AMDGPUDisassembler::getTtmpClassId(const OpWidthTy Width) const {
15490b57cec5SDimitry Andric   using namespace AMDGPU;
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric   assert(OPW_FIRST_ <= Width && Width < OPW_LAST_);
15520b57cec5SDimitry Andric   switch (Width) {
15530b57cec5SDimitry Andric   default: // fall
15540b57cec5SDimitry Andric   case OPW32:
15550b57cec5SDimitry Andric   case OPW16:
15560b57cec5SDimitry Andric   case OPWV216:
15570b57cec5SDimitry Andric     return TTMP_32RegClassID;
1558fe6060f1SDimitry Andric   case OPW64:
1559fe6060f1SDimitry Andric   case OPWV232: return TTMP_64RegClassID;
15600b57cec5SDimitry Andric   case OPW128: return TTMP_128RegClassID;
15610b57cec5SDimitry Andric   case OPW256: return TTMP_256RegClassID;
1562bdd1243dSDimitry Andric   case OPW288: return TTMP_288RegClassID;
1563bdd1243dSDimitry Andric   case OPW320: return TTMP_320RegClassID;
1564bdd1243dSDimitry Andric   case OPW352: return TTMP_352RegClassID;
1565bdd1243dSDimitry Andric   case OPW384: return TTMP_384RegClassID;
15660b57cec5SDimitry Andric   case OPW512: return TTMP_512RegClassID;
15670b57cec5SDimitry Andric   }
15680b57cec5SDimitry Andric }
15690b57cec5SDimitry Andric 
getTTmpIdx(unsigned Val) const15700b57cec5SDimitry Andric int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const {
15710b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
15720b57cec5SDimitry Andric 
1573e8d8bef9SDimitry Andric   unsigned TTmpMin = isGFX9Plus() ? TTMP_GFX9PLUS_MIN : TTMP_VI_MIN;
1574e8d8bef9SDimitry Andric   unsigned TTmpMax = isGFX9Plus() ? TTMP_GFX9PLUS_MAX : TTMP_VI_MAX;
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric   return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1;
15770b57cec5SDimitry Andric }
15780b57cec5SDimitry Andric 
decodeSrcOp(const OpWidthTy Width,unsigned Val,bool MandatoryLiteral,unsigned ImmWidth,bool IsFP) const1579349cc55cSDimitry Andric MCOperand AMDGPUDisassembler::decodeSrcOp(const OpWidthTy Width, unsigned Val,
1580fe013be4SDimitry Andric                                           bool MandatoryLiteral,
1581c9157d92SDimitry Andric                                           unsigned ImmWidth, bool IsFP) const {
15820b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric   assert(Val < 1024); // enum10
15850b57cec5SDimitry Andric 
15860b57cec5SDimitry Andric   bool IsAGPR = Val & 512;
15870b57cec5SDimitry Andric   Val &= 511;
15880b57cec5SDimitry Andric 
15890b57cec5SDimitry Andric   if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
15900b57cec5SDimitry Andric     return createRegOperand(IsAGPR ? getAgprClassId(Width)
15910b57cec5SDimitry Andric                                    : getVgprClassId(Width), Val - VGPR_MIN);
15920b57cec5SDimitry Andric   }
1593c9157d92SDimitry Andric   return decodeNonVGPRSrcOp(Width, Val & 0xFF, MandatoryLiteral, ImmWidth,
1594c9157d92SDimitry Andric                             IsFP);
1595c9157d92SDimitry Andric }
1596c9157d92SDimitry Andric 
decodeNonVGPRSrcOp(const OpWidthTy Width,unsigned Val,bool MandatoryLiteral,unsigned ImmWidth,bool IsFP) const1597c9157d92SDimitry Andric MCOperand AMDGPUDisassembler::decodeNonVGPRSrcOp(const OpWidthTy Width,
1598c9157d92SDimitry Andric                                                  unsigned Val,
1599c9157d92SDimitry Andric                                                  bool MandatoryLiteral,
1600c9157d92SDimitry Andric                                                  unsigned ImmWidth,
1601c9157d92SDimitry Andric                                                  bool IsFP) const {
1602c9157d92SDimitry Andric   // Cases when Val{8} is 1 (vgpr, agpr or true 16 vgpr) should have been
1603c9157d92SDimitry Andric   // decoded earlier.
1604c9157d92SDimitry Andric   assert(Val < (1 << 8) && "9-bit Src encoding when Val{8} is 0");
1605c9157d92SDimitry Andric   using namespace AMDGPU::EncValues;
1606c9157d92SDimitry Andric 
16070b57cec5SDimitry Andric   if (Val <= SGPR_MAX) {
1608e8d8bef9SDimitry Andric     // "SGPR_MIN <= Val" is always true and causes compilation warning.
1609bdd1243dSDimitry Andric     static_assert(SGPR_MIN == 0);
16100b57cec5SDimitry Andric     return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);
16110b57cec5SDimitry Andric   }
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   int TTmpIdx = getTTmpIdx(Val);
16140b57cec5SDimitry Andric   if (TTmpIdx >= 0) {
16150b57cec5SDimitry Andric     return createSRegOperand(getTtmpClassId(Width), TTmpIdx);
16160b57cec5SDimitry Andric   }
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric   if (INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX)
16190b57cec5SDimitry Andric     return decodeIntImmed(Val);
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric   if (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX)
1622fe013be4SDimitry Andric     return decodeFPImmed(ImmWidth, Val);
16230b57cec5SDimitry Andric 
1624349cc55cSDimitry Andric   if (Val == LITERAL_CONST) {
1625349cc55cSDimitry Andric     if (MandatoryLiteral)
1626349cc55cSDimitry Andric       // Keep a sentinel value for deferred setting
1627349cc55cSDimitry Andric       return MCOperand::createImm(LITERAL_CONST);
1628349cc55cSDimitry Andric     else
1629c9157d92SDimitry Andric       return decodeLiteralConstant(IsFP && ImmWidth == 64);
1630349cc55cSDimitry Andric   }
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric   switch (Width) {
16330b57cec5SDimitry Andric   case OPW32:
16340b57cec5SDimitry Andric   case OPW16:
16350b57cec5SDimitry Andric   case OPWV216:
16360b57cec5SDimitry Andric     return decodeSpecialReg32(Val);
16370b57cec5SDimitry Andric   case OPW64:
1638fe6060f1SDimitry Andric   case OPWV232:
16390b57cec5SDimitry Andric     return decodeSpecialReg64(Val);
16400b57cec5SDimitry Andric   default:
16410b57cec5SDimitry Andric     llvm_unreachable("unexpected immediate type");
16420b57cec5SDimitry Andric   }
16430b57cec5SDimitry Andric }
16440b57cec5SDimitry Andric 
164581ad6265SDimitry Andric // Bit 0 of DstY isn't stored in the instruction, because it's always the
164681ad6265SDimitry Andric // opposite of bit 0 of DstX.
decodeVOPDDstYOp(MCInst & Inst,unsigned Val) const164781ad6265SDimitry Andric MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst,
164881ad6265SDimitry Andric                                                unsigned Val) const {
164981ad6265SDimitry Andric   int VDstXInd =
165081ad6265SDimitry Andric       AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::vdstX);
165181ad6265SDimitry Andric   assert(VDstXInd != -1);
165281ad6265SDimitry Andric   assert(Inst.getOperand(VDstXInd).isReg());
165381ad6265SDimitry Andric   unsigned XDstReg = MRI.getEncodingValue(Inst.getOperand(VDstXInd).getReg());
165481ad6265SDimitry Andric   Val |= ~XDstReg & 1;
165581ad6265SDimitry Andric   auto Width = llvm::AMDGPUDisassembler::OPW32;
165681ad6265SDimitry Andric   return createRegOperand(getVgprClassId(Width), Val);
165781ad6265SDimitry Andric }
165881ad6265SDimitry Andric 
decodeSpecialReg32(unsigned Val) const16590b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
16600b57cec5SDimitry Andric   using namespace AMDGPU;
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric   switch (Val) {
1663bdd1243dSDimitry Andric   // clang-format off
16640b57cec5SDimitry Andric   case 102: return createRegOperand(FLAT_SCR_LO);
16650b57cec5SDimitry Andric   case 103: return createRegOperand(FLAT_SCR_HI);
16660b57cec5SDimitry Andric   case 104: return createRegOperand(XNACK_MASK_LO);
16670b57cec5SDimitry Andric   case 105: return createRegOperand(XNACK_MASK_HI);
16680b57cec5SDimitry Andric   case 106: return createRegOperand(VCC_LO);
16690b57cec5SDimitry Andric   case 107: return createRegOperand(VCC_HI);
16700b57cec5SDimitry Andric   case 108: return createRegOperand(TBA_LO);
16710b57cec5SDimitry Andric   case 109: return createRegOperand(TBA_HI);
16720b57cec5SDimitry Andric   case 110: return createRegOperand(TMA_LO);
16730b57cec5SDimitry Andric   case 111: return createRegOperand(TMA_HI);
167481ad6265SDimitry Andric   case 124:
167581ad6265SDimitry Andric     return isGFX11Plus() ? createRegOperand(SGPR_NULL) : createRegOperand(M0);
167681ad6265SDimitry Andric   case 125:
167781ad6265SDimitry Andric     return isGFX11Plus() ? createRegOperand(M0) : createRegOperand(SGPR_NULL);
16780b57cec5SDimitry Andric   case 126: return createRegOperand(EXEC_LO);
16790b57cec5SDimitry Andric   case 127: return createRegOperand(EXEC_HI);
1680bdd1243dSDimitry Andric   case 235: return createRegOperand(SRC_SHARED_BASE_LO);
1681bdd1243dSDimitry Andric   case 236: return createRegOperand(SRC_SHARED_LIMIT_LO);
1682bdd1243dSDimitry Andric   case 237: return createRegOperand(SRC_PRIVATE_BASE_LO);
1683bdd1243dSDimitry Andric   case 238: return createRegOperand(SRC_PRIVATE_LIMIT_LO);
16840b57cec5SDimitry Andric   case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);
16850b57cec5SDimitry Andric   case 251: return createRegOperand(SRC_VCCZ);
16860b57cec5SDimitry Andric   case 252: return createRegOperand(SRC_EXECZ);
16870b57cec5SDimitry Andric   case 253: return createRegOperand(SRC_SCC);
16880b57cec5SDimitry Andric   case 254: return createRegOperand(LDS_DIRECT);
16890b57cec5SDimitry Andric   default: break;
1690bdd1243dSDimitry Andric     // clang-format on
16910b57cec5SDimitry Andric   }
16920b57cec5SDimitry Andric   return errOperand(Val, "unknown operand encoding " + Twine(Val));
16930b57cec5SDimitry Andric }
16940b57cec5SDimitry Andric 
decodeSpecialReg64(unsigned Val) const16950b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
16960b57cec5SDimitry Andric   using namespace AMDGPU;
16970b57cec5SDimitry Andric 
16980b57cec5SDimitry Andric   switch (Val) {
16990b57cec5SDimitry Andric   case 102: return createRegOperand(FLAT_SCR);
17000b57cec5SDimitry Andric   case 104: return createRegOperand(XNACK_MASK);
17010b57cec5SDimitry Andric   case 106: return createRegOperand(VCC);
17020b57cec5SDimitry Andric   case 108: return createRegOperand(TBA);
17030b57cec5SDimitry Andric   case 110: return createRegOperand(TMA);
170481ad6265SDimitry Andric   case 124:
170581ad6265SDimitry Andric     if (isGFX11Plus())
170681ad6265SDimitry Andric       return createRegOperand(SGPR_NULL);
170781ad6265SDimitry Andric     break;
170881ad6265SDimitry Andric   case 125:
170981ad6265SDimitry Andric     if (!isGFX11Plus())
171081ad6265SDimitry Andric       return createRegOperand(SGPR_NULL);
171181ad6265SDimitry Andric     break;
17120b57cec5SDimitry Andric   case 126: return createRegOperand(EXEC);
17130b57cec5SDimitry Andric   case 235: return createRegOperand(SRC_SHARED_BASE);
17140b57cec5SDimitry Andric   case 236: return createRegOperand(SRC_SHARED_LIMIT);
17150b57cec5SDimitry Andric   case 237: return createRegOperand(SRC_PRIVATE_BASE);
17160b57cec5SDimitry Andric   case 238: return createRegOperand(SRC_PRIVATE_LIMIT);
17170b57cec5SDimitry Andric   case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);
17180b57cec5SDimitry Andric   case 251: return createRegOperand(SRC_VCCZ);
17190b57cec5SDimitry Andric   case 252: return createRegOperand(SRC_EXECZ);
17200b57cec5SDimitry Andric   case 253: return createRegOperand(SRC_SCC);
17210b57cec5SDimitry Andric   default: break;
17220b57cec5SDimitry Andric   }
17230b57cec5SDimitry Andric   return errOperand(Val, "unknown operand encoding " + Twine(Val));
17240b57cec5SDimitry Andric }
17250b57cec5SDimitry Andric 
decodeSDWASrc(const OpWidthTy Width,const unsigned Val,unsigned ImmWidth) const17260b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc(const OpWidthTy Width,
1727fe013be4SDimitry Andric                                             const unsigned Val,
1728fe013be4SDimitry Andric                                             unsigned ImmWidth) const {
17290b57cec5SDimitry Andric   using namespace AMDGPU::SDWA;
17300b57cec5SDimitry Andric   using namespace AMDGPU::EncValues;
17310b57cec5SDimitry Andric 
1732fe013be4SDimitry Andric   if (STI.hasFeature(AMDGPU::FeatureGFX9) ||
1733fe013be4SDimitry Andric       STI.hasFeature(AMDGPU::FeatureGFX10)) {
17340b57cec5SDimitry Andric     // XXX: cast to int is needed to avoid stupid warning:
17350b57cec5SDimitry Andric     // compare with unsigned is always true
17360b57cec5SDimitry Andric     if (int(SDWA9EncValues::SRC_VGPR_MIN) <= int(Val) &&
17370b57cec5SDimitry Andric         Val <= SDWA9EncValues::SRC_VGPR_MAX) {
17380b57cec5SDimitry Andric       return createRegOperand(getVgprClassId(Width),
17390b57cec5SDimitry Andric                               Val - SDWA9EncValues::SRC_VGPR_MIN);
17400b57cec5SDimitry Andric     }
17410b57cec5SDimitry Andric     if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
1742e8d8bef9SDimitry Andric         Val <= (isGFX10Plus() ? SDWA9EncValues::SRC_SGPR_MAX_GFX10
17430b57cec5SDimitry Andric                               : SDWA9EncValues::SRC_SGPR_MAX_SI)) {
17440b57cec5SDimitry Andric       return createSRegOperand(getSgprClassId(Width),
17450b57cec5SDimitry Andric                                Val - SDWA9EncValues::SRC_SGPR_MIN);
17460b57cec5SDimitry Andric     }
17470b57cec5SDimitry Andric     if (SDWA9EncValues::SRC_TTMP_MIN <= Val &&
17480b57cec5SDimitry Andric         Val <= SDWA9EncValues::SRC_TTMP_MAX) {
17490b57cec5SDimitry Andric       return createSRegOperand(getTtmpClassId(Width),
17500b57cec5SDimitry Andric                                Val - SDWA9EncValues::SRC_TTMP_MIN);
17510b57cec5SDimitry Andric     }
17520b57cec5SDimitry Andric 
17530b57cec5SDimitry Andric     const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric     if (INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX)
17560b57cec5SDimitry Andric       return decodeIntImmed(SVal);
17570b57cec5SDimitry Andric 
17580b57cec5SDimitry Andric     if (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX)
1759fe013be4SDimitry Andric       return decodeFPImmed(ImmWidth, SVal);
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric     return decodeSpecialReg32(SVal);
1762fe013be4SDimitry Andric   } else if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) {
17630b57cec5SDimitry Andric     return createRegOperand(getVgprClassId(Width), Val);
17640b57cec5SDimitry Andric   }
17650b57cec5SDimitry Andric   llvm_unreachable("unsupported target");
17660b57cec5SDimitry Andric }
17670b57cec5SDimitry Andric 
decodeSDWASrc16(unsigned Val) const17680b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
1769fe013be4SDimitry Andric   return decodeSDWASrc(OPW16, Val, 16);
17700b57cec5SDimitry Andric }
17710b57cec5SDimitry Andric 
decodeSDWASrc32(unsigned Val) const17720b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
1773fe013be4SDimitry Andric   return decodeSDWASrc(OPW32, Val, 32);
17740b57cec5SDimitry Andric }
17750b57cec5SDimitry Andric 
decodeSDWAVopcDst(unsigned Val) const17760b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
17770b57cec5SDimitry Andric   using namespace AMDGPU::SDWA;
17780b57cec5SDimitry Andric 
1779fe013be4SDimitry Andric   assert((STI.hasFeature(AMDGPU::FeatureGFX9) ||
1780fe013be4SDimitry Andric           STI.hasFeature(AMDGPU::FeatureGFX10)) &&
17810b57cec5SDimitry Andric          "SDWAVopcDst should be present only on GFX9+");
17820b57cec5SDimitry Andric 
1783fe013be4SDimitry Andric   bool IsWave64 = STI.hasFeature(AMDGPU::FeatureWavefrontSize64);
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric   if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
17860b57cec5SDimitry Andric     Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
17870b57cec5SDimitry Andric 
17880b57cec5SDimitry Andric     int TTmpIdx = getTTmpIdx(Val);
17890b57cec5SDimitry Andric     if (TTmpIdx >= 0) {
17908bcb0991SDimitry Andric       auto TTmpClsId = getTtmpClassId(IsWave64 ? OPW64 : OPW32);
17918bcb0991SDimitry Andric       return createSRegOperand(TTmpClsId, TTmpIdx);
17920b57cec5SDimitry Andric     } else if (Val > SGPR_MAX) {
17930b57cec5SDimitry Andric       return IsWave64 ? decodeSpecialReg64(Val)
17940b57cec5SDimitry Andric                       : decodeSpecialReg32(Val);
17950b57cec5SDimitry Andric     } else {
17960b57cec5SDimitry Andric       return createSRegOperand(getSgprClassId(IsWave64 ? OPW64 : OPW32), Val);
17970b57cec5SDimitry Andric     }
17980b57cec5SDimitry Andric   } else {
17990b57cec5SDimitry Andric     return createRegOperand(IsWave64 ? AMDGPU::VCC : AMDGPU::VCC_LO);
18000b57cec5SDimitry Andric   }
18010b57cec5SDimitry Andric }
18020b57cec5SDimitry Andric 
decodeBoolReg(unsigned Val) const18030b57cec5SDimitry Andric MCOperand AMDGPUDisassembler::decodeBoolReg(unsigned Val) const {
1804fe013be4SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureWavefrontSize64)
1805fe013be4SDimitry Andric              ? decodeSrcOp(OPW64, Val)
1806fe013be4SDimitry Andric              : decodeSrcOp(OPW32, Val);
18070b57cec5SDimitry Andric }
18080b57cec5SDimitry Andric 
decodeSplitBarrier(unsigned Val) const1809c9157d92SDimitry Andric MCOperand AMDGPUDisassembler::decodeSplitBarrier(unsigned Val) const {
1810c9157d92SDimitry Andric   return decodeSrcOp(OPW32, Val);
1811c9157d92SDimitry Andric }
1812c9157d92SDimitry Andric 
isVI() const18130b57cec5SDimitry Andric bool AMDGPUDisassembler::isVI() const {
1814fe013be4SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric 
isGFX9() const1817e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9() const { return AMDGPU::isGFX9(STI); }
1818e8d8bef9SDimitry Andric 
isGFX90A() const1819fe6060f1SDimitry Andric bool AMDGPUDisassembler::isGFX90A() const {
1820fe013be4SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX90AInsts);
1821fe6060f1SDimitry Andric }
1822fe6060f1SDimitry Andric 
isGFX9Plus() const1823e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX9Plus() const { return AMDGPU::isGFX9Plus(STI); }
1824e8d8bef9SDimitry Andric 
isGFX10() const1825e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10() const { return AMDGPU::isGFX10(STI); }
1826e8d8bef9SDimitry Andric 
isGFX10Plus() const1827e8d8bef9SDimitry Andric bool AMDGPUDisassembler::isGFX10Plus() const {
1828e8d8bef9SDimitry Andric   return AMDGPU::isGFX10Plus(STI);
18290b57cec5SDimitry Andric }
18300b57cec5SDimitry Andric 
isGFX11() const183181ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11() const {
1832fe013be4SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureGFX11);
183381ad6265SDimitry Andric }
183481ad6265SDimitry Andric 
isGFX11Plus() const183581ad6265SDimitry Andric bool AMDGPUDisassembler::isGFX11Plus() const {
183681ad6265SDimitry Andric   return AMDGPU::isGFX11Plus(STI);
183781ad6265SDimitry Andric }
183881ad6265SDimitry Andric 
isGFX12Plus() const1839c9157d92SDimitry Andric bool AMDGPUDisassembler::isGFX12Plus() const {
1840c9157d92SDimitry Andric   return AMDGPU::isGFX12Plus(STI);
1841c9157d92SDimitry Andric }
184281ad6265SDimitry Andric 
hasArchitectedFlatScratch() const1843fe6060f1SDimitry Andric bool AMDGPUDisassembler::hasArchitectedFlatScratch() const {
1844fe013be4SDimitry Andric   return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch);
1845fe6060f1SDimitry Andric }
1846fe6060f1SDimitry Andric 
hasKernargPreload() const1847c9157d92SDimitry Andric bool AMDGPUDisassembler::hasKernargPreload() const {
1848c9157d92SDimitry Andric   return AMDGPU::hasKernargPreload(STI);
1849c9157d92SDimitry Andric }
1850c9157d92SDimitry Andric 
1851e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1852e8d8bef9SDimitry Andric // AMDGPU specific symbol handling
1853e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
1854fe013be4SDimitry Andric #define GET_FIELD(MASK) (AMDHSA_BITS_GET(FourByteBuffer, MASK))
1855e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK)                                       \
1856e8d8bef9SDimitry Andric   do {                                                                         \
1857fe013be4SDimitry Andric     KdStream << Indent << DIRECTIVE " " << GET_FIELD(MASK) << '\n';            \
1858fe013be4SDimitry Andric   } while (0)
1859fe013be4SDimitry Andric #define PRINT_PSEUDO_DIRECTIVE_COMMENT(DIRECTIVE, MASK)                        \
1860fe013be4SDimitry Andric   do {                                                                         \
1861fe013be4SDimitry Andric     KdStream << Indent << MAI.getCommentString() << ' ' << DIRECTIVE " "       \
1862fe013be4SDimitry Andric              << GET_FIELD(MASK) << '\n';                                       \
1863e8d8bef9SDimitry Andric   } while (0)
1864e8d8bef9SDimitry Andric 
1865e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer,raw_string_ostream & KdStream) const1866e8d8bef9SDimitry Andric MCDisassembler::DecodeStatus AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1(
1867e8d8bef9SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
1868e8d8bef9SDimitry Andric   using namespace amdhsa;
1869e8d8bef9SDimitry Andric   StringRef Indent = "\t";
1870e8d8bef9SDimitry Andric 
1871e8d8bef9SDimitry Andric   // We cannot accurately backward compute #VGPRs used from
1872e8d8bef9SDimitry Andric   // GRANULATED_WORKITEM_VGPR_COUNT. But we are concerned with getting the same
1873e8d8bef9SDimitry Andric   // value of GRANULATED_WORKITEM_VGPR_COUNT in the reassembled binary. So we
1874e8d8bef9SDimitry Andric   // simply calculate the inverse of what the assembler does.
1875e8d8bef9SDimitry Andric 
1876e8d8bef9SDimitry Andric   uint32_t GranulatedWorkitemVGPRCount =
1877fe013be4SDimitry Andric       GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT);
1878e8d8bef9SDimitry Andric 
1879fe013be4SDimitry Andric   uint32_t NextFreeVGPR =
1880fe013be4SDimitry Andric       (GranulatedWorkitemVGPRCount + 1) *
1881fe013be4SDimitry Andric       AMDGPU::IsaInfo::getVGPREncodingGranule(&STI, EnableWavefrontSize32);
1882e8d8bef9SDimitry Andric 
1883e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_next_free_vgpr " << NextFreeVGPR << '\n';
1884e8d8bef9SDimitry Andric 
1885e8d8bef9SDimitry Andric   // We cannot backward compute values used to calculate
1886e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT. Hence the original values for following
1887e8d8bef9SDimitry Andric   // directives can't be computed:
1888e8d8bef9SDimitry Andric   // .amdhsa_reserve_vcc
1889e8d8bef9SDimitry Andric   // .amdhsa_reserve_flat_scratch
1890e8d8bef9SDimitry Andric   // .amdhsa_reserve_xnack_mask
1891e8d8bef9SDimitry Andric   // They take their respective default values if not specified in the assembly.
1892e8d8bef9SDimitry Andric   //
1893e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT
1894e8d8bef9SDimitry Andric   //    = f(NEXT_FREE_SGPR + VCC + FLAT_SCRATCH + XNACK_MASK)
1895e8d8bef9SDimitry Andric   //
1896e8d8bef9SDimitry Andric   // We compute the inverse as though all directives apart from NEXT_FREE_SGPR
1897e8d8bef9SDimitry Andric   // are set to 0. So while disassembling we consider that:
1898e8d8bef9SDimitry Andric   //
1899e8d8bef9SDimitry Andric   // GRANULATED_WAVEFRONT_SGPR_COUNT
1900e8d8bef9SDimitry Andric   //    = f(NEXT_FREE_SGPR + 0 + 0 + 0)
1901e8d8bef9SDimitry Andric   //
1902e8d8bef9SDimitry Andric   // The disassembler cannot recover the original values of those 3 directives.
1903e8d8bef9SDimitry Andric 
1904e8d8bef9SDimitry Andric   uint32_t GranulatedWavefrontSGPRCount =
1905fe013be4SDimitry Andric       GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT);
1906e8d8bef9SDimitry Andric 
1907e8d8bef9SDimitry Andric   if (isGFX10Plus() && GranulatedWavefrontSGPRCount)
1908e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1909e8d8bef9SDimitry Andric 
1910e8d8bef9SDimitry Andric   uint32_t NextFreeSGPR = (GranulatedWavefrontSGPRCount + 1) *
1911e8d8bef9SDimitry Andric                           AMDGPU::IsaInfo::getSGPREncodingGranule(&STI);
1912e8d8bef9SDimitry Andric 
1913e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_reserve_vcc " << 0 << '\n';
1914fe6060f1SDimitry Andric   if (!hasArchitectedFlatScratch())
1915e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_reserve_flat_scratch " << 0 << '\n';
1916e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_reserve_xnack_mask " << 0 << '\n';
1917e8d8bef9SDimitry Andric   KdStream << Indent << ".amdhsa_next_free_sgpr " << NextFreeSGPR << "\n";
1918e8d8bef9SDimitry Andric 
1919e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_PRIORITY)
1920e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1921e8d8bef9SDimitry Andric 
1922e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_round_mode_32",
1923e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32);
1924e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_round_mode_16_64",
1925e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64);
1926e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_32",
1927e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32);
1928e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_16_64",
1929e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64);
1930e8d8bef9SDimitry Andric 
1931e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_PRIV)
1932e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1933e8d8bef9SDimitry Andric 
1934c9157d92SDimitry Andric   if (!isGFX12Plus())
1935c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_dx10_clamp",
1936c9157d92SDimitry Andric                     COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP);
1937e8d8bef9SDimitry Andric 
1938e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_DEBUG_MODE)
1939e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1940e8d8bef9SDimitry Andric 
1941c9157d92SDimitry Andric   if (!isGFX12Plus())
1942c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_ieee_mode",
1943c9157d92SDimitry Andric                     COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE);
1944e8d8bef9SDimitry Andric 
1945e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_BULKY)
1946e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1947e8d8bef9SDimitry Andric 
1948e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_CDBG_USER)
1949e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
1950e8d8bef9SDimitry Andric 
1951c9157d92SDimitry Andric   if (isGFX9Plus())
1952c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_fp16_overflow", COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL);
1953e8d8bef9SDimitry Andric 
1954c9157d92SDimitry Andric   if (!isGFX9Plus())
1955c9157d92SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC1_GFX6_GFX8_RESERVED0)
1956c9157d92SDimitry Andric       return MCDisassembler::Fail;
1957c9157d92SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC1_RESERVED1)
1958c9157d92SDimitry Andric     return MCDisassembler::Fail;
1959c9157d92SDimitry Andric   if (!isGFX10Plus())
1960c9157d92SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC1_GFX6_GFX9_RESERVED2)
1961e8d8bef9SDimitry Andric       return MCDisassembler::Fail;
1962e8d8bef9SDimitry Andric 
1963e8d8bef9SDimitry Andric   if (isGFX10Plus()) {
1964e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_workgroup_processor_mode",
1965c9157d92SDimitry Andric                     COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE);
1966c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_memory_ordered", COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED);
1967c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_forward_progress", COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS);
1968e8d8bef9SDimitry Andric   }
1969c9157d92SDimitry Andric 
1970c9157d92SDimitry Andric   if (isGFX12Plus())
1971c9157d92SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_round_robin_scheduling",
1972c9157d92SDimitry Andric                     COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN);
1973c9157d92SDimitry Andric 
1974e8d8bef9SDimitry Andric   return MCDisassembler::Success;
1975e8d8bef9SDimitry Andric }
1976e8d8bef9SDimitry Andric 
1977e8d8bef9SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer,raw_string_ostream & KdStream) const1978e8d8bef9SDimitry Andric MCDisassembler::DecodeStatus AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC2(
1979e8d8bef9SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
1980e8d8bef9SDimitry Andric   using namespace amdhsa;
1981e8d8bef9SDimitry Andric   StringRef Indent = "\t";
1982fe6060f1SDimitry Andric   if (hasArchitectedFlatScratch())
1983fe6060f1SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_enable_private_segment",
1984fe6060f1SDimitry Andric                     COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
1985fe6060f1SDimitry Andric   else
1986fe6060f1SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_system_sgpr_private_segment_wavefront_offset",
1987e8d8bef9SDimitry Andric                     COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
1988e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_x",
1989e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X);
1990e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_y",
1991e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y);
1992e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_z",
1993e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z);
1994e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_info",
1995e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO);
1996e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_system_vgpr_workitem_id",
1997e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID);
1998e8d8bef9SDimitry Andric 
1999e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_ADDRESS_WATCH)
2000e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2001e8d8bef9SDimitry Andric 
2002e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_MEMORY)
2003e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2004e8d8bef9SDimitry Andric 
2005e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC2_GRANULATED_LDS_SIZE)
2006e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2007e8d8bef9SDimitry Andric 
2008e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(
2009e8d8bef9SDimitry Andric       ".amdhsa_exception_fp_ieee_invalid_op",
2010e8d8bef9SDimitry Andric       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION);
2011e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_denorm_src",
2012e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE);
2013e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(
2014e8d8bef9SDimitry Andric       ".amdhsa_exception_fp_ieee_div_zero",
2015e8d8bef9SDimitry Andric       COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO);
2016e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_overflow",
2017e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW);
2018e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_underflow",
2019e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW);
2020e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_inexact",
2021e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT);
2022e8d8bef9SDimitry Andric   PRINT_DIRECTIVE(".amdhsa_exception_int_div_zero",
2023e8d8bef9SDimitry Andric                   COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO);
2024e8d8bef9SDimitry Andric 
2025e8d8bef9SDimitry Andric   if (FourByteBuffer & COMPUTE_PGM_RSRC2_RESERVED0)
2026e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2027e8d8bef9SDimitry Andric 
2028e8d8bef9SDimitry Andric   return MCDisassembler::Success;
2029e8d8bef9SDimitry Andric }
2030e8d8bef9SDimitry Andric 
2031fe013be4SDimitry Andric // NOLINTNEXTLINE(readability-identifier-naming)
decodeCOMPUTE_PGM_RSRC3(uint32_t FourByteBuffer,raw_string_ostream & KdStream) const2032fe013be4SDimitry Andric MCDisassembler::DecodeStatus AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3(
2033fe013be4SDimitry Andric     uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
2034fe013be4SDimitry Andric   using namespace amdhsa;
2035fe013be4SDimitry Andric   StringRef Indent = "\t";
2036fe013be4SDimitry Andric   if (isGFX90A()) {
2037fe013be4SDimitry Andric     KdStream << Indent << ".amdhsa_accum_offset "
2038fe013be4SDimitry Andric              << (GET_FIELD(COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4
2039fe013be4SDimitry Andric              << '\n';
2040fe013be4SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX90A_RESERVED0)
2041fe013be4SDimitry Andric       return MCDisassembler::Fail;
2042fe013be4SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_tg_split", COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT);
2043fe013be4SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX90A_RESERVED1)
2044fe013be4SDimitry Andric       return MCDisassembler::Fail;
2045fe013be4SDimitry Andric   } else if (isGFX10Plus()) {
2046de8261c4SDimitry Andric     // Bits [0-3].
2047de8261c4SDimitry Andric     if (!isGFX12Plus()) {
2048fe013be4SDimitry Andric       if (!EnableWavefrontSize32 || !*EnableWavefrontSize32) {
2049fe013be4SDimitry Andric         PRINT_DIRECTIVE(".amdhsa_shared_vgpr_count",
2050de8261c4SDimitry Andric                         COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
2051fe013be4SDimitry Andric       } else {
2052fe013be4SDimitry Andric         PRINT_PSEUDO_DIRECTIVE_COMMENT(
2053de8261c4SDimitry Andric             "SHARED_VGPR_COUNT",
2054de8261c4SDimitry Andric             COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
2055fe013be4SDimitry Andric       }
2056c9157d92SDimitry Andric     } else {
2057de8261c4SDimitry Andric       if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX12_PLUS_RESERVED0)
2058fe013be4SDimitry Andric         return MCDisassembler::Fail;
2059c9157d92SDimitry Andric     }
2060c9157d92SDimitry Andric 
2061de8261c4SDimitry Andric     // Bits [4-11].
2062de8261c4SDimitry Andric     if (isGFX11()) {
2063de8261c4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("INST_PREF_SIZE",
2064de8261c4SDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE);
2065de8261c4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START",
2066de8261c4SDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START);
2067de8261c4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END",
2068de8261c4SDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END);
2069de8261c4SDimitry Andric     } else if (isGFX12Plus()) {
2070de8261c4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT(
2071de8261c4SDimitry Andric           "INST_PREF_SIZE", COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE);
2072de8261c4SDimitry Andric     } else {
2073de8261c4SDimitry Andric       if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX10_RESERVED1)
2074de8261c4SDimitry Andric         return MCDisassembler::Fail;
2075de8261c4SDimitry Andric     }
2076de8261c4SDimitry Andric 
2077de8261c4SDimitry Andric     // Bits [12].
2078de8261c4SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED2)
2079c9157d92SDimitry Andric       return MCDisassembler::Fail;
2080c9157d92SDimitry Andric 
2081de8261c4SDimitry Andric     // Bits [13].
2082de8261c4SDimitry Andric     if (isGFX12Plus()) {
2083de8261c4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("GLG_EN",
2084de8261c4SDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX12_PLUS_GLG_EN);
2085de8261c4SDimitry Andric     } else {
2086de8261c4SDimitry Andric       if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX10_GFX11_RESERVED3)
2087de8261c4SDimitry Andric         return MCDisassembler::Fail;
2088de8261c4SDimitry Andric     }
2089de8261c4SDimitry Andric 
2090de8261c4SDimitry Andric     // Bits [14-30].
2091de8261c4SDimitry Andric     if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED4)
2092de8261c4SDimitry Andric       return MCDisassembler::Fail;
2093de8261c4SDimitry Andric 
2094de8261c4SDimitry Andric     // Bits [31].
2095c9157d92SDimitry Andric     if (isGFX11Plus()) {
2096fe013be4SDimitry Andric       PRINT_PSEUDO_DIRECTIVE_COMMENT("IMAGE_OP",
2097de8261c4SDimitry Andric                                      COMPUTE_PGM_RSRC3_GFX11_PLUS_IMAGE_OP);
2098c9157d92SDimitry Andric     } else {
2099de8261c4SDimitry Andric       if (FourByteBuffer & COMPUTE_PGM_RSRC3_GFX10_RESERVED5)
2100c9157d92SDimitry Andric         return MCDisassembler::Fail;
2101c9157d92SDimitry Andric     }
2102fe013be4SDimitry Andric   } else if (FourByteBuffer) {
2103fe013be4SDimitry Andric     return MCDisassembler::Fail;
2104fe013be4SDimitry Andric   }
2105fe013be4SDimitry Andric   return MCDisassembler::Success;
2106fe013be4SDimitry Andric }
2107fe013be4SDimitry Andric #undef PRINT_PSEUDO_DIRECTIVE_COMMENT
2108e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE
2109fe013be4SDimitry Andric #undef GET_FIELD
2110e8d8bef9SDimitry Andric 
2111e8d8bef9SDimitry Andric MCDisassembler::DecodeStatus
decodeKernelDescriptorDirective(DataExtractor::Cursor & Cursor,ArrayRef<uint8_t> Bytes,raw_string_ostream & KdStream) const2112e8d8bef9SDimitry Andric AMDGPUDisassembler::decodeKernelDescriptorDirective(
2113e8d8bef9SDimitry Andric     DataExtractor::Cursor &Cursor, ArrayRef<uint8_t> Bytes,
2114e8d8bef9SDimitry Andric     raw_string_ostream &KdStream) const {
2115e8d8bef9SDimitry Andric #define PRINT_DIRECTIVE(DIRECTIVE, MASK)                                       \
2116e8d8bef9SDimitry Andric   do {                                                                         \
2117e8d8bef9SDimitry Andric     KdStream << Indent << DIRECTIVE " "                                        \
2118e8d8bef9SDimitry Andric              << ((TwoByteBuffer & MASK) >> (MASK##_SHIFT)) << '\n';            \
2119e8d8bef9SDimitry Andric   } while (0)
2120e8d8bef9SDimitry Andric 
2121e8d8bef9SDimitry Andric   uint16_t TwoByteBuffer = 0;
2122e8d8bef9SDimitry Andric   uint32_t FourByteBuffer = 0;
2123e8d8bef9SDimitry Andric 
2124e8d8bef9SDimitry Andric   StringRef ReservedBytes;
2125e8d8bef9SDimitry Andric   StringRef Indent = "\t";
2126e8d8bef9SDimitry Andric 
2127e8d8bef9SDimitry Andric   assert(Bytes.size() == 64);
2128e8d8bef9SDimitry Andric   DataExtractor DE(Bytes, /*IsLittleEndian=*/true, /*AddressSize=*/8);
2129e8d8bef9SDimitry Andric 
2130e8d8bef9SDimitry Andric   switch (Cursor.tell()) {
2131e8d8bef9SDimitry Andric   case amdhsa::GROUP_SEGMENT_FIXED_SIZE_OFFSET:
2132e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2133e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_group_segment_fixed_size " << FourByteBuffer
2134e8d8bef9SDimitry Andric              << '\n';
2135e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2136e8d8bef9SDimitry Andric 
2137e8d8bef9SDimitry Andric   case amdhsa::PRIVATE_SEGMENT_FIXED_SIZE_OFFSET:
2138e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2139e8d8bef9SDimitry Andric     KdStream << Indent << ".amdhsa_private_segment_fixed_size "
2140e8d8bef9SDimitry Andric              << FourByteBuffer << '\n';
2141e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2142e8d8bef9SDimitry Andric 
2143fe6060f1SDimitry Andric   case amdhsa::KERNARG_SIZE_OFFSET:
2144fe6060f1SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2145fe6060f1SDimitry Andric     KdStream << Indent << ".amdhsa_kernarg_size "
2146fe6060f1SDimitry Andric              << FourByteBuffer << '\n';
2147fe6060f1SDimitry Andric     return MCDisassembler::Success;
2148fe6060f1SDimitry Andric 
2149e8d8bef9SDimitry Andric   case amdhsa::RESERVED0_OFFSET:
2150fe6060f1SDimitry Andric     // 4 reserved bytes, must be 0.
2151fe6060f1SDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 4);
2152fe6060f1SDimitry Andric     for (int I = 0; I < 4; ++I) {
2153fe6060f1SDimitry Andric       if (ReservedBytes[I] != 0) {
2154e8d8bef9SDimitry Andric         return MCDisassembler::Fail;
2155e8d8bef9SDimitry Andric       }
2156fe6060f1SDimitry Andric     }
2157e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2158e8d8bef9SDimitry Andric 
2159e8d8bef9SDimitry Andric   case amdhsa::KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET:
2160e8d8bef9SDimitry Andric     // KERNEL_CODE_ENTRY_BYTE_OFFSET
2161e8d8bef9SDimitry Andric     // So far no directive controls this for Code Object V3, so simply skip for
2162e8d8bef9SDimitry Andric     // disassembly.
2163e8d8bef9SDimitry Andric     DE.skip(Cursor, 8);
2164e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2165e8d8bef9SDimitry Andric 
2166e8d8bef9SDimitry Andric   case amdhsa::RESERVED1_OFFSET:
2167e8d8bef9SDimitry Andric     // 20 reserved bytes, must be 0.
2168e8d8bef9SDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 20);
2169e8d8bef9SDimitry Andric     for (int I = 0; I < 20; ++I) {
2170e8d8bef9SDimitry Andric       if (ReservedBytes[I] != 0) {
2171e8d8bef9SDimitry Andric         return MCDisassembler::Fail;
2172e8d8bef9SDimitry Andric       }
2173e8d8bef9SDimitry Andric     }
2174e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2175e8d8bef9SDimitry Andric 
2176e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC3_OFFSET:
2177e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2178fe013be4SDimitry Andric     return decodeCOMPUTE_PGM_RSRC3(FourByteBuffer, KdStream);
2179e8d8bef9SDimitry Andric 
2180e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC1_OFFSET:
2181e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2182fe013be4SDimitry Andric     return decodeCOMPUTE_PGM_RSRC1(FourByteBuffer, KdStream);
2183e8d8bef9SDimitry Andric 
2184e8d8bef9SDimitry Andric   case amdhsa::COMPUTE_PGM_RSRC2_OFFSET:
2185e8d8bef9SDimitry Andric     FourByteBuffer = DE.getU32(Cursor);
2186fe013be4SDimitry Andric     return decodeCOMPUTE_PGM_RSRC2(FourByteBuffer, KdStream);
2187e8d8bef9SDimitry Andric 
2188e8d8bef9SDimitry Andric   case amdhsa::KERNEL_CODE_PROPERTIES_OFFSET:
2189e8d8bef9SDimitry Andric     using namespace amdhsa;
2190e8d8bef9SDimitry Andric     TwoByteBuffer = DE.getU16(Cursor);
2191e8d8bef9SDimitry Andric 
2192fe6060f1SDimitry Andric     if (!hasArchitectedFlatScratch())
2193e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_buffer",
2194e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER);
2195e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_ptr",
2196e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR);
2197e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_queue_ptr",
2198e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR);
2199e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_segment_ptr",
2200e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR);
2201e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_id",
2202e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID);
2203fe6060f1SDimitry Andric     if (!hasArchitectedFlatScratch())
2204e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_flat_scratch_init",
2205e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT);
2206e8d8bef9SDimitry Andric     PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_size",
2207e8d8bef9SDimitry Andric                     KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE);
2208e8d8bef9SDimitry Andric 
2209e8d8bef9SDimitry Andric     if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED0)
2210e8d8bef9SDimitry Andric       return MCDisassembler::Fail;
2211e8d8bef9SDimitry Andric 
2212e8d8bef9SDimitry Andric     // Reserved for GFX9
2213e8d8bef9SDimitry Andric     if (isGFX9() &&
2214e8d8bef9SDimitry Andric         (TwoByteBuffer & KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32)) {
2215e8d8bef9SDimitry Andric       return MCDisassembler::Fail;
2216e8d8bef9SDimitry Andric     } else if (isGFX10Plus()) {
2217e8d8bef9SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_wavefront_size32",
2218e8d8bef9SDimitry Andric                       KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
2219e8d8bef9SDimitry Andric     }
2220e8d8bef9SDimitry Andric 
2221a58f00eaSDimitry Andric     // FIXME: We should be looking at the ELF header ABI version for this.
2222a58f00eaSDimitry Andric     if (AMDGPU::getDefaultAMDHSACodeObjectVersion() >= AMDGPU::AMDHSA_COV5)
2223fcaf7f86SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_uses_dynamic_stack",
2224fcaf7f86SDimitry Andric                       KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK);
2225fcaf7f86SDimitry Andric 
2226e8d8bef9SDimitry Andric     if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED1)
2227e8d8bef9SDimitry Andric       return MCDisassembler::Fail;
2228e8d8bef9SDimitry Andric 
2229e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2230e8d8bef9SDimitry Andric 
2231c9157d92SDimitry Andric   case amdhsa::KERNARG_PRELOAD_OFFSET:
2232c9157d92SDimitry Andric     using namespace amdhsa;
2233c9157d92SDimitry Andric     TwoByteBuffer = DE.getU16(Cursor);
2234c9157d92SDimitry Andric     if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_LENGTH) {
2235c9157d92SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_length",
2236c9157d92SDimitry Andric                       KERNARG_PRELOAD_SPEC_LENGTH);
2237c9157d92SDimitry Andric     }
2238c9157d92SDimitry Andric 
2239c9157d92SDimitry Andric     if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_OFFSET) {
2240c9157d92SDimitry Andric       PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_offset",
2241c9157d92SDimitry Andric                       KERNARG_PRELOAD_SPEC_OFFSET);
2242c9157d92SDimitry Andric     }
2243c9157d92SDimitry Andric     return MCDisassembler::Success;
2244c9157d92SDimitry Andric 
2245c9157d92SDimitry Andric   case amdhsa::RESERVED3_OFFSET:
2246c9157d92SDimitry Andric     // 4 bytes from here are reserved, must be 0.
2247c9157d92SDimitry Andric     ReservedBytes = DE.getBytes(Cursor, 4);
2248c9157d92SDimitry Andric     for (int I = 0; I < 4; ++I) {
2249e8d8bef9SDimitry Andric       if (ReservedBytes[I] != 0)
2250e8d8bef9SDimitry Andric         return MCDisassembler::Fail;
2251e8d8bef9SDimitry Andric     }
2252e8d8bef9SDimitry Andric     return MCDisassembler::Success;
2253e8d8bef9SDimitry Andric 
2254e8d8bef9SDimitry Andric   default:
2255e8d8bef9SDimitry Andric     llvm_unreachable("Unhandled index. Case statements cover everything.");
2256e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2257e8d8bef9SDimitry Andric   }
2258e8d8bef9SDimitry Andric #undef PRINT_DIRECTIVE
2259e8d8bef9SDimitry Andric }
2260e8d8bef9SDimitry Andric 
decodeKernelDescriptor(StringRef KdName,ArrayRef<uint8_t> Bytes,uint64_t KdAddress) const2261e8d8bef9SDimitry Andric MCDisassembler::DecodeStatus AMDGPUDisassembler::decodeKernelDescriptor(
2262e8d8bef9SDimitry Andric     StringRef KdName, ArrayRef<uint8_t> Bytes, uint64_t KdAddress) const {
2263e8d8bef9SDimitry Andric   // CP microcode requires the kernel descriptor to be 64 aligned.
2264e8d8bef9SDimitry Andric   if (Bytes.size() != 64 || KdAddress % 64 != 0)
2265e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2266e8d8bef9SDimitry Andric 
2267fe013be4SDimitry Andric   // FIXME: We can't actually decode "in order" as is done below, as e.g. GFX10
2268fe013be4SDimitry Andric   // requires us to know the setting of .amdhsa_wavefront_size32 in order to
2269fe013be4SDimitry Andric   // accurately produce .amdhsa_next_free_vgpr, and they appear in the wrong
2270fe013be4SDimitry Andric   // order. Workaround this by first looking up .amdhsa_wavefront_size32 here
2271fe013be4SDimitry Andric   // when required.
2272fe013be4SDimitry Andric   if (isGFX10Plus()) {
2273fe013be4SDimitry Andric     uint16_t KernelCodeProperties =
2274fe013be4SDimitry Andric         support::endian::read16(&Bytes[amdhsa::KERNEL_CODE_PROPERTIES_OFFSET],
2275c9157d92SDimitry Andric                                 llvm::endianness::little);
2276fe013be4SDimitry Andric     EnableWavefrontSize32 =
2277fe013be4SDimitry Andric         AMDHSA_BITS_GET(KernelCodeProperties,
2278fe013be4SDimitry Andric                         amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
2279fe013be4SDimitry Andric   }
2280fe013be4SDimitry Andric 
2281e8d8bef9SDimitry Andric   std::string Kd;
2282e8d8bef9SDimitry Andric   raw_string_ostream KdStream(Kd);
2283e8d8bef9SDimitry Andric   KdStream << ".amdhsa_kernel " << KdName << '\n';
2284e8d8bef9SDimitry Andric 
2285e8d8bef9SDimitry Andric   DataExtractor::Cursor C(0);
2286e8d8bef9SDimitry Andric   while (C && C.tell() < Bytes.size()) {
2287e8d8bef9SDimitry Andric     MCDisassembler::DecodeStatus Status =
2288e8d8bef9SDimitry Andric         decodeKernelDescriptorDirective(C, Bytes, KdStream);
2289e8d8bef9SDimitry Andric 
2290e8d8bef9SDimitry Andric     cantFail(C.takeError());
2291e8d8bef9SDimitry Andric 
2292e8d8bef9SDimitry Andric     if (Status == MCDisassembler::Fail)
2293e8d8bef9SDimitry Andric       return MCDisassembler::Fail;
2294e8d8bef9SDimitry Andric   }
2295e8d8bef9SDimitry Andric   KdStream << ".end_amdhsa_kernel\n";
2296e8d8bef9SDimitry Andric   outs() << KdStream.str();
2297e8d8bef9SDimitry Andric   return MCDisassembler::Success;
2298e8d8bef9SDimitry Andric }
2299e8d8bef9SDimitry Andric 
2300bdd1243dSDimitry Andric std::optional<MCDisassembler::DecodeStatus>
onSymbolStart(SymbolInfoTy & Symbol,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CStream) const2301e8d8bef9SDimitry Andric AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
2302e8d8bef9SDimitry Andric                                   ArrayRef<uint8_t> Bytes, uint64_t Address,
2303e8d8bef9SDimitry Andric                                   raw_ostream &CStream) const {
2304e8d8bef9SDimitry Andric   // Right now only kernel descriptor needs to be handled.
2305e8d8bef9SDimitry Andric   // We ignore all other symbols for target specific handling.
2306e8d8bef9SDimitry Andric   // TODO:
2307e8d8bef9SDimitry Andric   // Fix the spurious symbol issue for AMDGPU kernels. Exists for both Code
2308e8d8bef9SDimitry Andric   // Object V2 and V3 when symbols are marked protected.
2309e8d8bef9SDimitry Andric 
2310e8d8bef9SDimitry Andric   // amd_kernel_code_t for Code Object V2.
2311e8d8bef9SDimitry Andric   if (Symbol.Type == ELF::STT_AMDGPU_HSA_KERNEL) {
2312e8d8bef9SDimitry Andric     Size = 256;
2313e8d8bef9SDimitry Andric     return MCDisassembler::Fail;
2314e8d8bef9SDimitry Andric   }
2315e8d8bef9SDimitry Andric 
2316e8d8bef9SDimitry Andric   // Code Object V3 kernel descriptors.
2317e8d8bef9SDimitry Andric   StringRef Name = Symbol.Name;
2318c9157d92SDimitry Andric   if (Symbol.Type == ELF::STT_OBJECT && Name.ends_with(StringRef(".kd"))) {
2319e8d8bef9SDimitry Andric     Size = 64; // Size = 64 regardless of success or failure.
2320e8d8bef9SDimitry Andric     return decodeKernelDescriptor(Name.drop_back(3), Bytes, Address);
2321e8d8bef9SDimitry Andric   }
2322bdd1243dSDimitry Andric   return std::nullopt;
23230b57cec5SDimitry Andric }
23240b57cec5SDimitry Andric 
23250b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23260b57cec5SDimitry Andric // AMDGPUSymbolizer
23270b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric // Try to find symbol name for specified label
tryAddingSymbolicOperand(MCInst & Inst,raw_ostream &,int64_t Value,uint64_t,bool IsBranch,uint64_t,uint64_t,uint64_t)233081ad6265SDimitry Andric bool AMDGPUSymbolizer::tryAddingSymbolicOperand(
233181ad6265SDimitry Andric     MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value,
233281ad6265SDimitry Andric     uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/,
233381ad6265SDimitry Andric     uint64_t /*OpSize*/, uint64_t /*InstSize*/) {
23340b57cec5SDimitry Andric 
23350b57cec5SDimitry Andric   if (!IsBranch) {
23360b57cec5SDimitry Andric     return false;
23370b57cec5SDimitry Andric   }
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric   auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
23400b57cec5SDimitry Andric   if (!Symbols)
23410b57cec5SDimitry Andric     return false;
23420b57cec5SDimitry Andric 
2343e8d8bef9SDimitry Andric   auto Result = llvm::find_if(*Symbols, [Value](const SymbolInfoTy &Val) {
2344e8d8bef9SDimitry Andric     return Val.Addr == static_cast<uint64_t>(Value) &&
2345e8d8bef9SDimitry Andric            Val.Type == ELF::STT_NOTYPE;
23460b57cec5SDimitry Andric   });
23470b57cec5SDimitry Andric   if (Result != Symbols->end()) {
23485ffd83dbSDimitry Andric     auto *Sym = Ctx.getOrCreateSymbol(Result->Name);
23490b57cec5SDimitry Andric     const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);
23500b57cec5SDimitry Andric     Inst.addOperand(MCOperand::createExpr(Add));
23510b57cec5SDimitry Andric     return true;
23520b57cec5SDimitry Andric   }
2353fe6060f1SDimitry Andric   // Add to list of referenced addresses, so caller can synthesize a label.
2354fe6060f1SDimitry Andric   ReferencedAddresses.push_back(static_cast<uint64_t>(Value));
23550b57cec5SDimitry Andric   return false;
23560b57cec5SDimitry Andric }
23570b57cec5SDimitry Andric 
tryAddingPcLoadReferenceComment(raw_ostream & cStream,int64_t Value,uint64_t Address)23580b57cec5SDimitry Andric void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
23590b57cec5SDimitry Andric                                                        int64_t Value,
23600b57cec5SDimitry Andric                                                        uint64_t Address) {
23610b57cec5SDimitry Andric   llvm_unreachable("unimplemented");
23620b57cec5SDimitry Andric }
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23650b57cec5SDimitry Andric // Initialization
23660b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
23670b57cec5SDimitry Andric 
createAMDGPUSymbolizer(const Triple &,LLVMOpInfoCallback,LLVMSymbolLookupCallback,void * DisInfo,MCContext * Ctx,std::unique_ptr<MCRelocationInfo> && RelInfo)23680b57cec5SDimitry Andric static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
23690b57cec5SDimitry Andric                               LLVMOpInfoCallback /*GetOpInfo*/,
23700b57cec5SDimitry Andric                               LLVMSymbolLookupCallback /*SymbolLookUp*/,
23710b57cec5SDimitry Andric                               void *DisInfo,
23720b57cec5SDimitry Andric                               MCContext *Ctx,
23730b57cec5SDimitry Andric                               std::unique_ptr<MCRelocationInfo> &&RelInfo) {
23740b57cec5SDimitry Andric   return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
23750b57cec5SDimitry Andric }
23760b57cec5SDimitry Andric 
createAMDGPUDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)23770b57cec5SDimitry Andric static MCDisassembler *createAMDGPUDisassembler(const Target &T,
23780b57cec5SDimitry Andric                                                 const MCSubtargetInfo &STI,
23790b57cec5SDimitry Andric                                                 MCContext &Ctx) {
23800b57cec5SDimitry Andric   return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());
23810b57cec5SDimitry Andric }
23820b57cec5SDimitry Andric 
LLVMInitializeAMDGPUDisassembler()2383480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAMDGPUDisassembler() {
23840b57cec5SDimitry Andric   TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),
23850b57cec5SDimitry Andric                                          createAMDGPUDisassembler);
23860b57cec5SDimitry Andric   TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),
23870b57cec5SDimitry Andric                                        createAMDGPUSymbolizer);
23880b57cec5SDimitry Andric }
2389