2910 lines · cpp
1//===- AMDGPUDisassembler.cpp - Disassembler for AMDGPU ISA ---------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9//===----------------------------------------------------------------------===//10//11/// \file12///13/// This file contains definition for AMDGPU ISA disassembler14//15//===----------------------------------------------------------------------===//16 17// ToDo: What to do with instruction suffixes (v_mov_b32 vs v_mov_b32_e32)?18 19#include "Disassembler/AMDGPUDisassembler.h"20#include "MCTargetDesc/AMDGPUMCExpr.h"21#include "MCTargetDesc/AMDGPUMCTargetDesc.h"22#include "SIDefines.h"23#include "SIRegisterInfo.h"24#include "TargetInfo/AMDGPUTargetInfo.h"25#include "Utils/AMDGPUAsmUtils.h"26#include "Utils/AMDGPUBaseInfo.h"27#include "llvm-c/DisassemblerTypes.h"28#include "llvm/BinaryFormat/ELF.h"29#include "llvm/MC/MCAsmInfo.h"30#include "llvm/MC/MCContext.h"31#include "llvm/MC/MCDecoder.h"32#include "llvm/MC/MCDecoderOps.h"33#include "llvm/MC/MCExpr.h"34#include "llvm/MC/MCInstrDesc.h"35#include "llvm/MC/MCRegisterInfo.h"36#include "llvm/MC/MCSubtargetInfo.h"37#include "llvm/MC/TargetRegistry.h"38#include "llvm/Support/AMDHSAKernelDescriptor.h"39#include "llvm/Support/Compiler.h"40 41using namespace llvm;42using namespace llvm::MCD;43 44#define DEBUG_TYPE "amdgpu-disassembler"45 46#define SGPR_MAX \47 (isGFX10Plus() ? AMDGPU::EncValues::SGPR_MAX_GFX10 \48 : AMDGPU::EncValues::SGPR_MAX_SI)49 50using DecodeStatus = llvm::MCDisassembler::DecodeStatus;51 52static int64_t getInlineImmValF16(unsigned Imm);53static int64_t getInlineImmValBF16(unsigned Imm);54static int64_t getInlineImmVal32(unsigned Imm);55static int64_t getInlineImmVal64(unsigned Imm);56 57AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,58 MCContext &Ctx, MCInstrInfo const *MCII)59 : MCDisassembler(STI, Ctx), MCII(MCII), MRI(*Ctx.getRegisterInfo()),60 MAI(*Ctx.getAsmInfo()),61 HwModeRegClass(STI.getHwMode(MCSubtargetInfo::HwMode_RegInfo)),62 TargetMaxInstBytes(MAI.getMaxInstLength(&STI)),63 CodeObjectVersion(AMDGPU::getDefaultAMDHSACodeObjectVersion()) {64 // ToDo: AMDGPUDisassembler supports only VI ISA.65 if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())66 reportFatalUsageError("disassembly not yet supported for subtarget");67 68 for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())69 createConstantSymbolExpr(Symbol, Code);70 71 UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000);72 UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000);73 UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000);74}75 76void AMDGPUDisassembler::setABIVersion(unsigned Version) {77 CodeObjectVersion = AMDGPU::getAMDHSACodeObjectVersion(Version);78}79 80inline static MCDisassembler::DecodeStatus81addOperand(MCInst &Inst, const MCOperand& Opnd) {82 Inst.addOperand(Opnd);83 return Opnd.isValid() ?84 MCDisassembler::Success :85 MCDisassembler::Fail;86}87 88static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op,89 AMDGPU::OpName Name) {90 int OpIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), Name);91 if (OpIdx != -1) {92 auto *I = MI.begin();93 std::advance(I, OpIdx);94 MI.insert(I, Op);95 }96 return OpIdx;97}98 99static DecodeStatus decodeSOPPBrTarget(MCInst &Inst, unsigned Imm,100 uint64_t Addr,101 const MCDisassembler *Decoder) {102 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);103 104 // Our branches take a simm16.105 int64_t Offset = SignExtend64<16>(Imm) * 4 + 4 + Addr;106 107 if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2, 0))108 return MCDisassembler::Success;109 return addOperand(Inst, MCOperand::createImm(Imm));110}111 112static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, uint64_t Addr,113 const MCDisassembler *Decoder) {114 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);115 int64_t Offset;116 if (DAsm->isGFX12Plus()) { // GFX12 supports 24-bit signed offsets.117 Offset = SignExtend64<24>(Imm);118 } else if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets.119 Offset = Imm & 0xFFFFF;120 } else { // GFX9+ supports 21-bit signed offsets.121 Offset = SignExtend64<21>(Imm);122 }123 return addOperand(Inst, MCOperand::createImm(Offset));124}125 126static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, uint64_t Addr,127 const MCDisassembler *Decoder) {128 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);129 return addOperand(Inst, DAsm->decodeBoolReg(Inst, Val));130}131 132static DecodeStatus decodeSplitBarrier(MCInst &Inst, unsigned Val,133 uint64_t Addr,134 const MCDisassembler *Decoder) {135 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);136 return addOperand(Inst, DAsm->decodeSplitBarrier(Inst, Val));137}138 139static DecodeStatus decodeDpp8FI(MCInst &Inst, unsigned Val, uint64_t Addr,140 const MCDisassembler *Decoder) {141 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);142 return addOperand(Inst, DAsm->decodeDpp8FI(Val));143}144 145#define DECODE_OPERAND(StaticDecoderName, DecoderName) \146 static DecodeStatus StaticDecoderName(MCInst &Inst, unsigned Imm, \147 uint64_t /*Addr*/, \148 const MCDisassembler *Decoder) { \149 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \150 return addOperand(Inst, DAsm->DecoderName(Imm)); \151 }152 153// Decoder for registers, decode directly using RegClassID. Imm(8-bit) is154// number of register. Used by VGPR only and AGPR only operands.155#define DECODE_OPERAND_REG_8(RegClass) \156 static DecodeStatus Decode##RegClass##RegisterClass( \157 MCInst &Inst, unsigned Imm, uint64_t /*Addr*/, \158 const MCDisassembler *Decoder) { \159 assert(Imm < (1 << 8) && "8-bit encoding"); \160 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \161 return addOperand( \162 Inst, DAsm->createRegOperand(AMDGPU::RegClass##RegClassID, Imm)); \163 }164 165#define DECODE_SrcOp(Name, EncSize, OpWidth, EncImm) \166 static DecodeStatus Name(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/, \167 const MCDisassembler *Decoder) { \168 assert(Imm < (1 << EncSize) && #EncSize "-bit encoding"); \169 auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \170 return addOperand(Inst, DAsm->decodeSrcOp(Inst, OpWidth, EncImm)); \171 }172 173static DecodeStatus decodeSrcOp(MCInst &Inst, unsigned EncSize,174 unsigned OpWidth, unsigned Imm, unsigned EncImm,175 const MCDisassembler *Decoder) {176 assert(Imm < (1U << EncSize) && "Operand doesn't fit encoding!");177 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);178 return addOperand(Inst, DAsm->decodeSrcOp(Inst, OpWidth, EncImm));179}180 181// Decoder for registers. Imm(7-bit) is number of register, uses decodeSrcOp to182// get register class. Used by SGPR only operands.183#define DECODE_OPERAND_SREG_7(RegClass, OpWidth) \184 DECODE_SrcOp(Decode##RegClass##RegisterClass, 7, OpWidth, Imm)185 186#define DECODE_OPERAND_SREG_8(RegClass, OpWidth) \187 DECODE_SrcOp(Decode##RegClass##RegisterClass, 8, OpWidth, Imm)188 189// Decoder for registers. Imm(10-bit): Imm{7-0} is number of register,190// Imm{9} is acc(agpr or vgpr) Imm{8} should be 0 (see VOP3Pe_SMFMAC).191// Set Imm{8} to 1 (IS_VGPR) to decode using 'enum10' from decodeSrcOp.192// Used by AV_ register classes (AGPR or VGPR only register operands).193template <unsigned OpWidth>194static DecodeStatus decodeAV10(MCInst &Inst, unsigned Imm, uint64_t /* Addr */,195 const MCDisassembler *Decoder) {196 return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm | AMDGPU::EncValues::IS_VGPR,197 Decoder);198}199 200// Decoder for Src(9-bit encoding) registers only.201template <unsigned OpWidth>202static DecodeStatus decodeSrcReg9(MCInst &Inst, unsigned Imm,203 uint64_t /* Addr */,204 const MCDisassembler *Decoder) {205 return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, Decoder);206}207 208// Decoder for Src(9-bit encoding) AGPR, register number encoded in 9bits, set209// Imm{9} to 1 (set acc) and decode using 'enum10' from decodeSrcOp, registers210// only.211template <unsigned OpWidth>212static DecodeStatus decodeSrcA9(MCInst &Inst, unsigned Imm, uint64_t /* Addr */,213 const MCDisassembler *Decoder) {214 return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, Decoder);215}216 217// Decoder for 'enum10' from decodeSrcOp, Imm{0-8} is 9-bit Src encoding218// Imm{9} is acc, registers only.219template <unsigned OpWidth>220static DecodeStatus decodeSrcAV10(MCInst &Inst, unsigned Imm,221 uint64_t /* Addr */,222 const MCDisassembler *Decoder) {223 return decodeSrcOp(Inst, 10, OpWidth, Imm, Imm, Decoder);224}225 226// Decoder for RegisterOperands using 9-bit Src encoding. Operand can be227// register from RegClass or immediate. Registers that don't belong to RegClass228// will be decoded and InstPrinter will report warning. Immediate will be229// decoded into constant matching the OperandType (important for floating point230// types).231template <unsigned OpWidth>232static DecodeStatus decodeSrcRegOrImm9(MCInst &Inst, unsigned Imm,233 uint64_t /* Addr */,234 const MCDisassembler *Decoder) {235 return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm, Decoder);236}237 238// Decoder for Src(9-bit encoding) AGPR or immediate. Set Imm{9} to 1 (set acc)239// and decode using 'enum10' from decodeSrcOp.240template <unsigned OpWidth>241static DecodeStatus decodeSrcRegOrImmA9(MCInst &Inst, unsigned Imm,242 uint64_t /* Addr */,243 const MCDisassembler *Decoder) {244 return decodeSrcOp(Inst, 9, OpWidth, Imm, Imm | 512, Decoder);245}246 247// Default decoders generated by tablegen: 'Decode<RegClass>RegisterClass'248// when RegisterClass is used as an operand. Most often used for destination249// operands.250 251DECODE_OPERAND_REG_8(VGPR_32)252DECODE_OPERAND_REG_8(VGPR_32_Lo128)253DECODE_OPERAND_REG_8(VReg_64)254DECODE_OPERAND_REG_8(VReg_96)255DECODE_OPERAND_REG_8(VReg_128)256DECODE_OPERAND_REG_8(VReg_192)257DECODE_OPERAND_REG_8(VReg_256)258DECODE_OPERAND_REG_8(VReg_288)259DECODE_OPERAND_REG_8(VReg_320)260DECODE_OPERAND_REG_8(VReg_352)261DECODE_OPERAND_REG_8(VReg_384)262DECODE_OPERAND_REG_8(VReg_512)263DECODE_OPERAND_REG_8(VReg_1024)264 265DECODE_OPERAND_SREG_7(SReg_32, 32)266DECODE_OPERAND_SREG_7(SReg_32_XM0, 32)267DECODE_OPERAND_SREG_7(SReg_32_XEXEC, 32)268DECODE_OPERAND_SREG_7(SReg_32_XM0_XEXEC, 32)269DECODE_OPERAND_SREG_7(SReg_32_XEXEC_HI, 32)270DECODE_OPERAND_SREG_7(SReg_64_XEXEC, 64)271DECODE_OPERAND_SREG_7(SReg_64_XEXEC_XNULL, 64)272DECODE_OPERAND_SREG_7(SReg_96, 96)273DECODE_OPERAND_SREG_7(SReg_128, 128)274DECODE_OPERAND_SREG_7(SReg_128_XNULL, 128)275DECODE_OPERAND_SREG_7(SReg_256, 256)276DECODE_OPERAND_SREG_7(SReg_256_XNULL, 256)277DECODE_OPERAND_SREG_7(SReg_512, 512)278 279DECODE_OPERAND_SREG_8(SReg_64, 64)280 281DECODE_OPERAND_REG_8(AGPR_32)282DECODE_OPERAND_REG_8(AReg_64)283DECODE_OPERAND_REG_8(AReg_128)284DECODE_OPERAND_REG_8(AReg_256)285DECODE_OPERAND_REG_8(AReg_512)286DECODE_OPERAND_REG_8(AReg_1024)287 288static DecodeStatus DecodeVGPR_16RegisterClass(MCInst &Inst, unsigned Imm,289 uint64_t /*Addr*/,290 const MCDisassembler *Decoder) {291 assert(isUInt<10>(Imm) && "10-bit encoding expected");292 assert((Imm & (1 << 8)) == 0 && "Imm{8} should not be used");293 294 bool IsHi = Imm & (1 << 9);295 unsigned RegIdx = Imm & 0xff;296 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);297 return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));298}299 300static DecodeStatus301DecodeVGPR_16_Lo128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t /*Addr*/,302 const MCDisassembler *Decoder) {303 assert(isUInt<8>(Imm) && "8-bit encoding expected");304 305 bool IsHi = Imm & (1 << 7);306 unsigned RegIdx = Imm & 0x7f;307 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);308 return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));309}310 311template <unsigned OpWidth>312static DecodeStatus decodeOperand_VSrcT16_Lo128(MCInst &Inst, unsigned Imm,313 uint64_t /*Addr*/,314 const MCDisassembler *Decoder) {315 assert(isUInt<9>(Imm) && "9-bit encoding expected");316 317 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);318 if (Imm & AMDGPU::EncValues::IS_VGPR) {319 bool IsHi = Imm & (1 << 7);320 unsigned RegIdx = Imm & 0x7f;321 return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));322 }323 return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(Inst, OpWidth, Imm & 0xFF));324}325 326template <unsigned OpWidth>327static DecodeStatus decodeOperand_VSrcT16(MCInst &Inst, unsigned Imm,328 uint64_t /*Addr*/,329 const MCDisassembler *Decoder) {330 assert(isUInt<10>(Imm) && "10-bit encoding expected");331 332 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);333 if (Imm & AMDGPU::EncValues::IS_VGPR) {334 bool IsHi = Imm & (1 << 9);335 unsigned RegIdx = Imm & 0xff;336 return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));337 }338 return addOperand(Inst, DAsm->decodeNonVGPRSrcOp(Inst, OpWidth, Imm & 0xFF));339}340 341static DecodeStatus decodeOperand_VGPR_16(MCInst &Inst, unsigned Imm,342 uint64_t /*Addr*/,343 const MCDisassembler *Decoder) {344 assert(isUInt<10>(Imm) && "10-bit encoding expected");345 assert(Imm & AMDGPU::EncValues::IS_VGPR && "VGPR expected");346 347 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);348 349 bool IsHi = Imm & (1 << 9);350 unsigned RegIdx = Imm & 0xff;351 return addOperand(Inst, DAsm->createVGPR16Operand(RegIdx, IsHi));352}353 354static DecodeStatus decodeOperand_KImmFP(MCInst &Inst, unsigned Imm,355 uint64_t Addr,356 const MCDisassembler *Decoder) {357 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);358 return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm));359}360 361static DecodeStatus decodeOperand_KImmFP64(MCInst &Inst, uint64_t Imm,362 uint64_t Addr,363 const MCDisassembler *Decoder) {364 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);365 return addOperand(Inst, DAsm->decodeMandatoryLiteral64Constant(Imm));366}367 368static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val,369 uint64_t Addr, const void *Decoder) {370 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);371 return addOperand(Inst, DAsm->decodeVOPDDstYOp(Inst, Val));372}373 374static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm, unsigned Opw,375 const MCDisassembler *Decoder) {376 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);377 return addOperand(Inst, DAsm->decodeSrcOp(Inst, Opw, Imm | 256));378}379 380template <unsigned Opw>381static DecodeStatus decodeAVLdSt(MCInst &Inst, unsigned Imm,382 uint64_t /* Addr */,383 const MCDisassembler *Decoder) {384 return decodeAVLdSt(Inst, Imm, Opw, Decoder);385}386 387static DecodeStatus decodeOperand_VSrc_f64(MCInst &Inst, unsigned Imm,388 uint64_t Addr,389 const MCDisassembler *Decoder) {390 assert(Imm < (1 << 9) && "9-bit encoding");391 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);392 return addOperand(Inst, DAsm->decodeSrcOp(Inst, 64, Imm));393}394 395#define DECODE_SDWA(DecName) \396DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName)397 398DECODE_SDWA(Src32)399DECODE_SDWA(Src16)400DECODE_SDWA(VopcDst)401 402static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm,403 uint64_t /* Addr */,404 const MCDisassembler *Decoder) {405 const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);406 return addOperand(Inst, DAsm->decodeVersionImm(Imm));407}408 409#include "AMDGPUGenDisassemblerTables.inc"410 411namespace {412// Define bitwidths for various types used to instantiate the decoder.413template <> constexpr uint32_t InsnBitWidth<uint32_t> = 32;414template <> constexpr uint32_t InsnBitWidth<uint64_t> = 64;415template <> constexpr uint32_t InsnBitWidth<std::bitset<96>> = 96;416template <> constexpr uint32_t InsnBitWidth<std::bitset<128>> = 128;417} // namespace418 419//===----------------------------------------------------------------------===//420//421//===----------------------------------------------------------------------===//422 423template <typename InsnType>424DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t *Table, MCInst &MI,425 InsnType Inst, uint64_t Address,426 raw_ostream &Comments) const {427 assert(MI.getOpcode() == 0);428 assert(MI.getNumOperands() == 0);429 MCInst TmpInst;430 HasLiteral = false;431 const auto SavedBytes = Bytes;432 433 SmallString<64> LocalComments;434 raw_svector_ostream LocalCommentStream(LocalComments);435 CommentStream = &LocalCommentStream;436 437 DecodeStatus Res =438 decodeInstruction(Table, TmpInst, Inst, Address, this, STI);439 440 CommentStream = nullptr;441 442 if (Res != MCDisassembler::Fail) {443 MI = TmpInst;444 Comments << LocalComments;445 return MCDisassembler::Success;446 }447 Bytes = SavedBytes;448 return MCDisassembler::Fail;449}450 451template <typename InsnType>452DecodeStatus453AMDGPUDisassembler::tryDecodeInst(const uint8_t *Table1, const uint8_t *Table2,454 MCInst &MI, InsnType Inst, uint64_t Address,455 raw_ostream &Comments) const {456 for (const uint8_t *T : {Table1, Table2}) {457 if (DecodeStatus Res = tryDecodeInst(T, MI, Inst, Address, Comments))458 return Res;459 }460 return MCDisassembler::Fail;461}462 463template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) {464 assert(Bytes.size() >= sizeof(T));465 const auto Res =466 support::endian::read<T, llvm::endianness::little>(Bytes.data());467 Bytes = Bytes.slice(sizeof(T));468 return Res;469}470 471static inline std::bitset<96> eat12Bytes(ArrayRef<uint8_t> &Bytes) {472 using namespace llvm::support::endian;473 assert(Bytes.size() >= 12);474 std::bitset<96> Lo(read<uint64_t, endianness::little>(Bytes.data()));475 Bytes = Bytes.slice(8);476 std::bitset<96> Hi(read<uint32_t, endianness::little>(Bytes.data()));477 Bytes = Bytes.slice(4);478 return (Hi << 64) | Lo;479}480 481static inline std::bitset<128> eat16Bytes(ArrayRef<uint8_t> &Bytes) {482 using namespace llvm::support::endian;483 assert(Bytes.size() >= 16);484 std::bitset<128> Lo(read<uint64_t, endianness::little>(Bytes.data()));485 Bytes = Bytes.slice(8);486 std::bitset<128> Hi(read<uint64_t, endianness::little>(Bytes.data()));487 Bytes = Bytes.slice(8);488 return (Hi << 64) | Lo;489}490 491void AMDGPUDisassembler::decodeImmOperands(MCInst &MI,492 const MCInstrInfo &MCII) const {493 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());494 for (auto [OpNo, OpDesc] : enumerate(Desc.operands())) {495 if (OpNo >= MI.getNumOperands())496 continue;497 498 // TODO: Fix V_DUAL_FMAMK_F32_X_FMAAK_F32_gfx12 vsrc operands,499 // defined to take VGPR_32, but in reality allowing inline constants.500 bool IsSrc = AMDGPU::OPERAND_SRC_FIRST <= OpDesc.OperandType &&501 OpDesc.OperandType <= AMDGPU::OPERAND_SRC_LAST;502 if (!IsSrc && OpDesc.OperandType != MCOI::OPERAND_REGISTER)503 continue;504 505 MCOperand &Op = MI.getOperand(OpNo);506 if (!Op.isImm())507 continue;508 int64_t Imm = Op.getImm();509 if (AMDGPU::EncValues::INLINE_INTEGER_C_MIN <= Imm &&510 Imm <= AMDGPU::EncValues::INLINE_INTEGER_C_MAX) {511 Op = decodeIntImmed(Imm);512 continue;513 }514 515 if (Imm == AMDGPU::EncValues::LITERAL_CONST) {516 Op = decodeLiteralConstant(Desc, OpDesc);517 continue;518 }519 520 if (AMDGPU::EncValues::INLINE_FLOATING_C_MIN <= Imm &&521 Imm <= AMDGPU::EncValues::INLINE_FLOATING_C_MAX) {522 switch (OpDesc.OperandType) {523 case AMDGPU::OPERAND_REG_IMM_BF16:524 case AMDGPU::OPERAND_REG_IMM_V2BF16:525 case AMDGPU::OPERAND_REG_INLINE_C_BF16:526 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:527 Imm = getInlineImmValBF16(Imm);528 break;529 case AMDGPU::OPERAND_REG_IMM_FP16:530 case AMDGPU::OPERAND_REG_IMM_INT16:531 case AMDGPU::OPERAND_REG_IMM_V2FP16:532 case AMDGPU::OPERAND_REG_INLINE_C_FP16:533 case AMDGPU::OPERAND_REG_INLINE_C_INT16:534 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:535 Imm = getInlineImmValF16(Imm);536 break;537 case AMDGPU::OPERAND_REG_IMM_FP64:538 case AMDGPU::OPERAND_REG_IMM_INT64:539 case AMDGPU::OPERAND_REG_INLINE_AC_FP64:540 case AMDGPU::OPERAND_REG_INLINE_C_FP64:541 case AMDGPU::OPERAND_REG_INLINE_C_INT64:542 Imm = getInlineImmVal64(Imm);543 break;544 default:545 Imm = getInlineImmVal32(Imm);546 }547 Op.setImm(Imm);548 }549 }550}551 552DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size,553 ArrayRef<uint8_t> Bytes_,554 uint64_t Address,555 raw_ostream &CS) const {556 unsigned MaxInstBytesNum = std::min((size_t)TargetMaxInstBytes, Bytes_.size());557 Bytes = Bytes_.slice(0, MaxInstBytesNum);558 559 // In case the opcode is not recognized we'll assume a Size of 4 bytes (unless560 // there are fewer bytes left). This will be overridden on success.561 Size = std::min((size_t)4, Bytes_.size());562 563 do {564 // ToDo: better to switch encoding length using some bit predicate565 // but it is unknown yet, so try all we can566 567 // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2568 // encodings569 if (isGFX1250() && Bytes.size() >= 16) {570 std::bitset<128> DecW = eat16Bytes(Bytes);571 if (tryDecodeInst(DecoderTableGFX1250128, MI, DecW, Address, CS))572 break;573 Bytes = Bytes_.slice(0, MaxInstBytesNum);574 }575 576 if (isGFX11Plus() && Bytes.size() >= 12) {577 std::bitset<96> DecW = eat12Bytes(Bytes);578 579 if (isGFX11() &&580 tryDecodeInst(DecoderTableGFX1196, DecoderTableGFX11_FAKE1696, MI,581 DecW, Address, CS))582 break;583 584 if (isGFX1250() &&585 tryDecodeInst(DecoderTableGFX125096, DecoderTableGFX1250_FAKE1696, MI,586 DecW, Address, CS))587 break;588 589 if (isGFX12() &&590 tryDecodeInst(DecoderTableGFX1296, DecoderTableGFX12_FAKE1696, MI,591 DecW, Address, CS))592 break;593 594 if (isGFX12() &&595 tryDecodeInst(DecoderTableGFX12W6496, MI, DecW, Address, CS))596 break;597 598 if (STI.hasFeature(AMDGPU::Feature64BitLiterals)) {599 // Return 8 bytes for a potential literal.600 Bytes = Bytes_.slice(4, MaxInstBytesNum - 4);601 602 if (isGFX1250() &&603 tryDecodeInst(DecoderTableGFX125096, MI, DecW, Address, CS))604 break;605 }606 607 // Reinitialize Bytes608 Bytes = Bytes_.slice(0, MaxInstBytesNum);609 610 } else if (Bytes.size() >= 16 &&611 STI.hasFeature(AMDGPU::FeatureGFX950Insts)) {612 std::bitset<128> DecW = eat16Bytes(Bytes);613 if (tryDecodeInst(DecoderTableGFX940128, MI, DecW, Address, CS))614 break;615 616 // Reinitialize Bytes617 Bytes = Bytes_.slice(0, MaxInstBytesNum);618 }619 620 if (Bytes.size() >= 8) {621 const uint64_t QW = eatBytes<uint64_t>(Bytes);622 623 if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) &&624 tryDecodeInst(DecoderTableGFX10_B64, MI, QW, Address, CS))625 break;626 627 if (STI.hasFeature(AMDGPU::FeatureUnpackedD16VMem) &&628 tryDecodeInst(DecoderTableGFX80_UNPACKED64, MI, QW, Address, CS))629 break;630 631 if (STI.hasFeature(AMDGPU::FeatureGFX950Insts) &&632 tryDecodeInst(DecoderTableGFX95064, MI, QW, Address, CS))633 break;634 635 // Some GFX9 subtargets repurposed the v_mad_mix_f32, v_mad_mixlo_f16 and636 // v_mad_mixhi_f16 for FMA variants. Try to decode using this special637 // table first so we print the correct name.638 if (STI.hasFeature(AMDGPU::FeatureFmaMixInsts) &&639 tryDecodeInst(DecoderTableGFX9_DL64, MI, QW, Address, CS))640 break;641 642 if (STI.hasFeature(AMDGPU::FeatureGFX940Insts) &&643 tryDecodeInst(DecoderTableGFX94064, MI, QW, Address, CS))644 break;645 646 if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) &&647 tryDecodeInst(DecoderTableGFX90A64, MI, QW, Address, CS))648 break;649 650 if ((isVI() || isGFX9()) &&651 tryDecodeInst(DecoderTableGFX864, MI, QW, Address, CS))652 break;653 654 if (isGFX9() && tryDecodeInst(DecoderTableGFX964, MI, QW, Address, CS))655 break;656 657 if (isGFX10() && tryDecodeInst(DecoderTableGFX1064, MI, QW, Address, CS))658 break;659 660 if (isGFX1250() &&661 tryDecodeInst(DecoderTableGFX125064, DecoderTableGFX1250_FAKE1664, MI,662 QW, Address, CS))663 break;664 665 if (isGFX12() &&666 tryDecodeInst(DecoderTableGFX1264, DecoderTableGFX12_FAKE1664, MI, QW,667 Address, CS))668 break;669 670 if (isGFX11() &&671 tryDecodeInst(DecoderTableGFX1164, DecoderTableGFX11_FAKE1664, MI, QW,672 Address, CS))673 break;674 675 if (isGFX11() &&676 tryDecodeInst(DecoderTableGFX11W6464, MI, QW, Address, CS))677 break;678 679 if (isGFX12() &&680 tryDecodeInst(DecoderTableGFX12W6464, MI, QW, Address, CS))681 break;682 683 // Reinitialize Bytes684 Bytes = Bytes_.slice(0, MaxInstBytesNum);685 }686 687 // Try decode 32-bit instruction688 if (Bytes.size() >= 4) {689 const uint32_t DW = eatBytes<uint32_t>(Bytes);690 691 if ((isVI() || isGFX9()) &&692 tryDecodeInst(DecoderTableGFX832, MI, DW, Address, CS))693 break;694 695 if (tryDecodeInst(DecoderTableAMDGPU32, MI, DW, Address, CS))696 break;697 698 if (isGFX9() && tryDecodeInst(DecoderTableGFX932, MI, DW, Address, CS))699 break;700 701 if (STI.hasFeature(AMDGPU::FeatureGFX950Insts) &&702 tryDecodeInst(DecoderTableGFX95032, MI, DW, Address, CS))703 break;704 705 if (STI.hasFeature(AMDGPU::FeatureGFX90AInsts) &&706 tryDecodeInst(DecoderTableGFX90A32, MI, DW, Address, CS))707 break;708 709 if (STI.hasFeature(AMDGPU::FeatureGFX10_BEncoding) &&710 tryDecodeInst(DecoderTableGFX10_B32, MI, DW, Address, CS))711 break;712 713 if (isGFX10() && tryDecodeInst(DecoderTableGFX1032, MI, DW, Address, CS))714 break;715 716 if (isGFX11() &&717 tryDecodeInst(DecoderTableGFX1132, DecoderTableGFX11_FAKE1632, MI, DW,718 Address, CS))719 break;720 721 if (isGFX1250() &&722 tryDecodeInst(DecoderTableGFX125032, DecoderTableGFX1250_FAKE1632, MI,723 DW, Address, CS))724 break;725 726 if (isGFX12() &&727 tryDecodeInst(DecoderTableGFX1232, DecoderTableGFX12_FAKE1632, MI, DW,728 Address, CS))729 break;730 }731 732 return MCDisassembler::Fail;733 } while (false);734 735 DecodeStatus Status = MCDisassembler::Success;736 737 decodeImmOperands(MI, *MCII);738 739 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DPP) {740 if (isMacDPP(MI))741 convertMacDPPInst(MI);742 743 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3P)744 convertVOP3PDPPInst(MI);745 else if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC)746 convertVOPCDPPInst(MI); // Special VOP3 case747 else if (AMDGPU::isVOPC64DPP(MI.getOpcode()))748 convertVOPC64DPPInst(MI); // Special VOP3 case749 else if (AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dpp8) !=750 -1)751 convertDPP8Inst(MI);752 else if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3)753 convertVOP3DPPInst(MI); // Regular VOP3 case754 }755 756 convertTrue16OpSel(MI);757 758 if (AMDGPU::isMAC(MI.getOpcode())) {759 // Insert dummy unused src2_modifiers.760 insertNamedMCOperand(MI, MCOperand::createImm(0),761 AMDGPU::OpName::src2_modifiers);762 }763 764 if (MI.getOpcode() == AMDGPU::V_CVT_SR_BF8_F32_e64_dpp ||765 MI.getOpcode() == AMDGPU::V_CVT_SR_FP8_F32_e64_dpp) {766 // Insert dummy unused src2_modifiers.767 insertNamedMCOperand(MI, MCOperand::createImm(0),768 AMDGPU::OpName::src2_modifiers);769 }770 771 if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::DS) &&772 !AMDGPU::hasGDS(STI)) {773 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::gds);774 }775 776 if (MCII->get(MI.getOpcode()).TSFlags &777 (SIInstrFlags::MUBUF | SIInstrFlags::FLAT | SIInstrFlags::SMRD)) {778 int CPolPos = AMDGPU::getNamedOperandIdx(MI.getOpcode(),779 AMDGPU::OpName::cpol);780 if (CPolPos != -1) {781 unsigned CPol =782 (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsAtomicRet) ?783 AMDGPU::CPol::GLC : 0;784 if (MI.getNumOperands() <= (unsigned)CPolPos) {785 insertNamedMCOperand(MI, MCOperand::createImm(CPol),786 AMDGPU::OpName::cpol);787 } else if (CPol) {788 MI.getOperand(CPolPos).setImm(MI.getOperand(CPolPos).getImm() | CPol);789 }790 }791 }792 793 if ((MCII->get(MI.getOpcode()).TSFlags &794 (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) &&795 (STI.hasFeature(AMDGPU::FeatureGFX90AInsts))) {796 // GFX90A lost TFE, its place is occupied by ACC.797 int TFEOpIdx =798 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::tfe);799 if (TFEOpIdx != -1) {800 auto *TFEIter = MI.begin();801 std::advance(TFEIter, TFEOpIdx);802 MI.insert(TFEIter, MCOperand::createImm(0));803 }804 }805 806 // Validate buffer instruction offsets for GFX12+ - must not be a negative.807 if (isGFX12Plus() && isBufferInstruction(MI)) {808 int OffsetIdx =809 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::offset);810 if (OffsetIdx != -1) {811 uint32_t Imm = MI.getOperand(OffsetIdx).getImm();812 int64_t SignedOffset = SignExtend64<24>(Imm);813 if (SignedOffset < 0)814 return MCDisassembler::Fail;815 }816 }817 818 if (MCII->get(MI.getOpcode()).TSFlags &819 (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF)) {820 int SWZOpIdx =821 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::swz);822 if (SWZOpIdx != -1) {823 auto *SWZIter = MI.begin();824 std::advance(SWZIter, SWZOpIdx);825 MI.insert(SWZIter, MCOperand::createImm(0));826 }827 }828 829 const MCInstrDesc &Desc = MCII->get(MI.getOpcode());830 if (Desc.TSFlags & SIInstrFlags::MIMG) {831 int VAddr0Idx =832 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);833 int RsrcIdx =834 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);835 unsigned NSAArgs = RsrcIdx - VAddr0Idx - 1;836 if (VAddr0Idx >= 0 && NSAArgs > 0) {837 unsigned NSAWords = (NSAArgs + 3) / 4;838 if (Bytes.size() < 4 * NSAWords)839 return MCDisassembler::Fail;840 for (unsigned i = 0; i < NSAArgs; ++i) {841 const unsigned VAddrIdx = VAddr0Idx + 1 + i;842 auto VAddrRCID =843 MCII->getOpRegClassID(Desc.operands()[VAddrIdx], HwModeRegClass);844 MI.insert(MI.begin() + VAddrIdx, createRegOperand(VAddrRCID, Bytes[i]));845 }846 Bytes = Bytes.slice(4 * NSAWords);847 }848 849 convertMIMGInst(MI);850 }851 852 if (MCII->get(MI.getOpcode()).TSFlags &853 (SIInstrFlags::VIMAGE | SIInstrFlags::VSAMPLE))854 convertMIMGInst(MI);855 856 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::EXP)857 convertEXPInst(MI);858 859 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VINTERP)860 convertVINTERPInst(MI);861 862 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SDWA)863 convertSDWAInst(MI);864 865 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsMAI)866 convertMAIInst(MI);867 868 if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::IsWMMA)869 convertWMMAInst(MI);870 871 int VDstIn_Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),872 AMDGPU::OpName::vdst_in);873 if (VDstIn_Idx != -1) {874 int Tied = MCII->get(MI.getOpcode()).getOperandConstraint(VDstIn_Idx,875 MCOI::OperandConstraint::TIED_TO);876 if (Tied != -1 && (MI.getNumOperands() <= (unsigned)VDstIn_Idx ||877 !MI.getOperand(VDstIn_Idx).isReg() ||878 MI.getOperand(VDstIn_Idx).getReg() != MI.getOperand(Tied).getReg())) {879 if (MI.getNumOperands() > (unsigned)VDstIn_Idx)880 MI.erase(&MI.getOperand(VDstIn_Idx));881 insertNamedMCOperand(MI,882 MCOperand::createReg(MI.getOperand(Tied).getReg()),883 AMDGPU::OpName::vdst_in);884 }885 }886 887 bool IsSOPK = MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::SOPK;888 if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::imm) && !IsSOPK)889 convertFMAanyK(MI);890 891 // Some VOPC instructions, e.g., v_cmpx_f_f64, use VOP3 encoding and892 // have EXEC as implicit destination. Issue a warning if encoding for893 // vdst is not EXEC.894 if ((MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3) &&895 MCII->get(MI.getOpcode()).getNumDefs() == 0 &&896 MCII->get(MI.getOpcode()).hasImplicitDefOfPhysReg(AMDGPU::EXEC)) {897 auto ExecEncoding = MRI.getEncodingValue(AMDGPU::EXEC_LO);898 if (Bytes_[0] != ExecEncoding)899 Status = MCDisassembler::SoftFail;900 }901 902 Size = MaxInstBytesNum - Bytes.size();903 return Status;904}905 906void AMDGPUDisassembler::convertEXPInst(MCInst &MI) const {907 if (STI.hasFeature(AMDGPU::FeatureGFX11Insts)) {908 // The MCInst still has these fields even though they are no longer encoded909 // in the GFX11 instruction.910 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vm);911 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::compr);912 }913}914 915void AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const {916 convertTrue16OpSel(MI);917 if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_t16_gfx11 ||918 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_fake16_gfx11 ||919 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_t16_gfx12 ||920 MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_fake16_gfx12 ||921 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_t16_gfx11 ||922 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_fake16_gfx11 ||923 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_t16_gfx12 ||924 MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_fake16_gfx12 ||925 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_t16_gfx11 ||926 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_fake16_gfx11 ||927 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_t16_gfx12 ||928 MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_fake16_gfx12 ||929 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_t16_gfx11 ||930 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_fake16_gfx11 ||931 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_t16_gfx12 ||932 MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_fake16_gfx12) {933 // The MCInst has this field that is not directly encoded in the934 // instruction.935 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::op_sel);936 }937}938 939void AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const {940 if (STI.hasFeature(AMDGPU::FeatureGFX9) ||941 STI.hasFeature(AMDGPU::FeatureGFX10)) {942 if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::sdst))943 // VOPC - insert clamp944 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::clamp);945 } else if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands)) {946 int SDst = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sdst);947 if (SDst != -1) {948 // VOPC - insert VCC register as sdst949 insertNamedMCOperand(MI, createRegOperand(AMDGPU::VCC),950 AMDGPU::OpName::sdst);951 } else {952 // VOP1/2 - insert omod if present in instruction953 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::omod);954 }955 }956}957 958/// Adjust the register values used by V_MFMA_F8F6F4_f8_f8 instructions to the959/// appropriate subregister for the used format width.960static void adjustMFMA_F8F6F4OpRegClass(const MCRegisterInfo &MRI,961 MCOperand &MO, uint8_t NumRegs) {962 switch (NumRegs) {963 case 4:964 return MO.setReg(MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3));965 case 6:966 return MO.setReg(967 MRI.getSubReg(MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5));968 case 8:969 if (MCRegister NewReg = MRI.getSubReg(970 MO.getReg(), AMDGPU::sub0_sub1_sub2_sub3_sub4_sub5_sub6_sub7)) {971 MO.setReg(NewReg);972 }973 return;974 case 12: {975 // There is no 384-bit subreg index defined.976 MCRegister BaseReg = MRI.getSubReg(MO.getReg(), AMDGPU::sub0);977 MCRegister NewReg = MRI.getMatchingSuperReg(978 BaseReg, AMDGPU::sub0, &MRI.getRegClass(AMDGPU::VReg_384RegClassID));979 return MO.setReg(NewReg);980 }981 case 16:982 // No-op in cases where one operand is still f8/bf8.983 return;984 default:985 llvm_unreachable("Unexpected size for mfma/wmma f8f6f4 operand");986 }987}988 989/// f8f6f4 instructions have different pseudos depending on the used formats. In990/// the disassembler table, we only have the variants with the largest register991/// classes which assume using an fp8/bf8 format for both operands. The actual992/// register class depends on the format in blgp and cbsz operands. Adjust the993/// register classes depending on the used format.994void AMDGPUDisassembler::convertMAIInst(MCInst &MI) const {995 int BlgpIdx =996 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::blgp);997 if (BlgpIdx == -1)998 return;999 1000 int CbszIdx =1001 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::cbsz);1002 1003 unsigned CBSZ = MI.getOperand(CbszIdx).getImm();1004 unsigned BLGP = MI.getOperand(BlgpIdx).getImm();1005 1006 const AMDGPU::MFMA_F8F6F4_Info *AdjustedRegClassOpcode =1007 AMDGPU::getMFMA_F8F6F4_WithFormatArgs(CBSZ, BLGP, MI.getOpcode());1008 if (!AdjustedRegClassOpcode ||1009 AdjustedRegClassOpcode->Opcode == MI.getOpcode())1010 return;1011 1012 MI.setOpcode(AdjustedRegClassOpcode->Opcode);1013 int Src0Idx =1014 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);1015 int Src1Idx =1016 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);1017 adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),1018 AdjustedRegClassOpcode->NumRegsSrcA);1019 adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),1020 AdjustedRegClassOpcode->NumRegsSrcB);1021}1022 1023void AMDGPUDisassembler::convertWMMAInst(MCInst &MI) const {1024 int FmtAIdx =1025 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::matrix_a_fmt);1026 if (FmtAIdx == -1)1027 return;1028 1029 int FmtBIdx =1030 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::matrix_b_fmt);1031 1032 unsigned FmtA = MI.getOperand(FmtAIdx).getImm();1033 unsigned FmtB = MI.getOperand(FmtBIdx).getImm();1034 1035 const AMDGPU::MFMA_F8F6F4_Info *AdjustedRegClassOpcode =1036 AMDGPU::getWMMA_F8F6F4_WithFormatArgs(FmtA, FmtB, MI.getOpcode());1037 if (!AdjustedRegClassOpcode ||1038 AdjustedRegClassOpcode->Opcode == MI.getOpcode())1039 return;1040 1041 MI.setOpcode(AdjustedRegClassOpcode->Opcode);1042 int Src0Idx =1043 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);1044 int Src1Idx =1045 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src1);1046 adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src0Idx),1047 AdjustedRegClassOpcode->NumRegsSrcA);1048 adjustMFMA_F8F6F4OpRegClass(MRI, MI.getOperand(Src1Idx),1049 AdjustedRegClassOpcode->NumRegsSrcB);1050}1051 1052struct VOPModifiers {1053 unsigned OpSel = 0;1054 unsigned OpSelHi = 0;1055 unsigned NegLo = 0;1056 unsigned NegHi = 0;1057};1058 1059// Reconstruct values of VOP3/VOP3P operands such as op_sel.1060// Note that these values do not affect disassembler output,1061// so this is only necessary for consistency with src_modifiers.1062static VOPModifiers collectVOPModifiers(const MCInst &MI,1063 bool IsVOP3P = false) {1064 VOPModifiers Modifiers;1065 unsigned Opc = MI.getOpcode();1066 const AMDGPU::OpName ModOps[] = {AMDGPU::OpName::src0_modifiers,1067 AMDGPU::OpName::src1_modifiers,1068 AMDGPU::OpName::src2_modifiers};1069 for (int J = 0; J < 3; ++J) {1070 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]);1071 if (OpIdx == -1)1072 continue;1073 1074 unsigned Val = MI.getOperand(OpIdx).getImm();1075 1076 Modifiers.OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J;1077 if (IsVOP3P) {1078 Modifiers.OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J;1079 Modifiers.NegLo |= !!(Val & SISrcMods::NEG) << J;1080 Modifiers.NegHi |= !!(Val & SISrcMods::NEG_HI) << J;1081 } else if (J == 0) {1082 Modifiers.OpSel |= !!(Val & SISrcMods::DST_OP_SEL) << 3;1083 }1084 }1085 1086 return Modifiers;1087}1088 1089// Instructions decode the op_sel/suffix bits into the src_modifier1090// operands. Copy those bits into the src operands for true16 VGPRs.1091void AMDGPUDisassembler::convertTrue16OpSel(MCInst &MI) const {1092 const unsigned Opc = MI.getOpcode();1093 const MCRegisterClass &ConversionRC =1094 MRI.getRegClass(AMDGPU::VGPR_16RegClassID);1095 constexpr std::array<std::tuple<AMDGPU::OpName, AMDGPU::OpName, unsigned>, 4>1096 OpAndOpMods = {{{AMDGPU::OpName::src0, AMDGPU::OpName::src0_modifiers,1097 SISrcMods::OP_SEL_0},1098 {AMDGPU::OpName::src1, AMDGPU::OpName::src1_modifiers,1099 SISrcMods::OP_SEL_0},1100 {AMDGPU::OpName::src2, AMDGPU::OpName::src2_modifiers,1101 SISrcMods::OP_SEL_0},1102 {AMDGPU::OpName::vdst, AMDGPU::OpName::src0_modifiers,1103 SISrcMods::DST_OP_SEL}}};1104 for (const auto &[OpName, OpModsName, OpSelMask] : OpAndOpMods) {1105 int OpIdx = AMDGPU::getNamedOperandIdx(Opc, OpName);1106 int OpModsIdx = AMDGPU::getNamedOperandIdx(Opc, OpModsName);1107 if (OpIdx == -1 || OpModsIdx == -1)1108 continue;1109 MCOperand &Op = MI.getOperand(OpIdx);1110 if (!Op.isReg())1111 continue;1112 if (!ConversionRC.contains(Op.getReg()))1113 continue;1114 unsigned OpEnc = MRI.getEncodingValue(Op.getReg());1115 const MCOperand &OpMods = MI.getOperand(OpModsIdx);1116 unsigned ModVal = OpMods.getImm();1117 if (ModVal & OpSelMask) { // isHi1118 unsigned RegIdx = OpEnc & AMDGPU::HWEncoding::REG_IDX_MASK;1119 Op.setReg(ConversionRC.getRegister(RegIdx * 2 + 1));1120 }1121 }1122}1123 1124// MAC opcodes have special old and src2 operands.1125// src2 is tied to dst, while old is not tied (but assumed to be).1126bool AMDGPUDisassembler::isMacDPP(MCInst &MI) const {1127 constexpr int DST_IDX = 0;1128 auto Opcode = MI.getOpcode();1129 const auto &Desc = MCII->get(Opcode);1130 auto OldIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::old);1131 1132 if (OldIdx != -1 && Desc.getOperandConstraint(1133 OldIdx, MCOI::OperandConstraint::TIED_TO) == -1) {1134 assert(AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src2));1135 assert(Desc.getOperandConstraint(1136 AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2),1137 MCOI::OperandConstraint::TIED_TO) == DST_IDX);1138 (void)DST_IDX;1139 return true;1140 }1141 1142 return false;1143}1144 1145// Create dummy old operand and insert dummy unused src2_modifiers1146void AMDGPUDisassembler::convertMacDPPInst(MCInst &MI) const {1147 assert(MI.getNumOperands() + 1 < MCII->get(MI.getOpcode()).getNumOperands());1148 insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);1149 insertNamedMCOperand(MI, MCOperand::createImm(0),1150 AMDGPU::OpName::src2_modifiers);1151}1152 1153void AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const {1154 unsigned Opc = MI.getOpcode();1155 1156 int VDstInIdx =1157 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);1158 if (VDstInIdx != -1)1159 insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);1160 1161 unsigned DescNumOps = MCII->get(Opc).getNumOperands();1162 if (MI.getNumOperands() < DescNumOps &&1163 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {1164 convertTrue16OpSel(MI);1165 auto Mods = collectVOPModifiers(MI);1166 insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),1167 AMDGPU::OpName::op_sel);1168 } else {1169 // Insert dummy unused src modifiers.1170 if (MI.getNumOperands() < DescNumOps &&1171 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))1172 insertNamedMCOperand(MI, MCOperand::createImm(0),1173 AMDGPU::OpName::src0_modifiers);1174 1175 if (MI.getNumOperands() < DescNumOps &&1176 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))1177 insertNamedMCOperand(MI, MCOperand::createImm(0),1178 AMDGPU::OpName::src1_modifiers);1179 }1180}1181 1182void AMDGPUDisassembler::convertVOP3DPPInst(MCInst &MI) const {1183 convertTrue16OpSel(MI);1184 1185 int VDstInIdx =1186 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdst_in);1187 if (VDstInIdx != -1)1188 insertNamedMCOperand(MI, MI.getOperand(0), AMDGPU::OpName::vdst_in);1189 1190 unsigned Opc = MI.getOpcode();1191 unsigned DescNumOps = MCII->get(Opc).getNumOperands();1192 if (MI.getNumOperands() < DescNumOps &&1193 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {1194 auto Mods = collectVOPModifiers(MI);1195 insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),1196 AMDGPU::OpName::op_sel);1197 }1198}1199 1200// Given a wide tuple \p Reg check if it will overflow 256 registers.1201// \returns \p Reg on success or NoRegister otherwise.1202static MCRegister CheckVGPROverflow(MCRegister Reg, const MCRegisterClass &RC,1203 const MCRegisterInfo &MRI) {1204 unsigned NumRegs = RC.getSizeInBits() / 32;1205 MCRegister Sub0 = MRI.getSubReg(Reg, AMDGPU::sub0);1206 if (!Sub0)1207 return Reg;1208 1209 MCRegister BaseReg;1210 if (MRI.getRegClass(AMDGPU::VGPR_32RegClassID).contains(Sub0))1211 BaseReg = AMDGPU::VGPR0;1212 else if (MRI.getRegClass(AMDGPU::AGPR_32RegClassID).contains(Sub0))1213 BaseReg = AMDGPU::AGPR0;1214 1215 assert(BaseReg && "Only vector registers expected");1216 1217 return (Sub0 - BaseReg + NumRegs <= 256) ? Reg : MCRegister();1218}1219 1220// Note that before gfx10, the MIMG encoding provided no information about1221// VADDR size. Consequently, decoded instructions always show address as if it1222// has 1 dword, which could be not really so.1223void AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const {1224 auto TSFlags = MCII->get(MI.getOpcode()).TSFlags;1225 1226 int VDstIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),1227 AMDGPU::OpName::vdst);1228 1229 int VDataIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),1230 AMDGPU::OpName::vdata);1231 int VAddr0Idx =1232 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vaddr0);1233 AMDGPU::OpName RsrcOpName = (TSFlags & SIInstrFlags::MIMG)1234 ? AMDGPU::OpName::srsrc1235 : AMDGPU::OpName::rsrc;1236 int RsrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), RsrcOpName);1237 int DMaskIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),1238 AMDGPU::OpName::dmask);1239 1240 int TFEIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),1241 AMDGPU::OpName::tfe);1242 int D16Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),1243 AMDGPU::OpName::d16);1244 1245 const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(MI.getOpcode());1246 const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =1247 AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);1248 1249 assert(VDataIdx != -1);1250 if (BaseOpcode->BVH) {1251 // Add A16 operand for intersect_ray instructions1252 addOperand(MI, MCOperand::createImm(BaseOpcode->A16));1253 return;1254 }1255 1256 bool IsAtomic = (VDstIdx != -1);1257 bool IsGather4 = TSFlags & SIInstrFlags::Gather4;1258 bool IsVSample = TSFlags & SIInstrFlags::VSAMPLE;1259 bool IsNSA = false;1260 bool IsPartialNSA = false;1261 unsigned AddrSize = Info->VAddrDwords;1262 1263 if (isGFX10Plus()) {1264 unsigned DimIdx =1265 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dim);1266 int A16Idx =1267 AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::a16);1268 const AMDGPU::MIMGDimInfo *Dim =1269 AMDGPU::getMIMGDimInfoByEncoding(MI.getOperand(DimIdx).getImm());1270 const bool IsA16 = (A16Idx != -1 && MI.getOperand(A16Idx).getImm());1271 1272 AddrSize =1273 AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, AMDGPU::hasG16(STI));1274 1275 // VSAMPLE insts that do not use vaddr3 behave the same as NSA forms.1276 // VIMAGE insts other than BVH never use vaddr4.1277 IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA ||1278 Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA ||1279 Info->MIMGEncoding == AMDGPU::MIMGEncGfx12;1280 if (!IsNSA) {1281 if (!IsVSample && AddrSize > 12)1282 AddrSize = 16;1283 } else {1284 if (AddrSize > Info->VAddrDwords) {1285 if (!STI.hasFeature(AMDGPU::FeaturePartialNSAEncoding)) {1286 // The NSA encoding does not contain enough operands for the1287 // combination of base opcode / dimension. Should this be an error?1288 return;1289 }1290 IsPartialNSA = true;1291 }1292 }1293 }1294 1295 unsigned DMask = MI.getOperand(DMaskIdx).getImm() & 0xf;1296 unsigned DstSize = IsGather4 ? 4 : std::max(llvm::popcount(DMask), 1);1297 1298 bool D16 = D16Idx >= 0 && MI.getOperand(D16Idx).getImm();1299 if (D16 && AMDGPU::hasPackedD16(STI)) {1300 DstSize = (DstSize + 1) / 2;1301 }1302 1303 if (TFEIdx != -1 && MI.getOperand(TFEIdx).getImm())1304 DstSize += 1;1305 1306 if (DstSize == Info->VDataDwords && AddrSize == Info->VAddrDwords)1307 return;1308 1309 int NewOpcode =1310 AMDGPU::getMIMGOpcode(Info->BaseOpcode, Info->MIMGEncoding, DstSize, AddrSize);1311 if (NewOpcode == -1)1312 return;1313 1314 // Widen the register to the correct number of enabled channels.1315 MCRegister NewVdata;1316 if (DstSize != Info->VDataDwords) {1317 auto DataRCID = MCII->getOpRegClassID(1318 MCII->get(NewOpcode).operands()[VDataIdx], HwModeRegClass);1319 1320 // Get first subregister of VData1321 MCRegister Vdata0 = MI.getOperand(VDataIdx).getReg();1322 MCRegister VdataSub0 = MRI.getSubReg(Vdata0, AMDGPU::sub0);1323 Vdata0 = (VdataSub0 != 0)? VdataSub0 : Vdata0;1324 1325 const MCRegisterClass &NewRC = MRI.getRegClass(DataRCID);1326 NewVdata = MRI.getMatchingSuperReg(Vdata0, AMDGPU::sub0, &NewRC);1327 NewVdata = CheckVGPROverflow(NewVdata, NewRC, MRI);1328 if (!NewVdata) {1329 // It's possible to encode this such that the low register + enabled1330 // components exceeds the register count.1331 return;1332 }1333 }1334 1335 // If not using NSA on GFX10+, widen vaddr0 address register to correct size.1336 // If using partial NSA on GFX11+ widen last address register.1337 int VAddrSAIdx = IsPartialNSA ? (RsrcIdx - 1) : VAddr0Idx;1338 MCRegister NewVAddrSA;1339 if (STI.hasFeature(AMDGPU::FeatureNSAEncoding) && (!IsNSA || IsPartialNSA) &&1340 AddrSize != Info->VAddrDwords) {1341 MCRegister VAddrSA = MI.getOperand(VAddrSAIdx).getReg();1342 MCRegister VAddrSubSA = MRI.getSubReg(VAddrSA, AMDGPU::sub0);1343 VAddrSA = VAddrSubSA ? VAddrSubSA : VAddrSA;1344 1345 auto AddrRCID = MCII->getOpRegClassID(1346 MCII->get(NewOpcode).operands()[VAddrSAIdx], HwModeRegClass);1347 1348 const MCRegisterClass &NewRC = MRI.getRegClass(AddrRCID);1349 NewVAddrSA = MRI.getMatchingSuperReg(VAddrSA, AMDGPU::sub0, &NewRC);1350 NewVAddrSA = CheckVGPROverflow(NewVAddrSA, NewRC, MRI);1351 if (!NewVAddrSA)1352 return;1353 }1354 1355 MI.setOpcode(NewOpcode);1356 1357 if (NewVdata != AMDGPU::NoRegister) {1358 MI.getOperand(VDataIdx) = MCOperand::createReg(NewVdata);1359 1360 if (IsAtomic) {1361 // Atomic operations have an additional operand (a copy of data)1362 MI.getOperand(VDstIdx) = MCOperand::createReg(NewVdata);1363 }1364 }1365 1366 if (NewVAddrSA) {1367 MI.getOperand(VAddrSAIdx) = MCOperand::createReg(NewVAddrSA);1368 } else if (IsNSA) {1369 assert(AddrSize <= Info->VAddrDwords);1370 MI.erase(MI.begin() + VAddr0Idx + AddrSize,1371 MI.begin() + VAddr0Idx + Info->VAddrDwords);1372 }1373}1374 1375// Opsel and neg bits are used in src_modifiers and standalone operands. Autogen1376// decoder only adds to src_modifiers, so manually add the bits to the other1377// operands.1378void AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const {1379 unsigned Opc = MI.getOpcode();1380 unsigned DescNumOps = MCII->get(Opc).getNumOperands();1381 auto Mods = collectVOPModifiers(MI, true);1382 1383 if (MI.getNumOperands() < DescNumOps &&1384 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::vdst_in))1385 insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vdst_in);1386 1387 if (MI.getNumOperands() < DescNumOps &&1388 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel))1389 insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),1390 AMDGPU::OpName::op_sel);1391 if (MI.getNumOperands() < DescNumOps &&1392 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel_hi))1393 insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSelHi),1394 AMDGPU::OpName::op_sel_hi);1395 if (MI.getNumOperands() < DescNumOps &&1396 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_lo))1397 insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegLo),1398 AMDGPU::OpName::neg_lo);1399 if (MI.getNumOperands() < DescNumOps &&1400 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::neg_hi))1401 insertNamedMCOperand(MI, MCOperand::createImm(Mods.NegHi),1402 AMDGPU::OpName::neg_hi);1403}1404 1405// Create dummy old operand and insert optional operands1406void AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const {1407 unsigned Opc = MI.getOpcode();1408 unsigned DescNumOps = MCII->get(Opc).getNumOperands();1409 1410 if (MI.getNumOperands() < DescNumOps &&1411 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::old))1412 insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old);1413 1414 if (MI.getNumOperands() < DescNumOps &&1415 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src0_modifiers))1416 insertNamedMCOperand(MI, MCOperand::createImm(0),1417 AMDGPU::OpName::src0_modifiers);1418 1419 if (MI.getNumOperands() < DescNumOps &&1420 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::src1_modifiers))1421 insertNamedMCOperand(MI, MCOperand::createImm(0),1422 AMDGPU::OpName::src1_modifiers);1423}1424 1425void AMDGPUDisassembler::convertVOPC64DPPInst(MCInst &MI) const {1426 unsigned Opc = MI.getOpcode();1427 unsigned DescNumOps = MCII->get(Opc).getNumOperands();1428 1429 convertTrue16OpSel(MI);1430 1431 if (MI.getNumOperands() < DescNumOps &&1432 AMDGPU::hasNamedOperand(Opc, AMDGPU::OpName::op_sel)) {1433 VOPModifiers Mods = collectVOPModifiers(MI);1434 insertNamedMCOperand(MI, MCOperand::createImm(Mods.OpSel),1435 AMDGPU::OpName::op_sel);1436 }1437}1438 1439void AMDGPUDisassembler::convertFMAanyK(MCInst &MI) const {1440 assert(HasLiteral && "Should have decoded a literal");1441 insertNamedMCOperand(MI, MCOperand::createImm(Literal), AMDGPU::OpName::immX);1442}1443 1444const char* AMDGPUDisassembler::getRegClassName(unsigned RegClassID) const {1445 return getContext().getRegisterInfo()->1446 getRegClassName(&AMDGPUMCRegisterClasses[RegClassID]);1447}1448 1449inline1450MCOperand AMDGPUDisassembler::errOperand(unsigned V,1451 const Twine& ErrMsg) const {1452 *CommentStream << "Error: " + ErrMsg;1453 1454 // ToDo: add support for error operands to MCInst.h1455 // return MCOperand::createError(V);1456 return MCOperand();1457}1458 1459inline MCOperand AMDGPUDisassembler::createRegOperand(MCRegister Reg) const {1460 return MCOperand::createReg(AMDGPU::getMCReg(Reg, STI));1461}1462 1463inline1464MCOperand AMDGPUDisassembler::createRegOperand(unsigned RegClassID,1465 unsigned Val) const {1466 const auto& RegCl = AMDGPUMCRegisterClasses[RegClassID];1467 if (Val >= RegCl.getNumRegs())1468 return errOperand(Val, Twine(getRegClassName(RegClassID)) +1469 ": unknown register " + Twine(Val));1470 return createRegOperand(RegCl.getRegister(Val));1471}1472 1473inline1474MCOperand AMDGPUDisassembler::createSRegOperand(unsigned SRegClassID,1475 unsigned Val) const {1476 // ToDo: SI/CI have 104 SGPRs, VI - 1021477 // Valery: here we accepting as much as we can, let assembler sort it out1478 int shift = 0;1479 switch (SRegClassID) {1480 case AMDGPU::SGPR_32RegClassID:1481 case AMDGPU::TTMP_32RegClassID:1482 break;1483 case AMDGPU::SGPR_64RegClassID:1484 case AMDGPU::TTMP_64RegClassID:1485 shift = 1;1486 break;1487 case AMDGPU::SGPR_96RegClassID:1488 case AMDGPU::TTMP_96RegClassID:1489 case AMDGPU::SGPR_128RegClassID:1490 case AMDGPU::TTMP_128RegClassID:1491 // ToDo: unclear if s[100:104] is available on VI. Can we use VCC as SGPR in1492 // this bundle?1493 case AMDGPU::SGPR_256RegClassID:1494 case AMDGPU::TTMP_256RegClassID:1495 // ToDo: unclear if s[96:104] is available on VI. Can we use VCC as SGPR in1496 // this bundle?1497 case AMDGPU::SGPR_288RegClassID:1498 case AMDGPU::TTMP_288RegClassID:1499 case AMDGPU::SGPR_320RegClassID:1500 case AMDGPU::TTMP_320RegClassID:1501 case AMDGPU::SGPR_352RegClassID:1502 case AMDGPU::TTMP_352RegClassID:1503 case AMDGPU::SGPR_384RegClassID:1504 case AMDGPU::TTMP_384RegClassID:1505 case AMDGPU::SGPR_512RegClassID:1506 case AMDGPU::TTMP_512RegClassID:1507 shift = 2;1508 break;1509 // ToDo: unclear if s[88:104] is available on VI. Can we use VCC as SGPR in1510 // this bundle?1511 default:1512 llvm_unreachable("unhandled register class");1513 }1514 1515 if (Val % (1 << shift)) {1516 *CommentStream << "Warning: " << getRegClassName(SRegClassID)1517 << ": scalar reg isn't aligned " << Val;1518 }1519 1520 return createRegOperand(SRegClassID, Val >> shift);1521}1522 1523MCOperand AMDGPUDisassembler::createVGPR16Operand(unsigned RegIdx,1524 bool IsHi) const {1525 unsigned RegIdxInVGPR16 = RegIdx * 2 + (IsHi ? 1 : 0);1526 return createRegOperand(AMDGPU::VGPR_16RegClassID, RegIdxInVGPR16);1527}1528 1529// Decode Literals for insts which always have a literal in the encoding1530MCOperand1531AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const {1532 if (HasLiteral) {1533 assert(1534 AMDGPU::hasVOPD(STI) &&1535 "Should only decode multiple kimm with VOPD, check VSrc operand types");1536 if (Literal != Val)1537 return errOperand(Val, "More than one unique literal is illegal");1538 }1539 HasLiteral = true;1540 Literal = Val;1541 return MCOperand::createImm(Literal);1542}1543 1544MCOperand1545AMDGPUDisassembler::decodeMandatoryLiteral64Constant(uint64_t Val) const {1546 if (HasLiteral) {1547 if (Literal != Val)1548 return errOperand(Val, "More than one unique literal is illegal");1549 }1550 HasLiteral = true;1551 Literal = Val;1552 1553 bool UseLit64 = Hi_32(Literal) == 0;1554 return UseLit64 ? MCOperand::createExpr(AMDGPUMCExpr::createLit(1555 LitModifier::Lit64, Literal, getContext()))1556 : MCOperand::createImm(Literal);1557}1558 1559MCOperand1560AMDGPUDisassembler::decodeLiteralConstant(const MCInstrDesc &Desc,1561 const MCOperandInfo &OpDesc) const {1562 // For now all literal constants are supposed to be unsigned integer1563 // ToDo: deal with signed/unsigned 64-bit integer constants1564 // ToDo: deal with float/double constants1565 if (!HasLiteral) {1566 if (Bytes.size() < 4) {1567 return errOperand(0, "cannot read literal, inst bytes left " +1568 Twine(Bytes.size()));1569 }1570 HasLiteral = true;1571 Literal = eatBytes<uint32_t>(Bytes);1572 }1573 1574 // For disassembling always assume all inline constants are available.1575 bool HasInv2Pi = true;1576 1577 // Invalid instruction codes may contain literals for inline-only1578 // operands, so we support them here as well.1579 int64_t Val = Literal;1580 bool UseLit = false;1581 switch (OpDesc.OperandType) {1582 default:1583 llvm_unreachable("Unexpected operand type!");1584 case AMDGPU::OPERAND_REG_IMM_BF16:1585 case AMDGPU::OPERAND_REG_INLINE_C_BF16:1586 case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:1587 UseLit = AMDGPU::isInlinableLiteralBF16(Val, HasInv2Pi);1588 break;1589 case AMDGPU::OPERAND_REG_IMM_V2BF16:1590 UseLit = AMDGPU::isInlinableLiteralV2BF16(Val);1591 break;1592 case AMDGPU::OPERAND_REG_IMM_FP16:1593 case AMDGPU::OPERAND_REG_INLINE_C_FP16:1594 case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:1595 UseLit = AMDGPU::isInlinableLiteralFP16(Val, HasInv2Pi);1596 break;1597 case AMDGPU::OPERAND_REG_IMM_V2FP16:1598 UseLit = AMDGPU::isInlinableLiteralV2F16(Val);1599 break;1600 case AMDGPU::OPERAND_REG_IMM_NOINLINE_V2FP16:1601 break;1602 case AMDGPU::OPERAND_REG_IMM_INT16:1603 case AMDGPU::OPERAND_REG_INLINE_C_INT16:1604 case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:1605 UseLit = AMDGPU::isInlinableLiteralI16(Val, HasInv2Pi);1606 break;1607 case AMDGPU::OPERAND_REG_IMM_V2INT16:1608 UseLit = AMDGPU::isInlinableLiteralV2I16(Val);1609 break;1610 case AMDGPU::OPERAND_REG_IMM_FP32:1611 case AMDGPU::OPERAND_REG_INLINE_C_FP32:1612 case AMDGPU::OPERAND_REG_INLINE_AC_FP32:1613 case AMDGPU::OPERAND_REG_IMM_INT32:1614 case AMDGPU::OPERAND_REG_INLINE_C_INT32:1615 case AMDGPU::OPERAND_REG_INLINE_AC_INT32:1616 case AMDGPU::OPERAND_REG_IMM_V2FP32:1617 case AMDGPU::OPERAND_REG_IMM_V2INT32:1618 case AMDGPU::OPERAND_KIMM32:1619 UseLit = AMDGPU::isInlinableLiteral32(Val, HasInv2Pi);1620 break;1621 case AMDGPU::OPERAND_REG_IMM_FP64:1622 case AMDGPU::OPERAND_REG_INLINE_C_FP64:1623 case AMDGPU::OPERAND_REG_INLINE_AC_FP64:1624 Val <<= 32;1625 break;1626 case AMDGPU::OPERAND_REG_IMM_INT64:1627 case AMDGPU::OPERAND_REG_INLINE_C_INT64:1628 UseLit = AMDGPU::isInlinableLiteral64(Val, HasInv2Pi);1629 break;1630 case MCOI::OPERAND_REGISTER:1631 // TODO: Disassembling V_DUAL_FMAMK_F32_X_FMAMK_F32_gfx11 hits1632 // decoding a literal in a position of a register operand. Give1633 // it special handling in the caller, decodeImmOperands(), instead1634 // of quietly allowing it here.1635 break;1636 }1637 1638 return UseLit ? MCOperand::createExpr(AMDGPUMCExpr::createLit(1639 LitModifier::Lit, Val, getContext()))1640 : MCOperand::createImm(Val);1641}1642 1643MCOperand AMDGPUDisassembler::decodeLiteral64Constant() const {1644 assert(STI.hasFeature(AMDGPU::Feature64BitLiterals));1645 1646 if (!HasLiteral) {1647 if (Bytes.size() < 8) {1648 return errOperand(0, "cannot read literal64, inst bytes left " +1649 Twine(Bytes.size()));1650 }1651 HasLiteral = true;1652 Literal = eatBytes<uint64_t>(Bytes);1653 }1654 1655 bool UseLit64 = Hi_32(Literal) == 0;1656 return UseLit64 ? MCOperand::createExpr(AMDGPUMCExpr::createLit(1657 LitModifier::Lit64, Literal, getContext()))1658 : MCOperand::createImm(Literal);1659}1660 1661MCOperand AMDGPUDisassembler::decodeIntImmed(unsigned Imm) {1662 using namespace AMDGPU::EncValues;1663 1664 assert(Imm >= INLINE_INTEGER_C_MIN && Imm <= INLINE_INTEGER_C_MAX);1665 return MCOperand::createImm((Imm <= INLINE_INTEGER_C_POSITIVE_MAX) ?1666 (static_cast<int64_t>(Imm) - INLINE_INTEGER_C_MIN) :1667 (INLINE_INTEGER_C_POSITIVE_MAX - static_cast<int64_t>(Imm)));1668 // Cast prevents negative overflow.1669}1670 1671static int64_t getInlineImmVal32(unsigned Imm) {1672 switch (Imm) {1673 case 240:1674 return llvm::bit_cast<uint32_t>(0.5f);1675 case 241:1676 return llvm::bit_cast<uint32_t>(-0.5f);1677 case 242:1678 return llvm::bit_cast<uint32_t>(1.0f);1679 case 243:1680 return llvm::bit_cast<uint32_t>(-1.0f);1681 case 244:1682 return llvm::bit_cast<uint32_t>(2.0f);1683 case 245:1684 return llvm::bit_cast<uint32_t>(-2.0f);1685 case 246:1686 return llvm::bit_cast<uint32_t>(4.0f);1687 case 247:1688 return llvm::bit_cast<uint32_t>(-4.0f);1689 case 248: // 1 / (2 * PI)1690 return 0x3e22f983;1691 default:1692 llvm_unreachable("invalid fp inline imm");1693 }1694}1695 1696static int64_t getInlineImmVal64(unsigned Imm) {1697 switch (Imm) {1698 case 240:1699 return llvm::bit_cast<uint64_t>(0.5);1700 case 241:1701 return llvm::bit_cast<uint64_t>(-0.5);1702 case 242:1703 return llvm::bit_cast<uint64_t>(1.0);1704 case 243:1705 return llvm::bit_cast<uint64_t>(-1.0);1706 case 244:1707 return llvm::bit_cast<uint64_t>(2.0);1708 case 245:1709 return llvm::bit_cast<uint64_t>(-2.0);1710 case 246:1711 return llvm::bit_cast<uint64_t>(4.0);1712 case 247:1713 return llvm::bit_cast<uint64_t>(-4.0);1714 case 248: // 1 / (2 * PI)1715 return 0x3fc45f306dc9c882;1716 default:1717 llvm_unreachable("invalid fp inline imm");1718 }1719}1720 1721static int64_t getInlineImmValF16(unsigned Imm) {1722 switch (Imm) {1723 case 240:1724 return 0x3800;1725 case 241:1726 return 0xB800;1727 case 242:1728 return 0x3C00;1729 case 243:1730 return 0xBC00;1731 case 244:1732 return 0x4000;1733 case 245:1734 return 0xC000;1735 case 246:1736 return 0x4400;1737 case 247:1738 return 0xC400;1739 case 248: // 1 / (2 * PI)1740 return 0x3118;1741 default:1742 llvm_unreachable("invalid fp inline imm");1743 }1744}1745 1746static int64_t getInlineImmValBF16(unsigned Imm) {1747 switch (Imm) {1748 case 240:1749 return 0x3F00;1750 case 241:1751 return 0xBF00;1752 case 242:1753 return 0x3F80;1754 case 243:1755 return 0xBF80;1756 case 244:1757 return 0x4000;1758 case 245:1759 return 0xC000;1760 case 246:1761 return 0x4080;1762 case 247:1763 return 0xC080;1764 case 248: // 1 / (2 * PI)1765 return 0x3E22;1766 default:1767 llvm_unreachable("invalid fp inline imm");1768 }1769}1770 1771unsigned AMDGPUDisassembler::getVgprClassId(unsigned Width) const {1772 using namespace AMDGPU;1773 1774 switch (Width) {1775 case 16:1776 case 32:1777 return VGPR_32RegClassID;1778 case 64:1779 return VReg_64RegClassID;1780 case 96:1781 return VReg_96RegClassID;1782 case 128:1783 return VReg_128RegClassID;1784 case 160:1785 return VReg_160RegClassID;1786 case 192:1787 return VReg_192RegClassID;1788 case 256:1789 return VReg_256RegClassID;1790 case 288:1791 return VReg_288RegClassID;1792 case 320:1793 return VReg_320RegClassID;1794 case 352:1795 return VReg_352RegClassID;1796 case 384:1797 return VReg_384RegClassID;1798 case 512:1799 return VReg_512RegClassID;1800 case 1024:1801 return VReg_1024RegClassID;1802 }1803 llvm_unreachable("Invalid register width!");1804}1805 1806unsigned AMDGPUDisassembler::getAgprClassId(unsigned Width) const {1807 using namespace AMDGPU;1808 1809 switch (Width) {1810 case 16:1811 case 32:1812 return AGPR_32RegClassID;1813 case 64:1814 return AReg_64RegClassID;1815 case 96:1816 return AReg_96RegClassID;1817 case 128:1818 return AReg_128RegClassID;1819 case 160:1820 return AReg_160RegClassID;1821 case 256:1822 return AReg_256RegClassID;1823 case 288:1824 return AReg_288RegClassID;1825 case 320:1826 return AReg_320RegClassID;1827 case 352:1828 return AReg_352RegClassID;1829 case 384:1830 return AReg_384RegClassID;1831 case 512:1832 return AReg_512RegClassID;1833 case 1024:1834 return AReg_1024RegClassID;1835 }1836 llvm_unreachable("Invalid register width!");1837}1838 1839unsigned AMDGPUDisassembler::getSgprClassId(unsigned Width) const {1840 using namespace AMDGPU;1841 1842 switch (Width) {1843 case 16:1844 case 32:1845 return SGPR_32RegClassID;1846 case 64:1847 return SGPR_64RegClassID;1848 case 96:1849 return SGPR_96RegClassID;1850 case 128:1851 return SGPR_128RegClassID;1852 case 160:1853 return SGPR_160RegClassID;1854 case 256:1855 return SGPR_256RegClassID;1856 case 288:1857 return SGPR_288RegClassID;1858 case 320:1859 return SGPR_320RegClassID;1860 case 352:1861 return SGPR_352RegClassID;1862 case 384:1863 return SGPR_384RegClassID;1864 case 512:1865 return SGPR_512RegClassID;1866 }1867 llvm_unreachable("Invalid register width!");1868}1869 1870unsigned AMDGPUDisassembler::getTtmpClassId(unsigned Width) const {1871 using namespace AMDGPU;1872 1873 switch (Width) {1874 case 16:1875 case 32:1876 return TTMP_32RegClassID;1877 case 64:1878 return TTMP_64RegClassID;1879 case 128:1880 return TTMP_128RegClassID;1881 case 256:1882 return TTMP_256RegClassID;1883 case 288:1884 return TTMP_288RegClassID;1885 case 320:1886 return TTMP_320RegClassID;1887 case 352:1888 return TTMP_352RegClassID;1889 case 384:1890 return TTMP_384RegClassID;1891 case 512:1892 return TTMP_512RegClassID;1893 }1894 llvm_unreachable("Invalid register width!");1895}1896 1897int AMDGPUDisassembler::getTTmpIdx(unsigned Val) const {1898 using namespace AMDGPU::EncValues;1899 1900 unsigned TTmpMin = isGFX9Plus() ? TTMP_GFX9PLUS_MIN : TTMP_VI_MIN;1901 unsigned TTmpMax = isGFX9Plus() ? TTMP_GFX9PLUS_MAX : TTMP_VI_MAX;1902 1903 return (TTmpMin <= Val && Val <= TTmpMax)? Val - TTmpMin : -1;1904}1905 1906MCOperand AMDGPUDisassembler::decodeSrcOp(const MCInst &Inst, unsigned Width,1907 unsigned Val) const {1908 using namespace AMDGPU::EncValues;1909 1910 assert(Val < 1024); // enum101911 1912 bool IsAGPR = Val & 512;1913 Val &= 511;1914 1915 if (VGPR_MIN <= Val && Val <= VGPR_MAX) {1916 return createRegOperand(IsAGPR ? getAgprClassId(Width)1917 : getVgprClassId(Width), Val - VGPR_MIN);1918 }1919 return decodeNonVGPRSrcOp(Inst, Width, Val & 0xFF);1920}1921 1922MCOperand AMDGPUDisassembler::decodeNonVGPRSrcOp(const MCInst &Inst,1923 unsigned Width,1924 unsigned Val) const {1925 // Cases when Val{8} is 1 (vgpr, agpr or true 16 vgpr) should have been1926 // decoded earlier.1927 assert(Val < (1 << 8) && "9-bit Src encoding when Val{8} is 0");1928 using namespace AMDGPU::EncValues;1929 1930 if (Val <= SGPR_MAX) {1931 // "SGPR_MIN <= Val" is always true and causes compilation warning.1932 static_assert(SGPR_MIN == 0);1933 return createSRegOperand(getSgprClassId(Width), Val - SGPR_MIN);1934 }1935 1936 int TTmpIdx = getTTmpIdx(Val);1937 if (TTmpIdx >= 0) {1938 return createSRegOperand(getTtmpClassId(Width), TTmpIdx);1939 }1940 1941 if ((INLINE_INTEGER_C_MIN <= Val && Val <= INLINE_INTEGER_C_MAX) ||1942 (INLINE_FLOATING_C_MIN <= Val && Val <= INLINE_FLOATING_C_MAX) ||1943 Val == LITERAL_CONST)1944 return MCOperand::createImm(Val);1945 1946 if (Val == LITERAL64_CONST && STI.hasFeature(AMDGPU::Feature64BitLiterals)) {1947 return decodeLiteral64Constant();1948 }1949 1950 switch (Width) {1951 case 32:1952 case 16:1953 return decodeSpecialReg32(Val);1954 case 64:1955 return decodeSpecialReg64(Val);1956 case 96:1957 case 128:1958 case 256:1959 case 512:1960 return decodeSpecialReg96Plus(Val);1961 default:1962 llvm_unreachable("unexpected immediate type");1963 }1964}1965 1966// Bit 0 of DstY isn't stored in the instruction, because it's always the1967// opposite of bit 0 of DstX.1968MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst,1969 unsigned Val) const {1970 int VDstXInd =1971 AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::vdstX);1972 assert(VDstXInd != -1);1973 assert(Inst.getOperand(VDstXInd).isReg());1974 unsigned XDstReg = MRI.getEncodingValue(Inst.getOperand(VDstXInd).getReg());1975 Val |= ~XDstReg & 1;1976 return createRegOperand(getVgprClassId(32), Val);1977}1978 1979MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const {1980 using namespace AMDGPU;1981 1982 switch (Val) {1983 // clang-format off1984 case 102: return createRegOperand(FLAT_SCR_LO);1985 case 103: return createRegOperand(FLAT_SCR_HI);1986 case 104: return createRegOperand(XNACK_MASK_LO);1987 case 105: return createRegOperand(XNACK_MASK_HI);1988 case 106: return createRegOperand(VCC_LO);1989 case 107: return createRegOperand(VCC_HI);1990 case 108: return createRegOperand(TBA_LO);1991 case 109: return createRegOperand(TBA_HI);1992 case 110: return createRegOperand(TMA_LO);1993 case 111: return createRegOperand(TMA_HI);1994 case 124:1995 return isGFX11Plus() ? createRegOperand(SGPR_NULL) : createRegOperand(M0);1996 case 125:1997 return isGFX11Plus() ? createRegOperand(M0) : createRegOperand(SGPR_NULL);1998 case 126: return createRegOperand(EXEC_LO);1999 case 127: return createRegOperand(EXEC_HI);2000 case 230: return createRegOperand(SRC_FLAT_SCRATCH_BASE_LO);2001 case 231: return createRegOperand(SRC_FLAT_SCRATCH_BASE_HI);2002 case 235: return createRegOperand(SRC_SHARED_BASE_LO);2003 case 236: return createRegOperand(SRC_SHARED_LIMIT_LO);2004 case 237: return createRegOperand(SRC_PRIVATE_BASE_LO);2005 case 238: return createRegOperand(SRC_PRIVATE_LIMIT_LO);2006 case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);2007 case 251: return createRegOperand(SRC_VCCZ);2008 case 252: return createRegOperand(SRC_EXECZ);2009 case 253: return createRegOperand(SRC_SCC);2010 case 254: return createRegOperand(LDS_DIRECT);2011 default: break;2012 // clang-format on2013 }2014 return errOperand(Val, "unknown operand encoding " + Twine(Val));2015}2016 2017MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const {2018 using namespace AMDGPU;2019 2020 switch (Val) {2021 case 102: return createRegOperand(FLAT_SCR);2022 case 104: return createRegOperand(XNACK_MASK);2023 case 106: return createRegOperand(VCC);2024 case 108: return createRegOperand(TBA);2025 case 110: return createRegOperand(TMA);2026 case 124:2027 if (isGFX11Plus())2028 return createRegOperand(SGPR_NULL);2029 break;2030 case 125:2031 if (!isGFX11Plus())2032 return createRegOperand(SGPR_NULL);2033 break;2034 case 126: return createRegOperand(EXEC);2035 case 230: return createRegOperand(SRC_FLAT_SCRATCH_BASE_LO);2036 case 235: return createRegOperand(SRC_SHARED_BASE);2037 case 236: return createRegOperand(SRC_SHARED_LIMIT);2038 case 237: return createRegOperand(SRC_PRIVATE_BASE);2039 case 238: return createRegOperand(SRC_PRIVATE_LIMIT);2040 case 239: return createRegOperand(SRC_POPS_EXITING_WAVE_ID);2041 case 251: return createRegOperand(SRC_VCCZ);2042 case 252: return createRegOperand(SRC_EXECZ);2043 case 253: return createRegOperand(SRC_SCC);2044 default: break;2045 }2046 return errOperand(Val, "unknown operand encoding " + Twine(Val));2047}2048 2049MCOperand AMDGPUDisassembler::decodeSpecialReg96Plus(unsigned Val) const {2050 using namespace AMDGPU;2051 2052 switch (Val) {2053 case 124:2054 if (isGFX11Plus())2055 return createRegOperand(SGPR_NULL);2056 break;2057 case 125:2058 if (!isGFX11Plus())2059 return createRegOperand(SGPR_NULL);2060 break;2061 default:2062 break;2063 }2064 return errOperand(Val, "unknown operand encoding " + Twine(Val));2065}2066 2067MCOperand AMDGPUDisassembler::decodeSDWASrc(unsigned Width,2068 const unsigned Val) const {2069 using namespace AMDGPU::SDWA;2070 using namespace AMDGPU::EncValues;2071 2072 if (STI.hasFeature(AMDGPU::FeatureGFX9) ||2073 STI.hasFeature(AMDGPU::FeatureGFX10)) {2074 // XXX: cast to int is needed to avoid stupid warning:2075 // compare with unsigned is always true2076 if (int(SDWA9EncValues::SRC_VGPR_MIN) <= int(Val) &&2077 Val <= SDWA9EncValues::SRC_VGPR_MAX) {2078 return createRegOperand(getVgprClassId(Width),2079 Val - SDWA9EncValues::SRC_VGPR_MIN);2080 }2081 if (SDWA9EncValues::SRC_SGPR_MIN <= Val &&2082 Val <= (isGFX10Plus() ? SDWA9EncValues::SRC_SGPR_MAX_GFX102083 : SDWA9EncValues::SRC_SGPR_MAX_SI)) {2084 return createSRegOperand(getSgprClassId(Width),2085 Val - SDWA9EncValues::SRC_SGPR_MIN);2086 }2087 if (SDWA9EncValues::SRC_TTMP_MIN <= Val &&2088 Val <= SDWA9EncValues::SRC_TTMP_MAX) {2089 return createSRegOperand(getTtmpClassId(Width),2090 Val - SDWA9EncValues::SRC_TTMP_MIN);2091 }2092 2093 const unsigned SVal = Val - SDWA9EncValues::SRC_SGPR_MIN;2094 2095 if ((INLINE_INTEGER_C_MIN <= SVal && SVal <= INLINE_INTEGER_C_MAX) ||2096 (INLINE_FLOATING_C_MIN <= SVal && SVal <= INLINE_FLOATING_C_MAX))2097 return MCOperand::createImm(SVal);2098 2099 return decodeSpecialReg32(SVal);2100 }2101 if (STI.hasFeature(AMDGPU::FeatureVolcanicIslands))2102 return createRegOperand(getVgprClassId(Width), Val);2103 llvm_unreachable("unsupported target");2104}2105 2106MCOperand AMDGPUDisassembler::decodeSDWASrc16(unsigned Val) const {2107 return decodeSDWASrc(16, Val);2108}2109 2110MCOperand AMDGPUDisassembler::decodeSDWASrc32(unsigned Val) const {2111 return decodeSDWASrc(32, Val);2112}2113 2114MCOperand AMDGPUDisassembler::decodeSDWAVopcDst(unsigned Val) const {2115 using namespace AMDGPU::SDWA;2116 2117 assert((STI.hasFeature(AMDGPU::FeatureGFX9) ||2118 STI.hasFeature(AMDGPU::FeatureGFX10)) &&2119 "SDWAVopcDst should be present only on GFX9+");2120 2121 bool IsWave32 = STI.hasFeature(AMDGPU::FeatureWavefrontSize32);2122 2123 if (Val & SDWA9EncValues::VOPC_DST_VCC_MASK) {2124 Val &= SDWA9EncValues::VOPC_DST_SGPR_MASK;2125 2126 int TTmpIdx = getTTmpIdx(Val);2127 if (TTmpIdx >= 0) {2128 auto TTmpClsId = getTtmpClassId(IsWave32 ? 32 : 64);2129 return createSRegOperand(TTmpClsId, TTmpIdx);2130 }2131 if (Val > SGPR_MAX) {2132 return IsWave32 ? decodeSpecialReg32(Val) : decodeSpecialReg64(Val);2133 }2134 return createSRegOperand(getSgprClassId(IsWave32 ? 32 : 64), Val);2135 }2136 return createRegOperand(IsWave32 ? AMDGPU::VCC_LO : AMDGPU::VCC);2137}2138 2139MCOperand AMDGPUDisassembler::decodeBoolReg(const MCInst &Inst,2140 unsigned Val) const {2141 return STI.hasFeature(AMDGPU::FeatureWavefrontSize32)2142 ? decodeSrcOp(Inst, 32, Val)2143 : decodeSrcOp(Inst, 64, Val);2144}2145 2146MCOperand AMDGPUDisassembler::decodeSplitBarrier(const MCInst &Inst,2147 unsigned Val) const {2148 return decodeSrcOp(Inst, 32, Val);2149}2150 2151MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {2152 if (Val != AMDGPU::DPP::DPP8_FI_0 && Val != AMDGPU::DPP::DPP8_FI_1)2153 return MCOperand();2154 return MCOperand::createImm(Val);2155}2156 2157MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {2158 using VersionField = AMDGPU::EncodingField<7, 0>;2159 using W64Bit = AMDGPU::EncodingBit<13>;2160 using W32Bit = AMDGPU::EncodingBit<14>;2161 using MDPBit = AMDGPU::EncodingBit<15>;2162 using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;2163 2164 auto [Version, W64, W32, MDP] = Encoding::decode(Imm);2165 2166 // Decode into a plain immediate if any unused bits are raised.2167 if (Encoding::encode(Version, W64, W32, MDP) != Imm)2168 return MCOperand::createImm(Imm);2169 2170 const auto &Versions = AMDGPU::UCVersion::getGFXVersions();2171 const auto *I = find_if(2172 Versions, [Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {2173 return V.Code == Version;2174 });2175 MCContext &Ctx = getContext();2176 const MCExpr *E;2177 if (I == Versions.end())2178 E = MCConstantExpr::create(Version, Ctx);2179 else2180 E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx);2181 2182 if (W64)2183 E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx);2184 if (W32)2185 E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx);2186 if (MDP)2187 E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx);2188 2189 return MCOperand::createExpr(E);2190}2191 2192bool AMDGPUDisassembler::isVI() const {2193 return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);2194}2195 2196bool AMDGPUDisassembler::isGFX9() const { return AMDGPU::isGFX9(STI); }2197 2198bool AMDGPUDisassembler::isGFX90A() const {2199 return STI.hasFeature(AMDGPU::FeatureGFX90AInsts);2200}2201 2202bool AMDGPUDisassembler::isGFX9Plus() const { return AMDGPU::isGFX9Plus(STI); }2203 2204bool AMDGPUDisassembler::isGFX10() const { return AMDGPU::isGFX10(STI); }2205 2206bool AMDGPUDisassembler::isGFX10Plus() const {2207 return AMDGPU::isGFX10Plus(STI);2208}2209 2210bool AMDGPUDisassembler::isGFX11() const {2211 return STI.hasFeature(AMDGPU::FeatureGFX11);2212}2213 2214bool AMDGPUDisassembler::isGFX11Plus() const {2215 return AMDGPU::isGFX11Plus(STI);2216}2217 2218bool AMDGPUDisassembler::isGFX12() const {2219 return STI.hasFeature(AMDGPU::FeatureGFX12);2220}2221 2222bool AMDGPUDisassembler::isGFX12Plus() const {2223 return AMDGPU::isGFX12Plus(STI);2224}2225 2226bool AMDGPUDisassembler::isGFX1250() const { return AMDGPU::isGFX1250(STI); }2227 2228bool AMDGPUDisassembler::hasArchitectedFlatScratch() const {2229 return STI.hasFeature(AMDGPU::FeatureArchitectedFlatScratch);2230}2231 2232bool AMDGPUDisassembler::hasKernargPreload() const {2233 return AMDGPU::hasKernargPreload(STI);2234}2235 2236//===----------------------------------------------------------------------===//2237// AMDGPU specific symbol handling2238//===----------------------------------------------------------------------===//2239 2240/// Print a string describing the reserved bit range specified by Mask with2241/// offset BaseBytes for use in error comments. Mask is a single continuous2242/// range of 1s surrounded by zeros. The format here is meant to align with the2243/// tables that describe these bits in llvm.org/docs/AMDGPUUsage.html.2244static SmallString<32> getBitRangeFromMask(uint32_t Mask, unsigned BaseBytes) {2245 SmallString<32> Result;2246 raw_svector_ostream S(Result);2247 2248 int TrailingZeros = llvm::countr_zero(Mask);2249 int PopCount = llvm::popcount(Mask);2250 2251 if (PopCount == 1) {2252 S << "bit (" << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';2253 } else {2254 S << "bits in range ("2255 << (TrailingZeros + PopCount - 1 + BaseBytes * CHAR_BIT) << ':'2256 << (TrailingZeros + BaseBytes * CHAR_BIT) << ')';2257 }2258 2259 return Result;2260}2261 2262#define GET_FIELD(MASK) (AMDHSA_BITS_GET(FourByteBuffer, MASK))2263#define PRINT_DIRECTIVE(DIRECTIVE, MASK) \2264 do { \2265 KdStream << Indent << DIRECTIVE " " << GET_FIELD(MASK) << '\n'; \2266 } while (0)2267#define PRINT_PSEUDO_DIRECTIVE_COMMENT(DIRECTIVE, MASK) \2268 do { \2269 KdStream << Indent << MAI.getCommentString() << ' ' << DIRECTIVE " " \2270 << GET_FIELD(MASK) << '\n'; \2271 } while (0)2272 2273#define CHECK_RESERVED_BITS_IMPL(MASK, DESC, MSG) \2274 do { \2275 if (FourByteBuffer & (MASK)) { \2276 return createStringError(std::errc::invalid_argument, \2277 "kernel descriptor " DESC \2278 " reserved %s set" MSG, \2279 getBitRangeFromMask((MASK), 0).c_str()); \2280 } \2281 } while (0)2282 2283#define CHECK_RESERVED_BITS(MASK) CHECK_RESERVED_BITS_IMPL(MASK, #MASK, "")2284#define CHECK_RESERVED_BITS_MSG(MASK, MSG) \2285 CHECK_RESERVED_BITS_IMPL(MASK, #MASK, ", " MSG)2286#define CHECK_RESERVED_BITS_DESC(MASK, DESC) \2287 CHECK_RESERVED_BITS_IMPL(MASK, DESC, "")2288#define CHECK_RESERVED_BITS_DESC_MSG(MASK, DESC, MSG) \2289 CHECK_RESERVED_BITS_IMPL(MASK, DESC, ", " MSG)2290 2291// NOLINTNEXTLINE(readability-identifier-naming)2292Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC1(2293 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {2294 using namespace amdhsa;2295 StringRef Indent = "\t";2296 2297 // We cannot accurately backward compute #VGPRs used from2298 // GRANULATED_WORKITEM_VGPR_COUNT. But we are concerned with getting the same2299 // value of GRANULATED_WORKITEM_VGPR_COUNT in the reassembled binary. So we2300 // simply calculate the inverse of what the assembler does.2301 2302 uint32_t GranulatedWorkitemVGPRCount =2303 GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WORKITEM_VGPR_COUNT);2304 2305 uint32_t NextFreeVGPR =2306 (GranulatedWorkitemVGPRCount + 1) *2307 AMDGPU::IsaInfo::getVGPREncodingGranule(&STI, EnableWavefrontSize32);2308 2309 KdStream << Indent << ".amdhsa_next_free_vgpr " << NextFreeVGPR << '\n';2310 2311 // We cannot backward compute values used to calculate2312 // GRANULATED_WAVEFRONT_SGPR_COUNT. Hence the original values for following2313 // directives can't be computed:2314 // .amdhsa_reserve_vcc2315 // .amdhsa_reserve_flat_scratch2316 // .amdhsa_reserve_xnack_mask2317 // They take their respective default values if not specified in the assembly.2318 //2319 // GRANULATED_WAVEFRONT_SGPR_COUNT2320 // = f(NEXT_FREE_SGPR + VCC + FLAT_SCRATCH + XNACK_MASK)2321 //2322 // We compute the inverse as though all directives apart from NEXT_FREE_SGPR2323 // are set to 0. So while disassembling we consider that:2324 //2325 // GRANULATED_WAVEFRONT_SGPR_COUNT2326 // = f(NEXT_FREE_SGPR + 0 + 0 + 0)2327 //2328 // The disassembler cannot recover the original values of those 3 directives.2329 2330 uint32_t GranulatedWavefrontSGPRCount =2331 GET_FIELD(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT);2332 2333 if (isGFX10Plus())2334 CHECK_RESERVED_BITS_MSG(COMPUTE_PGM_RSRC1_GRANULATED_WAVEFRONT_SGPR_COUNT,2335 "must be zero on gfx10+");2336 2337 uint32_t NextFreeSGPR = (GranulatedWavefrontSGPRCount + 1) *2338 AMDGPU::IsaInfo::getSGPREncodingGranule(&STI);2339 2340 KdStream << Indent << ".amdhsa_reserve_vcc " << 0 << '\n';2341 if (!hasArchitectedFlatScratch())2342 KdStream << Indent << ".amdhsa_reserve_flat_scratch " << 0 << '\n';2343 bool ReservedXnackMask = STI.hasFeature(AMDGPU::FeatureXNACK);2344 assert(!ReservedXnackMask || STI.hasFeature(AMDGPU::FeatureSupportsXNACK));2345 KdStream << Indent << ".amdhsa_reserve_xnack_mask " << ReservedXnackMask2346 << '\n';2347 KdStream << Indent << ".amdhsa_next_free_sgpr " << NextFreeSGPR << "\n";2348 2349 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIORITY);2350 2351 PRINT_DIRECTIVE(".amdhsa_float_round_mode_32",2352 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_32);2353 PRINT_DIRECTIVE(".amdhsa_float_round_mode_16_64",2354 COMPUTE_PGM_RSRC1_FLOAT_ROUND_MODE_16_64);2355 PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_32",2356 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_32);2357 PRINT_DIRECTIVE(".amdhsa_float_denorm_mode_16_64",2358 COMPUTE_PGM_RSRC1_FLOAT_DENORM_MODE_16_64);2359 2360 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_PRIV);2361 2362 if (!isGFX12Plus())2363 PRINT_DIRECTIVE(".amdhsa_dx10_clamp",2364 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_DX10_CLAMP);2365 2366 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_DEBUG_MODE);2367 2368 if (!isGFX12Plus())2369 PRINT_DIRECTIVE(".amdhsa_ieee_mode",2370 COMPUTE_PGM_RSRC1_GFX6_GFX11_ENABLE_IEEE_MODE);2371 2372 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_BULKY);2373 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC1_CDBG_USER);2374 2375 // Bits [26].2376 if (isGFX9Plus()) {2377 PRINT_DIRECTIVE(".amdhsa_fp16_overflow", COMPUTE_PGM_RSRC1_GFX9_PLUS_FP16_OVFL);2378 } else {2379 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC1_GFX6_GFX8_RESERVED0,2380 "COMPUTE_PGM_RSRC1", "must be zero pre-gfx9");2381 }2382 2383 // Bits [27].2384 if (isGFX1250()) {2385 PRINT_PSEUDO_DIRECTIVE_COMMENT("FLAT_SCRATCH_IS_NV",2386 COMPUTE_PGM_RSRC1_GFX125_FLAT_SCRATCH_IS_NV);2387 } else {2388 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_GFX6_GFX120_RESERVED1,2389 "COMPUTE_PGM_RSRC1");2390 }2391 2392 // Bits [28].2393 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_RESERVED2, "COMPUTE_PGM_RSRC1");2394 2395 // Bits [29-31].2396 if (isGFX10Plus()) {2397 // WGP_MODE is not available on GFX1250.2398 if (!isGFX1250()) {2399 PRINT_DIRECTIVE(".amdhsa_workgroup_processor_mode",2400 COMPUTE_PGM_RSRC1_GFX10_PLUS_WGP_MODE);2401 }2402 PRINT_DIRECTIVE(".amdhsa_memory_ordered", COMPUTE_PGM_RSRC1_GFX10_PLUS_MEM_ORDERED);2403 PRINT_DIRECTIVE(".amdhsa_forward_progress", COMPUTE_PGM_RSRC1_GFX10_PLUS_FWD_PROGRESS);2404 } else {2405 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC1_GFX6_GFX9_RESERVED3,2406 "COMPUTE_PGM_RSRC1");2407 }2408 2409 if (isGFX12Plus())2410 PRINT_DIRECTIVE(".amdhsa_round_robin_scheduling",2411 COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN);2412 2413 return true;2414}2415 2416// NOLINTNEXTLINE(readability-identifier-naming)2417Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC2(2418 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {2419 using namespace amdhsa;2420 StringRef Indent = "\t";2421 if (hasArchitectedFlatScratch())2422 PRINT_DIRECTIVE(".amdhsa_enable_private_segment",2423 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);2424 else2425 PRINT_DIRECTIVE(".amdhsa_system_sgpr_private_segment_wavefront_offset",2426 COMPUTE_PGM_RSRC2_ENABLE_PRIVATE_SEGMENT);2427 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_x",2428 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_X);2429 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_y",2430 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Y);2431 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_id_z",2432 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_ID_Z);2433 PRINT_DIRECTIVE(".amdhsa_system_sgpr_workgroup_info",2434 COMPUTE_PGM_RSRC2_ENABLE_SGPR_WORKGROUP_INFO);2435 PRINT_DIRECTIVE(".amdhsa_system_vgpr_workitem_id",2436 COMPUTE_PGM_RSRC2_ENABLE_VGPR_WORKITEM_ID);2437 2438 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_ADDRESS_WATCH);2439 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_MEMORY);2440 CHECK_RESERVED_BITS(COMPUTE_PGM_RSRC2_GRANULATED_LDS_SIZE);2441 2442 PRINT_DIRECTIVE(2443 ".amdhsa_exception_fp_ieee_invalid_op",2444 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION);2445 PRINT_DIRECTIVE(".amdhsa_exception_fp_denorm_src",2446 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_FP_DENORMAL_SOURCE);2447 PRINT_DIRECTIVE(2448 ".amdhsa_exception_fp_ieee_div_zero",2449 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_DIVISION_BY_ZERO);2450 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_overflow",2451 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_OVERFLOW);2452 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_underflow",2453 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_UNDERFLOW);2454 PRINT_DIRECTIVE(".amdhsa_exception_fp_ieee_inexact",2455 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_IEEE_754_FP_INEXACT);2456 PRINT_DIRECTIVE(".amdhsa_exception_int_div_zero",2457 COMPUTE_PGM_RSRC2_ENABLE_EXCEPTION_INT_DIVIDE_BY_ZERO);2458 2459 CHECK_RESERVED_BITS_DESC(COMPUTE_PGM_RSRC2_RESERVED0, "COMPUTE_PGM_RSRC2");2460 2461 return true;2462}2463 2464// NOLINTNEXTLINE(readability-identifier-naming)2465Expected<bool> AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3(2466 uint32_t FourByteBuffer, raw_string_ostream &KdStream) const {2467 using namespace amdhsa;2468 StringRef Indent = "\t";2469 if (isGFX90A()) {2470 KdStream << Indent << ".amdhsa_accum_offset "2471 << (GET_FIELD(COMPUTE_PGM_RSRC3_GFX90A_ACCUM_OFFSET) + 1) * 42472 << '\n';2473 2474 PRINT_DIRECTIVE(".amdhsa_tg_split", COMPUTE_PGM_RSRC3_GFX90A_TG_SPLIT);2475 2476 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED0,2477 "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");2478 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX90A_RESERVED1,2479 "COMPUTE_PGM_RSRC3", "must be zero on gfx90a");2480 } else if (isGFX10Plus()) {2481 // Bits [0-3].2482 if (!isGFX12Plus()) {2483 if (!EnableWavefrontSize32 || !*EnableWavefrontSize32) {2484 PRINT_DIRECTIVE(".amdhsa_shared_vgpr_count",2485 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);2486 } else {2487 PRINT_PSEUDO_DIRECTIVE_COMMENT(2488 "SHARED_VGPR_COUNT",2489 COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT);2490 }2491 } else {2492 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX12_PLUS_RESERVED0,2493 "COMPUTE_PGM_RSRC3",2494 "must be zero on gfx12+");2495 }2496 2497 // Bits [4-11].2498 if (isGFX11()) {2499 PRINT_DIRECTIVE(".amdhsa_inst_pref_size",2500 COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE);2501 PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START",2502 COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START);2503 PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END",2504 COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END);2505 } else if (isGFX12Plus()) {2506 PRINT_DIRECTIVE(".amdhsa_inst_pref_size",2507 COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE);2508 } else {2509 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED1,2510 "COMPUTE_PGM_RSRC3",2511 "must be zero on gfx10");2512 }2513 2514 // Bits [12].2515 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED2,2516 "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");2517 2518 // Bits [13].2519 if (isGFX12Plus()) {2520 PRINT_PSEUDO_DIRECTIVE_COMMENT("GLG_EN",2521 COMPUTE_PGM_RSRC3_GFX12_PLUS_GLG_EN);2522 } else {2523 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX11_RESERVED3,2524 "COMPUTE_PGM_RSRC3",2525 "must be zero on gfx10 or gfx11");2526 }2527 2528 // Bits [14-21].2529 if (isGFX1250()) {2530 PRINT_DIRECTIVE(".amdhsa_named_barrier_count",2531 COMPUTE_PGM_RSRC3_GFX125_NAMED_BAR_CNT);2532 PRINT_PSEUDO_DIRECTIVE_COMMENT(2533 "ENABLE_DYNAMIC_VGPR", COMPUTE_PGM_RSRC3_GFX125_ENABLE_DYNAMIC_VGPR);2534 PRINT_PSEUDO_DIRECTIVE_COMMENT("TCP_SPLIT",2535 COMPUTE_PGM_RSRC3_GFX125_TCP_SPLIT);2536 PRINT_PSEUDO_DIRECTIVE_COMMENT(2537 "ENABLE_DIDT_THROTTLE",2538 COMPUTE_PGM_RSRC3_GFX125_ENABLE_DIDT_THROTTLE);2539 } else {2540 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_GFX120_RESERVED4,2541 "COMPUTE_PGM_RSRC3",2542 "must be zero on gfx10+");2543 }2544 2545 // Bits [22-30].2546 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_PLUS_RESERVED5,2547 "COMPUTE_PGM_RSRC3", "must be zero on gfx10+");2548 2549 // Bits [31].2550 if (isGFX11Plus()) {2551 PRINT_PSEUDO_DIRECTIVE_COMMENT("IMAGE_OP",2552 COMPUTE_PGM_RSRC3_GFX11_PLUS_IMAGE_OP);2553 } else {2554 CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED6,2555 "COMPUTE_PGM_RSRC3",2556 "must be zero on gfx10");2557 }2558 } else if (FourByteBuffer) {2559 return createStringError(2560 std::errc::invalid_argument,2561 "kernel descriptor COMPUTE_PGM_RSRC3 must be all zero before gfx9");2562 }2563 return true;2564}2565#undef PRINT_PSEUDO_DIRECTIVE_COMMENT2566#undef PRINT_DIRECTIVE2567#undef GET_FIELD2568#undef CHECK_RESERVED_BITS_IMPL2569#undef CHECK_RESERVED_BITS2570#undef CHECK_RESERVED_BITS_MSG2571#undef CHECK_RESERVED_BITS_DESC2572#undef CHECK_RESERVED_BITS_DESC_MSG2573 2574/// Create an error object to return from onSymbolStart for reserved kernel2575/// descriptor bits being set.2576static Error createReservedKDBitsError(uint32_t Mask, unsigned BaseBytes,2577 const char *Msg = "") {2578 return createStringError(2579 std::errc::invalid_argument, "kernel descriptor reserved %s set%s%s",2580 getBitRangeFromMask(Mask, BaseBytes).c_str(), *Msg ? ", " : "", Msg);2581}2582 2583/// Create an error object to return from onSymbolStart for reserved kernel2584/// descriptor bytes being set.2585static Error createReservedKDBytesError(unsigned BaseInBytes,2586 unsigned WidthInBytes) {2587 // Create an error comment in the same format as the "Kernel Descriptor"2588 // table here: https://llvm.org/docs/AMDGPUUsage.html#kernel-descriptor .2589 return createStringError(2590 std::errc::invalid_argument,2591 "kernel descriptor reserved bits in range (%u:%u) set",2592 (BaseInBytes + WidthInBytes) * CHAR_BIT - 1, BaseInBytes * CHAR_BIT);2593}2594 2595Expected<bool> AMDGPUDisassembler::decodeKernelDescriptorDirective(2596 DataExtractor::Cursor &Cursor, ArrayRef<uint8_t> Bytes,2597 raw_string_ostream &KdStream) const {2598#define PRINT_DIRECTIVE(DIRECTIVE, MASK) \2599 do { \2600 KdStream << Indent << DIRECTIVE " " \2601 << ((TwoByteBuffer & MASK) >> (MASK##_SHIFT)) << '\n'; \2602 } while (0)2603 2604 uint16_t TwoByteBuffer = 0;2605 uint32_t FourByteBuffer = 0;2606 2607 StringRef ReservedBytes;2608 StringRef Indent = "\t";2609 2610 assert(Bytes.size() == 64);2611 DataExtractor DE(Bytes, /*IsLittleEndian=*/true, /*AddressSize=*/8);2612 2613 switch (Cursor.tell()) {2614 case amdhsa::GROUP_SEGMENT_FIXED_SIZE_OFFSET:2615 FourByteBuffer = DE.getU32(Cursor);2616 KdStream << Indent << ".amdhsa_group_segment_fixed_size " << FourByteBuffer2617 << '\n';2618 return true;2619 2620 case amdhsa::PRIVATE_SEGMENT_FIXED_SIZE_OFFSET:2621 FourByteBuffer = DE.getU32(Cursor);2622 KdStream << Indent << ".amdhsa_private_segment_fixed_size "2623 << FourByteBuffer << '\n';2624 return true;2625 2626 case amdhsa::KERNARG_SIZE_OFFSET:2627 FourByteBuffer = DE.getU32(Cursor);2628 KdStream << Indent << ".amdhsa_kernarg_size "2629 << FourByteBuffer << '\n';2630 return true;2631 2632 case amdhsa::RESERVED0_OFFSET:2633 // 4 reserved bytes, must be 0.2634 ReservedBytes = DE.getBytes(Cursor, 4);2635 for (int I = 0; I < 4; ++I) {2636 if (ReservedBytes[I] != 0)2637 return createReservedKDBytesError(amdhsa::RESERVED0_OFFSET, 4);2638 }2639 return true;2640 2641 case amdhsa::KERNEL_CODE_ENTRY_BYTE_OFFSET_OFFSET:2642 // KERNEL_CODE_ENTRY_BYTE_OFFSET2643 // So far no directive controls this for Code Object V3, so simply skip for2644 // disassembly.2645 DE.skip(Cursor, 8);2646 return true;2647 2648 case amdhsa::RESERVED1_OFFSET:2649 // 20 reserved bytes, must be 0.2650 ReservedBytes = DE.getBytes(Cursor, 20);2651 for (int I = 0; I < 20; ++I) {2652 if (ReservedBytes[I] != 0)2653 return createReservedKDBytesError(amdhsa::RESERVED1_OFFSET, 20);2654 }2655 return true;2656 2657 case amdhsa::COMPUTE_PGM_RSRC3_OFFSET:2658 FourByteBuffer = DE.getU32(Cursor);2659 return decodeCOMPUTE_PGM_RSRC3(FourByteBuffer, KdStream);2660 2661 case amdhsa::COMPUTE_PGM_RSRC1_OFFSET:2662 FourByteBuffer = DE.getU32(Cursor);2663 return decodeCOMPUTE_PGM_RSRC1(FourByteBuffer, KdStream);2664 2665 case amdhsa::COMPUTE_PGM_RSRC2_OFFSET:2666 FourByteBuffer = DE.getU32(Cursor);2667 return decodeCOMPUTE_PGM_RSRC2(FourByteBuffer, KdStream);2668 2669 case amdhsa::KERNEL_CODE_PROPERTIES_OFFSET:2670 using namespace amdhsa;2671 TwoByteBuffer = DE.getU16(Cursor);2672 2673 if (!hasArchitectedFlatScratch())2674 PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_buffer",2675 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_BUFFER);2676 PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_ptr",2677 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_PTR);2678 PRINT_DIRECTIVE(".amdhsa_user_sgpr_queue_ptr",2679 KERNEL_CODE_PROPERTY_ENABLE_SGPR_QUEUE_PTR);2680 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_segment_ptr",2681 KERNEL_CODE_PROPERTY_ENABLE_SGPR_KERNARG_SEGMENT_PTR);2682 PRINT_DIRECTIVE(".amdhsa_user_sgpr_dispatch_id",2683 KERNEL_CODE_PROPERTY_ENABLE_SGPR_DISPATCH_ID);2684 if (!hasArchitectedFlatScratch())2685 PRINT_DIRECTIVE(".amdhsa_user_sgpr_flat_scratch_init",2686 KERNEL_CODE_PROPERTY_ENABLE_SGPR_FLAT_SCRATCH_INIT);2687 PRINT_DIRECTIVE(".amdhsa_user_sgpr_private_segment_size",2688 KERNEL_CODE_PROPERTY_ENABLE_SGPR_PRIVATE_SEGMENT_SIZE);2689 2690 if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED0)2691 return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED0,2692 amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);2693 2694 // Reserved for GFX92695 if (isGFX9() &&2696 (TwoByteBuffer & KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32)) {2697 return createReservedKDBitsError(2698 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32,2699 amdhsa::KERNEL_CODE_PROPERTIES_OFFSET, "must be zero on gfx9");2700 }2701 if (isGFX10Plus()) {2702 PRINT_DIRECTIVE(".amdhsa_wavefront_size32",2703 KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);2704 }2705 2706 if (CodeObjectVersion >= AMDGPU::AMDHSA_COV5)2707 PRINT_DIRECTIVE(".amdhsa_uses_dynamic_stack",2708 KERNEL_CODE_PROPERTY_USES_DYNAMIC_STACK);2709 2710 if (TwoByteBuffer & KERNEL_CODE_PROPERTY_RESERVED1) {2711 return createReservedKDBitsError(KERNEL_CODE_PROPERTY_RESERVED1,2712 amdhsa::KERNEL_CODE_PROPERTIES_OFFSET);2713 }2714 2715 return true;2716 2717 case amdhsa::KERNARG_PRELOAD_OFFSET:2718 using namespace amdhsa;2719 TwoByteBuffer = DE.getU16(Cursor);2720 if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_LENGTH) {2721 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_length",2722 KERNARG_PRELOAD_SPEC_LENGTH);2723 }2724 2725 if (TwoByteBuffer & KERNARG_PRELOAD_SPEC_OFFSET) {2726 PRINT_DIRECTIVE(".amdhsa_user_sgpr_kernarg_preload_offset",2727 KERNARG_PRELOAD_SPEC_OFFSET);2728 }2729 return true;2730 2731 case amdhsa::RESERVED3_OFFSET:2732 // 4 bytes from here are reserved, must be 0.2733 ReservedBytes = DE.getBytes(Cursor, 4);2734 for (int I = 0; I < 4; ++I) {2735 if (ReservedBytes[I] != 0)2736 return createReservedKDBytesError(amdhsa::RESERVED3_OFFSET, 4);2737 }2738 return true;2739 2740 default:2741 llvm_unreachable("Unhandled index. Case statements cover everything.");2742 return true;2743 }2744#undef PRINT_DIRECTIVE2745}2746 2747Expected<bool> AMDGPUDisassembler::decodeKernelDescriptor(2748 StringRef KdName, ArrayRef<uint8_t> Bytes, uint64_t KdAddress) const {2749 2750 // CP microcode requires the kernel descriptor to be 64 aligned.2751 if (Bytes.size() != 64 || KdAddress % 64 != 0)2752 return createStringError(std::errc::invalid_argument,2753 "kernel descriptor must be 64-byte aligned");2754 2755 // FIXME: We can't actually decode "in order" as is done below, as e.g. GFX102756 // requires us to know the setting of .amdhsa_wavefront_size32 in order to2757 // accurately produce .amdhsa_next_free_vgpr, and they appear in the wrong2758 // order. Workaround this by first looking up .amdhsa_wavefront_size32 here2759 // when required.2760 if (isGFX10Plus()) {2761 uint16_t KernelCodeProperties =2762 support::endian::read16(&Bytes[amdhsa::KERNEL_CODE_PROPERTIES_OFFSET],2763 llvm::endianness::little);2764 EnableWavefrontSize32 =2765 AMDHSA_BITS_GET(KernelCodeProperties,2766 amdhsa::KERNEL_CODE_PROPERTY_ENABLE_WAVEFRONT_SIZE32);2767 }2768 2769 std::string Kd;2770 raw_string_ostream KdStream(Kd);2771 KdStream << ".amdhsa_kernel " << KdName << '\n';2772 2773 DataExtractor::Cursor C(0);2774 while (C && C.tell() < Bytes.size()) {2775 Expected<bool> Res = decodeKernelDescriptorDirective(C, Bytes, KdStream);2776 2777 cantFail(C.takeError());2778 2779 if (!Res)2780 return Res;2781 }2782 KdStream << ".end_amdhsa_kernel\n";2783 outs() << KdStream.str();2784 return true;2785}2786 2787Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,2788 uint64_t &Size,2789 ArrayRef<uint8_t> Bytes,2790 uint64_t Address) const {2791 // Right now only kernel descriptor needs to be handled.2792 // We ignore all other symbols for target specific handling.2793 // TODO:2794 // Fix the spurious symbol issue for AMDGPU kernels. Exists for both Code2795 // Object V2 and V3 when symbols are marked protected.2796 2797 // amd_kernel_code_t for Code Object V2.2798 if (Symbol.Type == ELF::STT_AMDGPU_HSA_KERNEL) {2799 Size = 256;2800 return createStringError(std::errc::invalid_argument,2801 "code object v2 is not supported");2802 }2803 2804 // Code Object V3 kernel descriptors.2805 StringRef Name = Symbol.Name;2806 if (Symbol.Type == ELF::STT_OBJECT && Name.ends_with(StringRef(".kd"))) {2807 Size = 64; // Size = 64 regardless of success or failure.2808 return decodeKernelDescriptor(Name.drop_back(3), Bytes, Address);2809 }2810 2811 return false;2812}2813 2814const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,2815 int64_t Val) {2816 MCContext &Ctx = getContext();2817 MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);2818 // Note: only set value to Val on a new symbol in case an dissassembler2819 // has already been initialized in this context.2820 if (!Sym->isVariable()) {2821 Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));2822 } else {2823 int64_t Res = ~Val;2824 bool Valid = Sym->getVariableValue()->evaluateAsAbsolute(Res);2825 if (!Valid || Res != Val)2826 Ctx.reportWarning(SMLoc(), "unsupported redefinition of " + Id);2827 }2828 return MCSymbolRefExpr::create(Sym, Ctx);2829}2830 2831bool AMDGPUDisassembler::isBufferInstruction(const MCInst &MI) const {2832 const uint64_t TSFlags = MCII->get(MI.getOpcode()).TSFlags;2833 2834 // Check for MUBUF and MTBUF instructions2835 if (TSFlags & (SIInstrFlags::MTBUF | SIInstrFlags::MUBUF))2836 return true;2837 2838 // Check for SMEM buffer instructions (S_BUFFER_* instructions)2839 if ((TSFlags & SIInstrFlags::SMRD) && AMDGPU::getSMEMIsBuffer(MI.getOpcode()))2840 return true;2841 2842 return false;2843}2844 2845//===----------------------------------------------------------------------===//2846// AMDGPUSymbolizer2847//===----------------------------------------------------------------------===//2848 2849// Try to find symbol name for specified label2850bool AMDGPUSymbolizer::tryAddingSymbolicOperand(2851 MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value,2852 uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/,2853 uint64_t /*OpSize*/, uint64_t /*InstSize*/) {2854 2855 if (!IsBranch) {2856 return false;2857 }2858 2859 auto *Symbols = static_cast<SectionSymbolsTy *>(DisInfo);2860 if (!Symbols)2861 return false;2862 2863 auto Result = llvm::find_if(*Symbols, [Value](const SymbolInfoTy &Val) {2864 return Val.Addr == static_cast<uint64_t>(Value) &&2865 Val.Type == ELF::STT_NOTYPE;2866 });2867 if (Result != Symbols->end()) {2868 auto *Sym = Ctx.getOrCreateSymbol(Result->Name);2869 const auto *Add = MCSymbolRefExpr::create(Sym, Ctx);2870 Inst.addOperand(MCOperand::createExpr(Add));2871 return true;2872 }2873 // Add to list of referenced addresses, so caller can synthesize a label.2874 ReferencedAddresses.push_back(static_cast<uint64_t>(Value));2875 return false;2876}2877 2878void AMDGPUSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream,2879 int64_t Value,2880 uint64_t Address) {2881 llvm_unreachable("unimplemented");2882}2883 2884//===----------------------------------------------------------------------===//2885// Initialization2886//===----------------------------------------------------------------------===//2887 2888static MCSymbolizer *createAMDGPUSymbolizer(const Triple &/*TT*/,2889 LLVMOpInfoCallback /*GetOpInfo*/,2890 LLVMSymbolLookupCallback /*SymbolLookUp*/,2891 void *DisInfo,2892 MCContext *Ctx,2893 std::unique_ptr<MCRelocationInfo> &&RelInfo) {2894 return new AMDGPUSymbolizer(*Ctx, std::move(RelInfo), DisInfo);2895}2896 2897static MCDisassembler *createAMDGPUDisassembler(const Target &T,2898 const MCSubtargetInfo &STI,2899 MCContext &Ctx) {2900 return new AMDGPUDisassembler(STI, Ctx, T.createMCInstrInfo());2901}2902 2903extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void2904LLVMInitializeAMDGPUDisassembler() {2905 TargetRegistry::RegisterMCDisassembler(getTheGCNTarget(),2906 createAMDGPUDisassembler);2907 TargetRegistry::RegisterMCSymbolizer(getTheGCNTarget(),2908 createAMDGPUSymbolizer);2909}2910