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