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 uint64_t extractBitsAsZExtValue(unsigned NumBits, 47 unsigned BitPosition) const { 48 assert(NumBits && NumBits <= 64); 49 assert(BitPosition < 128); 50 uint64_t Val; 51 if (BitPosition < 64) 52 Val = Lo >> BitPosition | Hi << 1 << (63 - BitPosition); 53 else 54 Val = Hi >> (BitPosition - 64); 55 return Val & ((uint64_t(2) << (NumBits - 1)) - 1); 56 } 57 DecoderUInt128 operator&(const DecoderUInt128 &RHS) const { 58 return DecoderUInt128(Lo & RHS.Lo, Hi & RHS.Hi); 59 } 60 DecoderUInt128 operator&(const uint64_t &RHS) const { 61 return *this & DecoderUInt128(RHS); 62 } 63 DecoderUInt128 operator~() const { return DecoderUInt128(~Lo, ~Hi); } 64 bool operator==(const DecoderUInt128 &RHS) { 65 return Lo == RHS.Lo && Hi == RHS.Hi; 66 } 67 bool operator!=(const DecoderUInt128 &RHS) { 68 return Lo != RHS.Lo || Hi != RHS.Hi; 69 } 70 bool operator!=(const int &RHS) { return *this != DecoderUInt128(RHS); } 71 }; 72 73 //===----------------------------------------------------------------------===// 74 // AMDGPUDisassembler 75 //===----------------------------------------------------------------------===// 76 77 class AMDGPUDisassembler : public MCDisassembler { 78 private: 79 std::unique_ptr<MCInstrInfo const> const MCII; 80 const MCRegisterInfo &MRI; 81 const MCAsmInfo &MAI; 82 const unsigned TargetMaxInstBytes; 83 mutable ArrayRef<uint8_t> Bytes; 84 mutable uint32_t Literal; 85 mutable uint64_t Literal64; 86 mutable bool HasLiteral; 87 mutable std::optional<bool> EnableWavefrontSize32; 88 unsigned CodeObjectVersion; 89 const MCExpr *UCVersionW64Expr; 90 const MCExpr *UCVersionW32Expr; 91 const MCExpr *UCVersionMDPExpr; 92 93 const MCExpr *createConstantSymbolExpr(StringRef Id, int64_t Val); 94 95 void decodeImmOperands(MCInst &MI, const MCInstrInfo &MCII) const; 96 97 public: 98 AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, 99 MCInstrInfo const *MCII); 100 ~AMDGPUDisassembler() override = default; 101 102 void setABIVersion(unsigned Version) override; 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 MCOperand createVGPR16Operand(unsigned RegIdx, bool IsHi) const; 114 115 MCOperand errOperand(unsigned V, const Twine& ErrMsg) const; 116 117 template <typename InsnType> 118 DecodeStatus tryDecodeInst(const uint8_t *Table, MCInst &MI, InsnType Inst, 119 uint64_t Address, raw_ostream &Comments) const; 120 template <typename InsnType> 121 DecodeStatus tryDecodeInst(const uint8_t *Table1, const uint8_t *Table2, 122 MCInst &MI, InsnType Inst, uint64_t Address, 123 raw_ostream &Comments) const; 124 125 Expected<bool> onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size, 126 ArrayRef<uint8_t> Bytes, 127 uint64_t Address) const override; 128 129 Expected<bool> decodeKernelDescriptor(StringRef KdName, 130 ArrayRef<uint8_t> Bytes, 131 uint64_t KdAddress) const; 132 133 Expected<bool> 134 decodeKernelDescriptorDirective(DataExtractor::Cursor &Cursor, 135 ArrayRef<uint8_t> Bytes, 136 raw_string_ostream &KdStream) const; 137 138 /// Decode as directives that handle COMPUTE_PGM_RSRC1. 139 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC1. 140 /// \param KdStream - Stream to write the disassembled directives to. 141 // NOLINTNEXTLINE(readability-identifier-naming) 142 Expected<bool> decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer, 143 raw_string_ostream &KdStream) const; 144 145 /// Decode as directives that handle COMPUTE_PGM_RSRC2. 146 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC2. 147 /// \param KdStream - Stream to write the disassembled directives to. 148 // NOLINTNEXTLINE(readability-identifier-naming) 149 Expected<bool> decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer, 150 raw_string_ostream &KdStream) const; 151 152 /// Decode as directives that handle COMPUTE_PGM_RSRC3. 153 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC3. 154 /// \param KdStream - Stream to write the disassembled directives to. 155 // NOLINTNEXTLINE(readability-identifier-naming) 156 Expected<bool> decodeCOMPUTE_PGM_RSRC3(uint32_t FourByteBuffer, 157 raw_string_ostream &KdStream) const; 158 159 void convertEXPInst(MCInst &MI) const; 160 void convertVINTERPInst(MCInst &MI) const; 161 void convertFMAanyK(MCInst &MI) const; 162 void convertSDWAInst(MCInst &MI) const; 163 void convertMAIInst(MCInst &MI) const; 164 void convertDPP8Inst(MCInst &MI) const; 165 void convertMIMGInst(MCInst &MI) const; 166 void convertVOP3DPPInst(MCInst &MI) const; 167 void convertVOP3PDPPInst(MCInst &MI) const; 168 void convertVOPCDPPInst(MCInst &MI) const; 169 void convertVOPC64DPPInst(MCInst &MI) const; 170 void convertMacDPPInst(MCInst &MI) const; 171 void convertTrue16OpSel(MCInst &MI) const; 172 173 unsigned getVgprClassId(unsigned Width) const; 174 unsigned getAgprClassId(unsigned Width) const; 175 unsigned getSgprClassId(unsigned Width) const; 176 unsigned getTtmpClassId(unsigned Width) const; 177 178 static MCOperand decodeIntImmed(unsigned Imm); 179 180 MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const; 181 MCOperand decodeMandatoryLiteral64Constant(uint64_t Imm) const; 182 MCOperand decodeLiteralConstant(bool ExtendFP64) const; 183 MCOperand decodeLiteral64Constant() const; 184 185 MCOperand decodeSrcOp(unsigned Width, unsigned Val) const; 186 187 MCOperand decodeNonVGPRSrcOp(unsigned Width, unsigned Val) const; 188 189 MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const; 190 MCOperand decodeSpecialReg32(unsigned Val) const; 191 MCOperand decodeSpecialReg64(unsigned Val) const; 192 MCOperand decodeSpecialReg96Plus(unsigned Val) const; 193 194 MCOperand decodeSDWASrc(unsigned Width, unsigned Val) const; 195 MCOperand decodeSDWASrc16(unsigned Val) const; 196 MCOperand decodeSDWASrc32(unsigned Val) const; 197 MCOperand decodeSDWAVopcDst(unsigned Val) const; 198 199 MCOperand decodeBoolReg(unsigned Val) const; 200 MCOperand decodeSplitBarrier(unsigned Val) const; 201 MCOperand decodeDpp8FI(unsigned Val) const; 202 203 MCOperand decodeVersionImm(unsigned Imm) const; 204 205 int getTTmpIdx(unsigned Val) const; 206 207 const MCInstrInfo *getMCII() const { return MCII.get(); } 208 209 bool isVI() const; 210 bool isGFX9() const; 211 bool isGFX90A() const; 212 bool isGFX9Plus() const; 213 bool isGFX10() const; 214 bool isGFX10Plus() const; 215 bool isGFX11() const; 216 bool isGFX11Plus() const; 217 bool isGFX12() const; 218 bool isGFX12Plus() const; 219 bool isGFX1250() const; 220 221 bool hasArchitectedFlatScratch() const; 222 bool hasKernargPreload() const; 223 224 bool isMacDPP(MCInst &MI) const; 225 }; 226 227 //===----------------------------------------------------------------------===// 228 // AMDGPUSymbolizer 229 //===----------------------------------------------------------------------===// 230 231 class AMDGPUSymbolizer : public MCSymbolizer { 232 private: 233 void *DisInfo; 234 std::vector<uint64_t> ReferencedAddresses; 235 236 public: 237 AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo, 238 void *disInfo) 239 : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {} 240 241 bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, 242 int64_t Value, uint64_t Address, bool IsBranch, 243 uint64_t Offset, uint64_t OpSize, 244 uint64_t InstSize) override; 245 246 void tryAddingPcLoadReferenceComment(raw_ostream &cStream, 247 int64_t Value, 248 uint64_t Address) override; 249 250 ArrayRef<uint64_t> getReferencedAddresses() const override { 251 return ReferencedAddresses; 252 } 253 }; 254 255 } // end namespace llvm 256 257 #endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H 258