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