xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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;
Lo(Lo)44   DecoderUInt128(uint64_t Lo, uint64_t Hi = 0) : Lo(Lo), Hi(Hi) {}
45   operator bool() const { return Lo || Hi; }
insertBits(uint64_t SubBits,unsigned BitPosition,unsigned NumBits)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   }
extractBitsAsZExtValue(unsigned NumBits,unsigned BitPosition)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>
tryDecodeInst(const uint8_t * Table,MCInst & MI,InsnType Inst,uint64_t Address,raw_ostream & Comments)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>
tryDecodeInst(const uint8_t * Table1,const uint8_t * Table2,MCInst & MI,InsnType Inst,uint64_t Address,raw_ostream & Comments)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 convertDPP8Inst(MCInst &MI) const;
208   void convertMIMGInst(MCInst &MI) const;
209   void convertVOP3DPPInst(MCInst &MI) const;
210   void convertVOP3PDPPInst(MCInst &MI) const;
211   void convertVOPCDPPInst(MCInst &MI) const;
212   void convertMacDPPInst(MCInst &MI) const;
213   void convertTrue16OpSel(MCInst &MI) const;
214 
215   enum OpWidthTy {
216     OPW32,
217     OPW64,
218     OPW96,
219     OPW128,
220     OPW160,
221     OPW256,
222     OPW288,
223     OPW320,
224     OPW352,
225     OPW384,
226     OPW512,
227     OPW1024,
228     OPW16,
229     OPWV216,
230     OPWV232,
231     OPW_LAST_,
232     OPW_FIRST_ = OPW32
233   };
234 
235   unsigned getVgprClassId(const OpWidthTy Width) const;
236   unsigned getAgprClassId(const OpWidthTy Width) const;
237   unsigned getSgprClassId(const OpWidthTy Width) const;
238   unsigned getTtmpClassId(const OpWidthTy Width) const;
239 
240   static MCOperand decodeIntImmed(unsigned Imm);
241   static MCOperand decodeFPImmed(unsigned ImmWidth, unsigned Imm,
242                                  AMDGPU::OperandSemantics Sema);
243 
244   MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const;
245   MCOperand decodeLiteralConstant(bool ExtendFP64) const;
246 
247   MCOperand decodeSrcOp(
248       const OpWidthTy Width, unsigned Val, bool MandatoryLiteral = false,
249       unsigned ImmWidth = 0,
250       AMDGPU::OperandSemantics Sema = AMDGPU::OperandSemantics::INT) const;
251 
252   MCOperand decodeNonVGPRSrcOp(
253       const OpWidthTy Width, unsigned Val, bool MandatoryLiteral = false,
254       unsigned ImmWidth = 0,
255       AMDGPU::OperandSemantics Sema = AMDGPU::OperandSemantics::INT) const;
256 
257   MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const;
258   MCOperand decodeSpecialReg32(unsigned Val) const;
259   MCOperand decodeSpecialReg64(unsigned Val) const;
260 
261   MCOperand decodeSDWASrc(const OpWidthTy Width, unsigned Val,
262                           unsigned ImmWidth,
263                           AMDGPU::OperandSemantics Sema) const;
264   MCOperand decodeSDWASrc16(unsigned Val) const;
265   MCOperand decodeSDWASrc32(unsigned Val) const;
266   MCOperand decodeSDWAVopcDst(unsigned Val) const;
267 
268   MCOperand decodeBoolReg(unsigned Val) const;
269   MCOperand decodeSplitBarrier(unsigned Val) const;
270   MCOperand decodeDpp8FI(unsigned Val) const;
271 
272   MCOperand decodeVersionImm(unsigned Imm) const;
273 
274   int getTTmpIdx(unsigned Val) const;
275 
getMCII()276   const MCInstrInfo *getMCII() const { return MCII.get(); }
277 
278   bool isVI() const;
279   bool isGFX9() const;
280   bool isGFX90A() const;
281   bool isGFX9Plus() const;
282   bool isGFX10() const;
283   bool isGFX10Plus() const;
284   bool isGFX11() const;
285   bool isGFX11Plus() const;
286   bool isGFX12() const;
287   bool isGFX12Plus() const;
288 
289   bool hasArchitectedFlatScratch() const;
290   bool hasKernargPreload() const;
291 
292   bool isMacDPP(MCInst &MI) const;
293 };
294 
295 //===----------------------------------------------------------------------===//
296 // AMDGPUSymbolizer
297 //===----------------------------------------------------------------------===//
298 
299 class AMDGPUSymbolizer : public MCSymbolizer {
300 private:
301   void *DisInfo;
302   std::vector<uint64_t> ReferencedAddresses;
303 
304 public:
AMDGPUSymbolizer(MCContext & Ctx,std::unique_ptr<MCRelocationInfo> && RelInfo,void * disInfo)305   AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo,
306                    void *disInfo)
307                    : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {}
308 
309   bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
310                                 int64_t Value, uint64_t Address, bool IsBranch,
311                                 uint64_t Offset, uint64_t OpSize,
312                                 uint64_t InstSize) override;
313 
314   void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
315                                        int64_t Value,
316                                        uint64_t Address) override;
317 
getReferencedAddresses()318   ArrayRef<uint64_t> getReferencedAddresses() const override {
319     return ReferencedAddresses;
320   }
321 };
322 
323 } // end namespace llvm
324 
325 #endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
326