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