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