1//===- AMDGPUDisassembler.hpp - Disassembler for AMDGPU ISA -----*- C++ -*-===//
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/// \file
10///
11/// This file contains declaration for AMDGPU ISA disassembler
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
16#define LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
17
18#include "SIDefines.h"
19#include "llvm/ADT/APInt.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/MC/MCDisassembler/MCDisassembler.h"
22#include "llvm/MC/MCInst.h"
23#include "llvm/MC/MCInstrInfo.h"
24#include "llvm/Support/DataExtractor.h"
25#include <memory>
26
27namespace llvm {
28
29class MCAsmInfo;
30class MCInst;
31class MCOperand;
32class MCSubtargetInfo;
33class Twine;
34
35// Exposes an interface expected by autogenerated code in
36// FixedLenDecoderEmitter
37class DecoderUInt128 {
38private:
39 uint64_t Lo = 0;
40 uint64_t Hi = 0;
41
42public:
43 DecoderUInt128() = default;
44 DecoderUInt128(uint64_t Lo, uint64_t Hi = 0) : Lo(Lo), Hi(Hi) {}
45 operator bool() const { return Lo || Hi; }
46 void insertBits(uint64_t SubBits, unsigned BitPosition, unsigned NumBits) {
47 assert(NumBits && NumBits <= 64);
48 assert(SubBits >> 1 >> (NumBits - 1) == 0);
49 assert(BitPosition < 128);
50 if (BitPosition < 64) {
51 Lo |= SubBits << BitPosition;
52 Hi |= SubBits >> 1 >> (63 - BitPosition);
53 } else {
54 Hi |= SubBits << (BitPosition - 64);
55 }
56 }
57 uint64_t extractBitsAsZExtValue(unsigned NumBits,
58 unsigned BitPosition) const {
59 assert(NumBits && NumBits <= 64);
60 assert(BitPosition < 128);
61 uint64_t Val;
62 if (BitPosition < 64)
63 Val = Lo >> BitPosition | Hi << 1 << (63 - BitPosition);
64 else
65 Val = Hi >> (BitPosition - 64);
66 return Val & ((uint64_t(2) << (NumBits - 1)) - 1);
67 }
68 DecoderUInt128 operator&(const DecoderUInt128 &RHS) const {
69 return DecoderUInt128(Lo & RHS.Lo, Hi & RHS.Hi);
70 }
71 DecoderUInt128 operator&(const uint64_t &RHS) const {
72 return *this & DecoderUInt128(RHS);
73 }
74 DecoderUInt128 operator~() const { return DecoderUInt128(~Lo, ~Hi); }
75 bool operator==(const DecoderUInt128 &RHS) {
76 return Lo == RHS.Lo && Hi == RHS.Hi;
77 }
78 bool operator!=(const DecoderUInt128 &RHS) {
79 return Lo != RHS.Lo || Hi != RHS.Hi;
80 }
81 bool operator!=(const int &RHS) {
82 return *this != DecoderUInt128(RHS);
83 }
84 friend raw_ostream &operator<<(raw_ostream &OS, const DecoderUInt128 &RHS) {
85 return OS << APInt(128, {RHS.Lo, RHS.Hi});
86 }
87};
88
89//===----------------------------------------------------------------------===//
90// AMDGPUDisassembler
91//===----------------------------------------------------------------------===//
92
93class AMDGPUDisassembler : public MCDisassembler {
94private:
95 std::unique_ptr<MCInstrInfo const> const MCII;
96 const MCRegisterInfo &MRI;
97 const MCAsmInfo &MAI;
98 const unsigned TargetMaxInstBytes;
99 mutable ArrayRef<uint8_t> Bytes;
100 mutable uint32_t Literal;
101 mutable uint64_t Literal64;
102 mutable bool HasLiteral;
103 mutable std::optional<bool> EnableWavefrontSize32;
104 unsigned CodeObjectVersion;
105 const MCExpr *UCVersionW64Expr;
106 const MCExpr *UCVersionW32Expr;
107 const MCExpr *UCVersionMDPExpr;
108
109 const MCExpr *createConstantSymbolExpr(StringRef Id, int64_t Val);
110
111 void decodeImmOperands(MCInst &MI, const MCInstrInfo &MCII) const;
112
113public:
114 AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
115 MCInstrInfo const *MCII);
116 ~AMDGPUDisassembler() override = default;
117
118 void setABIVersion(unsigned Version) override;
119
120 DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,
121 ArrayRef<uint8_t> Bytes, uint64_t Address,
122 raw_ostream &CS) const override;
123
124 const char* getRegClassName(unsigned RegClassID) const;
125
126 MCOperand createRegOperand(unsigned int RegId) const;
127 MCOperand createRegOperand(unsigned RegClassID, unsigned Val) const;
128 MCOperand createSRegOperand(unsigned SRegClassID, unsigned Val) const;
129 MCOperand createVGPR16Operand(unsigned RegIdx, bool IsHi) const;
130
131 MCOperand errOperand(unsigned V, const Twine& ErrMsg) const;
132
133 template <typename InsnType>
134 DecodeStatus tryDecodeInst(const uint8_t *Table, MCInst &MI, InsnType Inst,
135 uint64_t Address, raw_ostream &Comments) const;
136 template <typename InsnType>
137 DecodeStatus tryDecodeInst(const uint8_t *Table1, const uint8_t *Table2,
138 MCInst &MI, InsnType Inst, uint64_t Address,
139 raw_ostream &Comments) const;
140
141 Expected<bool> onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
142 ArrayRef<uint8_t> Bytes,
143 uint64_t Address) const override;
144
145 Expected<bool> decodeKernelDescriptor(StringRef KdName,
146 ArrayRef<uint8_t> Bytes,
147 uint64_t KdAddress) const;
148
149 Expected<bool>
150 decodeKernelDescriptorDirective(DataExtractor::Cursor &Cursor,
151 ArrayRef<uint8_t> Bytes,
152 raw_string_ostream &KdStream) const;
153
154 /// Decode as directives that handle COMPUTE_PGM_RSRC1.
155 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC1.
156 /// \param KdStream - Stream to write the disassembled directives to.
157 // NOLINTNEXTLINE(readability-identifier-naming)
158 Expected<bool> decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer,
159 raw_string_ostream &KdStream) const;
160
161 /// Decode as directives that handle COMPUTE_PGM_RSRC2.
162 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC2.
163 /// \param KdStream - Stream to write the disassembled directives to.
164 // NOLINTNEXTLINE(readability-identifier-naming)
165 Expected<bool> decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer,
166 raw_string_ostream &KdStream) const;
167
168 /// Decode as directives that handle COMPUTE_PGM_RSRC3.
169 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC3.
170 /// \param KdStream - Stream to write the disassembled directives to.
171 // NOLINTNEXTLINE(readability-identifier-naming)
172 Expected<bool> decodeCOMPUTE_PGM_RSRC3(uint32_t FourByteBuffer,
173 raw_string_ostream &KdStream) const;
174
175 void convertEXPInst(MCInst &MI) const;
176 void convertVINTERPInst(MCInst &MI) const;
177 void convertFMAanyK(MCInst &MI) const;
178 void convertSDWAInst(MCInst &MI) const;
179 void convertMAIInst(MCInst &MI) const;
180 void convertDPP8Inst(MCInst &MI) const;
181 void convertMIMGInst(MCInst &MI) const;
182 void convertVOP3DPPInst(MCInst &MI) const;
183 void convertVOP3PDPPInst(MCInst &MI) const;
184 void convertVOPCDPPInst(MCInst &MI) const;
185 void convertVOPC64DPPInst(MCInst &MI) const;
186 void convertMacDPPInst(MCInst &MI) const;
187 void convertTrue16OpSel(MCInst &MI) const;
188
189 unsigned getVgprClassId(unsigned Width) const;
190 unsigned getAgprClassId(unsigned Width) const;
191 unsigned getSgprClassId(unsigned Width) const;
192 unsigned getTtmpClassId(unsigned Width) const;
193
194 static MCOperand decodeIntImmed(unsigned Imm);
195
196 MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const;
197 MCOperand decodeLiteralConstant(bool ExtendFP64) const;
198
199 MCOperand decodeSrcOp(unsigned Width, unsigned Val) const;
200
201 MCOperand decodeNonVGPRSrcOp(unsigned Width, unsigned Val) const;
202
203 MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const;
204 MCOperand decodeSpecialReg32(unsigned Val) const;
205 MCOperand decodeSpecialReg64(unsigned Val) const;
206 MCOperand decodeSpecialReg96Plus(unsigned Val) const;
207
208 MCOperand decodeSDWASrc(unsigned Width, unsigned Val) const;
209 MCOperand decodeSDWASrc16(unsigned Val) const;
210 MCOperand decodeSDWASrc32(unsigned Val) const;
211 MCOperand decodeSDWAVopcDst(unsigned Val) const;
212
213 MCOperand decodeBoolReg(unsigned Val) const;
214 MCOperand decodeSplitBarrier(unsigned Val) const;
215 MCOperand decodeDpp8FI(unsigned Val) const;
216
217 MCOperand decodeVersionImm(unsigned Imm) const;
218
219 int getTTmpIdx(unsigned Val) const;
220
221 const MCInstrInfo *getMCII() const { return MCII.get(); }
222
223 bool isVI() const;
224 bool isGFX9() const;
225 bool isGFX90A() const;
226 bool isGFX9Plus() const;
227 bool isGFX10() const;
228 bool isGFX10Plus() const;
229 bool isGFX11() const;
230 bool isGFX11Plus() const;
231 bool isGFX12() const;
232 bool isGFX12Plus() const;
233 bool isGFX1250() const;
234
235 bool hasArchitectedFlatScratch() const;
236 bool hasKernargPreload() const;
237
238 bool isMacDPP(MCInst &MI) const;
239};
240
241//===----------------------------------------------------------------------===//
242// AMDGPUSymbolizer
243//===----------------------------------------------------------------------===//
244
245class AMDGPUSymbolizer : public MCSymbolizer {
246private:
247 void *DisInfo;
248 std::vector<uint64_t> ReferencedAddresses;
249
250public:
251 AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo,
252 void *disInfo)
253 : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {}
254
255 bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
256 int64_t Value, uint64_t Address, bool IsBranch,
257 uint64_t Offset, uint64_t OpSize,
258 uint64_t InstSize) override;
259
260 void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
261 int64_t Value,
262 uint64_t Address) override;
263
264 ArrayRef<uint64_t> getReferencedAddresses() const override {
265 return ReferencedAddresses;
266 }
267};
268
269} // end namespace llvm
270
271#endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
272