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 bool HasLiteral; 101 mutable std::optional<bool> EnableWavefrontSize32; 102 103 public: 104 AMDGPUDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, 105 MCInstrInfo const *MCII); 106 ~AMDGPUDisassembler() override = default; 107 108 DecodeStatus getInstruction(MCInst &MI, uint64_t &Size, 109 ArrayRef<uint8_t> Bytes, uint64_t Address, 110 raw_ostream &CS) const override; 111 112 const char* getRegClassName(unsigned RegClassID) const; 113 114 MCOperand createRegOperand(unsigned int RegId) const; 115 MCOperand createRegOperand(unsigned RegClassID, unsigned Val) const; 116 MCOperand createSRegOperand(unsigned SRegClassID, unsigned Val) const; 117 118 MCOperand errOperand(unsigned V, const Twine& ErrMsg) const; 119 120 template <typename InsnType> 121 DecodeStatus tryDecodeInst(const uint8_t *Table, MCInst &MI, InsnType Inst, 122 uint64_t Address, raw_ostream &Comments) const { 123 assert(MI.getOpcode() == 0); 124 assert(MI.getNumOperands() == 0); 125 MCInst TmpInst; 126 HasLiteral = false; 127 const auto SavedBytes = Bytes; 128 129 SmallString<64> LocalComments; 130 raw_svector_ostream LocalCommentStream(LocalComments); 131 CommentStream = &LocalCommentStream; 132 133 DecodeStatus Res = 134 decodeInstruction(Table, TmpInst, Inst, Address, this, STI); 135 136 CommentStream = nullptr; 137 138 if (Res != Fail) { 139 MI = TmpInst; 140 Comments << LocalComments; 141 return MCDisassembler::Success; 142 } 143 Bytes = SavedBytes; 144 return MCDisassembler::Fail; 145 } 146 147 std::optional<DecodeStatus> 148 onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size, ArrayRef<uint8_t> Bytes, 149 uint64_t Address, raw_ostream &CStream) const override; 150 151 DecodeStatus decodeKernelDescriptor(StringRef KdName, ArrayRef<uint8_t> Bytes, 152 uint64_t KdAddress) const; 153 154 DecodeStatus 155 decodeKernelDescriptorDirective(DataExtractor::Cursor &Cursor, 156 ArrayRef<uint8_t> Bytes, 157 raw_string_ostream &KdStream) const; 158 159 /// Decode as directives that handle COMPUTE_PGM_RSRC1. 160 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC1. 161 /// \param KdStream - Stream to write the disassembled directives to. 162 // NOLINTNEXTLINE(readability-identifier-naming) 163 DecodeStatus decodeCOMPUTE_PGM_RSRC1(uint32_t FourByteBuffer, 164 raw_string_ostream &KdStream) const; 165 166 /// Decode as directives that handle COMPUTE_PGM_RSRC2. 167 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC2. 168 /// \param KdStream - Stream to write the disassembled directives to. 169 // NOLINTNEXTLINE(readability-identifier-naming) 170 DecodeStatus decodeCOMPUTE_PGM_RSRC2(uint32_t FourByteBuffer, 171 raw_string_ostream &KdStream) const; 172 173 /// Decode as directives that handle COMPUTE_PGM_RSRC3. 174 /// \param FourByteBuffer - Bytes holding contents of COMPUTE_PGM_RSRC3. 175 /// \param KdStream - Stream to write the disassembled directives to. 176 // NOLINTNEXTLINE(readability-identifier-naming) 177 DecodeStatus decodeCOMPUTE_PGM_RSRC3(uint32_t FourByteBuffer, 178 raw_string_ostream &KdStream) const; 179 180 DecodeStatus convertEXPInst(MCInst &MI) const; 181 DecodeStatus convertVINTERPInst(MCInst &MI) const; 182 DecodeStatus convertFMAanyK(MCInst &MI, int ImmLitIdx) const; 183 DecodeStatus convertSDWAInst(MCInst &MI) const; 184 DecodeStatus convertDPP8Inst(MCInst &MI) const; 185 DecodeStatus convertMIMGInst(MCInst &MI) const; 186 DecodeStatus convertVOP3DPPInst(MCInst &MI) const; 187 DecodeStatus convertVOP3PDPPInst(MCInst &MI) const; 188 DecodeStatus convertVOPCDPPInst(MCInst &MI) const; 189 void convertMacDPPInst(MCInst &MI) const; 190 191 enum OpWidthTy { 192 OPW32, 193 OPW64, 194 OPW96, 195 OPW128, 196 OPW160, 197 OPW256, 198 OPW288, 199 OPW320, 200 OPW352, 201 OPW384, 202 OPW512, 203 OPW1024, 204 OPW16, 205 OPWV216, 206 OPWV232, 207 OPW_LAST_, 208 OPW_FIRST_ = OPW32 209 }; 210 211 unsigned getVgprClassId(const OpWidthTy Width) const; 212 unsigned getAgprClassId(const OpWidthTy Width) const; 213 unsigned getSgprClassId(const OpWidthTy Width) const; 214 unsigned getTtmpClassId(const OpWidthTy Width) const; 215 216 static MCOperand decodeIntImmed(unsigned Imm); 217 static MCOperand decodeFPImmed(unsigned ImmWidth, unsigned Imm); 218 219 MCOperand decodeMandatoryLiteralConstant(unsigned Imm) const; 220 MCOperand decodeLiteralConstant() const; 221 222 MCOperand decodeSrcOp(const OpWidthTy Width, unsigned Val, 223 bool MandatoryLiteral = false, 224 unsigned ImmWidth = 0) const; 225 226 MCOperand decodeVOPDDstYOp(MCInst &Inst, unsigned Val) const; 227 MCOperand decodeSpecialReg32(unsigned Val) const; 228 MCOperand decodeSpecialReg64(unsigned Val) const; 229 230 MCOperand decodeSDWASrc(const OpWidthTy Width, unsigned Val, 231 unsigned ImmWidth = 0) const; 232 MCOperand decodeSDWASrc16(unsigned Val) const; 233 MCOperand decodeSDWASrc32(unsigned Val) const; 234 MCOperand decodeSDWAVopcDst(unsigned Val) const; 235 236 MCOperand decodeBoolReg(unsigned Val) const; 237 238 int getTTmpIdx(unsigned Val) const; 239 240 const MCInstrInfo *getMCII() const { return MCII.get(); } 241 242 bool isVI() const; 243 bool isGFX9() const; 244 bool isGFX90A() const; 245 bool isGFX9Plus() const; 246 bool isGFX10() const; 247 bool isGFX10Plus() const; 248 bool isGFX11() const; 249 bool isGFX11Plus() const; 250 251 bool hasArchitectedFlatScratch() const; 252 253 bool isMacDPP(MCInst &MI) const; 254 }; 255 256 //===----------------------------------------------------------------------===// 257 // AMDGPUSymbolizer 258 //===----------------------------------------------------------------------===// 259 260 class AMDGPUSymbolizer : public MCSymbolizer { 261 private: 262 void *DisInfo; 263 std::vector<uint64_t> ReferencedAddresses; 264 265 public: 266 AMDGPUSymbolizer(MCContext &Ctx, std::unique_ptr<MCRelocationInfo> &&RelInfo, 267 void *disInfo) 268 : MCSymbolizer(Ctx, std::move(RelInfo)), DisInfo(disInfo) {} 269 270 bool tryAddingSymbolicOperand(MCInst &Inst, raw_ostream &cStream, 271 int64_t Value, uint64_t Address, bool IsBranch, 272 uint64_t Offset, uint64_t OpSize, 273 uint64_t InstSize) override; 274 275 void tryAddingPcLoadReferenceComment(raw_ostream &cStream, 276 int64_t Value, 277 uint64_t Address) override; 278 279 ArrayRef<uint64_t> getReferencedAddresses() const override { 280 return ReferencedAddresses; 281 } 282 }; 283 284 } // end namespace llvm 285 286 #endif // LLVM_LIB_TARGET_AMDGPU_DISASSEMBLER_AMDGPUDISASSEMBLER_H 287