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/MC/MCDisassembler/MCDisassembler.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCInst.h"
22 #include "llvm/Support/DataExtractor.h"
23 #include <memory>
24 
25 namespace llvm {
26 
27 class MCInst;
28 class MCOperand;
29 class MCSubtargetInfo;
30 class Twine;
31 
32 // Exposes an interface expected by autogenerated code in
33 // FixedLenDecoderEmitter
34 class DecoderUInt128 {
35 private:
36   uint64_t Lo = 0;
37   uint64_t Hi = 0;
38 
39 public:
40   DecoderUInt128() = default;
41   DecoderUInt128(uint64_t Lo, uint64_t Hi = 0) : Lo(Lo), Hi(Hi) {}
42   operator bool() const { return Lo || Hi; }
43   void insertBits(uint64_t SubBits, unsigned BitPosition, unsigned NumBits) {
44     assert(NumBits && NumBits <= 64);
45     assert(SubBits >> 1 >> (NumBits - 1) == 0);
46     assert(BitPosition < 128);
47     if (BitPosition < 64) {
48       Lo |= SubBits << BitPosition;
49       Hi |= SubBits >> 1 >> (63 - BitPosition);
50     } else {
51       Hi |= SubBits << (BitPosition - 64);
52     }
53   }
54   uint64_t extractBitsAsZExtValue(unsigned NumBits,
55                                   unsigned BitPosition) const {
56     assert(NumBits && NumBits <= 64);
57     assert(BitPosition < 128);
58     uint64_t Val;
59     if (BitPosition < 64)
60       Val = Lo >> BitPosition | Hi << 1 << (63 - BitPosition);
61     else
62       Val = Hi >> (BitPosition - 64);
63     return Val & ((uint64_t(2) << (NumBits - 1)) - 1);
64   }
65   DecoderUInt128 operator&(const DecoderUInt128 &RHS) const {
66     return DecoderUInt128(Lo & RHS.Lo, Hi & RHS.Hi);
67   }
68   DecoderUInt128 operator&(const uint64_t &RHS) const {
69     return *this & DecoderUInt128(RHS);
70   }
71   DecoderUInt128 operator~() const { return DecoderUInt128(~Lo, ~Hi); }
72   bool operator==(const DecoderUInt128 &RHS) {
73     return Lo == RHS.Lo && Hi == RHS.Hi;
74   }
75   bool operator!=(const DecoderUInt128 &RHS) {
76     return Lo != RHS.Lo || Hi != RHS.Hi;
77   }
78   bool operator!=(const int &RHS) {
79     return *this != DecoderUInt128(RHS);
80   }
81   friend raw_ostream &operator<<(raw_ostream &OS, const DecoderUInt128 &RHS) {
82     return OS << APInt(128, {RHS.Lo, RHS.Hi});
83   }
84 };
85 
86 //===----------------------------------------------------------------------===//
87 // AMDGPUDisassembler
88 //===----------------------------------------------------------------------===//
89 
90 class AMDGPUDisassembler : public MCDisassembler {
91 private:
92   std::unique_ptr<MCInstrInfo const> const MCII;
93   const MCRegisterInfo &MRI;
94   const unsigned TargetMaxInstBytes;
95   mutable ArrayRef<uint8_t> Bytes;
96   mutable uint32_t Literal;
97   mutable bool HasLiteral;
98 
99 public:
100   AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
101                      MCInstrInfo const *MCII);
102   ~AMDGPUDisassembler() override = default;
103 
104   DecodeStatus getInstruction(MCInst &MI, uint64_t &Size,
105                               ArrayRef<uint8_t> Bytes, uint64_t Address,
106                               raw_ostream &CS) const override;
107 
108   const char* getRegClassName(unsigned RegClassID) const;
109 
110   MCOperand createRegOperand(unsigned int RegId) const;
111   MCOperand createRegOperand(unsigned RegClassID, unsigned Val) const;
112   MCOperand createSRegOperand(unsigned SRegClassID, unsigned Val) const;
113 
114   MCOperand errOperand(unsigned V, const Twine& ErrMsg) const;
115 
116   template <typename InsnType>
117   DecodeStatus tryDecodeInst(const uint8_t *Table, MCInst &MI, InsnType Inst,
118                              uint64_t Address) const {
119     assert(MI.getOpcode() == 0);
120     assert(MI.getNumOperands() == 0);
121     MCInst TmpInst;
122     HasLiteral = false;
123     const auto SavedBytes = Bytes;
124     if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) {
125       MI = TmpInst;
126       return MCDisassembler::Success;
127     }
128     Bytes = SavedBytes;
129     return MCDisassembler::Fail;
130   }
131 
132   Optional<DecodeStatus> onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size,
133                                        ArrayRef<uint8_t> Bytes,
134                                        uint64_t Address,
135                                        raw_ostream &CStream) const override;
136 
137   DecodeStatus decodeKernelDescriptor(StringRef KdName, ArrayRef<uint8_t> Bytes,
138                                       uint64_t KdAddress) const;
139 
140   DecodeStatus
141   decodeKernelDescriptorDirective(DataExtractor::Cursor &Cursor,
142                                   ArrayRef<uint8_t> Bytes,
143                                   raw_string_ostream &KdStream) const;
144 
145   /// Decode as directives that handle COMPUTE_PGM_RSRC1.
146   /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC1.
147   /// \param KdStream       - Stream to write the disassembled directives to.
148   // NOLINTNEXTLINE(readability-identifier-naming)
149   DecodeStatus decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer,
150                                        raw_string_ostream &KdStream) const;
151 
152   /// Decode as directives that handle COMPUTE_PGM_RSRC2.
153   /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC2.
154   /// \param KdStream       - Stream to write the disassembled directives to.
155   // NOLINTNEXTLINE(readability-identifier-naming)
156   DecodeStatus decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer,
157                                        raw_string_ostream &KdStream) const;
158 
159   DecodeStatus convertEXPInst(MCInst &MI) const;
160   DecodeStatus convertVINTERPInst(MCInst &MI) const;
161   DecodeStatus convertFMAanyK(MCInst &MI, int ImmLitIdx) const;
162   DecodeStatus convertSDWAInst(MCInst &MI) const;
163   DecodeStatus convertDPP8Inst(MCInst &MI) const;
164   DecodeStatus convertMIMGInst(MCInst &MI) const;
165   DecodeStatus convertVOP3DPPInst(MCInst &MI) const;
166   DecodeStatus convertVOP3PDPPInst(MCInst &MI) const;
167   DecodeStatus convertVOPCDPPInst(MCInst &MI) const;
168 
169   MCOperand decodeOperand_VGPR_32(unsigned Val) const;
170   MCOperand decodeOperand_VRegOrLds_32(unsigned Val) const;
171 
172   MCOperand decodeOperand_VS_32(unsigned Val) const;
173   MCOperand decodeOperand_VS_64(unsigned Val) const;
174   MCOperand decodeOperand_VS_128(unsigned Val) const;
175   MCOperand decodeOperand_VSrc16(unsigned Val) const;
176   MCOperand decodeOperand_VSrcV216(unsigned Val) const;
177   MCOperand decodeOperand_VSrcV232(unsigned Val) const;
178 
179   MCOperand decodeOperand_VReg_64(unsigned Val) const;
180   MCOperand decodeOperand_VReg_96(unsigned Val) const;
181   MCOperand decodeOperand_VReg_128(unsigned Val) const;
182   MCOperand decodeOperand_VReg_256(unsigned Val) const;
183   MCOperand decodeOperand_VReg_512(unsigned Val) const;
184   MCOperand decodeOperand_VReg_1024(unsigned Val) const;
185 
186   MCOperand decodeOperand_SReg_32(unsigned Val) const;
187   MCOperand decodeOperand_SReg_32_XM0_XEXEC(unsigned Val) const;
188   MCOperand decodeOperand_SReg_32_XEXEC_HI(unsigned Val) const;
189   MCOperand decodeOperand_SRegOrLds_32(unsigned Val) const;
190   MCOperand decodeOperand_SReg_64(unsigned Val) const;
191   MCOperand decodeOperand_SReg_64_XEXEC(unsigned Val) const;
192   MCOperand decodeOperand_SReg_128(unsigned Val) const;
193   MCOperand decodeOperand_SReg_256(unsigned Val) const;
194   MCOperand decodeOperand_SReg_512(unsigned Val) const;
195 
196   MCOperand decodeOperand_AGPR_32(unsigned Val) const;
197   MCOperand decodeOperand_AReg_64(unsigned Val) const;
198   MCOperand decodeOperand_AReg_128(unsigned Val) const;
199   MCOperand decodeOperand_AReg_256(unsigned Val) const;
200   MCOperand decodeOperand_AReg_512(unsigned Val) const;
201   MCOperand decodeOperand_AReg_1024(unsigned Val) const;
202   MCOperand decodeOperand_AV_32(unsigned Val) const;
203   MCOperand decodeOperand_AV_64(unsigned Val) const;
204   MCOperand decodeOperand_AV_128(unsigned Val) const;
205   MCOperand decodeOperand_AVDst_128(unsigned Val) const;
206   MCOperand decodeOperand_AVDst_512(unsigned Val) const;
207 
208   enum OpWidthTy {
209     OPW32,
210     OPW64,
211     OPW96,
212     OPW128,
213     OPW160,
214     OPW256,
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(OpWidthTy Width, unsigned Imm);
231   MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const;
232   MCOperand decodeLiteralConstant() const;
233 
234   MCOperand decodeSrcOp(const OpWidthTy Width, unsigned Val,
235                         bool MandatoryLiteral = false) const;
236   MCOperand decodeDstOp(const OpWidthTy Width, unsigned Val) const;
237   MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const;
238   MCOperand decodeSpecialReg32(unsigned Val) const;
239   MCOperand decodeSpecialReg64(unsigned Val) const;
240 
241   MCOperand decodeSDWASrc(const OpWidthTy Width, unsigned Val) const;
242   MCOperand decodeSDWASrc16(unsigned Val) const;
243   MCOperand decodeSDWASrc32(unsigned Val) const;
244   MCOperand decodeSDWAVopcDst(unsigned Val) const;
245 
246   MCOperand decodeBoolReg(unsigned Val) const;
247 
248   int getTTmpIdx(unsigned Val) const;
249 
250   const MCInstrInfo *getMCII() const { return MCII.get(); }
251 
252   bool isVI() const;
253   bool isGFX9() const;
254   bool isGFX90A() const;
255   bool isGFX9Plus() const;
256   bool isGFX10() const;
257   bool isGFX10Plus() const;
258   bool isGFX11() const;
259   bool isGFX11Plus() const;
260 
261   bool hasArchitectedFlatScratch() const;
262 };
263 
264 //===----------------------------------------------------------------------===//
265 // AMDGPUSymbolizer
266 //===----------------------------------------------------------------------===//
267 
268 class AMDGPUSymbolizer : public MCSymbolizer {
269 private:
270   void *DisInfo;
271   std::vector<uint64_t> ReferencedAddresses;
272 
273 public:
274   AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo,
275                    void *disInfo)
276                    : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {}
277 
278   bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream,
279                                 int64_t Value, uint64_t Address, bool IsBranch,
280                                 uint64_t Offset, uint64_t OpSize,
281                                 uint64_t InstSize) override;
282 
283   void tryAddingPcLoadReferenceComment(raw_ostream &cStream,
284                                        int64_t Value,
285                                        uint64_t Address) override;
286 
287   ArrayRef<uint64_t> getReferencedAddresses() const override {
288     return ReferencedAddresses;
289   }
290 };
291 
292 } // end namespace llvm
293 
294 #endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H
295