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