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