1//===- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA ---------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//===----------------------------------------------------------------------===//
10//
11/// \file
12///
13/// This file contains definition for AMDGPU ISA disassembler
14//
15//===----------------------------------------------------------------------===//
16
17// ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)?
18
19#include "Disassembler/AMDGPUDisassembler.h"
20#include "MCTargetDesc/AMDGPUMCExpr.h"
21#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
22#include "SIDefines.h"
23#include "SIRegisterInfo.h"
24#include "TargetInfo/AMDGPUTargetInfo.h"
25#include "Utils/AMDGPUAsmUtils.h"
26#include "Utils/AMDGPUBaseInfo.h"
27#include "llvm-c/DisassemblerTypes.h"
28#include "llvm/BinaryFormat/ELF.h"
29#include "llvm/MC/MCAsmInfo.h"
30#include "llvm/MC/MCContext.h"
31#include "llvm/MC/MCDecoder.h"
32#include "llvm/MC/MCDecoderOps.h"
33#include "llvm/MC/MCExpr.h"
34#include "llvm/MC/MCInstrDesc.h"
35#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCSubtargetInfo.h"
37#include "llvm/MC/TargetRegistry.h"
38#include "llvm/Support/AMDHSAKernelDescriptor.h"
39#include "llvm/Support/Compiler.h"
40
41using namespace llvm;
42using namespace llvm::MCD;
43
44#define DEBUG_TYPE "amdgpu-disassembler"
45
46#define SGPR_MAX \
47 (isGFX10Plus() ? AMDGPU::EncValues::SGPR_MAX_GFX10 \
48 : AMDGPU::EncValues::SGPR_MAX_SI)
49
50using DecodeStatus = llvm::MCDisassembler::DecodeStatus;
51
52static int64_t getInlineImmValF16(unsigned Imm);
53static int64_t getInlineImmValBF16(unsigned Imm);
54static int64_t getInlineImmVal32(unsigned Imm);
55static int64_t getInlineImmVal64(unsigned Imm);
56
57AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
58 MCContext &Ctx, MCInstrInfo const *MCII)
59 : MCDisassembler(STI, Ctx), MCII(MCII), MRI(*Ctx.getRegisterInfo()),
60 MAI(Ctx.getAsmInfo()),
61 HwModeRegClass(STI.getHwMode(type: MCSubtargetInfo::HwMode_RegInfo)),
62 TargetMaxInstBytes(MAI.getMaxInstLength(STI: &STI)),
63 TargetID(AMDGPU::createAMDGPUTargetID(STI, FeatureString: "")),
64 CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) {
65 // ToDo: AMDGPUDisassembler supports only VI ISA.
66 if (!STI.hasFeature(Feature: AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
67 reportFatalUsageError(reason: "disassembly not yet supported for subtarget");
68
69 for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
70 createConstantSymbolExpr(Id: Symbol, Val: Code);
71
72 UCVersionW64Expr = createConstantSymbolExpr(Id: "UC_VERSION_W64_BIT", Val: 0x2000);
73 UCVersionW32Expr = createConstantSymbolExpr(Id: "UC_VERSION_W32_BIT", Val: 0x4000);
74 UCVersionMDPExpr = createConstantSymbolExpr(Id: "UC_VERSION_MDP_BIT", Val: 0x8000);
75}
76
77void AMDGPUDisassembler::setABIVersion(unsigned Version) {
78 CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(ABIVersion: Version);
79}
80
81void AMDGPUDisassembler::emitTargetIDIfSupported(raw_ostream &OS,
82 unsigned EFlags) const {
83 OS << "\t.amdgcn_target \""
84 << STI.getTargetTriple().normalize(Form: Triple::CanonicalForm::FOUR_IDENT)
85 << '-';
86
87 // Get CPU name from ELF e_flags MACH field
88 unsigned MACH = EFlags & ELF::EF_AMDGPU_MACH;
89
90#define X(NUM, ENUM, NAME) \
91 case ELF::ENUM: \
92 OS << NAME; \
93 break;
94 switch (MACH) {
95 AMDGPU_MACH_LIST(X)
96 default:
97 OS << "unknown";
98 break;
99 }
100#undef X
101
102 // Add xnack and sramecc from ELF flags (v4 format)
103 if (CodeObjectVersion >= AMDGPU::AMDHSA_COV4) {
104 // Hardwired-on features are not selectable target-ID modifiers.
105 bool SramEccHardwiredOn = TargetID.isSramEccSupported() &&
106 !STI.hasFeature(Feature: AMDGPU::FeatureSRAMECCOnOffModes);
107 unsigned SrameccSetting = EFlags & ELF::EF_AMDGPU_FEATURE_SRAMECC_V4;
108 switch (SrameccSetting) {
109 case ELF::EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4:
110 break;
111 case ELF::EF_AMDGPU_FEATURE_SRAMECC_ANY_V4:
112 TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::Any);
113 break;
114 case ELF::EF_AMDGPU_FEATURE_SRAMECC_OFF_V4:
115 TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::Off);
116 if (!SramEccHardwiredOn)
117 OS << ":sramecc-";
118 break;
119 case ELF::EF_AMDGPU_FEATURE_SRAMECC_ON_V4:
120 TargetID.setSramEccSetting(AMDGPU::TargetIDSetting::On);
121 if (!SramEccHardwiredOn)
122 OS << ":sramecc+";
123 break;
124 }
125
126 // Targets that hardwire xnack on (e.g. gfx1250) don't expose it as a
127 // selectable modifier, so don't print it.
128 bool XnackHardwiredOn = TargetID.isXnackSupported() &&
129 !STI.hasFeature(Feature: AMDGPU::FeatureXNACKOnOffModes);
130 unsigned XnackSetting = EFlags & ELF::EF_AMDGPU_FEATURE_XNACK_V4;
131 switch (XnackSetting) {
132 case ELF::EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4:
133 break;
134 case ELF::EF_AMDGPU_FEATURE_XNACK_ANY_V4:
135 TargetID.setXnackSetting(AMDGPU::TargetIDSetting::Any);
136 break;
137 case ELF::EF_AMDGPU_FEATURE_XNACK_OFF_V4:
138 TargetID.setXnackSetting(AMDGPU::TargetIDSetting::Off);
139 if (!XnackHardwiredOn)
140 OS << ":xnack-";
141 break;
142 case ELF::EF_AMDGPU_FEATURE_XNACK_ON_V4:
143 TargetID.setXnackSetting(AMDGPU::TargetIDSetting::On);
144 if (!XnackHardwiredOn)
145 OS << ":xnack+";
146 break;
147 }
148 }
149
150 OS << "\"\n";
151}
152
153inline static MCDisassembler::DecodeStatus
154addOperand(MCInst &Inst, const MCOperand& Opnd) {
155 Inst.addOperand(Op: Opnd);
156 return Opnd.isValid() ?
157 MCDisassembler::Success :
158 MCDisassembler::Fail;
159}
160
161static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,
162 AMDGPU::OpName Name) {
163 int OpIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name);
164 if (OpIdx != -1) {
165 auto *I = MI.begin();
166 std::advance(i&: I, n: OpIdx);
167 MI.insert(I, Op);
168 }
169 return OpIdx;
170}
171
172static DecodeStatus decodeSOPPBrTarget(MCInst &Inst, uint64_t Imm,
173 uint64_t Addr,
174 const MCDisassembler *Decoder) {
175 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
176
177 // Our branches take a simm16.
178 int64_t Offset = SignExtend64<16>(x: Imm) * 4 + 4 + Addr;
179
180 if (DAsm->tryAddingSymbolicOperand(Inst, Value: Offset, Address: Addr, IsBranch: true, Offset: 2, OpSize: 2, InstSize: 0))
181 return MCDisassembler::Success;
182 return addOperand(Inst, Opnd: MCOperand::createImm(Val: Imm));
183}
184
185static DecodeStatus decodeSMEMOffset(MCInst &Inst, uint64_t Imm, uint64_t Addr,
186 const MCDisassembler *Decoder) {
187 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
188 int64_t Offset;
189 if (DAsm->isGFX12Plus()) { // GFX12 supports 24-bit signed offsets.
190 Offset = SignExtend64<24>(x: Imm);
191 } else if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets.
192 Offset = Imm & 0xFFFFF;
193 } else { // GFX9+ supports 21-bit signed offsets.
194 Offset = SignExtend64<21>(x: Imm);
195 }
196 return addOperand(Inst, Opnd: MCOperand::createImm(Val: Offset));
197}
198
199static DecodeStatus decodeBoolReg(MCInst &Inst, uint64_t Val, uint64_t Addr,
200 const MCDisassembler *Decoder) {
201 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
202 return addOperand(Inst,
203 Opnd: DAsm->decodeBoolReg(Inst, Val: static_cast<unsigned>(Val)));
204}
205
206static DecodeStatus decodeSplitBarrier(MCInst &Inst, uint64_t Val,
207 uint64_t Addr,
208 const MCDisassembler *Decoder) {
209 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
210 return addOperand(Inst,
211 Opnd: DAsm->decodeSplitBarrier(Inst, Val: static_cast<unsigned>(Val)));
212}
213
214static DecodeStatus decodeDpp8FI(MCInst &Inst, uint64_t Val, uint64_t Addr,
215 const MCDisassembler *Decoder) {
216 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
217 return addOperand(Inst, Opnd: DAsm->decodeDpp8FI(Val: static_cast<unsigned>(Val)));
218}
219
220#define DECODE_OPERAND(StaticDecoderName, DecoderName) \
221 static DecodeStatus StaticDecoderName(MCInst &Inst, uint64_t Imm, \
222 uint64_t /*Addr*/, \
223 const MCDisassembler *Decoder) { \
224 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \
225 return addOperand(Inst, DAsm->DecoderName(static_cast<unsigned>(Imm))); \
226 }
227
228// Decoder for registers, decode directly using RegClassID. Imm(8-bit) is
229// number of register. Used by VGPR only and AGPR only operands.
230#define DECODE_OPERAND_REG_8(RegClass) \
231 static DecodeStatus Decode##RegClass##RegisterClass( \
232 MCInst &Inst, uint64_t Imm, uint64_t /*Addr*/, \
233 const MCDisassembler *Decoder) { \
234 assert(Imm < (1 << 8) && "8-bit encoding"); \
235 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \
236 return addOperand(Inst, \
237 DAsm->createRegOperand(AMDGPU::RegClass##RegClassID, \
238 static_cast<unsigned>(Imm))); \
239 }
240
241#define DECODE_SrcOp(Name, EncSize, OpWidth, EncImm) \
242 static DecodeStatus Name(MCInst &Inst, uint64_t Imm, uint64_t /*Addr*/, \
243 const MCDisassembler *Decoder) { \
244 if (!isUInt<EncSize>(Imm)) \
245 return MCDisassembler::Fail; \
246 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \
247 return addOperand(Inst, DAsm->decodeSrcOp(Inst, OpWidth, \
248 static_cast<unsigned>(EncImm))); \
249 }
250
251static DecodeStatus decodeSrcOp(MCInst &Inst, unsigned EncSize,
252 unsigned OpWidth, uint64_t Imm, uint64_t EncImm,
253 const MCDisassembler *Decoder) {
254 assert(Imm < (1U << EncSize) && "Operand doesn't fit encoding!");
255 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
256 return addOperand(
257 Inst, Opnd: DAsm->decodeSrcOp(Inst, Width: OpWidth, Val: static_cast<unsigned>(EncImm)));
258}
259
260// Decode an indexed-resource (rsrcidx) 9-bit srsrc field into a 32-bit index
261// register. SGPRs are encoded as 128-251, VGPRs have bit 8 set.
262static DecodeStatus decodeRsrcRegOp(MCInst &Inst, unsigned Imm,
263 uint64_t /* Addr */,
264 const MCDisassembler *Decoder,
265 unsigned OpWidth) {
266 // Uniform-indexed resource. SGPR[0..123] encoded as 128-251.
267 if (Imm >= 128 && Imm < 256)
268 Imm -= 128;
269 return decodeSrcOp(Inst, EncSize: 9, OpWidth, Imm, EncImm: Imm, Decoder);
270}
271
272static DecodeStatus decodeRsrcReg128(MCInst &Inst, unsigned Imm,
273 uint64_t /* Addr */,
274 const MCDisassembler *Decoder) {
275 unsigned OpWidth = 32;
276 // 0-127: Uniform-direct resource in SGPRs (SReg_128).
277 if (Imm < 128)
278 OpWidth = 128;
279 return decodeRsrcRegOp(Inst, Imm, 0, Decoder, OpWidth);
280}
281
282static DecodeStatus decodeRsrcReg256(MCInst &Inst, unsigned Imm,
283 uint64_t /* Addr */,
284 const MCDisassembler *Decoder) {
285 unsigned OpWidth = 32;
286 // 0-127: Uniform-direct resource in SGPRs (SReg_256).
287 if (Imm < 128)
288 OpWidth = 256;
289 return decodeRsrcRegOp(Inst, Imm, 0, Decoder, OpWidth);
290}
291
292// Decoder for registers. Imm(7-bit) is number of register, uses decodeSrcOp to
293// get register class. Used by SGPR only operands.
294#define DECODE_OPERAND_SREG_7(RegClass, OpWidth) \
295 DECODE_SrcOp(Decode##RegClass##RegisterClass, 7, OpWidth, Imm)
296
297#define DECODE_OPERAND_SREG_8(RegClass, OpWidth) \
298 DECODE_SrcOp(Decode##RegClass##RegisterClass, 8, OpWidth, Imm)
299
300#define DECODE_OPERAND_SREG_9(RegClass, OpWidth) \
301 DECODE_SrcOp(Decode##RegClass##RegisterClass, 9, OpWidth, Imm)
302
303// Decoder for registers. Imm(10-bit): Imm{7-0} is number of register,
304// Imm{9} is acc(agpr or vgpr) Imm{8} should be 0 (see VOP3Pe_SMFMAC).
305// Set Imm{8} to 1 (IS_VGPR) to decode using 'enum10' from decodeSrcOp.
306// Used by AV_ register classes (AGPR or VGPR only register operands).
307template <unsigned OpWidth>
308static DecodeStatus decodeAV10(MCInst &Inst, uint64_t Imm, uint64_t /* Addr */,
309 const MCDisassembler *Decoder) {
310 return decodeSrcOp(Inst, EncSize: 10, OpWidth, Imm, EncImm: Imm | AMDGPU::EncValues::IS_VGPR,
311 Decoder);
312}
313
314// Decoder for Src(9-bit encoding) registers only.
315template <unsigned OpWidth>
316static DecodeStatus decodeSrcReg9(MCInst &Inst, uint64_t Imm,
317 uint64_t /* Addr */,
318 const MCDisassembler *Decoder) {
319 return decodeSrcOp(Inst, EncSize: 9, OpWidth, Imm, EncImm: Imm, Decoder);
320}
321
322// Decoder for Src(9-bit encoding) AGPR, register number encoded in 9bits, set
323// Imm{9} to 1 (set acc) and decode using 'enum10' from decodeSrcOp, registers
324// only.
325template <unsigned OpWidth>
326static DecodeStatus decodeSrcA9(MCInst &Inst, uint64_t Imm, uint64_t /* Addr */,
327 const MCDisassembler *Decoder) {
328 // A clear Imm{8} names an SGPR or an inline constant, which this
329 // register-only operand cannot hold.
330 if (!(Imm & AMDGPU::EncValues::IS_VGPR))
331 return MCDisassembler::Fail;
332 return decodeSrcOp(Inst, EncSize: 9, OpWidth, Imm, EncImm: Imm | 512, Decoder);
333}
334
335// Decoder for 'enum10' from decodeSrcOp, Imm{0-8} is 9-bit Src encoding
336// Imm{9} is acc, registers only.
337template <unsigned OpWidth>
338static DecodeStatus decodeSrcAV10(MCInst &Inst, uint64_t Imm,
339 uint64_t /* Addr */,
340 const MCDisassembler *Decoder) {
341 // A clear Imm{8} names an SGPR or an inline constant, which this
342 // register-only operand cannot hold.
343 if (!(Imm & AMDGPU::EncValues::IS_VGPR))
344 return MCDisassembler::Fail;
345 return decodeSrcOp(Inst, EncSize: 10, OpWidth, Imm, EncImm: Imm, Decoder);
346}
347
348// Decoder for RegisterOperands using 9-bit Src encoding. Operand can be
349// register from RegClass or immediate. Registers that don't belong to RegClass
350// will be decoded and InstPrinter will report warning. Immediate will be
351// decoded into constant matching the OperandType (important for floating point
352// types).
353template <unsigned OpWidth>
354static DecodeStatus decodeSrcRegOrImm9(MCInst &Inst, uint64_t Imm,
355 uint64_t /* Addr */,
356 const MCDisassembler *Decoder) {
357 return decodeSrcOp(Inst, EncSize: 9, OpWidth, Imm, EncImm: Imm, Decoder);
358}
359
360// Decoder for Src(9-bit encoding) AGPR or immediate. Set Imm{9} to 1 (set acc)
361// and decode using 'enum10' from decodeSrcOp.
362template <unsigned OpWidth>
363static DecodeStatus decodeSrcRegOrImmA9(MCInst &Inst, uint64_t Imm,
364 uint64_t /* Addr */,
365 const MCDisassembler *Decoder) {
366 return decodeSrcOp(Inst, EncSize: 9, OpWidth, Imm, EncImm: Imm | 512, Decoder);
367}
368
369// Default decoders generated by tablegen: 'Decode<RegClass>RegisterClass'
370// when RegisterClass is used as an operand. Most often used for destination
371// operands.
372
373DECODE_OPERAND_REG_8(VGPR_32)
374DECODE_OPERAND_REG_8(VGPR_32_Lo128)
375DECODE_OPERAND_REG_8(VReg_64)
376DECODE_OPERAND_REG_8(VReg_96)
377DECODE_OPERAND_REG_8(VReg_128)
378DECODE_OPERAND_REG_8(VReg_192)
379DECODE_OPERAND_REG_8(VReg_256)
380DECODE_OPERAND_REG_8(VReg_288)
381DECODE_OPERAND_REG_8(VReg_320)
382DECODE_OPERAND_REG_8(VReg_352)
383DECODE_OPERAND_REG_8(VReg_384)
384DECODE_OPERAND_REG_8(VReg_512)
385DECODE_OPERAND_REG_8(VReg_1024)
386
387DECODE_OPERAND_SREG_7(SReg_32, 32)
388DECODE_OPERAND_SREG_7(SReg_32_XM0, 32)
389DECODE_OPERAND_SREG_7(SReg_32_XEXEC, 32)
390DECODE_OPERAND_SREG_7(SReg_32_XM0_XEXEC, 32)
391DECODE_OPERAND_SREG_7(SReg_32_XEXEC_HI, 32)
392DECODE_OPERAND_SREG_7(SReg_64_XEXEC, 64)
393DECODE_OPERAND_SREG_7(SReg_64_XEXEC_XNULL, 64)
394DECODE_OPERAND_SREG_7(SReg_96, 96)
395DECODE_OPERAND_SREG_7(SReg_128, 128)
396DECODE_OPERAND_SREG_7(SReg_256, 256)
397DECODE_OPERAND_SREG_7(SReg_256_XNULL, 256)
398DECODE_OPERAND_SREG_7(SReg_512, 512)
399
400DECODE_OPERAND_SREG_8(SReg_64, 64)
401
402// GFX13 VBUFFER instructions use a 9-bit srsrc field. For the non-indexed form
403// the two extra MSBs are always 0, so the value still decodes to an SReg_128.
404DECODE_OPERAND_SREG_9(SReg_128_XNULL, 128)
405
406DECODE_OPERAND_REG_8(AGPR_32)
407DECODE_OPERAND_REG_8(AReg_64)
408DECODE_OPERAND_REG_8(AReg_128)
409DECODE_OPERAND_REG_8(AReg_256)
410DECODE_OPERAND_REG_8(AReg_512)
411DECODE_OPERAND_REG_8(AReg_1024)
412
413static DecodeStatus DecodeVGPR_16RegisterClass(MCInst &Inst, uint64_t Imm,
414 uint64_t /*Addr*/,
415 const MCDisassembler *Decoder) {
416 assert(isUInt<10>(Imm) && "10-bit encoding expected");
417 assert((Imm & (1 << 8)) == 0 && "Imm{8} should not be used");
418
419 bool IsHi = Imm & (1 << 9);
420 unsigned RegIdx = static_cast<unsigned>(Imm & 0xff);
421 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
422 return addOperand(Inst, Opnd: DAsm->createVGPR16Operand(RegIdx, IsHi));
423}
424
425static DecodeStatus
426DecodeVGPR_16_Lo128RegisterClass(MCInst &Inst, uint64_t Imm, uint64_t /*Addr*/,
427 const MCDisassembler *Decoder) {
428 assert(isUInt<8>(Imm) && "8-bit encoding expected");
429
430 bool IsHi = Imm & (1 << 7);
431 unsigned RegIdx = static_cast<unsigned>(Imm & 0x7f);
432 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
433 return addOperand(Inst, Opnd: DAsm->createVGPR16Operand(RegIdx, IsHi));
434}
435
436template <unsigned OpWidth>
437static DecodeStatus decodeOperand_VSrcT16_Lo128(MCInst &Inst, uint64_t Imm,
438 uint64_t /*Addr*/,
439 const MCDisassembler *Decoder) {
440 assert(isUInt<9>(Imm) && "9-bit encoding expected");
441
442 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
443 if (Imm & AMDGPU::EncValues::IS_VGPR) {
444 bool IsHi = Imm & (1 << 7);
445 unsigned RegIdx = static_cast<unsigned>(Imm & 0x7f);
446 return addOperand(Inst, Opnd: DAsm->createVGPR16Operand(RegIdx, IsHi));
447 }
448 return addOperand(
449 Inst, Opnd: DAsm->decodeNonVGPRSrcOp(Inst, Width: OpWidth,
450 Val: static_cast<unsigned>(Imm & 0xFF)));
451}
452
453template <unsigned OpWidth>
454static DecodeStatus decodeOperand_VSrcT16(MCInst &Inst, uint64_t Imm,
455 uint64_t /*Addr*/,
456 const MCDisassembler *Decoder) {
457 assert(isUInt<10>(Imm) && "10-bit encoding expected");
458
459 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
460 if (Imm & AMDGPU::EncValues::IS_VGPR) {
461 bool IsHi = Imm & (1 << 9);
462 unsigned RegIdx = static_cast<unsigned>(Imm & 0xff);
463 return addOperand(Inst, Opnd: DAsm->createVGPR16Operand(RegIdx, IsHi));
464 }
465 return addOperand(
466 Inst, Opnd: DAsm->decodeNonVGPRSrcOp(Inst, Width: OpWidth,
467 Val: static_cast<unsigned>(Imm & 0xFF)));
468}
469
470static DecodeStatus decodeOperand_VGPR_16(MCInst &Inst, uint64_t Imm,
471 uint64_t /*Addr*/,
472 const MCDisassembler *Decoder) {
473 assert(isUInt<10>(Imm) && "10-bit encoding expected");
474 if (!(Imm & AMDGPU::EncValues::IS_VGPR))
475 return MCDisassembler::Fail;
476
477 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
478
479 bool IsHi = Imm & (1 << 9);
480 unsigned RegIdx = static_cast<unsigned>(Imm & 0xff);
481 return addOperand(Inst, Opnd: DAsm->createVGPR16Operand(RegIdx, IsHi));
482}
483
484static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, uint64_t Imm,
485 uint64_t Addr,
486 const MCDisassembler *Decoder) {
487 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
488 return addOperand(
489 Inst, Opnd: DAsm->decodeMandatoryLiteralConstant(Imm: static_cast<unsigned>(Imm)));
490}
491
492static DecodeStatus decodeOperand_KImmFP64(MCInst &Inst, uint64_t Imm,
493 uint64_t Addr,
494 const MCDisassembler *Decoder) {
495 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
496 return addOperand(Inst, Opnd: DAsm->decodeMandatoryLiteral64Constant(Imm));
497}
498
499static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, uint64_t Val,
500 uint64_t Addr, const void *Decoder) {
501 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
502 return addOperand(Inst,
503 Opnd: DAsm->decodeVOPDDstYOp(Inst, Val: static_cast<unsigned>(Val)));
504}
505
506static DecodeStatus decodeAVLdSt(MCInst &Inst, uint64_t Imm, unsigned Opw,
507 const MCDisassembler *Decoder) {
508 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
509 return addOperand(
510 Inst, Opnd: DAsm->decodeSrcOp(Inst, Width: Opw, Val: static_cast<unsigned>(Imm | 256)));
511}
512
513template <unsigned Opw>
514static DecodeStatus decodeAVLdSt(MCInst &Inst, uint64_t Imm,
515 uint64_t /* Addr */,
516 const MCDisassembler *Decoder) {
517 return decodeAVLdSt(Inst, Imm, Opw, Decoder);
518}
519
520static DecodeStatus decodeOperand_VSrc_f64(MCInst &Inst, uint64_t Imm,
521 uint64_t Addr,
522 const MCDisassembler *Decoder) {
523 assert(Imm < (1 << 9) && "9-bit encoding");
524 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
525 return addOperand(Inst,
526 Opnd: DAsm->decodeSrcOp(Inst, Width: 64, Val: static_cast<unsigned>(Imm)));
527}
528
529#define DECODE_SDWA(DecName) \
530DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)
531
532DECODE_SDWA(Src32)
533DECODE_SDWA(Src16)
534DECODE_SDWA(VopcDst)
535
536#define DECODE_SDWA_IMM_FIELD(Name, MaxImm) \
537 static DecodeStatus Name(MCInst &Inst, uint64_t Imm, uint64_t /* Addr */, \
538 const MCDisassembler * /* Decoder */) { \
539 if (Imm > (MaxImm)) \
540 return MCDisassembler::Fail; \
541 return addOperand(Inst, MCOperand::createImm(Imm)); \
542 }
543
544// The 3-bit SDWA sel fields only define values up to DWORD; 7 is reserved.
545DECODE_SDWA_IMM_FIELD(decodeSDWASel, AMDGPU::SDWA::SdwaSel::DWORD)
546// The 2-bit SDWA dst_unused field only defines values up to UNUSED_PRESERVE;
547// 3 is reserved.
548DECODE_SDWA_IMM_FIELD(decodeSDWADstUnused,
549 AMDGPU::SDWA::DstUnused::UNUSED_PRESERVE)
550#undef DECODE_SDWA_IMM_FIELD
551
552static DecodeStatus decodeVersionImm(MCInst &Inst, uint64_t Imm,
553 uint64_t /* Addr */,
554 const MCDisassembler *Decoder) {
555 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
556 return addOperand(Inst, Opnd: DAsm->decodeVersionImm(Imm: static_cast<unsigned>(Imm)));
557}
558
559#include "AMDGPUGenDisassemblerTables.inc"
560
561namespace {
562// Define bitwidths for various types used to instantiate the decoder.
563template <> constexpr uint32_t InsnBitWidth<uint32_t> = 32;
564template <> constexpr uint32_t InsnBitWidth<uint64_t> = 64;
565template <> constexpr uint32_t InsnBitWidth<std::bitset<96>> = 96;
566template <> constexpr uint32_t InsnBitWidth<std::bitset<128>> = 128;
567} // namespace
568
569//===----------------------------------------------------------------------===//
570//
571//===----------------------------------------------------------------------===//
572
573template <typename InsnType>
574DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t *Table, MCInst &MI,
575 InsnType Inst, uint64_t Address,
576 raw_ostream &Comments) const {
577 assert(MI.getOpcode() == 0);
578 assert(MI.getNumOperands() == 0);
579 MCInst TmpInst;
580 HasLiteral = false;
581 const auto SavedBytes = Bytes;
582
583 SmallString<64> LocalComments;
584 raw_svector_ostream LocalCommentStream(LocalComments);
585 CommentStream = &LocalCommentStream;
586
587 DecodeStatus Res =
588 decodeInstruction(Table, TmpInst, Inst, Address, this, STI);
589 if (Res != MCDisassembler::Fail && !decodeImmOperands(MI&: TmpInst, MCII: *MCII))
590 Res = MCDisassembler::Fail;
591
592 CommentStream = nullptr;
593
594 if (Res != MCDisassembler::Fail) {
595 MI = TmpInst;
596 Comments << LocalComments;
597 return MCDisassembler::Success;
598 }
599 Bytes = SavedBytes;
600 return MCDisassembler::Fail;
601}
602
603template <typename InsnType>
604DecodeStatus
605AMDGPUDisassembler::tryDecodeInst(const uint8_t *Table1, const uint8_t *Table2,
606 MCInst &MI, InsnType Inst, uint64_t Address,
607 raw_ostream &Comments) const {
608 for (const uint8_t *T : {Table1, Table2}) {
609 if (DecodeStatus Res = tryDecodeInst(T, MI, Inst, Address, Comments))
610 return Res;
611 }
612 return MCDisassembler::Fail;
613}
614
615template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {
616 assert(Bytes.size() >= sizeof(T));
617 const auto Res =
618 support::endian::read<T, llvm::endianness::little>(Bytes.data());
619 Bytes = Bytes.slice(N: sizeof(T));
620 return Res;
621}
622
623static inline std::bitset<96> eat12Bytes(ArrayRef<uint8_t> &Bytes) {
624 using namespace llvm::support::endian;
625 assert(Bytes.size() >= 12);
626 std::bitset<96> Lo(read<uint64_t, endianness::little>(P: Bytes.data()));
627 Bytes = Bytes.slice(N: 8);
628 std::bitset<96> Hi(read<uint32_t, endianness::little>(P: Bytes.data()));
629 Bytes = Bytes.slice(N: 4);
630 return (Hi << 64) | Lo;
631}
632
633static inline std::bitset<128> eat16Bytes(ArrayRef<uint8_t> &Bytes) {
634 using namespace llvm::support::endian;
635 assert(Bytes.size() >= 16);
636 std::bitset<128> Lo(read<uint64_t, endianness::little>(P: Bytes.data()));
637 Bytes = Bytes.slice(N: 8);
638 std::bitset<128> Hi(read<uint64_t, endianness::little>(P: Bytes.data()));
639 Bytes = Bytes.slice(N: 8);
640 return (Hi << 64) | Lo;
641}
642
643bool AMDGPUDisassembler::decodeImmOperands(MCInst &MI,
644 const MCInstrInfo &MCII) const {
645 const MCInstrDesc &Desc = MCII.get(Opcode: MI.getOpcode());
646 for (auto [OpNo, OpDesc] : enumerate(First: Desc.operands())) {
647 if (OpNo >= MI.getNumOperands())
648 continue;
649
650 // TODO: Fix V_DUAL_FMAMK_F32_X_FMAAK_F32_gfx12 vsrc operands,
651 // defined to take VGPR_32, but in reality allowing inline constants.
652 bool IsSrc = AMDGPU::OPERAND_SRC_FIRST <= OpDesc.OperandType &&
653 OpDesc.OperandType <= AMDGPU::OPERAND_SRC_LAST;
654 if (!IsSrc && OpDesc.OperandType != MCOI::OPERAND_REGISTER)
655 continue;
656
657 MCOperand &Op = MI.getOperand(i: OpNo);
658 if (!Op.isImm())
659 continue;
660 int64_t Imm = Op.getImm();
661 if (AMDGPU::EncValues::INLINE_INTEGER_C_MIN <= Imm &&
662 Imm <= AMDGPU::EncValues::INLINE_INTEGER_C_MAX) {
663 Op = decodeIntImmed(Imm);
664 continue;
665 }
666
667 if (Imm == AMDGPU::EncValues::LITERAL_CONST) {
668 Op = decodeLiteralConstant(Desc, OpDesc);
669 if (!Op.isValid())
670 return false;
671 continue;
672 }
673
674 if (AMDGPU::EncValues::INLINE_FLOATING_C_MIN <= Imm &&
675 Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX) {
676 switch (OpDesc.OperandType) {
677 case AMDGPU::OPERAND_REG_IMM_NOINLINE_FP16:
678 case AMDGPU::OPERAND_REG_IMM_NOINLINE_V2FP16:
679 // Inline constant encodings are not allowed for NOINLINE operand types.
680 // Keep the raw encoding value.
681 continue;
682 case AMDGPU::OPERAND_REG_IMM_BF16:
683 case AMDGPU::OPERAND_REG_IMM_V2BF16:
684 case AMDGPU::OPERAND_REG_INLINE_C_BF16:
685 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
686 Imm = getInlineImmValBF16(Imm);
687 break;
688 case AMDGPU::OPERAND_REG_IMM_FP16:
689 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
690 Imm = getInlineImmValF16(Imm);
691 break;
692 case AMDGPU::OPERAND_REG_IMM_V2FP16:
693 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
694 Imm = getInlineImmValF16(Imm);
695 break;
696 case AMDGPU::OPERAND_REG_IMM_V2FP16_SPLAT: {
697 // V_PK_FMAC_F16 on GFX11+ duplicates the f16 inline constant to both
698 // halves, so we need to produce the duplicated value for correct
699 // round-trip.
700 if (isGFX11Plus()) {
701 int64_t F16Val = getInlineImmValF16(Imm);
702 Imm = (F16Val << 16) | (F16Val & 0xFFFF);
703 } else {
704 Imm = getInlineImmValF16(Imm);
705 }
706 break;
707 }
708 case AMDGPU::OPERAND_REG_IMM_FP64:
709 case AMDGPU::OPERAND_REG_IMM_INT64:
710 case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
711 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
712 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
713 case AMDGPU::OPERAND_REG_IMM_V2FP64:
714 case AMDGPU::OPERAND_REG_IMM_V2INT64:
715 Imm = getInlineImmVal64(Imm);
716 break;
717 default:
718 Imm = getInlineImmVal32(Imm);
719 }
720 Op.setImm(Imm);
721 }
722 }
723 return true;
724}
725
726DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
727 ArrayRef<uint8_t> Bytes_,
728 uint64_t Address,
729 raw_ostream &CS) const {
730 unsigned MaxInstBytesNum = std::min(a: (size_t)TargetMaxInstBytes, b: Bytes_.size());
731 Bytes = Bytes_.slice(N: 0, M: MaxInstBytesNum);
732
733 // In case the opcode is not recognized we'll assume a Size of 4 bytes (unless
734 // there are fewer bytes left). This will be overridden on success.
735 Size = std::min(a: (size_t)4, b: Bytes_.size());
736
737 do {
738 // ToDo: better to switch encoding length using some bit predicate
739 // but it is unknown yet, so try all we can
740
741 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2
742 // encodings
743 if (isGFX1250Plus() && Bytes.size() >= 16) {
744 std::bitset<128> DecW = eat16Bytes(Bytes);
745 if (tryDecodeInst(Table: DecoderTableGFX1250128, MI, Inst: DecW, Address, Comments&: CS))
746 break;
747 Bytes = Bytes_.slice(N: 0, M: MaxInstBytesNum);
748 }
749
750 if (isGFX11Plus() && Bytes.size() >= 12) {
751 std::bitset<96> DecW = eat12Bytes(Bytes);
752
753 if (isGFX1170() &&
754 tryDecodeInst(Table1: DecoderTableGFX117096, Table2: DecoderTableGFX1170_FAKE1696, MI,
755 Inst: DecW, Address, Comments&: CS))
756 break;
757
758 if (isGFX11() &&
759 tryDecodeInst(Table1: DecoderTableGFX1196, Table2: DecoderTableGFX11_FAKE1696, MI,
760 Inst: DecW, Address, Comments&: CS))
761 break;
762
763 if (isGFX1250() &&
764 tryDecodeInst(Table1: DecoderTableGFX125096, Table2: DecoderTableGFX1250_FAKE1696, MI,
765 Inst: DecW, Address, Comments&: CS))
766 break;
767
768 if (isGFX12() &&
769 tryDecodeInst(Table1: DecoderTableGFX1296, Table2: DecoderTableGFX12_FAKE1696, MI,
770 Inst: DecW, Address, Comments&: CS))
771 break;
772
773 if (isGFX12() &&
774 tryDecodeInst(Table: DecoderTableGFX12W6496, MI, Inst: DecW, Address, Comments&: CS))
775 break;
776
777 if (isGFX13() &&
778 tryDecodeInst(Table1: DecoderTableGFX1396, Table2: DecoderTableGFX13_FAKE1696, MI,
779 Inst: DecW, Address, Comments&: CS))
780 break;
781
782 if (STI.hasFeature(Feature: AMDGPU::Feature64BitLiterals)) {
783 // Return 8 bytes for a potential literal.
784 Bytes = Bytes_.slice(N: 4, M: MaxInstBytesNum - 4);
785
786 if (isGFX1250() &&
787 tryDecodeInst(Table: DecoderTableGFX125096, MI, Inst: DecW, Address, Comments&: CS))
788 break;
789 }
790
791 // Reinitialize Bytes
792 Bytes = Bytes_.slice(N: 0, M: MaxInstBytesNum);
793
794 } else if (Bytes.size() >= 16 &&
795 STI.hasFeature(Feature: AMDGPU::FeatureGFX950Insts)) {
796 std::bitset<128> DecW = eat16Bytes(Bytes);
797 if (tryDecodeInst(Table: DecoderTableGFX940128, MI, Inst: DecW, Address, Comments&: CS))
798 break;
799
800 // Reinitialize Bytes
801 Bytes = Bytes_.slice(N: 0, M: MaxInstBytesNum);
802 }
803
804 if (Bytes.size() >= 8) {
805 const uint64_t QW = eatBytes<uint64_t>(Bytes);
806
807 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX10_BEncoding) &&
808 tryDecodeInst(Table: DecoderTableGFX10_B64, MI, Inst: QW, Address, Comments&: CS))
809 break;
810
811 if (STI.hasFeature(Feature: AMDGPU::FeatureUnpackedD16VMem) &&
812 tryDecodeInst(Table: DecoderTableGFX80_UNPACKED64, MI, Inst: QW, Address, Comments&: CS))
813 break;
814
815 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX950Insts) &&
816 tryDecodeInst(Table: DecoderTableGFX95064, MI, Inst: QW, Address, Comments&: CS))
817 break;
818
819 // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and
820 // v_mad_mixhi_f16 for FMA variants. Try to decode using this special
821 // table first so we print the correct name.
822 if (STI.hasFeature(Feature: AMDGPU::FeatureFmaMixInsts) &&
823 tryDecodeInst(Table: DecoderTableGFX9_DL64, MI, Inst: QW, Address, Comments&: CS))
824 break;
825
826 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX940Insts) &&
827 tryDecodeInst(Table: DecoderTableGFX94064, MI, Inst: QW, Address, Comments&: CS))
828 break;
829
830 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX90AInsts) &&
831 tryDecodeInst(Table: DecoderTableGFX90A64, MI, Inst: QW, Address, Comments&: CS))
832 break;
833
834 if ((isVI() || isGFX9()) &&
835 tryDecodeInst(Table: DecoderTableGFX864, MI, Inst: QW, Address, Comments&: CS))
836 break;
837
838 if (isGFX9() && tryDecodeInst(Table: DecoderTableGFX964, MI, Inst: QW, Address, Comments&: CS))
839 break;
840
841 if (isGFX10() && tryDecodeInst(Table: DecoderTableGFX1064, MI, Inst: QW, Address, Comments&: CS))
842 break;
843
844 if (isGFX1250() &&
845 tryDecodeInst(Table1: DecoderTableGFX125064, Table2: DecoderTableGFX1250_FAKE1664, MI,
846 Inst: QW, Address, Comments&: CS))
847 break;
848
849 if (isGFX12() &&
850 tryDecodeInst(Table1: DecoderTableGFX1264, Table2: DecoderTableGFX12_FAKE1664, MI, Inst: QW,
851 Address, Comments&: CS))
852 break;
853
854 if (isGFX1170() &&
855 tryDecodeInst(Table1: DecoderTableGFX117064, Table2: DecoderTableGFX1170_FAKE1664, MI,
856 Inst: QW, Address, Comments&: CS))
857 break;
858
859 if (isGFX11() &&
860 tryDecodeInst(Table1: DecoderTableGFX1164, Table2: DecoderTableGFX11_FAKE1664, MI, Inst: QW,
861 Address, Comments&: CS))
862 break;
863
864 if (isGFX1170() &&
865 tryDecodeInst(Table: DecoderTableGFX1170W6464, MI, Inst: QW, Address, Comments&: CS))
866 break;
867
868 if (isGFX11() &&
869 tryDecodeInst(Table: DecoderTableGFX11W6464, MI, Inst: QW, Address, Comments&: CS))
870 break;
871
872 if (isGFX12() &&
873 tryDecodeInst(Table: DecoderTableGFX12W6464, MI, Inst: QW, Address, Comments&: CS))
874 break;
875
876 if (isGFX13() &&
877 tryDecodeInst(Table1: DecoderTableGFX1364, Table2: DecoderTableGFX13_FAKE1664, MI, Inst: QW,
878 Address, Comments&: CS))
879 break;
880
881 // Reinitialize Bytes
882 Bytes = Bytes_.slice(N: 0, M: MaxInstBytesNum);
883 }
884
885 // Try decode 32-bit instruction
886 if (Bytes.size() >= 4) {
887 const uint32_t DW = eatBytes<uint32_t>(Bytes);
888
889 if ((isVI() || isGFX9()) &&
890 tryDecodeInst(Table: DecoderTableGFX832, MI, Inst: DW, Address, Comments&: CS))
891 break;
892
893 if (tryDecodeInst(Table: DecoderTableAMDGPU32, MI, Inst: DW, Address, Comments&: CS))
894 break;
895
896 if (isGFX9() && tryDecodeInst(Table: DecoderTableGFX932, MI, Inst: DW, Address, Comments&: CS))
897 break;
898
899 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX950Insts) &&
900 tryDecodeInst(Table: DecoderTableGFX95032, MI, Inst: DW, Address, Comments&: CS))
901 break;
902
903 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX90AInsts) &&
904 tryDecodeInst(Table: DecoderTableGFX90A32, MI, Inst: DW, Address, Comments&: CS))
905 break;
906
907 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX10_BEncoding) &&
908 tryDecodeInst(Table: DecoderTableGFX10_B32, MI, Inst: DW, Address, Comments&: CS))
909 break;
910
911 if (isGFX10() && tryDecodeInst(Table: DecoderTableGFX1032, MI, Inst: DW, Address, Comments&: CS))
912 break;
913
914 if (isGFX1170() &&
915 tryDecodeInst(Table1: DecoderTableGFX117032, Table2: DecoderTableGFX1170_FAKE1632, MI,
916 Inst: DW, Address, Comments&: CS))
917 break;
918
919 if (isGFX11() &&
920 tryDecodeInst(Table1: DecoderTableGFX1132, Table2: DecoderTableGFX11_FAKE1632, MI, Inst: DW,
921 Address, Comments&: CS))
922 break;
923
924 if (isGFX1250() &&
925 tryDecodeInst(Table1: DecoderTableGFX125032, Table2: DecoderTableGFX1250_FAKE1632, MI,
926 Inst: DW, Address, Comments&: CS))
927 break;
928
929 if (isGFX12() &&
930 tryDecodeInst(Table1: DecoderTableGFX1232, Table2: DecoderTableGFX12_FAKE1632, MI, Inst: DW,
931 Address, Comments&: CS))
932 break;
933
934 if (isGFX13() &&
935 tryDecodeInst(Table1: DecoderTableGFX1332, Table2: DecoderTableGFX13_FAKE1632, MI, Inst: DW,
936 Address, Comments&: CS))
937 break;
938 }
939
940 return MCDisassembler::Fail;
941 } while (false);
942
943 DecodeStatus Status = MCDisassembler::Success;
944
945 if (SIInstrFlags::isDPP(O: *MCII, O: MI)) {
946 if (isMacDPP(MI))
947 convertMacDPPInst(MI);
948
949 if (SIInstrFlags::isVOP3P(O: *MCII, O: MI))
950 convertVOP3PDPPInst(MI);
951 else if (SIInstrFlags::isVOPC(O: *MCII, O: MI))
952 convertVOPCDPPInst(MI); // Special VOP3 case
953 else if (AMDGPU::isVOPC64DPP(Opc: MI.getOpcode()))
954 convertVOPC64DPPInst(MI); // Special VOP3 case
955 else if (AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::dpp8) !=
956 -1)
957 convertDPP8Inst(MI);
958 else if (SIInstrFlags::isVOP3(O: *MCII, O: MI))
959 convertVOP3DPPInst(MI); // Regular VOP3 case
960 }
961
962 convertTrue16OpSel(MI);
963
964 if (AMDGPU::isMAC(Opc: MI.getOpcode())) {
965 // Insert dummy unused src2_modifiers.
966 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
967 Name: AMDGPU::OpName::src2_modifiers);
968 }
969
970 if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp ||
971 MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp) {
972 // Insert dummy unused src2_modifiers.
973 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
974 Name: AMDGPU::OpName::src2_modifiers);
975 }
976
977 if (SIInstrFlags::isDS(O: *MCII, O: MI) && !AMDGPU::hasGDS(STI)) {
978 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::gds);
979 }
980
981 if (SIInstrFlags::isMUBUF(O: *MCII, O: MI) || SIInstrFlags::isFLAT(O: *MCII, O: MI) ||
982 SIInstrFlags::isSMRD(O: *MCII, O: MI)) {
983 int CPolPos = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
984 Name: AMDGPU::OpName::cpol);
985 if (CPolPos != -1) {
986 unsigned CPol =
987 SIInstrFlags::isAtomicRet(O: *MCII, O: MI) ? AMDGPU::CPol::GLC : 0;
988 if (MI.getNumOperands() <= (unsigned)CPolPos) {
989 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: CPol),
990 Name: AMDGPU::OpName::cpol);
991 } else if (CPol) {
992 MI.getOperand(i: CPolPos).setImm(MI.getOperand(i: CPolPos).getImm() | CPol);
993 }
994 }
995 }
996
997 if (SIInstrFlags::isBuffer(O: *MCII, O: MI) &&
998 (STI.hasFeature(Feature: AMDGPU::FeatureGFX90AInsts))) {
999 // GFX90A lost TFE, its place is occupied by ACC.
1000 int TFEOpIdx =
1001 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::tfe);
1002 if (TFEOpIdx != -1) {
1003 auto *TFEIter = MI.begin();
1004 std::advance(i&: TFEIter, n: TFEOpIdx);
1005 MI.insert(I: TFEIter, Op: MCOperand::createImm(Val: 0));
1006 }
1007 }
1008
1009 // Validate buffer instruction offsets for GFX12+ - must not be a negative.
1010 if (isGFX12Plus() && isBufferInstruction(MI)) {
1011 int OffsetIdx =
1012 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::offset);
1013 if (OffsetIdx != -1) {
1014 uint32_t Imm = MI.getOperand(i: OffsetIdx).getImm();
1015 int64_t SignedOffset = SignExtend64<24>(x: Imm);
1016 if (SignedOffset < 0)
1017 return MCDisassembler::Fail;
1018 }
1019 }
1020
1021 if (SIInstrFlags::isBuffer(O: *MCII, O: MI)) {
1022 int SWZOpIdx =
1023 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::swz);
1024 if (SWZOpIdx != -1) {
1025 auto *SWZIter = MI.begin();
1026 std::advance(i&: SWZIter, n: SWZOpIdx);
1027 MI.insert(I: SWZIter, Op: MCOperand::createImm(Val: 0));
1028 }
1029 }
1030
1031 const MCInstrDesc &Desc = MCII->get(Opcode: MI.getOpcode());
1032 if (SIInstrFlags::isMIMG(O: Desc)) {
1033 int VAddr0Idx =
1034 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::vaddr0);
1035 int RsrcIdx =
1036 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::srsrc);
1037 unsigned NSAArgs = RsrcIdx - VAddr0Idx - 1;
1038 if (VAddr0Idx >= 0 && NSAArgs > 0) {
1039 unsigned NSAWords = (NSAArgs + 3) / 4;
1040 if (Bytes.size() < 4 * NSAWords)
1041 return MCDisassembler::Fail;
1042 for (unsigned i = 0; i < NSAArgs; ++i) {
1043 const unsigned VAddrIdx = VAddr0Idx + 1 + i;
1044 auto VAddrRCID =
1045 MCII->getOpRegClassID(OpInfo: Desc.operands()[VAddrIdx], HwModeId: HwModeRegClass);
1046 MI.insert(I: MI.begin() + VAddrIdx, Op: createRegOperand(RegClassID: VAddrRCID, Val: Bytes[i]));
1047 }
1048 Bytes = Bytes.slice(N: 4 * NSAWords);
1049 }
1050
1051 convertMIMGInst(MI);
1052 }
1053
1054 if (SIInstrFlags::isVIMAGE(O: *MCII, O: MI) || SIInstrFlags::isVSAMPLE(O: *MCII, O: MI))
1055 convertMIMGInst(MI);
1056
1057 if (SIInstrFlags::isEXP(O: *MCII, O: MI))
1058 convertEXPInst(MI);
1059
1060 if (SIInstrFlags::isVINTERP(O: *MCII, O: MI))
1061 convertVINTERPInst(MI);
1062
1063 if (SIInstrFlags::isSDWA(O: *MCII, O: MI))
1064 convertSDWAInst(MI);
1065
1066 if (SIInstrFlags::isMAI(O: *MCII, O: MI) && !convertMAIInst(MI))
1067 return MCDisassembler::Fail;
1068
1069 if (SIInstrFlags::isWMMA(O: *MCII, O: MI) && !convertWMMAInst(MI))
1070 return MCDisassembler::Fail;
1071
1072 int VDstIn_Idx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1073 Name: AMDGPU::OpName::vdst_in);
1074 if (VDstIn_Idx != -1) {
1075 int Tied = MCII->get(Opcode: MI.getOpcode()).getOperandConstraint(OpNum: VDstIn_Idx,
1076 Constraint: MCOI::OperandConstraint::TIED_TO);
1077 if (Tied != -1 && (MI.getNumOperands() <= (unsigned)VDstIn_Idx ||
1078 !MI.getOperand(i: VDstIn_Idx).isReg() ||
1079 MI.getOperand(i: VDstIn_Idx).getReg() != MI.getOperand(i: Tied).getReg())) {
1080 if (MI.getNumOperands() > (unsigned)VDstIn_Idx)
1081 MI.erase(I: &MI.getOperand(i: VDstIn_Idx));
1082 insertNamedMCOperand(MI,
1083 Op: MCOperand::createReg(Reg: MI.getOperand(i: Tied).getReg()),
1084 Name: AMDGPU::OpName::vdst_in);
1085 }
1086 }
1087
1088 bool IsSOPK = SIInstrFlags::isSOPK(O: *MCII, O: MI);
1089 if (AMDGPU::hasNamedOperand(Opcode: MI.getOpcode(), NamedIdx: AMDGPU::OpName::imm) && !IsSOPK)
1090 convertFMAanyK(MI);
1091
1092 // Some VOPC instructions, e.g., v_cmpx_f_f64, use VOP3 encoding and
1093 // have EXEC as implicit destination. Issue a warning if encoding for
1094 // vdst is not EXEC.
1095 if (SIInstrFlags::isVOP3(O: *MCII, O: MI) &&
1096 MCII->get(Opcode: MI.getOpcode()).getNumDefs() == 0 &&
1097 MCII->get(Opcode: MI.getOpcode()).hasImplicitDefOfPhysReg(Reg: AMDGPU::EXEC)) {
1098 auto ExecEncoding = MRI.getEncodingValue(Reg: AMDGPU::EXEC_LO);
1099 if (Bytes_[0] != ExecEncoding)
1100 Status = MCDisassembler::SoftFail;
1101 }
1102
1103 Size = MaxInstBytesNum - Bytes.size();
1104 return Status;
1105}
1106
1107void AMDGPUDisassembler::convertEXPInst(MCInst &MI) const {
1108 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX11Insts)) {
1109 // The MCInst still has these fields even though they are no longer encoded
1110 // in the GFX11 instruction.
1111 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::vm);
1112 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::compr);
1113 }
1114}
1115
1116void AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const {
1117 convertTrue16OpSel(MI);
1118 if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_t16_gfx11 ||
1119 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_fake16_gfx11 ||
1120 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_t16_gfx12 ||
1121 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_fake16_gfx12 ||
1122 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_t16_gfx13 ||
1123 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_fake16_gfx13 ||
1124 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_t16_gfx11 ||
1125 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_fake16_gfx11 ||
1126 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_t16_gfx12 ||
1127 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_fake16_gfx12 ||
1128 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_t16_gfx13 ||
1129 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_fake16_gfx13 ||
1130 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_t16_gfx11 ||
1131 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_fake16_gfx11 ||
1132 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_t16_gfx12 ||
1133 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_fake16_gfx12 ||
1134 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_t16_gfx13 ||
1135 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_fake16_gfx13 ||
1136 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_t16_gfx11 ||
1137 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_fake16_gfx11 ||
1138 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_t16_gfx12 ||
1139 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_fake16_gfx12 ||
1140 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_t16_gfx13 ||
1141 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_fake16_gfx13) {
1142 // The MCInst has this field that is not directly encoded in the
1143 // instruction.
1144 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::op_sel);
1145 }
1146}
1147
1148void AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {
1149 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX9) ||
1150 STI.hasFeature(Feature: AMDGPU::FeatureGFX10)) {
1151 if (AMDGPU::hasNamedOperand(Opcode: MI.getOpcode(), NamedIdx: AMDGPU::OpName::sdst))
1152 // VOPC - insert clamp
1153 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::clamp);
1154 } else if (STI.hasFeature(Feature: AMDGPU::FeatureVolcanicIslands)) {
1155 int SDst = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::sdst);
1156 if (SDst != -1) {
1157 // VOPC - insert VCC register as sdst
1158 insertNamedMCOperand(MI, Op: createRegOperand(Reg: AMDGPU::VCC),
1159 Name: AMDGPU::OpName::sdst);
1160 } else {
1161 // VOP1/2 - insert omod if present in instruction
1162 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::omod);
1163 }
1164 }
1165}
1166
1167/// Adjust the register values used by V_MFMA_F8F6F4_f8_f8 instructions to the
1168/// appropriate subregister for the used format width.
1169///
1170/// \returns false if the operand cannot be narrowed down to \p NumRegs, which
1171/// means the encoding is malformed.
1172static bool adjustMFMA_F8F6F4OpRegClass(const MCRegisterInfo &MRI,
1173 MCOperand &MO, uint8_t NumRegs) {
1174 // A malformed encoding can select an operand that is not a register at all.
1175 if (!MO.isReg())
1176 return false;
1177
1178 MCRegister NewReg;
1179 switch (NumRegs) {
1180 case 4:
1181 NewReg = MRI.getSubReg(Reg: MO.getReg(), Idx: AMDGPU::sub0_sub1_sub2_sub3);
1182 break;
1183 case 6:
1184 NewReg = MRI.getSubReg(Reg: MO.getReg(), Idx: AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5);
1185 break;
1186 case 8:
1187 NewReg = MRI.getSubReg(Reg: MO.getReg(),
1188 Idx: AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7);
1189 // For mfma f8/f8 is the widest format, so the operand already has the
1190 // requested width and there is no subregister to select.
1191 if (!NewReg)
1192 return true;
1193 break;
1194 case 12:
1195 // There is no 384-bit subreg index defined.
1196 if (MCRegister BaseReg = MRI.getSubReg(Reg: MO.getReg(), Idx: AMDGPU::sub0)) {
1197 NewReg = MRI.getMatchingSuperReg(
1198 Reg: BaseReg, SubIdx: AMDGPU::sub0, RC: &MRI.getRegClass(i: AMDGPU::VReg_384RegClassID));
1199 }
1200 break;
1201 case 16:
1202 // No-op in cases where one operand is still f8/bf8.
1203 return true;
1204 default:
1205 llvm_unreachable("Unexpected size for mfma/wmma f8f6f4 operand");
1206 }
1207
1208 if (!NewReg)
1209 return false;
1210
1211 MO.setReg(NewReg);
1212 return true;
1213}
1214
1215/// f8f6f4 instructions have different pseudos depending on the used formats. In
1216/// the disassembler table, we only have the variants with the largest register
1217/// classes which assume using an fp8/bf8 format for both operands. The actual
1218/// register class depends on the format in blgp and cbsz operands. Adjust the
1219/// register classes depending on the used format.
1220bool AMDGPUDisassembler::convertMAIInst(MCInst &MI) const {
1221 int BlgpIdx =
1222 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::blgp);
1223 if (BlgpIdx == -1)
1224 return true;
1225
1226 int CbszIdx =
1227 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::cbsz);
1228
1229 unsigned CBSZ = MI.getOperand(i: CbszIdx).getImm();
1230 unsigned BLGP = MI.getOperand(i: BlgpIdx).getImm();
1231
1232 const AMDGPU::MFMA_F8F6F4_Info *AdjustedRegClassOpcode =
1233 AMDGPU::getMFMA_F8F6F4_WithFormatArgs(CBSZ, BLGP, F8F8Opcode: MI.getOpcode());
1234 if (!AdjustedRegClassOpcode ||
1235 AdjustedRegClassOpcode->Opcode == MI.getOpcode())
1236 return true;
1237
1238 MI.setOpcode(AdjustedRegClassOpcode->Opcode);
1239 int Src0Idx =
1240 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::src0);
1241 int Src1Idx =
1242 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::src1);
1243 return adjustMFMA_F8F6F4OpRegClass(MRI, MO&: MI.getOperand(i: Src0Idx),
1244 NumRegs: AdjustedRegClassOpcode->NumRegsSrcA) &&
1245 adjustMFMA_F8F6F4OpRegClass(MRI, MO&: MI.getOperand(i: Src1Idx),
1246 NumRegs: AdjustedRegClassOpcode->NumRegsSrcB);
1247}
1248
1249bool AMDGPUDisassembler::convertWMMAInst(MCInst &MI) const {
1250 int FmtAIdx =
1251 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::matrix_a_fmt);
1252 if (FmtAIdx == -1)
1253 return true;
1254
1255 int FmtBIdx =
1256 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::matrix_b_fmt);
1257
1258 unsigned FmtA = MI.getOperand(i: FmtAIdx).getImm();
1259 unsigned FmtB = MI.getOperand(i: FmtBIdx).getImm();
1260
1261 const AMDGPU::MFMA_F8F6F4_Info *AdjustedRegClassOpcode =
1262 AMDGPU::getWMMA_F8F6F4_WithFormatArgs(FmtA, FmtB, F8F8Opcode: MI.getOpcode());
1263 if (!AdjustedRegClassOpcode ||
1264 AdjustedRegClassOpcode->Opcode == MI.getOpcode())
1265 return true;
1266
1267 MI.setOpcode(AdjustedRegClassOpcode->Opcode);
1268 int Src0Idx =
1269 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::src0);
1270 int Src1Idx =
1271 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::src1);
1272 return adjustMFMA_F8F6F4OpRegClass(MRI, MO&: MI.getOperand(i: Src0Idx),
1273 NumRegs: AdjustedRegClassOpcode->NumRegsSrcA) &&
1274 adjustMFMA_F8F6F4OpRegClass(MRI, MO&: MI.getOperand(i: Src1Idx),
1275 NumRegs: AdjustedRegClassOpcode->NumRegsSrcB);
1276}
1277
1278struct VOPModifiers {
1279 unsigned OpSel = 0;
1280 unsigned OpSelHi = 0;
1281 unsigned NegLo = 0;
1282 unsigned NegHi = 0;
1283};
1284
1285// Reconstruct values of VOP3/VOP3P operands such as op_sel.
1286// Note that these values do not affect disassembler output,
1287// so this is only necessary for consistency with src_modifiers.
1288static VOPModifiers collectVOPModifiers(const MCInst &MI,
1289 bool IsVOP3P = false) {
1290 VOPModifiers Modifiers;
1291 unsigned Opc = MI.getOpcode();
1292 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,
1293 AMDGPU::OpName::src1_modifiers,
1294 AMDGPU::OpName::src2_modifiers};
1295 for (int J = 0; J < 3; ++J) {
1296 int OpIdx = AMDGPU::getNamedOperandIdx(Opcode: Opc, Name: ModOps[J]);
1297 if (OpIdx == -1)
1298 continue;
1299
1300 unsigned Val = MI.getOperand(i: OpIdx).getImm();
1301
1302 Modifiers.OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J;
1303 if (IsVOP3P) {
1304 Modifiers.OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J;
1305 Modifiers.NegLo |= !!(Val & SISrcMods::NEG) << J;
1306 Modifiers.NegHi |= !!(Val & SISrcMods::NEG_HI) << J;
1307 } else if (J == 0) {
1308 Modifiers.OpSel |= !!(Val & SISrcMods::DST_OP_SEL) << 3;
1309 }
1310 }
1311
1312 return Modifiers;
1313}
1314
1315// Instructions decode the op_sel/suffix bits into the src_modifier
1316// operands. Copy those bits into the src operands for true16 VGPRs.
1317void AMDGPUDisassembler::convertTrue16OpSel(MCInst &MI) const {
1318 const unsigned Opc = MI.getOpcode();
1319 const MCRegisterClass &ConversionRC =
1320 MRI.getRegClass(i: AMDGPU::VGPR_16RegClassID);
1321 constexpr std::array<std::tuple<AMDGPU::OpName, AMDGPU::OpName, unsigned>, 4>
1322 OpAndOpMods = {._M_elems: {{AMDGPU::OpName::src0, AMDGPU::OpName::src0_modifiers,
1323 SISrcMods::OP_SEL_0},
1324 {AMDGPU::OpName::src1, AMDGPU::OpName::src1_modifiers,
1325 SISrcMods::OP_SEL_0},
1326 {AMDGPU::OpName::src2, AMDGPU::OpName::src2_modifiers,
1327 SISrcMods::OP_SEL_0},
1328 {AMDGPU::OpName::vdst, AMDGPU::OpName::src0_modifiers,
1329 SISrcMods::DST_OP_SEL}}};
1330 for (const auto &[OpName, OpModsName, OpSelMask] : OpAndOpMods) {
1331 int OpIdx = AMDGPU::getNamedOperandIdx(Opcode: Opc, Name: OpName);
1332 int OpModsIdx = AMDGPU::getNamedOperandIdx(Opcode: Opc, Name: OpModsName);
1333 if (OpIdx == -1 || OpModsIdx == -1)
1334 continue;
1335 MCOperand &Op = MI.getOperand(i: OpIdx);
1336 if (!Op.isReg())
1337 continue;
1338 if (!ConversionRC.contains(Reg: Op.getReg()))
1339 continue;
1340 unsigned OpEnc = MRI.getEncodingValue(Reg: Op.getReg());
1341 const MCOperand &OpMods = MI.getOperand(i: OpModsIdx);
1342 unsigned ModVal = OpMods.getImm();
1343 if (ModVal & OpSelMask) { // isHi
1344 unsigned RegIdx = OpEnc & AMDGPU::HWEncoding::REG_IDX_MASK;
1345 Op.setReg(ConversionRC.getRegister(i: RegIdx * 2 + 1));
1346 }
1347 }
1348}
1349
1350// MAC opcodes have special old and src2 operands.
1351// src2 is tied to dst, while old is not tied (but assumed to be).
1352bool AMDGPUDisassembler::isMacDPP(MCInst &MI) const {
1353 constexpr int DST_IDX = 0;
1354 auto Opcode = MI.getOpcode();
1355 const auto &Desc = MCII->get(Opcode);
1356 auto OldIdx = AMDGPU::getNamedOperandIdx(Opcode, Name: AMDGPU::OpName::old);
1357
1358 if (OldIdx != -1 && Desc.getOperandConstraint(
1359 OpNum: OldIdx, Constraint: MCOI::OperandConstraint::TIED_TO) == -1) {
1360 assert(AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2));
1361 assert(Desc.getOperandConstraint(
1362 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2),
1363 MCOI::OperandConstraint::TIED_TO) == DST_IDX);
1364 (void)DST_IDX;
1365 return true;
1366 }
1367
1368 return false;
1369}
1370
1371// Create dummy old operand and insert dummy unused src2_modifiers
1372void AMDGPUDisassembler::convertMacDPPInst(MCInst &MI) const {
1373 assert(MI.getNumOperands() + 1 < MCII->get(MI.getOpcode()).getNumOperands());
1374 insertNamedMCOperand(MI, Op: MCOperand::createReg(Reg: 0), Name: AMDGPU::OpName::old);
1375 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
1376 Name: AMDGPU::OpName::src2_modifiers);
1377}
1378
1379void AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const {
1380 unsigned Opc = MI.getOpcode();
1381
1382 int VDstInIdx =
1383 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::vdst_in);
1384 if (VDstInIdx != -1)
1385 insertNamedMCOperand(MI, Op: MI.getOperand(i: 0), Name: AMDGPU::OpName::vdst_in);
1386
1387 unsigned DescNumOps = MCII->get(Opcode: Opc).getNumOperands();
1388 if (MI.getNumOperands() < DescNumOps &&
1389 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::op_sel)) {
1390 convertTrue16OpSel(MI);
1391 auto Mods = collectVOPModifiers(MI);
1392 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.OpSel),
1393 Name: AMDGPU::OpName::op_sel);
1394 } else {
1395 // Insert dummy unused src modifiers.
1396 if (MI.getNumOperands() < DescNumOps &&
1397 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::src0_modifiers))
1398 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
1399 Name: AMDGPU::OpName::src0_modifiers);
1400
1401 if (MI.getNumOperands() < DescNumOps &&
1402 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::src1_modifiers))
1403 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
1404 Name: AMDGPU::OpName::src1_modifiers);
1405 }
1406}
1407
1408void AMDGPUDisassembler::convertVOP3DPPInst(MCInst &MI) const {
1409 convertTrue16OpSel(MI);
1410
1411 int VDstInIdx =
1412 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::vdst_in);
1413 if (VDstInIdx != -1)
1414 insertNamedMCOperand(MI, Op: MI.getOperand(i: 0), Name: AMDGPU::OpName::vdst_in);
1415
1416 unsigned Opc = MI.getOpcode();
1417 unsigned DescNumOps = MCII->get(Opcode: Opc).getNumOperands();
1418 if (MI.getNumOperands() < DescNumOps &&
1419 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::op_sel)) {
1420 auto Mods = collectVOPModifiers(MI);
1421 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.OpSel),
1422 Name: AMDGPU::OpName::op_sel);
1423 }
1424}
1425
1426// Given a wide tuple \p Reg check if it will overflow 256 registers.
1427// \returns \p Reg on success or NoRegister otherwise.
1428static MCRegister CheckVGPROverflow(MCRegister Reg, const MCRegisterClass &RC,
1429 const MCRegisterInfo &MRI) {
1430 unsigned NumRegs = RC.getSizeInBits() / 32;
1431 MCRegister Sub0 = MRI.getSubReg(Reg, Idx: AMDGPU::sub0);
1432 if (!Sub0)
1433 return Reg;
1434
1435 MCRegister BaseReg;
1436 if (MRI.getRegClass(i: AMDGPU::VGPR_32RegClassID).contains(Reg: Sub0))
1437 BaseReg = AMDGPU::VGPR0;
1438 else if (MRI.getRegClass(i: AMDGPU::AGPR_32RegClassID).contains(Reg: Sub0))
1439 BaseReg = AMDGPU::AGPR0;
1440
1441 assert(BaseReg && "Only vector registers expected");
1442
1443 return (Sub0 - BaseReg + NumRegs <= 256) ? Reg : MCRegister();
1444}
1445
1446// Note that before gfx10, the MIMG encoding provided no information about
1447// VADDR size. Consequently, decoded instructions always show address as if it
1448// has 1 dword, which could be not really so.
1449void AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {
1450 int VDstIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1451 Name: AMDGPU::OpName::vdst);
1452
1453 int VDataIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1454 Name: AMDGPU::OpName::vdata);
1455 int VAddr0Idx =
1456 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::vaddr0);
1457 AMDGPU::OpName RsrcOpName = SIInstrFlags::isMIMG(O: *MCII, O: MI)
1458 ? AMDGPU::OpName::srsrc
1459 : AMDGPU::OpName::rsrc;
1460 int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: RsrcOpName);
1461 int DMaskIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1462 Name: AMDGPU::OpName::dmask);
1463
1464 int TFEIdx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1465 Name: AMDGPU::OpName::tfe);
1466 int D16Idx = AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(),
1467 Name: AMDGPU::OpName::d16);
1468
1469 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opc: MI.getOpcode());
1470 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
1471 AMDGPU::getMIMGBaseOpcodeInfo(BaseOpcode: Info->BaseOpcode);
1472
1473 assert(VDataIdx != -1);
1474 if (BaseOpcode->BVH) {
1475 // Add A16 operand for intersect_ray instructions
1476 addOperand(Inst&: MI, Opnd: MCOperand::createImm(Val: BaseOpcode->A16));
1477 return;
1478 }
1479
1480 bool IsAtomic = (VDstIdx != -1);
1481 bool IsGather4 = SIInstrFlags::isGather4(O: *MCII, O: MI);
1482 bool IsVSample = SIInstrFlags::isVSAMPLE(O: *MCII, O: MI);
1483 bool IsNSA = false;
1484 bool IsPartialNSA = false;
1485 unsigned AddrSize = Info->VAddrDwords;
1486
1487 if (isGFX10Plus()) {
1488 unsigned DimIdx =
1489 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::dim);
1490 int A16Idx =
1491 AMDGPU::getNamedOperandIdx(Opcode: MI.getOpcode(), Name: AMDGPU::OpName::a16);
1492 const AMDGPU::MIMGDimInfo *Dim =
1493 AMDGPU::getMIMGDimInfoByEncoding(DimEnc: MI.getOperand(i: DimIdx).getImm());
1494 const bool IsA16 = (A16Idx != -1 && MI.getOperand(i: A16Idx).getImm());
1495
1496 AddrSize =
1497 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, IsG16Supported: AMDGPU::hasG16(STI));
1498
1499 // VSAMPLE insts that do not use vaddr3 behave the same as NSA forms.
1500 // VIMAGE insts other than BVH never use vaddr4.
1501 IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA ||
1502 Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA ||
1503 Info->MIMGEncoding == AMDGPU::MIMGEncGfx12 ||
1504 Info->MIMGEncoding == AMDGPU::MIMGEncGfx13;
1505 if (!IsNSA) {
1506 if (!IsVSample && AddrSize > 12)
1507 AddrSize = 16;
1508 } else {
1509 if (AddrSize > Info->VAddrDwords) {
1510 if (!STI.hasFeature(Feature: AMDGPU::FeaturePartialNSAEncoding)) {
1511 // The NSA encoding does not contain enough operands for the
1512 // combination of base opcode / dimension. Should this be an error?
1513 return;
1514 }
1515 IsPartialNSA = true;
1516 }
1517 }
1518 }
1519
1520 unsigned DMask = MI.getOperand(i: DMaskIdx).getImm() & 0xf;
1521 unsigned DstSize = IsGather4 ? 4 : std::max(a: llvm::popcount(Value: DMask), b: 1);
1522
1523 bool D16 = D16Idx >= 0 && MI.getOperand(i: D16Idx).getImm();
1524 if (D16 && AMDGPU::hasPackedD16(STI)) {
1525 DstSize = (DstSize + 1) / 2;
1526 }
1527
1528 if (TFEIdx != -1 && MI.getOperand(i: TFEIdx).getImm())
1529 DstSize += 1;
1530
1531 if (DstSize == Info->VDataDwords && AddrSize == Info->VAddrDwords)
1532 return;
1533
1534 int NewOpcode =
1535 AMDGPU::getMIMGOpcode(BaseOpcode: Info->BaseOpcode, MIMGEncoding: Info->MIMGEncoding, VDataDwords: DstSize,
1536 VAddrDwords: AddrSize, IndexedRsrc: Info->IndexedRsrc, IndexedSamp: Info->IndexedSamp);
1537 if (NewOpcode == -1)
1538 return;
1539
1540 // Widen the register to the correct number of enabled channels.
1541 MCRegister NewVdata;
1542 if (DstSize != Info->VDataDwords) {
1543 auto DataRCID = MCII->getOpRegClassID(
1544 OpInfo: MCII->get(Opcode: NewOpcode).operands()[VDataIdx], HwModeId: HwModeRegClass);
1545
1546 // Get first subregister of VData
1547 MCRegister Vdata0 = MI.getOperand(i: VDataIdx).getReg();
1548 MCRegister VdataSub0 = MRI.getSubReg(Reg: Vdata0, Idx: AMDGPU::sub0);
1549 Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;
1550
1551 const MCRegisterClass &NewRC = MRI.getRegClass(i: DataRCID);
1552 NewVdata = MRI.getMatchingSuperReg(Reg: Vdata0, SubIdx: AMDGPU::sub0, RC: &NewRC);
1553 NewVdata = CheckVGPROverflow(Reg: NewVdata, RC: NewRC, MRI);
1554 if (!NewVdata) {
1555 // It's possible to encode this such that the low register + enabled
1556 // components exceeds the register count.
1557 return;
1558 }
1559 }
1560
1561 // If not using NSA on GFX10+, widen vaddr0 address register to correct size.
1562 // If using partial NSA on GFX11+ widen last address register.
1563 int VAddrSAIdx = IsPartialNSA ? (RsrcIdx - 1) : VAddr0Idx;
1564 MCRegister NewVAddrSA;
1565 if (STI.hasFeature(Feature: AMDGPU::FeatureNSAEncoding) && (!IsNSA || IsPartialNSA) &&
1566 AddrSize != Info->VAddrDwords) {
1567 MCRegister VAddrSA = MI.getOperand(i: VAddrSAIdx).getReg();
1568 MCRegister VAddrSubSA = MRI.getSubReg(Reg: VAddrSA, Idx: AMDGPU::sub0);
1569 VAddrSA = VAddrSubSA ? VAddrSubSA : VAddrSA;
1570
1571 auto AddrRCID = MCII->getOpRegClassID(
1572 OpInfo: MCII->get(Opcode: NewOpcode).operands()[VAddrSAIdx], HwModeId: HwModeRegClass);
1573
1574 const MCRegisterClass &NewRC = MRI.getRegClass(i: AddrRCID);
1575 NewVAddrSA = MRI.getMatchingSuperReg(Reg: VAddrSA, SubIdx: AMDGPU::sub0, RC: &NewRC);
1576 NewVAddrSA = CheckVGPROverflow(Reg: NewVAddrSA, RC: NewRC, MRI);
1577 if (!NewVAddrSA)
1578 return;
1579 }
1580
1581 MI.setOpcode(NewOpcode);
1582
1583 if (NewVdata != AMDGPU::NoRegister) {
1584 MI.getOperand(i: VDataIdx) = MCOperand::createReg(Reg: NewVdata);
1585
1586 if (IsAtomic) {
1587 // Atomic operations have an additional operand (a copy of data)
1588 MI.getOperand(i: VDstIdx) = MCOperand::createReg(Reg: NewVdata);
1589 }
1590 }
1591
1592 if (NewVAddrSA) {
1593 MI.getOperand(i: VAddrSAIdx) = MCOperand::createReg(Reg: NewVAddrSA);
1594 } else if (IsNSA) {
1595 assert(AddrSize <= Info->VAddrDwords);
1596 MI.erase(First: MI.begin() + VAddr0Idx + AddrSize,
1597 Last: MI.begin() + VAddr0Idx + Info->VAddrDwords);
1598 }
1599}
1600
1601// Opsel and neg bits are used in src_modifiers and standalone operands. Autogen
1602// decoder only adds to src_modifiers, so manually add the bits to the other
1603// operands.
1604void AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const {
1605 unsigned Opc = MI.getOpcode();
1606 unsigned DescNumOps = MCII->get(Opcode: Opc).getNumOperands();
1607 auto Mods = collectVOPModifiers(MI, IsVOP3P: true);
1608
1609 if (MI.getNumOperands() < DescNumOps &&
1610 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::vdst_in))
1611 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0), Name: AMDGPU::OpName::vdst_in);
1612
1613 if (MI.getNumOperands() < DescNumOps &&
1614 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::op_sel))
1615 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.OpSel),
1616 Name: AMDGPU::OpName::op_sel);
1617 if (MI.getNumOperands() < DescNumOps &&
1618 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::op_sel_hi))
1619 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.OpSelHi),
1620 Name: AMDGPU::OpName::op_sel_hi);
1621 if (MI.getNumOperands() < DescNumOps &&
1622 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::neg_lo))
1623 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.NegLo),
1624 Name: AMDGPU::OpName::neg_lo);
1625 if (MI.getNumOperands() < DescNumOps &&
1626 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::neg_hi))
1627 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.NegHi),
1628 Name: AMDGPU::OpName::neg_hi);
1629}
1630
1631// Create dummy old operand and insert optional operands
1632void AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const {
1633 unsigned Opc = MI.getOpcode();
1634 unsigned DescNumOps = MCII->get(Opcode: Opc).getNumOperands();
1635
1636 if (MI.getNumOperands() < DescNumOps &&
1637 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::old))
1638 insertNamedMCOperand(MI, Op: MCOperand::createReg(Reg: 0), Name: AMDGPU::OpName::old);
1639
1640 if (MI.getNumOperands() < DescNumOps &&
1641 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::src0_modifiers))
1642 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
1643 Name: AMDGPU::OpName::src0_modifiers);
1644
1645 if (MI.getNumOperands() < DescNumOps &&
1646 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::src1_modifiers))
1647 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: 0),
1648 Name: AMDGPU::OpName::src1_modifiers);
1649}
1650
1651void AMDGPUDisassembler::convertVOPC64DPPInst(MCInst &MI) const {
1652 unsigned Opc = MI.getOpcode();
1653 unsigned DescNumOps = MCII->get(Opcode: Opc).getNumOperands();
1654
1655 convertTrue16OpSel(MI);
1656
1657 if (MI.getNumOperands() < DescNumOps &&
1658 AMDGPU::hasNamedOperand(Opcode: Opc, NamedIdx: AMDGPU::OpName::op_sel)) {
1659 VOPModifiers Mods = collectVOPModifiers(MI);
1660 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Mods.OpSel),
1661 Name: AMDGPU::OpName::op_sel);
1662 }
1663}
1664
1665void AMDGPUDisassembler::convertFMAanyK(MCInst &MI) const {
1666 assert(HasLiteral && "Should have decoded a literal");
1667 insertNamedMCOperand(MI, Op: MCOperand::createImm(Val: Literal), Name: AMDGPU::OpName::immX);
1668}
1669
1670const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {
1671 return getContext().getRegisterInfo()->getRegClassName(
1672 Class: &getAMDGPUMCRegisterClass(RC: RegClassID));
1673}
1674
1675inline
1676MCOperand AMDGPUDisassembler::errOperand(unsigned V,
1677 const Twine& ErrMsg) const {
1678 *CommentStream << "Error: " + ErrMsg;
1679
1680 // ToDo: add support for error operands to MCInst.h
1681 // return MCOperand::createError(V);
1682 return MCOperand();
1683}
1684
1685inline MCOperand AMDGPUDisassembler::createRegOperand(MCRegister Reg) const {
1686 return MCOperand::createReg(Reg: AMDGPU::getMCReg(Reg, STI));
1687}
1688
1689inline
1690MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,
1691 unsigned Val) const {
1692 const auto &RegCl = getAMDGPUMCRegisterClass(RC: RegClassID);
1693 if (Val >= RegCl.getNumRegs())
1694 return errOperand(V: Val, ErrMsg: Twine(getRegClassName(RegClassID)) +
1695 ": unknown register " + Twine(Val));
1696 return createRegOperand(Reg: RegCl.getRegister(i: Val));
1697}
1698
1699inline
1700MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,
1701 unsigned Val) const {
1702 // ToDo: SI/CI have 104 SGPRs, VI - 102
1703 // Valery: here we accepting as much as we can, let assembler sort it out
1704 int shift = 0;
1705 switch (SRegClassID) {
1706 case AMDGPU::SGPR_32RegClassID:
1707 case AMDGPU::TTMP_32RegClassID:
1708 break;
1709 case AMDGPU::SGPR_64RegClassID:
1710 case AMDGPU::TTMP_64RegClassID:
1711 shift = 1;
1712 break;
1713 case AMDGPU::SGPR_96RegClassID:
1714 case AMDGPU::TTMP_96RegClassID:
1715 case AMDGPU::SGPR_128RegClassID:
1716 case AMDGPU::TTMP_128RegClassID:
1717 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in
1718 // this bundle?
1719 case AMDGPU::SGPR_256RegClassID:
1720 case AMDGPU::TTMP_256RegClassID:
1721 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in
1722 // this bundle?
1723 case AMDGPU::SGPR_288RegClassID:
1724 case AMDGPU::TTMP_288RegClassID:
1725 case AMDGPU::SGPR_320RegClassID:
1726 case AMDGPU::TTMP_320RegClassID:
1727 case AMDGPU::SGPR_352RegClassID:
1728 case AMDGPU::TTMP_352RegClassID:
1729 case AMDGPU::SGPR_384RegClassID:
1730 case AMDGPU::TTMP_384RegClassID:
1731 case AMDGPU::SGPR_512RegClassID:
1732 case AMDGPU::TTMP_512RegClassID:
1733 shift = 2;
1734 break;
1735 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in
1736 // this bundle?
1737 default:
1738 llvm_unreachable("unhandled register class");
1739 }
1740
1741 if (Val % (1 << shift)) {
1742 *CommentStream << "Warning: " << getRegClassName(RegClassID: SRegClassID)
1743 << ": scalar reg isn't aligned " << Val;
1744 }
1745
1746 return createRegOperand(RegClassID: SRegClassID, Val: Val >> shift);
1747}
1748
1749MCOperand AMDGPUDisassembler::createVGPR16Operand(unsigned RegIdx,
1750 bool IsHi) const {
1751 unsigned RegIdxInVGPR16 = RegIdx * 2 + (IsHi ? 1 : 0);
1752 return createRegOperand(RegClassID: AMDGPU::VGPR_16RegClassID, Val: RegIdxInVGPR16);
1753}
1754
1755// Decode Literals for insts which always have a literal in the encoding
1756MCOperand
1757AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const {
1758 if (HasLiteral) {
1759 assert(
1760 AMDGPU::hasVOPD(STI) &&
1761 "Should only decode multiple kimm with VOPD, check VSrc operand types");
1762 if (Literal != Val)
1763 return errOperand(V: Val, ErrMsg: "More than one unique literal is illegal");
1764 }
1765 HasLiteral = true;
1766 Literal = Val;
1767 return MCOperand::createImm(Val: Literal);
1768}
1769
1770MCOperand
1771AMDGPUDisassembler::decodeMandatoryLiteral64Constant(uint64_t Val) const {
1772 if (HasLiteral) {
1773 if (Literal != Val)
1774 return errOperand(V: Val, ErrMsg: "More than one unique literal is illegal");
1775 }
1776 HasLiteral = true;
1777 Literal = Val;
1778
1779 bool UseLit64 = Hi_32(Value: Literal) == 0;
1780 return UseLit64 ? MCOperand::createExpr(Val: AMDGPUMCExpr::createLit(
1781 Lit: LitModifier::Lit64, Value: Literal, Ctx&: getContext()))
1782 : MCOperand::createImm(Val: Literal);
1783}
1784
1785MCOperand
1786AMDGPUDisassembler::decodeLiteralConstant(const MCInstrDesc &Desc,
1787 const MCOperandInfo &OpDesc) const {
1788 // For now all literal constants are supposed to be unsigned integer
1789 // ToDo: deal with signed/unsigned 64-bit integer constants
1790 // ToDo: deal with float/double constants
1791 if (!HasLiteral) {
1792 if (Bytes.size() < 4) {
1793 return errOperand(V: 0, ErrMsg: "cannot read literal, inst bytes left " +
1794 Twine(Bytes.size()));
1795 }
1796 HasLiteral = true;
1797 Literal = eatBytes<uint32_t>(Bytes);
1798 }
1799
1800 // For disassembling always assume all inline constants are available.
1801 bool HasInv2Pi = true;
1802
1803 // Invalid instruction codes may contain literals for inline-only
1804 // operands, so we support them here as well.
1805 int64_t Val = Literal;
1806 bool UseLit = false;
1807 switch (OpDesc.OperandType) {
1808 default:
1809 llvm_unreachable("Unexpected operand type!");
1810 case AMDGPU::OPERAND_REG_IMM_BF16:
1811 case AMDGPU::OPERAND_REG_INLINE_C_BF16:
1812 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
1813 UseLit = AMDGPU::isInlinableLiteralBF16(Literal: Val, HasInv2Pi);
1814 break;
1815 case AMDGPU::OPERAND_REG_IMM_V2BF16:
1816 UseLit = AMDGPU::isInlinableLiteralV2BF16(Literal: Val);
1817 break;
1818 case AMDGPU::OPERAND_REG_IMM_FP16:
1819 case AMDGPU::OPERAND_REG_INLINE_C_FP16:
1820 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
1821 UseLit = AMDGPU::isInlinableLiteralFP16(Literal: Val, HasInv2Pi);
1822 break;
1823 case AMDGPU::OPERAND_REG_IMM_V2FP16:
1824 UseLit = AMDGPU::isInlinableLiteralV2F16(Literal: Val);
1825 break;
1826 case AMDGPU::OPERAND_REG_IMM_V2FP16_SPLAT:
1827 UseLit = AMDGPU::isPKFMACF16InlineConstant(Literal: Val, IsGFX11Plus: isGFX11Plus());
1828 break;
1829 case AMDGPU::OPERAND_REG_IMM_NOINLINE_FP16:
1830 case AMDGPU::OPERAND_REG_IMM_NOINLINE_V2FP16:
1831 break;
1832 case AMDGPU::OPERAND_REG_IMM_INT16:
1833 case AMDGPU::OPERAND_REG_INLINE_C_INT16:
1834 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
1835 UseLit = AMDGPU::isInlinableLiteralI16(Literal: Val, HasInv2Pi);
1836 break;
1837 case AMDGPU::OPERAND_REG_IMM_V2INT16:
1838 UseLit = AMDGPU::isInlinableLiteralV2I16(Literal: Val);
1839 break;
1840 case AMDGPU::OPERAND_REG_IMM_FP32:
1841 case AMDGPU::OPERAND_REG_INLINE_C_FP32:
1842 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
1843 case AMDGPU::OPERAND_REG_IMM_INT32:
1844 case AMDGPU::OPERAND_REG_INLINE_C_INT32:
1845 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
1846 case AMDGPU::OPERAND_REG_IMM_V2FP32:
1847 case AMDGPU::OPERAND_REG_IMM_V2INT32:
1848 case AMDGPU::OPERAND_KIMM32:
1849 UseLit = AMDGPU::isInlinableLiteral32(Literal: Val, HasInv2Pi);
1850 break;
1851 case AMDGPU::OPERAND_REG_IMM_FP64:
1852 case AMDGPU::OPERAND_REG_INLINE_C_FP64:
1853 case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
1854 case AMDGPU::OPERAND_REG_IMM_V2FP64:
1855 UseLit = AMDGPU::isInlinableLiteral64(Literal: Val << 32, HasInv2Pi);
1856 if (!UseLit)
1857 Val <<= 32;
1858 break;
1859 case AMDGPU::OPERAND_REG_IMM_INT64:
1860 case AMDGPU::OPERAND_REG_INLINE_C_INT64:
1861 case AMDGPU::OPERAND_REG_IMM_V2INT64:
1862 UseLit = AMDGPU::isInlinableLiteral64(Literal: Val, HasInv2Pi);
1863 break;
1864 case MCOI::OPERAND_REGISTER:
1865 // TODO: Disassembling V_DUAL_FMAMK_F32_X_FMAMK_F32_gfx11 hits
1866 // decoding a literal in a position of a register operand. Give
1867 // it special handling in the caller, decodeImmOperands(), instead
1868 // of quietly allowing it here.
1869 break;
1870 }
1871
1872 return UseLit ? MCOperand::createExpr(Val: AMDGPUMCExpr::createLit(
1873 Lit: LitModifier::Lit, Value: Val, Ctx&: getContext()))
1874 : MCOperand::createImm(Val);
1875}
1876
1877MCOperand AMDGPUDisassembler::decodeLiteral64Constant() const {
1878 assert(STI.hasFeature(AMDGPU::Feature64BitLiterals));
1879
1880 if (!HasLiteral) {
1881 if (Bytes.size() < 8) {
1882 return errOperand(V: 0, ErrMsg: "cannot read literal64, inst bytes left " +
1883 Twine(Bytes.size()));
1884 }
1885 HasLiteral = true;
1886 Literal = eatBytes<uint64_t>(Bytes);
1887 }
1888
1889 bool UseLit64 = Hi_32(Value: Literal) == 0;
1890
1891 UseLit64 |= AMDGPU::isInlinableLiteral64(
1892 Literal, HasInv2Pi: STI.hasFeature(Feature: AMDGPU::FeatureInv2PiInlineImm));
1893
1894 return UseLit64 ? MCOperand::createExpr(Val: AMDGPUMCExpr::createLit(
1895 Lit: LitModifier::Lit64, Value: Literal, Ctx&: getContext()))
1896 : MCOperand::createImm(Val: Literal);
1897}
1898
1899MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {
1900 using namespace AMDGPU::EncValues;
1901
1902 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);
1903 return MCOperand::createImm(Val: (Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?
1904 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :
1905 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));
1906 // Cast prevents negative overflow.
1907}
1908
1909static int64_t getInlineImmVal32(unsigned Imm) {
1910 switch (Imm) {
1911 case 240:
1912 return llvm::bit_cast<uint32_t>(from: 0.5f);
1913 case 241:
1914 return llvm::bit_cast<uint32_t>(from: -0.5f);
1915 case 242:
1916 return llvm::bit_cast<uint32_t>(from: 1.0f);
1917 case 243:
1918 return llvm::bit_cast<uint32_t>(from: -1.0f);
1919 case 244:
1920 return llvm::bit_cast<uint32_t>(from: 2.0f);
1921 case 245:
1922 return llvm::bit_cast<uint32_t>(from: -2.0f);
1923 case 246:
1924 return llvm::bit_cast<uint32_t>(from: 4.0f);
1925 case 247:
1926 return llvm::bit_cast<uint32_t>(from: -4.0f);
1927 case 248: // 1 / (2 * PI)
1928 return 0x3e22f983;
1929 default:
1930 llvm_unreachable("invalid fp inline imm");
1931 }
1932}
1933
1934static int64_t getInlineImmVal64(unsigned Imm) {
1935 switch (Imm) {
1936 case 240:
1937 return llvm::bit_cast<uint64_t>(from: 0.5);
1938 case 241:
1939 return llvm::bit_cast<uint64_t>(from: -0.5);
1940 case 242:
1941 return llvm::bit_cast<uint64_t>(from: 1.0);
1942 case 243:
1943 return llvm::bit_cast<uint64_t>(from: -1.0);
1944 case 244:
1945 return llvm::bit_cast<uint64_t>(from: 2.0);
1946 case 245:
1947 return llvm::bit_cast<uint64_t>(from: -2.0);
1948 case 246:
1949 return llvm::bit_cast<uint64_t>(from: 4.0);
1950 case 247:
1951 return llvm::bit_cast<uint64_t>(from: -4.0);
1952 case 248: // 1 / (2 * PI)
1953 return 0x3fc45f306dc9c882;
1954 default:
1955 llvm_unreachable("invalid fp inline imm");
1956 }
1957}
1958
1959static int64_t getInlineImmValF16(unsigned Imm) {
1960 switch (Imm) {
1961 case 240:
1962 return 0x3800;
1963 case 241:
1964 return 0xB800;
1965 case 242:
1966 return 0x3C00;
1967 case 243:
1968 return 0xBC00;
1969 case 244:
1970 return 0x4000;
1971 case 245:
1972 return 0xC000;
1973 case 246:
1974 return 0x4400;
1975 case 247:
1976 return 0xC400;
1977 case 248: // 1 / (2 * PI)
1978 return 0x3118;
1979 default:
1980 llvm_unreachable("invalid fp inline imm");
1981 }
1982}
1983
1984static int64_t getInlineImmValBF16(unsigned Imm) {
1985 switch (Imm) {
1986 case 240:
1987 return 0x3F00;
1988 case 241:
1989 return 0xBF00;
1990 case 242:
1991 return 0x3F80;
1992 case 243:
1993 return 0xBF80;
1994 case 244:
1995 return 0x4000;
1996 case 245:
1997 return 0xC000;
1998 case 246:
1999 return 0x4080;
2000 case 247:
2001 return 0xC080;
2002 case 248: // 1 / (2 * PI)
2003 return 0x3E22;
2004 default:
2005 llvm_unreachable("invalid fp inline imm");
2006 }
2007}
2008
2009unsigned AMDGPUDisassembler::getVgprClassId(unsigned Width) const {
2010 using namespace AMDGPU;
2011
2012 switch (Width) {
2013 case 16:
2014 case 32:
2015 return VGPR_32RegClassID;
2016 case 64:
2017 return VReg_64RegClassID;
2018 case 96:
2019 return VReg_96RegClassID;
2020 case 128:
2021 return VReg_128RegClassID;
2022 case 160:
2023 return VReg_160RegClassID;
2024 case 192:
2025 return VReg_192RegClassID;
2026 case 256:
2027 return VReg_256RegClassID;
2028 case 288:
2029 return VReg_288RegClassID;
2030 case 320:
2031 return VReg_320RegClassID;
2032 case 352:
2033 return VReg_352RegClassID;
2034 case 384:
2035 return VReg_384RegClassID;
2036 case 512:
2037 return VReg_512RegClassID;
2038 case 1024:
2039 return VReg_1024RegClassID;
2040 }
2041 llvm_unreachable("Invalid register width!");
2042}
2043
2044unsigned AMDGPUDisassembler::getAgprClassId(unsigned Width) const {
2045 using namespace AMDGPU;
2046
2047 switch (Width) {
2048 case 16:
2049 case 32:
2050 return AGPR_32RegClassID;
2051 case 64:
2052 return AReg_64RegClassID;
2053 case 96:
2054 return AReg_96RegClassID;
2055 case 128:
2056 return AReg_128RegClassID;
2057 case 160:
2058 return AReg_160RegClassID;
2059 case 256:
2060 return AReg_256RegClassID;
2061 case 288:
2062 return AReg_288RegClassID;
2063 case 320:
2064 return AReg_320RegClassID;
2065 case 352:
2066 return AReg_352RegClassID;
2067 case 384:
2068 return AReg_384RegClassID;
2069 case 512:
2070 return AReg_512RegClassID;
2071 case 1024:
2072 return AReg_1024RegClassID;
2073 }
2074 llvm_unreachable("Invalid register width!");
2075}
2076
2077std::optional<unsigned>
2078AMDGPUDisassembler::getSgprClassId(unsigned Width) const {
2079 using namespace AMDGPU;
2080
2081 switch (Width) {
2082 case 16:
2083 case 32:
2084 return SGPR_32RegClassID;
2085 case 64:
2086 return SGPR_64RegClassID;
2087 case 96:
2088 return SGPR_96RegClassID;
2089 case 128:
2090 return SGPR_128RegClassID;
2091 case 160:
2092 return SGPR_160RegClassID;
2093 case 256:
2094 return SGPR_256RegClassID;
2095 case 288:
2096 return SGPR_288RegClassID;
2097 case 320:
2098 return SGPR_320RegClassID;
2099 case 352:
2100 return SGPR_352RegClassID;
2101 case 384:
2102 return SGPR_384RegClassID;
2103 case 512:
2104 return SGPR_512RegClassID;
2105 }
2106 return std::nullopt;
2107}
2108
2109std::optional<unsigned>
2110AMDGPUDisassembler::getTtmpClassId(unsigned Width) const {
2111 using namespace AMDGPU;
2112
2113 switch (Width) {
2114 case 16:
2115 case 32:
2116 return TTMP_32RegClassID;
2117 case 64:
2118 return TTMP_64RegClassID;
2119 case 128:
2120 return TTMP_128RegClassID;
2121 case 256:
2122 return TTMP_256RegClassID;
2123 case 288:
2124 return TTMP_288RegClassID;
2125 case 320:
2126 return TTMP_320RegClassID;
2127 case 352:
2128 return TTMP_352RegClassID;
2129 case 384:
2130 return TTMP_384RegClassID;
2131 case 512:
2132 return TTMP_512RegClassID;
2133 }
2134 return std::nullopt;
2135}
2136
2137int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const {
2138 using namespace AMDGPU::EncValues;
2139
2140 unsigned TTmpMin = isGFX9Plus() ? TTMP_GFX9PLUS_MIN : TTMP_VI_MIN;
2141 unsigned TTmpMax = isGFX9Plus() ? TTMP_GFX9PLUS_MAX : TTMP_VI_MAX;
2142
2143 return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1;
2144}
2145
2146MCOperand AMDGPUDisassembler::decodeSrcOp(const MCInst &Inst, unsigned Width,
2147 unsigned Val) const {
2148 using namespace AMDGPU::EncValues;
2149
2150 assert(Val < 1024); // enum10
2151
2152 bool IsAGPR = Val & 512;
2153 Val &= 511;
2154
2155 if (VGPR_MIN <= Val && Val <= VGPR_MAX) {
2156 return createRegOperand(RegClassID: IsAGPR ? getAgprClassId(Width)
2157 : getVgprClassId(Width), Val: Val - VGPR_MIN);
2158 }
2159 return decodeNonVGPRSrcOp(Inst, Width, Val: Val & 0xFF);
2160}
2161
2162MCOperand AMDGPUDisassembler::decodeNonVGPRSrcOp(const MCInst &Inst,
2163 unsigned Width,
2164 unsigned Val) const {
2165 // Cases when Val{8} is 1 (vgpr, agpr or true 16 vgpr) should have been
2166 // decoded earlier.
2167 assert(Val < (1 << 8) && "9-bit Src encoding when Val{8} is 0");
2168 using namespace AMDGPU::EncValues;
2169
2170 // Not every operand width has a supported non-VGPR source encoding.
2171 // Selecting an unsupported SGPR, ttmp, or special register is malformed.
2172 auto UnsupportedWidth = [&]() {
2173 return errOperand(V: Val, ErrMsg: "unsupported " + Twine(Width) +
2174 "-bit non-VGPR operand encoding " + Twine(Val));
2175 };
2176
2177 if (Val <= SGPR_MAX) {
2178 // "SGPR_MIN <= Val" is always true and causes compilation warning.
2179 static_assert(SGPR_MIN == 0);
2180 std::optional<unsigned> ClassId = getSgprClassId(Width);
2181 if (!ClassId)
2182 return UnsupportedWidth();
2183 return createSRegOperand(SRegClassID: *ClassId, Val: Val - SGPR_MIN);
2184 }
2185
2186 int TTmpIdx = getTTmpIdx(Val);
2187 if (TTmpIdx >= 0) {
2188 std::optional<unsigned> ClassId = getTtmpClassId(Width);
2189 if (!ClassId)
2190 return UnsupportedWidth();
2191 return createSRegOperand(SRegClassID: *ClassId, Val: TTmpIdx);
2192 }
2193
2194 if ((INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) ||
2195 (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) ||
2196 Val == LITERAL_CONST)
2197 return MCOperand::createImm(Val);
2198
2199 if (Val == LITERAL64_CONST && STI.hasFeature(Feature: AMDGPU::Feature64BitLiterals)) {
2200 // Only VOP1, VOP2, VOPC, SOP1, SOP2 and SOPC may encode a 64-bit literal.
2201 // VOP3, VOP3P and VOPD have to use a 32-bit one.
2202 if (SIInstrFlags::isVOP3Like(O: *MCII, O: Inst) ||
2203 AMDGPU::isVOPD(Opc: Inst.getOpcode())) {
2204 return errOperand(V: Val,
2205 ErrMsg: "64-bit literal is not supported by this instruction");
2206 }
2207 return decodeLiteral64Constant();
2208 }
2209
2210 switch (Width) {
2211 case 32:
2212 case 16:
2213 return decodeSpecialReg32(Val);
2214 case 64:
2215 return decodeSpecialReg64(Val);
2216 case 96:
2217 case 128:
2218 case 256:
2219 case 512:
2220 return decodeSpecialReg96Plus(Val);
2221 default:
2222 return UnsupportedWidth();
2223 }
2224}
2225
2226// Bit 0 of DstY isn't stored in the instruction, because it's always the
2227// opposite of bit 0 of DstX.
2228MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst,
2229 unsigned Val) const {
2230 int VDstXInd =
2231 AMDGPU::getNamedOperandIdx(Opcode: Inst.getOpcode(), Name: AMDGPU::OpName::vdstX);
2232 assert(VDstXInd != -1);
2233 assert(Inst.getOperand(VDstXInd).isReg());
2234 unsigned XDstReg = MRI.getEncodingValue(Reg: Inst.getOperand(i: VDstXInd).getReg());
2235 Val |= ~XDstReg & 1;
2236 return createRegOperand(RegClassID: getVgprClassId(Width: 32), Val);
2237}
2238
2239MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {
2240 using namespace AMDGPU;
2241
2242 switch (Val) {
2243 // clang-format off
2244 case 102: return createRegOperand(Reg: FLAT_SCR_LO);
2245 case 103: return createRegOperand(Reg: FLAT_SCR_HI);
2246 case 104: return createRegOperand(Reg: XNACK_MASK_LO);
2247 case 105: return createRegOperand(Reg: XNACK_MASK_HI);
2248 case 106: return createRegOperand(Reg: VCC_LO);
2249 case 107: return createRegOperand(Reg: VCC_HI);
2250 case 108: return createRegOperand(Reg: TBA_LO);
2251 case 109: return createRegOperand(Reg: TBA_HI);
2252 case 110: return createRegOperand(Reg: TMA_LO);
2253 case 111: return createRegOperand(Reg: TMA_HI);
2254 case 124:
2255 return isGFX11Plus() ? createRegOperand(Reg: SGPR_NULL) : createRegOperand(Reg: M0);
2256 case 125:
2257 return isGFX11Plus() ? createRegOperand(Reg: M0) : createRegOperand(Reg: SGPR_NULL);
2258 case 126: return createRegOperand(Reg: EXEC_LO);
2259 case 127: return createRegOperand(Reg: EXEC_HI);
2260 case 230: return createRegOperand(Reg: SRC_FLAT_SCRATCH_BASE_LO);
2261 case 231: return createRegOperand(Reg: SRC_FLAT_SCRATCH_BASE_HI);
2262 case 235: return createRegOperand(Reg: SRC_SHARED_BASE_LO);
2263 case 236: return createRegOperand(Reg: SRC_SHARED_LIMIT_LO);
2264 case 237:
2265 if (AMDGPU::hasPrivateApertureRegs(STI))
2266 return createRegOperand(Reg: SRC_PRIVATE_BASE_LO);
2267 break;
2268 case 238:
2269 if (AMDGPU::hasPrivateApertureRegs(STI))
2270 return createRegOperand(Reg: SRC_PRIVATE_LIMIT_LO);
2271 break;
2272 case 239:
2273 if (AMDGPU::hasPopsExitingWaveID(STI))
2274 return createRegOperand(Reg: SRC_POPS_EXITING_WAVE_ID);
2275 break;
2276 case 251:
2277 if (!isGFX11Plus())
2278 return createRegOperand(Reg: SRC_VCCZ);
2279 break;
2280 case 252:
2281 if (!isGFX11Plus())
2282 return createRegOperand(Reg: SRC_EXECZ);
2283 break;
2284 case 253: return createRegOperand(Reg: SRC_SCC);
2285 case 254: return createRegOperand(Reg: LDS_DIRECT);
2286 default: break;
2287 // clang-format on
2288 }
2289 return errOperand(V: Val, ErrMsg: "unknown operand encoding " + Twine(Val));
2290}
2291
2292MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {
2293 using namespace AMDGPU;
2294
2295 switch (Val) {
2296 case 102: return createRegOperand(Reg: FLAT_SCR);
2297 case 104: return createRegOperand(Reg: XNACK_MASK);
2298 case 106: return createRegOperand(Reg: VCC);
2299 case 108: return createRegOperand(Reg: TBA);
2300 case 110: return createRegOperand(Reg: TMA);
2301 case 124:
2302 if (isGFX11Plus())
2303 return createRegOperand(Reg: SGPR_NULL);
2304 break;
2305 case 125:
2306 if (!isGFX11Plus())
2307 return createRegOperand(Reg: SGPR_NULL);
2308 break;
2309 case 126: return createRegOperand(Reg: EXEC);
2310 case 230: return createRegOperand(Reg: SRC_FLAT_SCRATCH_BASE_LO);
2311 case 235: return createRegOperand(Reg: SRC_SHARED_BASE);
2312 case 236: return createRegOperand(Reg: SRC_SHARED_LIMIT);
2313 case 237:
2314 if (AMDGPU::hasPrivateApertureRegs(STI))
2315 return createRegOperand(Reg: SRC_PRIVATE_BASE);
2316 break;
2317 case 238:
2318 if (AMDGPU::hasPrivateApertureRegs(STI))
2319 return createRegOperand(Reg: SRC_PRIVATE_LIMIT);
2320 break;
2321 case 239:
2322 if (AMDGPU::hasPopsExitingWaveID(STI))
2323 return createRegOperand(Reg: SRC_POPS_EXITING_WAVE_ID);
2324 break;
2325 case 251:
2326 if (!isGFX11Plus())
2327 return createRegOperand(Reg: SRC_VCCZ);
2328 break;
2329 case 252:
2330 if (!isGFX11Plus())
2331 return createRegOperand(Reg: SRC_EXECZ);
2332 break;
2333 case 253: return createRegOperand(Reg: SRC_SCC);
2334 default: break;
2335 }
2336 return errOperand(V: Val, ErrMsg: "unknown operand encoding " + Twine(Val));
2337}
2338
2339MCOperand AMDGPUDisassembler::decodeSpecialReg96Plus(unsigned Val) const {
2340 using namespace AMDGPU;
2341
2342 switch (Val) {
2343 case 124:
2344 if (isGFX11Plus())
2345 return createRegOperand(Reg: SGPR_NULL);
2346 break;
2347 case 125:
2348 if (!isGFX11Plus())
2349 return createRegOperand(Reg: SGPR_NULL);
2350 break;
2351 default:
2352 break;
2353 }
2354 return errOperand(V: Val, ErrMsg: "unknown operand encoding " + Twine(Val));
2355}
2356
2357MCOperand AMDGPUDisassembler::decodeSDWASrc(unsigned Width,
2358 const unsigned Val) const {
2359 using namespace AMDGPU::SDWA;
2360 using namespace AMDGPU::EncValues;
2361
2362 if (STI.hasFeature(Feature: AMDGPU::FeatureGFX9) ||
2363 STI.hasFeature(Feature: AMDGPU::FeatureGFX10)) {
2364 // XXX: cast to int is needed to avoid stupid warning:
2365 // compare with unsigned is always true
2366 if (int(SDWA9EncValues::SRC_VGPR_MIN) <= int(Val) &&
2367 Val <= SDWA9EncValues::SRC_VGPR_MAX) {
2368 return createRegOperand(RegClassID: getVgprClassId(Width),
2369 Val: Val - SDWA9EncValues::SRC_VGPR_MIN);
2370 }
2371 if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&
2372 Val <= (isGFX10Plus() ? SDWA9EncValues::SRC_SGPR_MAX_GFX10
2373 : SDWA9EncValues::SRC_SGPR_MAX_SI)) {
2374 return createSRegOperand(SRegClassID: *getSgprClassId(Width),
2375 Val: Val - SDWA9EncValues::SRC_SGPR_MIN);
2376 }
2377 if (SDWA9EncValues::SRC_TTMP_MIN <= Val &&
2378 Val <= SDWA9EncValues::SRC_TTMP_MAX) {
2379 return createSRegOperand(SRegClassID: *getTtmpClassId(Width),
2380 Val: Val - SDWA9EncValues::SRC_TTMP_MIN);
2381 }
2382
2383 const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;
2384
2385 if ((INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX) ||
2386 (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX))
2387 return MCOperand::createImm(Val: SVal);
2388
2389 return decodeSpecialReg32(Val: SVal);
2390 }
2391 if (STI.hasFeature(Feature: AMDGPU::FeatureVolcanicIslands))
2392 return createRegOperand(RegClassID: getVgprClassId(Width), Val);
2393 llvm_unreachable("unsupported target");
2394}
2395
2396MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {
2397 return decodeSDWASrc(Width: 16, Val);
2398}
2399
2400MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {
2401 return decodeSDWASrc(Width: 32, Val);
2402}
2403
2404MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {
2405 using namespace AMDGPU::SDWA;
2406
2407 assert((STI.hasFeature(AMDGPU::FeatureGFX9) ||
2408 STI.hasFeature(AMDGPU::FeatureGFX10)) &&
2409 "SDWAVopcDst should be present only on GFX9+");
2410
2411 bool IsWave32 = STI.hasFeature(Feature: AMDGPU::FeatureWavefrontSize32);
2412
2413 if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {
2414 Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;
2415
2416 int TTmpIdx = getTTmpIdx(Val);
2417 if (TTmpIdx >= 0)
2418 return createSRegOperand(SRegClassID: *getTtmpClassId(Width: IsWave32 ? 32 : 64), Val: TTmpIdx);
2419 if (Val > SGPR_MAX) {
2420 return IsWave32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val);
2421 }
2422 return createSRegOperand(SRegClassID: *getSgprClassId(Width: IsWave32 ? 32 : 64), Val);
2423 }
2424 return createRegOperand(Reg: IsWave32 ? AMDGPU::VCC_LO : AMDGPU::VCC);
2425}
2426
2427MCOperand AMDGPUDisassembler::decodeBoolReg(const MCInst &Inst,
2428 unsigned Val) const {
2429 return STI.hasFeature(Feature: AMDGPU::FeatureWavefrontSize32)
2430 ? decodeSrcOp(Inst, Width: 32, Val)
2431 : decodeSrcOp(Inst, Width: 64, Val);
2432}
2433
2434MCOperand AMDGPUDisassembler::decodeSplitBarrier(const MCInst &Inst,
2435 unsigned Val) const {
2436 using namespace AMDGPU::EncValues;
2437 constexpr unsigned M0Encoding = 125;
2438 bool IsValidBarrier =
2439 Val == M0Encoding ||
2440 (INLINE_INTEGER_C_MIN <= Val && Val < INLINE_INTEGER_C_MIN + 32) ||
2441 (INLINE_INTEGER_C_POSITIVE_MAX < Val &&
2442 Val <= INLINE_INTEGER_C_POSITIVE_MAX + 4);
2443 if (!IsValidBarrier)
2444 return MCOperand();
2445 return decodeSrcOp(Inst, Width: 32, Val);
2446}
2447
2448MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {
2449 if (Val != AMDGPU::DPP::DPP8_FI_0 && Val != AMDGPU::DPP::DPP8_FI_1)
2450 return MCOperand();
2451 return MCOperand::createImm(Val);
2452}
2453
2454MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {
2455 using VersionField = AMDGPU::EncodingField<7, 0>;
2456 using W64Bit = AMDGPU::EncodingBit<13>;
2457 using W32Bit = AMDGPU::EncodingBit<14>;
2458 using MDPBit = AMDGPU::EncodingBit<15>;
2459 using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;
2460
2461 auto [Version, W64, W32, MDP] = Encoding::decode(Encoded: Imm);
2462
2463 // Decode into a plain immediate if any unused bits are raised.
2464 if (Encoding::encode(Values: Version, Values: W64, Values: W32, Values: MDP) != Imm)
2465 return MCOperand::createImm(Val: Imm);
2466
2467 const auto &Versions = AMDGPU::UCVersion::getGFXVersions();
2468 const auto *I = find_if(
2469 Range: Versions, P: [Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {
2470 return V.Code == Version;
2471 });
2472 MCContext &Ctx = getContext();
2473 const MCExpr *E;
2474 if (I == Versions.end())
2475 E = MCConstantExpr::create(Value: Version, Ctx);
2476 else
2477 E = MCSymbolRefExpr::create(Symbol: Ctx.getOrCreateSymbol(Name: I->Symbol), Ctx);
2478
2479 if (W64)
2480 E = MCBinaryExpr::createOr(LHS: E, RHS: UCVersionW64Expr, Ctx);
2481 if (W32)
2482 E = MCBinaryExpr::createOr(LHS: E, RHS: UCVersionW32Expr, Ctx);
2483 if (MDP)
2484 E = MCBinaryExpr::createOr(LHS: E, RHS: UCVersionMDPExpr, Ctx);
2485
2486 return MCOperand::createExpr(Val: E);
2487}
2488
2489bool AMDGPUDisassembler::isVI() const {
2490 return STI.hasFeature(Feature: AMDGPU::FeatureVolcanicIslands);
2491}
2492
2493bool AMDGPUDisassembler::isGFX9() const { return AMDGPU::isGFX9(STI); }
2494
2495bool AMDGPUDisassembler::isGFX90A() const {
2496 return STI.hasFeature(Feature: AMDGPU::FeatureGFX90AInsts);
2497}
2498
2499bool AMDGPUDisassembler::isGFX9Plus() const { return AMDGPU::isGFX9Plus(STI); }
2500
2501bool AMDGPUDisassembler::isGFX10() const { return AMDGPU::isGFX10(STI); }
2502
2503bool AMDGPUDisassembler::isGFX10Plus() const {
2504 return AMDGPU::isGFX10Plus(STI);
2505}
2506
2507bool AMDGPUDisassembler::isGFX11() const {
2508 return STI.hasFeature(Feature: AMDGPU::FeatureGFX11);
2509}
2510
2511bool AMDGPUDisassembler::isGFX11Plus() const {
2512 return AMDGPU::isGFX11Plus(STI);
2513}
2514
2515bool AMDGPUDisassembler::isGFX1170() const {
2516 return STI.hasFeature(Feature: AMDGPU::FeatureGFX11_7Insts);
2517}
2518
2519bool AMDGPUDisassembler::isGFX12() const {
2520 return STI.hasFeature(Feature: AMDGPU::FeatureGFX12);
2521}
2522
2523bool AMDGPUDisassembler::isGFX12Plus() const {
2524 return AMDGPU::isGFX12Plus(STI);
2525}
2526
2527bool AMDGPUDisassembler::isGFX1250() const { return AMDGPU::isGFX1250(STI); }
2528
2529bool AMDGPUDisassembler::isGFX1250Plus() const {
2530 return AMDGPU::isGFX1250Plus(STI);
2531}
2532
2533bool AMDGPUDisassembler::isGFX13() const { return AMDGPU::isGFX13(STI); }
2534
2535bool AMDGPUDisassembler::isGFX13Plus() const {
2536 return AMDGPU::isGFX13Plus(STI);
2537}
2538
2539bool AMDGPUDisassembler::hasArchitectedFlatScratch() const {
2540 return STI.hasFeature(Feature: AMDGPU::FeatureArchitectedFlatScratch);
2541}
2542
2543bool AMDGPUDisassembler::hasKernargPreload() const {
2544 return AMDGPU::hasKernargPreload(STI);
2545}
2546//===----------------------------------------------------------------------===//
2547// AMDGPU specific symbol handling
2548//===----------------------------------------------------------------------===//
2549
2550/// Print a string describing the reserved bit range specified by Mask with
2551/// offset BaseBytes for use in error comments. Mask is a single continuous
2552/// range of 1s surrounded by zeros. The format here is meant to align with the
2553/// tables that describe these bits in llvm.org/docs/AMDGPUUsage.html.
2554static SmallString<32> getBitRangeFromMask(uint32_t Mask, unsigned BaseBytes) {
2555 SmallString<32> Result;
2556 raw_svector_ostream S(Result);
2557
2558 int TrailingZeros = llvm::countr_zero(Val: Mask);
2559 int PopCount = llvm::popcount(Value: Mask);
2560
2561 if (PopCount == 1) {
2562 S << "bit (" << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';
2563 } else {
2564 S << "bits in range ("
2565 << (TrailingZeros + PopCount - 1 + BaseBytes * CHAR_BIT) << ':'
2566 << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';
2567 }
2568
2569 return Result;
2570}
2571
2572#define GET_FIELD(MASK) (AMDHSA_BITS_GET(FourByteBuffer, MASK))
2573#define PRINT_DIRECTIVE(DIRECTIVE, MASK) \
2574 do { \
2575 KdStream << Indent << DIRECTIVE " " << GET_FIELD(MASK) << '\n'; \
2576 } while (0)
2577#define PRINT_PSEUDO_DIRECTIVE_COMMENT(DIRECTIVE, MASK) \
2578 do { \
2579 KdStream << Indent << MAI.getCommentString() << ' ' << DIRECTIVE " " \
2580 << GET_FIELD(MASK) << '\n'; \
2581 } while (0)
2582
2583#define CHECK_RESERVED_BITS_IMPL(MASK, DESC, MSG) \
2584 do { \
2585 if (FourByteBuffer & (MASK)) { \
2586 return createStringError(std::errc::invalid_argument, \
2587 "kernel descriptor " DESC \
2588 " reserved %s set" MSG, \
2589 getBitRangeFromMask((MASK), 0).c_str()); \
2590 } \
2591 } while (0)
2592
2593#define CHECK_RESERVED_BITS(MASK) CHECK_RESERVED_BITS_IMPL(MASK, #MASK, "")
2594#define CHECK_RESERVED_BITS_MSG(MASK, MSG) \
2595 CHECK_RESERVED_BITS_IMPL(MASK, #MASK, ", " MSG)
2596#define CHECK_RESERVED_BITS_DESC(MASK, DESC) \
2597 CHECK_RESERVED_BITS_IMPL(MASK, DESC, "")
2598#define CHECK_RESERVED_BITS_DESC_MSG(MASK, DESC, MSG) \
2599 CHECK_RESERVED_BITS_IMPL(MASK, DESC, ", " MSG)
2600
2601// NOLINTNEXTLINE(readability-identifier-naming)
2602Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1(
2603 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
2604 using namespace amdhsa;
2605 StringRef Indent = "\t";
2606
2607 // We cannot accurately backward compute #VGPRs used from
2608 // GRANULATED_WORKITEM_VGPR_COUNT. But we are concerned with getting the same
2609 // value of GRANULATED_WORKITEM_VGPR_COUNT in the reassembled binary. So we
2610 // simply calculate the inverse of what the assembler does.
2611
2612 uint32_t GranulatedWorkitemVGPRCount =
2613 GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT);
2614
2615 uint32_t NextFreeVGPR =
2616 (GranulatedWorkitemVGPRCount + 1) *
2617 AMDGPU::IsaInfo::getVGPREncodingGranule(STI, EnableWavefrontSize32);
2618
2619 KdStream << Indent << ".amdhsa_next_free_vgpr " << NextFreeVGPR << '\n';
2620
2621 // We cannot backward compute values used to calculate
2622 // GRANULATED_WAVEFRONT_SGPR_COUNT. Hence the original values for following
2623 // directives can't be computed:
2624 // .amdhsa_reserve_vcc
2625 // .amdhsa_reserve_flat_scratch
2626 // .amdhsa_reserve_xnack_mask
2627 // They take their respective default values if not specified in the assembly.
2628 //
2629 // GRANULATED_WAVEFRONT_SGPR_COUNT
2630 // = f(NEXT_FREE_SGPR + VCC + FLAT_SCRATCH + XNACK_MASK)
2631 //
2632 // We compute the inverse as though all directives apart from NEXT_FREE_SGPR
2633 // are set to 0. So while disassembling we consider that:
2634 //
2635 // GRANULATED_WAVEFRONT_SGPR_COUNT
2636 // = f(NEXT_FREE_SGPR + 0 + 0 + 0)
2637 //
2638 // The disassembler cannot recover the original values of those 3 directives.
2639
2640 uint32_t GranulatedWavefrontSGPRCount =
2641 GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT);
2642
2643 if (isGFX10Plus())
2644 CHECK_RESERVED_BITS_MSG(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,
2645 "must be zero on gfx10+");
2646
2647 uint32_t NextFreeSGPR = (GranulatedWavefrontSGPRCount + 1) *
2648 AMDGPU::IsaInfo::getSGPREncodingGranule(STI);
2649
2650 KdStream << Indent << ".amdhsa_reserve_vcc " << 0 << '\n';
2651 if (!hasArchitectedFlatScratch())
2652 KdStream << Indent << ".amdhsa_reserve_flat_scratch " << 0 << '\n';
2653 // Only print the directive on xnack-supporting targets (matching the
2654 // asmprinter), unless the binary erronously set xnack on an unsupported
2655 // target
2656 bool ReservedXnackMask = TargetID.isXnackOnOrAny();
2657 if (STI.hasFeature(Feature: AMDGPU::FeatureSupportsXNACK) || ReservedXnackMask) {
2658 KdStream << Indent << ".amdhsa_reserve_xnack_mask " << ReservedXnackMask
2659 << '\n';
2660 }
2661 KdStream << Indent << ".amdhsa_next_free_sgpr " << NextFreeSGPR << "\n";
2662
2663 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIORITY);
2664
2665 PRINT_DIRECTIVE(".amdhsa_float_round_mode_32",
2666 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32);
2667 PRINT_DIRECTIVE(".amdhsa_float_round_mode_16_64",
2668 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64);
2669 PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_32",
2670 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32);
2671 PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_16_64",
2672 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64);
2673
2674 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIV);
2675
2676 if (STI.hasFeature(Feature: AMDGPU::FeatureDX10ClampAndIEEEMode))
2677 PRINT_DIRECTIVE(".amdhsa_dx10_clamp",
2678 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP);
2679
2680 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_DEBUG_MODE);
2681
2682 if (STI.hasFeature(Feature: AMDGPU::FeatureDX10ClampAndIEEEMode))
2683 PRINT_DIRECTIVE(".amdhsa_ieee_mode",
2684 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE);
2685
2686 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_BULKY);
2687 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_CDBG_USER);
2688
2689 // Bits [26].
2690 if (isGFX9Plus()) {
2691 PRINT_DIRECTIVE(".amdhsa_fp16_overflow", COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL);
2692 } else {
2693 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX8_RESERVED0,
2694 "COMPUTE_PGM_RSRC1", "must be zero pre-gfx9");
2695 }
2696
2697 // Bits [27].
2698 if (isGFX1250Plus()) {
2699 PRINT_PSEUDO_DIRECTIVE_COMMENT("FLAT_SCRATCH_IS_NV",
2700 COMPUTE_PGM_RSRC1_GFX125_FLAT_SCRATCH_IS_NV);
2701 } else {
2702 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_GFX6_GFX120_RESERVED1,
2703 "COMPUTE_PGM_RSRC1");
2704 }
2705
2706 // Bits [28].
2707 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_RESERVED2, "COMPUTE_PGM_RSRC1");
2708
2709 // Bits [29-31].
2710 if (isGFX10Plus()) {
2711 // WGP_MODE is not available on GFX1250.
2712 if (!isGFX1250Plus()) {
2713 PRINT_DIRECTIVE(".amdhsa_workgroup_processor_mode",
2714 COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE);
2715 }
2716 PRINT_DIRECTIVE(".amdhsa_memory_ordered", COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED);
2717 PRINT_DIRECTIVE(".amdhsa_forward_progress", COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS);
2718 } else {
2719 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_GFX6_GFX9_RESERVED3,
2720 "COMPUTE_PGM_RSRC1");
2721 }
2722
2723 if (isGFX12Plus())
2724 PRINT_DIRECTIVE(".amdhsa_round_robin_scheduling",
2725 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN);
2726
2727 return true;
2728}
2729
2730// NOLINTNEXTLINE(readability-identifier-naming)
2731Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC2(
2732 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
2733 using namespace amdhsa;
2734 StringRef Indent = "\t";
2735 if (hasArchitectedFlatScratch())
2736 PRINT_DIRECTIVE(".amdhsa_enable_private_segment",
2737 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
2738 else
2739 PRINT_DIRECTIVE(".amdhsa_system_sgpr_private_segment_wavefront_offset",
2740 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);
2741 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_x",
2742 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X);
2743 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_y",
2744 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y);
2745 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_z",
2746 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z);
2747 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_info",
2748 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO);
2749 PRINT_DIRECTIVE(".amdhsa_system_vgpr_workitem_id",
2750 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID);
2751
2752 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_ADDRESS_WATCH);
2753 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_MEMORY);
2754 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_GRANULATED_LDS_SIZE);
2755
2756 PRINT_DIRECTIVE(
2757 ".amdhsa_exception_fp_ieee_invalid_op",
2758 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION);
2759 PRINT_DIRECTIVE(".amdhsa_exception_fp_denorm_src",
2760 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE);
2761 PRINT_DIRECTIVE(
2762 ".amdhsa_exception_fp_ieee_div_zero",
2763 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO);
2764 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_overflow",
2765 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW);
2766 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_underflow",
2767 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW);
2768 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_inexact",
2769 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT);
2770 PRINT_DIRECTIVE(".amdhsa_exception_int_div_zero",
2771 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO);
2772
2773 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC2_RESERVED0, "COMPUTE_PGM_RSRC2");
2774
2775 return true;
2776}
2777
2778// NOLINTNEXTLINE(readability-identifier-naming)
2779Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3(
2780 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {
2781 using namespace amdhsa;
2782 StringRef Indent = "\t";
2783 if (isGFX90A()) {
2784 KdStream << Indent << ".amdhsa_accum_offset "
2785 << (GET_FIELD(COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 4
2786 << '\n';
2787
2788 PRINT_DIRECTIVE(".amdhsa_tg_split", COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT);
2789
2790 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED0,
2791 "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");
2792 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED1,
2793 "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");
2794 } else if (isGFX10Plus()) {
2795 // Bits [0-3].
2796 if (!isGFX12Plus()) {
2797 if (!EnableWavefrontSize32 || !*EnableWavefrontSize32) {
2798 PRINT_DIRECTIVE(".amdhsa_shared_vgpr_count",
2799 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
2800 } else {
2801 PRINT_PSEUDO_DIRECTIVE_COMMENT(
2802 "SHARED_VGPR_COUNT",
2803 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);
2804 }
2805 } else {
2806 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX12_PLUS_RESERVED0,
2807 "COMPUTE_PGM_RSRC3",
2808 "must be zero on gfx12+");
2809 }
2810
2811 // Bits [4-11].
2812 if (isGFX11()) {
2813 PRINT_DIRECTIVE(".amdhsa_inst_pref_size",
2814 COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE);
2815 PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START",
2816 COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START);
2817 PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END",
2818 COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END);
2819 } else if (isGFX12Plus()) {
2820 PRINT_DIRECTIVE(".amdhsa_inst_pref_size",
2821 COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE);
2822 } else {
2823 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED1,
2824 "COMPUTE_PGM_RSRC3",
2825 "must be zero on gfx10");
2826 }
2827
2828 // Bits [12].
2829 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED2,
2830 "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");
2831
2832 // Bits [13].
2833 if (isGFX12Plus()) {
2834 PRINT_PSEUDO_DIRECTIVE_COMMENT("GLG_EN",
2835 COMPUTE_PGM_RSRC3_GFX12_PLUS_GLG_EN);
2836 } else {
2837 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX11_RESERVED3,
2838 "COMPUTE_PGM_RSRC3",
2839 "must be zero on gfx10 or gfx11");
2840 }
2841
2842 // Bits [14-21].
2843 if (isGFX1250Plus()) {
2844 PRINT_DIRECTIVE(".amdhsa_named_barrier_count",
2845 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT);
2846 PRINT_PSEUDO_DIRECTIVE_COMMENT(
2847 "ENABLE_DYNAMIC_VGPR", COMPUTE_PGM_RSRC3_GFX125_ENABLE_DYNAMIC_VGPR);
2848 PRINT_PSEUDO_DIRECTIVE_COMMENT("TCP_SPLIT",
2849 COMPUTE_PGM_RSRC3_GFX125_TCP_SPLIT);
2850 PRINT_PSEUDO_DIRECTIVE_COMMENT(
2851 "ENABLE_DIDT_THROTTLE",
2852 COMPUTE_PGM_RSRC3_GFX125_ENABLE_DIDT_THROTTLE);
2853 } else {
2854 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX120_RESERVED4,
2855 "COMPUTE_PGM_RSRC3",
2856 "must be zero on gfx10+");
2857 }
2858
2859 // Bits [22-30].
2860 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED5,
2861 "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");
2862
2863 // Bits [31].
2864 if (isGFX11Plus()) {
2865 PRINT_PSEUDO_DIRECTIVE_COMMENT("IMAGE_OP",
2866 COMPUTE_PGM_RSRC3_GFX11_PLUS_IMAGE_OP);
2867 } else {
2868 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED6,
2869 "COMPUTE_PGM_RSRC3",
2870 "must be zero on gfx10");
2871 }
2872 } else if (FourByteBuffer) {
2873 return createStringError(
2874 EC: std::errc::invalid_argument,
2875 Fmt: "kernel descriptor COMPUTE_PGM_RSRC3 must be all zero before gfx9");
2876 }
2877 return true;
2878}
2879#undef PRINT_PSEUDO_DIRECTIVE_COMMENT
2880#undef PRINT_DIRECTIVE
2881#undef GET_FIELD
2882#undef CHECK_RESERVED_BITS_IMPL
2883#undef CHECK_RESERVED_BITS
2884#undef CHECK_RESERVED_BITS_MSG
2885#undef CHECK_RESERVED_BITS_DESC
2886#undef CHECK_RESERVED_BITS_DESC_MSG
2887
2888/// Create an error object to return from onSymbolStart for reserved kernel
2889/// descriptor bits being set.
2890static Error createReservedKDBitsError(uint32_t Mask, unsigned BaseBytes,
2891 const char *Msg = "") {
2892 return createStringError(
2893 EC: std::errc::invalid_argument, Fmt: "kernel descriptor reserved %s set%s%s",
2894 Vals: getBitRangeFromMask(Mask, BaseBytes).c_str(), Vals: *Msg ? ", " : "", Vals: Msg);
2895}
2896
2897/// Create an error object to return from onSymbolStart for reserved kernel
2898/// descriptor bytes being set.
2899static Error createReservedKDBytesError(unsigned BaseInBytes,
2900 unsigned WidthInBytes) {
2901 // Create an error comment in the same format as the "Kernel Descriptor"
2902 // table here: https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor .
2903 return createStringError(
2904 EC: std::errc::invalid_argument,
2905 Fmt: "kernel descriptor reserved bits in range (%u:%u) set",
2906 Vals: (BaseInBytes + WidthInBytes) * CHAR_BIT - 1, Vals: BaseInBytes * CHAR_BIT);
2907}
2908
2909Expected<bool> AMDGPUDisassembler::decodeKernelDescriptorDirective(
2910 DataExtractor::Cursor &Cursor, ArrayRef<uint8_t> Bytes,
2911 raw_string_ostream &KdStream) const {
2912#define PRINT_DIRECTIVE(DIRECTIVE, MASK) \
2913 do { \
2914 KdStream << Indent << DIRECTIVE " " \
2915 << ((TwoByteBuffer & MASK) >> (MASK##_SHIFT)) << '\n'; \
2916 } while (0)
2917
2918 uint16_t TwoByteBuffer = 0;
2919 uint32_t FourByteBuffer = 0;
2920
2921 StringRef ReservedBytes;
2922 StringRef Indent = "\t";
2923
2924 assert(Bytes.size() == 64);
2925 DataExtractor DE(Bytes, /*IsLittleEndian=*/true);
2926
2927 switch (Cursor.tell()) {
2928 case amdhsa::GROUP_SEGMENT_FIXED_SIZE_OFFSET:
2929 FourByteBuffer = DE.getU32(C&: Cursor);
2930 KdStream << Indent << ".amdhsa_group_segment_fixed_size " << FourByteBuffer
2931 << '\n';
2932 return true;
2933
2934 case amdhsa::PRIVATE_SEGMENT_FIXED_SIZE_OFFSET:
2935 FourByteBuffer = DE.getU32(C&: Cursor);
2936 KdStream << Indent << ".amdhsa_private_segment_fixed_size "
2937 << FourByteBuffer << '\n';
2938 return true;
2939
2940 case amdhsa::KERNARG_SIZE_OFFSET:
2941 FourByteBuffer = DE.getU32(C&: Cursor);
2942 KdStream << Indent << ".amdhsa_kernarg_size "
2943 << FourByteBuffer << '\n';
2944 return true;
2945
2946 case amdhsa::RESERVED0_OFFSET:
2947 // 4 reserved bytes, must be 0.
2948 ReservedBytes = DE.getBytes(C&: Cursor, Length: 4);
2949 for (char B : ReservedBytes) {
2950 if (B != 0)
2951 return createReservedKDBytesError(BaseInBytes: amdhsa::RESERVED0_OFFSET, WidthInBytes: 4);
2952 }
2953 return true;
2954
2955 case amdhsa::KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET:
2956 // KERNEL_CODE_ENTRY_BYTE_OFFSET
2957 // So far no directive controls this for Code Object V3, so simply skip for
2958 // disassembly.
2959 DE.skip(C&: Cursor, Length: 8);
2960 return true;
2961
2962 case amdhsa::RESERVED1_OFFSET:
2963 // 20 reserved bytes, must be 0.
2964 ReservedBytes = DE.getBytes(C&: Cursor, Length: 20);
2965 for (char B : ReservedBytes) {
2966 if (B != 0)
2967 return createReservedKDBytesError(BaseInBytes: amdhsa::RESERVED1_OFFSET, WidthInBytes: 20);
2968 }
2969 return true;
2970
2971 case amdhsa::COMPUTE_PGM_RSRC3_OFFSET:
2972 FourByteBuffer = DE.getU32(C&: Cursor);
2973 return decodeCOMPUTE_PGM_RSRC3(FourByteBuffer, KdStream);
2974
2975 case amdhsa::COMPUTE_PGM_RSRC1_OFFSET:
2976 FourByteBuffer = DE.getU32(C&: Cursor);
2977 return decodeCOMPUTE_PGM_RSRC1(FourByteBuffer, KdStream);
2978
2979 case amdhsa::COMPUTE_PGM_RSRC2_OFFSET:
2980 FourByteBuffer = DE.getU32(C&: Cursor);
2981 return decodeCOMPUTE_PGM_RSRC2(FourByteBuffer, KdStream);
2982
2983 case amdhsa::KERNEL_CODE_PROPERTIES_OFFSET:
2984 using namespace amdhsa;
2985 TwoByteBuffer = DE.getU16(C&: Cursor);
2986
2987 if (!hasArchitectedFlatScratch())
2988 PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_buffer",
2989 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER);
2990 PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_ptr",
2991 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR);
2992 PRINT_DIRECTIVE(".amdhsa_user_sgpr_queue_ptr",
2993 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR);
2994 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_segment_ptr",
2995 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR);
2996 PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_id",
2997 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID);
2998 if (!hasArchitectedFlatScratch())
2999 PRINT_DIRECTIVE(".amdhsa_user_sgpr_flat_scratch_init",
3000 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT);
3001 PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_size",
3002 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE);
3003
3004 if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED0)
3005 return createReservedKDBitsError(Mask: KERNEL_CODE_PROPERTY_RESERVED0,
3006 BaseBytes: amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);
3007
3008 // Reserved for GFX9
3009 if (isGFX9() &&
3010 (TwoByteBuffer & KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32)) {
3011 return createReservedKDBitsError(
3012 Mask: KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32,
3013 BaseBytes: amdhsa::KERNEL_CODE_PROPERTIES_OFFSET, Msg: "must be zero on gfx9");
3014 }
3015 if (isGFX10Plus()) {
3016 PRINT_DIRECTIVE(".amdhsa_wavefront_size32",
3017 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
3018 }
3019
3020 if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5)
3021 PRINT_DIRECTIVE(".amdhsa_uses_dynamic_stack",
3022 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK);
3023
3024 if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED1) {
3025 return createReservedKDBitsError(Mask: KERNEL_CODE_PROPERTY_RESERVED1,
3026 BaseBytes: amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);
3027 }
3028
3029 return true;
3030
3031 case amdhsa::KERNARG_PRELOAD_OFFSET:
3032 using namespace amdhsa;
3033 TwoByteBuffer = DE.getU16(C&: Cursor);
3034 if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_LENGTH) {
3035 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_length",
3036 KERNARG_PRELOAD_SPEC_LENGTH);
3037 }
3038
3039 if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_OFFSET) {
3040 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_offset",
3041 KERNARG_PRELOAD_SPEC_OFFSET);
3042 }
3043 return true;
3044
3045 case amdhsa::RESERVED3_OFFSET:
3046 // 4 bytes from here are reserved, must be 0.
3047 ReservedBytes = DE.getBytes(C&: Cursor, Length: 4);
3048 for (char B : ReservedBytes) {
3049 if (B != 0)
3050 return createReservedKDBytesError(BaseInBytes: amdhsa::RESERVED3_OFFSET, WidthInBytes: 4);
3051 }
3052 return true;
3053
3054 default:
3055 llvm_unreachable("Unhandled index. Case statements cover everything.");
3056 return true;
3057 }
3058#undef PRINT_DIRECTIVE
3059}
3060
3061Expected<bool> AMDGPUDisassembler::decodeKernelDescriptor(
3062 StringRef KdName, ArrayRef<uint8_t> Bytes, uint64_t KdAddress) const {
3063
3064 // CP microcode requires the kernel descriptor to be 64 aligned.
3065 if (Bytes.size() != 64 || KdAddress % 64 != 0)
3066 return createStringError(EC: std::errc::invalid_argument,
3067 Fmt: "kernel descriptor must be 64-byte aligned");
3068
3069 // FIXME: We can't actually decode "in order" as is done below, as e.g. GFX10
3070 // requires us to know the setting of .amdhsa_wavefront_size32 in order to
3071 // accurately produce .amdhsa_next_free_vgpr, and they appear in the wrong
3072 // order. Workaround this by first looking up .amdhsa_wavefront_size32 here
3073 // when required.
3074 if (isGFX10Plus()) {
3075 uint16_t KernelCodeProperties =
3076 support::endian::read16(P: &Bytes[amdhsa::KERNEL_CODE_PROPERTIES_OFFSET],
3077 E: llvm::endianness::little);
3078 EnableWavefrontSize32 =
3079 AMDHSA_BITS_GET(KernelCodeProperties,
3080 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);
3081 }
3082
3083 std::string Kd;
3084 raw_string_ostream KdStream(Kd);
3085 KdStream << ".amdhsa_kernel " << KdName << '\n';
3086
3087 DataExtractor::Cursor C(0);
3088 while (C && C.tell() < Bytes.size()) {
3089 Expected<bool> Res = decodeKernelDescriptorDirective(Cursor&: C, Bytes, KdStream);
3090
3091 cantFail(Err: C.takeError());
3092
3093 if (!Res)
3094 return Res;
3095 }
3096 KdStream << ".end_amdhsa_kernel\n";
3097 outs() << KdStream.str();
3098 return true;
3099}
3100
3101Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,
3102 uint64_t &Size,
3103 ArrayRef<uint8_t> Bytes,
3104 uint64_t Address) const {
3105 // Right now only kernel descriptor needs to be handled.
3106 // We ignore all other symbols for target specific handling.
3107 // TODO:
3108 // Fix the spurious symbol issue for AMDGPU kernels. Exists for both Code
3109 // Object V2 and V3 when symbols are marked protected.
3110
3111 // amd_kernel_code_t for Code Object V2.
3112 if (Symbol.Type == ELF::STT_AMDGPU_HSA_KERNEL) {
3113 Size = 256;
3114 return createStringError(EC: std::errc::invalid_argument,
3115 Fmt: "code object v2 is not supported");
3116 }
3117
3118 // Code Object V3 kernel descriptors.
3119 StringRef Name = Symbol.Name;
3120 if (Symbol.Type == ELF::STT_OBJECT && Name.ends_with(Suffix: StringRef(".kd"))) {
3121 Size = 64; // Size = 64 regardless of success or failure.
3122 return decodeKernelDescriptor(KdName: Name.drop_back(N: 3), Bytes, KdAddress: Address);
3123 }
3124
3125 return false;
3126}
3127
3128const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
3129 int64_t Val) {
3130 MCContext &Ctx = getContext();
3131 MCSymbol *Sym = Ctx.getOrCreateSymbol(Name: Id);
3132 // Note: only set value to Val on a new symbol in case an dissassembler
3133 // has already been initialized in this context.
3134 if (!Sym->isVariable()) {
3135 Sym->setVariableValue(MCConstantExpr::create(Value: Val, Ctx));
3136 } else {
3137 int64_t Res = ~Val;
3138 bool Valid = Sym->getVariableValue()->evaluateAsAbsolute(Res);
3139 if (!Valid || Res != Val)
3140 Ctx.reportWarning(L: SMLoc(), Msg: "unsupported redefinition of " + Id);
3141 }
3142 return MCSymbolRefExpr::create(Symbol: Sym, Ctx);
3143}
3144
3145bool AMDGPUDisassembler::isBufferInstruction(const MCInst &MI) const {
3146 // Check for MUBUF and MTBUF instructions
3147 if (SIInstrFlags::isBuffer(O: *MCII, O: MI))
3148 return true;
3149
3150 // Check for SMEM buffer instructions (S_BUFFER_* instructions)
3151 if (SIInstrFlags::isSMRD(O: *MCII, O: MI) &&
3152 AMDGPU::getSMEMIsBuffer(Opc: MI.getOpcode()))
3153 return true;
3154
3155 return false;
3156}
3157
3158//===----------------------------------------------------------------------===//
3159// AMDGPUSymbolizer
3160//===----------------------------------------------------------------------===//
3161
3162// Try to find symbol name for specified label
3163bool AMDGPUSymbolizer::tryAddingSymbolicOperand(
3164 MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value,
3165 uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/,
3166 uint64_t /*OpSize*/, uint64_t /*InstSize*/) {
3167
3168 if (!IsBranch) {
3169 return false;
3170 }
3171
3172 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);
3173 if (!Symbols)
3174 return false;
3175
3176 auto Result = llvm::find_if(Range&: *Symbols, P: [Value](const SymbolInfoTy &Val) {
3177 return Val.Addr == static_cast<uint64_t>(Value) &&
3178 Val.Type == ELF::STT_NOTYPE;
3179 });
3180 if (Result != Symbols->end()) {
3181 auto *Sym = Ctx.getOrCreateSymbol(Name: Result->Name);
3182 const auto *Add = MCSymbolRefExpr::create(Symbol: Sym, Ctx);
3183 Inst.addOperand(Op: MCOperand::createExpr(Val: Add));
3184 return true;
3185 }
3186 // Add to list of referenced addresses, so caller can synthesize a label.
3187 ReferencedAddresses.push_back(x: static_cast<uint64_t>(Value));
3188 return false;
3189}
3190
3191void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,
3192 int64_t Value,
3193 uint64_t Address) {
3194 llvm_unreachable("unimplemented");
3195}
3196
3197//===----------------------------------------------------------------------===//
3198// Initialization
3199//===----------------------------------------------------------------------===//
3200
3201static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,
3202 LLVMOpInfoCallback /*GetOpInfo*/,
3203 LLVMSymbolLookupCallback /*SymbolLookUp*/,
3204 void *DisInfo,
3205 MCContext *Ctx,
3206 std::unique_ptr<MCRelocationInfo> &&RelInfo) {
3207 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);
3208}
3209
3210static MCDisassembler *createAMDGPUDisassembler(const Target &T,
3211 const MCSubtargetInfo &STI,
3212 MCContext &Ctx) {
3213 return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());
3214}
3215
3216extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
3217LLVMInitializeAMDGPUDisassembler() {
3218 TargetRegistry::RegisterMCDisassembler(T&: getTheGCNTarget(),
3219 Fn: createAMDGPUDisassembler);
3220 TargetRegistry::RegisterMCSymbolizer(T&: getTheGCNTarget(),
3221 Fn: createAMDGPUSymbolizer);
3222 TargetRegistry::RegisterMCDisassembler(T&: getTheGCNLegacyTarget(),
3223 Fn: createAMDGPUDisassembler);
3224 TargetRegistry::RegisterMCSymbolizer(T&: getTheGCNLegacyTarget(),
3225 Fn: createAMDGPUSymbolizer);
3226}
3227