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