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
106public:
107 AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
108 MCInstrInfo const *MCII);
109 ~AMDGPUDisassembler() override = default;
110
111 void setABIVersion(unsigned Version) override;
112
113 DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,
114 ArrayRef<uint8_t> Bytes, uint64_t Address,
115 raw_ostream &CS) const override;
116
117 const char* getRegClassName(unsigned RegClassID) const;
118
119 MCOperand createRegOperand(unsigned int RegId) const;
120 MCOperand createRegOperand(unsigned RegClassID, unsigned Val) const;
121 MCOperand createSRegOperand(unsigned SRegClassID, unsigned Val) const;
122 MCOperand createVGPR16Operand(unsigned RegIdx, bool IsHi) const;
123
124 MCOperand errOperand(unsigned V, const Twine& ErrMsg) const;
125
126 template <typename InsnType>
127 DecodeStatus tryDecodeInst(const uint8_t *Table, MCInst &MI, InsnType Inst,
128 uint64_t Address, raw_ostream &Comments) const {
129 assert(MI.getOpcode() == 0);
130 assert(MI.getNumOperands() == 0);
131 MCInst TmpInst;
132 HasLiteral = false;
133 const auto SavedBytes = Bytes;
134
135 SmallString<64> LocalComments;
136 raw_svector_ostream LocalCommentStream(LocalComments);
137 CommentStream = &LocalCommentStream;
138
139 DecodeStatus Res =
140 decodeInstruction(Table, TmpInst, Inst, Address, this, STI);
141
142 CommentStream = nullptr;
143
144 if (Res != Fail) {
145 MI = TmpInst;
146 Comments << LocalComments;
147 return MCDisassembler::Success;
148 }
149 Bytes = SavedBytes;
150 return MCDisassembler::Fail;
151 }
152
153 template <typename InsnType>
154 DecodeStatus tryDecodeInst(const uint8_t *Table1, const uint8_t *Table2,
155 MCInst &MI, InsnType Inst, uint64_t Address,
156 raw_ostream &Comments) const {
157 for (const uint8_t *T : {Table1, Table2}) {
158 if (DecodeStatus Res = tryDecodeInst(T, MI, Inst, Address, Comments))
159 return Res;
160 }
161 return MCDisassembler::Fail;
162 }
163
164 Expected<bool> onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
165 ArrayRef<uint8_t> Bytes,
166 uint64_t Address) const override;
167
168 Expected<bool> decodeKernelDescriptor(StringRef KdName,
169 ArrayRef<uint8_t> Bytes,
170 uint64_t KdAddress) const;
171
172 Expected<bool>
173 decodeKernelDescriptorDirective(DataExtractor::Cursor &Cursor,
174 ArrayRef<uint8_t> Bytes,
175 raw_string_ostream &KdStream) const;
176
177 /// Decode as directives that handle COMPUTE_PGM_RSRC1.
178 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC1.
179 /// \param KdStream - Stream to write the disassembled directives to.
180 // NOLINTNEXTLINE(readability-identifier-naming)
181 Expected<bool> decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer,
182 raw_string_ostream &KdStream) const;
183
184 /// Decode as directives that handle COMPUTE_PGM_RSRC2.
185 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC2.
186 /// \param KdStream - Stream to write the disassembled directives to.
187 // NOLINTNEXTLINE(readability-identifier-naming)
188 Expected<bool> decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer,
189 raw_string_ostream &KdStream) const;
190
191 /// Decode as directives that handle COMPUTE_PGM_RSRC3.
192 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC3.
193 /// \param KdStream - Stream to write the disassembled directives to.
194 // NOLINTNEXTLINE(readability-identifier-naming)
195 Expected<bool> decodeCOMPUTE_PGM_RSRC3(uint32_t FourByteBuffer,
196 raw_string_ostream &KdStream) const;
197
198 void convertEXPInst(MCInst &MI) const;
199 void convertVINTERPInst(MCInst &MI) const;
200 void convertFMAanyK(MCInst &MI, int ImmLitIdx) const;
201 void convertSDWAInst(MCInst &MI) const;
202 void convertDPP8Inst(MCInst &MI) const;
203 void convertMIMGInst(MCInst &MI) const;
204 void convertVOP3DPPInst(MCInst &MI) const;
205 void convertVOP3PDPPInst(MCInst &MI) const;
206 void convertVOPCDPPInst(MCInst &MI) const;
207 void convertMacDPPInst(MCInst &MI) const;
208 void convertTrue16OpSel(MCInst &MI) const;
209
210 enum OpWidthTy {
211 OPW32,
212 OPW64,
213 OPW96,
214 OPW128,
215 OPW160,
216 OPW256,
217 OPW288,
218 OPW320,
219 OPW352,
220 OPW384,
221 OPW512,
222 OPW1024,
223 OPW16,
224 OPWV216,
225 OPWV232,
226 OPW_LAST_,
227 OPW_FIRST_ = OPW32
228 };
229
230 unsigned getVgprClassId(const OpWidthTy Width) const;
231 unsigned getAgprClassId(const OpWidthTy Width) const;
232 unsigned getSgprClassId(const OpWidthTy Width) const;
233 unsigned getTtmpClassId(const OpWidthTy Width) const;
234
235 static MCOperand decodeIntImmed(unsigned Imm);
236 static MCOperand decodeFPImmed(unsigned ImmWidth, unsigned Imm,
237 AMDGPU::OperandSemantics Sema);
238
239 MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const;
240 MCOperand decodeLiteralConstant(bool ExtendFP64) const;
241
242 MCOperand decodeSrcOp(
243 const OpWidthTy Width, unsigned Val, bool MandatoryLiteral = false,
244 unsigned ImmWidth = 0,
245 AMDGPU::OperandSemantics Sema = AMDGPU::OperandSemantics::INT) const;
246
247 MCOperand decodeNonVGPRSrcOp(
248 const OpWidthTy Width, unsigned Val, bool MandatoryLiteral = false,
249 unsigned ImmWidth = 0,
250 AMDGPU::OperandSemantics Sema = AMDGPU::OperandSemantics::INT) const;
251
252 MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const;
253 MCOperand decodeSpecialReg32(unsigned Val) const;
254 MCOperand decodeSpecialReg64(unsigned Val) const;
255
256 MCOperand decodeSDWASrc(const OpWidthTy Width, unsigned Val,
257 unsigned ImmWidth,
258 AMDGPU::OperandSemantics Sema) const;
259 MCOperand decodeSDWASrc16(unsigned Val) const;
260 MCOperand decodeSDWASrc32(unsigned Val) const;
261 MCOperand decodeSDWAVopcDst(unsigned Val) const;
262
263 MCOperand decodeBoolReg(unsigned Val) const;
264 MCOperand decodeSplitBarrier(unsigned Val) const;
265 MCOperand decodeDpp8FI(unsigned Val) const;
266
267 int getTTmpIdx(unsigned Val) const;
268
269 const MCInstrInfo *getMCII() const { return MCII.get(); }
270
271 bool isVI() const;
272 bool isGFX9() const;
273 bool isGFX90A() const;
274 bool isGFX9Plus() const;
275 bool isGFX10() const;
276 bool isGFX10Plus() const;
277 bool isGFX11() const;
278 bool isGFX11Plus() const;
279 bool isGFX12() const;
280 bool isGFX12Plus() const;
281
282 bool hasArchitectedFlatScratch() const;
283 bool hasKernargPreload() const;
284
285 bool isMacDPP(MCInst &MI) const;
286};
287
288//===----------------------------------------------------------------------===//
289// AMDGPUSymbolizer
290//===----------------------------------------------------------------------===//
291
292class AMDGPUSymbolizer : public MCSymbolizer {
293private:
294 void *DisInfo;
295 std::vector<uint64_t> ReferencedAddresses;
296
297public:
298 AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo,
299 void *disInfo)
300 : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {}
301
302 bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
303 int64_t Value, uint64_t Address, bool IsBranch,
304 uint64_t Offset, uint64_t OpSize,
305 uint64_t InstSize) override;
306
307 void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
308 int64_t Value,
309 uint64_t Address) override;
310
311 ArrayRef<uint64_t> getReferencedAddresses() const override {
312 return ReferencedAddresses;
313 }
314};
315
316} // end namespace llvm
317
318#endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
319

source code of llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h