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