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