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