diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-04 19:20:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:02:26 +0000 |
commit | 81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch) | |
tree | 311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp | |
parent | 5fff09660e06a66bed6482da9c70df328e16bbb6 (diff) | |
parent | 145449b1e420787bb99721a429341fa6be3adfb6 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp | 470 |
1 files changed, 329 insertions, 141 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp index e2186d4d533e..ccaf646008b1 100644 --- a/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ b/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -18,15 +18,20 @@ #include "Disassembler/AMDGPUDisassembler.h" #include "MCTargetDesc/AMDGPUMCTargetDesc.h" +#include "SIDefines.h" +#include "SIRegisterInfo.h" #include "TargetInfo/AMDGPUTargetInfo.h" #include "Utils/AMDGPUBaseInfo.h" #include "llvm-c/DisassemblerTypes.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDecoderOps.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixedLenDisassembler.h" -#include "llvm/MC/TargetRegistry.h" #include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/AMDHSAKernelDescriptor.h" using namespace llvm; @@ -70,7 +75,8 @@ static int insertNamedMCOperand(MCInst &MI, const MCOperand &Op, } static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm, - uint64_t Addr, const void *Decoder) { + uint64_t Addr, + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); // Our branches take a simm16, but we need two extra bits to account for the @@ -78,13 +84,13 @@ static DecodeStatus decodeSoppBrTarget(MCInst &Inst, unsigned Imm, APInt SignedOffset(18, Imm * 4, true); int64_t Offset = (SignedOffset.sext(64) + 4 + Addr).getSExtValue(); - if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2)) + if (DAsm->tryAddingSymbolicOperand(Inst, Offset, Addr, true, 2, 2, 0)) return MCDisassembler::Success; return addOperand(Inst, MCOperand::createImm(Imm)); } -static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, - uint64_t Addr, const void *Decoder) { +static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); int64_t Offset; if (DAsm->isVI()) { // VI supports 20-bit unsigned offsets. @@ -95,20 +101,19 @@ static DecodeStatus decodeSMEMOffset(MCInst &Inst, unsigned Imm, return addOperand(Inst, MCOperand::createImm(Offset)); } -static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, - uint64_t Addr, const void *Decoder) { +static DecodeStatus decodeBoolReg(MCInst &Inst, unsigned Val, uint64_t Addr, + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeBoolReg(Val)); } -#define DECODE_OPERAND(StaticDecoderName, DecoderName) \ -static DecodeStatus StaticDecoderName(MCInst &Inst, \ - unsigned Imm, \ - uint64_t /*Addr*/, \ - const void *Decoder) { \ - auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); \ - return addOperand(Inst, DAsm->DecoderName(Imm)); \ -} +#define DECODE_OPERAND(StaticDecoderName, DecoderName) \ + static DecodeStatus StaticDecoderName(MCInst &Inst, unsigned Imm, \ + uint64_t /*Addr*/, \ + const MCDisassembler *Decoder) { \ + auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); \ + return addOperand(Inst, DAsm->DecoderName(Imm)); \ + } #define DECODE_OPERAND_REG(RegClass) \ DECODE_OPERAND(Decode##RegClass##RegisterClass, decodeOperand_##RegClass) @@ -144,155 +149,151 @@ DECODE_OPERAND_REG(AReg_512) DECODE_OPERAND_REG(AReg_1024) DECODE_OPERAND_REG(AV_32) DECODE_OPERAND_REG(AV_64) +DECODE_OPERAND_REG(AV_128) +DECODE_OPERAND_REG(AVDst_128) +DECODE_OPERAND_REG(AVDst_512) -static DecodeStatus decodeOperand_VSrc16(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VSrc16(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm)); } -static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus decodeOperand_VSrcV216(MCInst &Inst, unsigned Imm, + uint64_t Addr, + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_VSrcV216(Imm)); } -static DecodeStatus decodeOperand_VSrcV232(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VSrcV232(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_VSrcV232(Imm)); } -static DecodeStatus decodeOperand_VS_16(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VS_16(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_VSrc16(Imm)); } -static DecodeStatus decodeOperand_VS_32(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VS_32(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_VS_32(Imm)); } -static DecodeStatus decodeOperand_AReg_64(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AReg_64(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW64, Imm | 512)); } -static DecodeStatus decodeOperand_AReg_128(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AReg_128(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW128, Imm | 512)); } -static DecodeStatus decodeOperand_AReg_256(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AReg_256(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW256, Imm | 512)); } -static DecodeStatus decodeOperand_AReg_512(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AReg_512(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW512, Imm | 512)); } -static DecodeStatus decodeOperand_AReg_1024(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AReg_1024(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW1024, Imm | 512)); } -static DecodeStatus decodeOperand_VReg_64(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VReg_64(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW64, Imm)); } -static DecodeStatus decodeOperand_VReg_128(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VReg_128(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW128, Imm)); } -static DecodeStatus decodeOperand_VReg_256(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VReg_256(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW256, Imm)); } -static DecodeStatus decodeOperand_VReg_512(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VReg_512(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW512, Imm)); } -static DecodeStatus decodeOperand_VReg_1024(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_VReg_1024(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW1024, Imm)); } static DecodeStatus decodeOperand_f32kimm(MCInst &Inst, unsigned Imm, - uint64_t Addr, const void *Decoder) { + uint64_t Addr, + const MCDisassembler *Decoder) { const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm)); } static DecodeStatus decodeOperand_f16kimm(MCInst &Inst, unsigned Imm, - uint64_t Addr, const void *Decoder) { + uint64_t Addr, + const MCDisassembler *Decoder) { const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); return addOperand(Inst, DAsm->decodeMandatoryLiteralConstant(Imm)); } -static DecodeStatus decodeOperand_VS_16_Deferred(MCInst &Inst, unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +decodeOperand_VS_16_Deferred(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); return addOperand( Inst, DAsm->decodeSrcOp(llvm::AMDGPUDisassembler::OPW16, Imm, true)); } -static DecodeStatus decodeOperand_VS_32_Deferred(MCInst &Inst, unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +decodeOperand_VS_32_Deferred(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); return addOperand( Inst, DAsm->decodeSrcOp(llvm::AMDGPUDisassembler::OPW32, Imm, true)); } +static DecodeStatus decodeOperandVOPDDstY(MCInst &Inst, unsigned Val, + uint64_t Addr, const void *Decoder) { + const auto *DAsm = static_cast<const AMDGPUDisassembler *>(Decoder); + return addOperand(Inst, DAsm->decodeVOPDDstYOp(Inst, Val)); +} + static bool IsAGPROperand(const MCInst &Inst, int OpIdx, const MCRegisterInfo *MRI) { if (OpIdx < 0) @@ -307,10 +308,9 @@ static bool IsAGPROperand(const MCInst &Inst, int OpIdx, return Reg >= AMDGPU::AGPR0 && Reg <= AMDGPU::AGPR255; } -static DecodeStatus decodeOperand_AVLdSt_Any(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_AVLdSt_Any(MCInst &Inst, unsigned Imm, AMDGPUDisassembler::OpWidthTy Opw, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); if (!DAsm->isGFX90A()) { Imm &= 511; @@ -342,54 +342,41 @@ static DecodeStatus decodeOperand_AVLdSt_Any(MCInst &Inst, return addOperand(Inst, DAsm->decodeSrcOp(Opw, Imm | 256)); } -static DecodeStatus DecodeAVLdSt_32RegisterClass(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +DecodeAVLdSt_32RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { return decodeOperand_AVLdSt_Any(Inst, Imm, AMDGPUDisassembler::OPW32, Decoder); } -static DecodeStatus DecodeAVLdSt_64RegisterClass(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +DecodeAVLdSt_64RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { return decodeOperand_AVLdSt_Any(Inst, Imm, AMDGPUDisassembler::OPW64, Decoder); } -static DecodeStatus DecodeAVLdSt_96RegisterClass(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +DecodeAVLdSt_96RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { return decodeOperand_AVLdSt_Any(Inst, Imm, AMDGPUDisassembler::OPW96, Decoder); } -static DecodeStatus DecodeAVLdSt_128RegisterClass(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { +static DecodeStatus +DecodeAVLdSt_128RegisterClass(MCInst &Inst, unsigned Imm, uint64_t Addr, + const MCDisassembler *Decoder) { return decodeOperand_AVLdSt_Any(Inst, Imm, AMDGPUDisassembler::OPW128, Decoder); } -static DecodeStatus decodeOperand_SReg_32(MCInst &Inst, - unsigned Imm, +static DecodeStatus decodeOperand_SReg_32(MCInst &Inst, unsigned Imm, uint64_t Addr, - const void *Decoder) { + const MCDisassembler *Decoder) { auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); return addOperand(Inst, DAsm->decodeOperand_SReg_32(Imm)); } -static DecodeStatus decodeOperand_VGPR_32(MCInst &Inst, - unsigned Imm, - uint64_t Addr, - const void *Decoder) { - auto DAsm = static_cast<const AMDGPUDisassembler*>(Decoder); - return addOperand(Inst, DAsm->decodeSrcOp(AMDGPUDisassembler::OPW32, Imm)); -} - #define DECODE_SDWA(DecName) \ DECODE_OPERAND(decodeSDWA##DecName, decodeSDWA##DecName) @@ -410,21 +397,15 @@ template <typename T> static inline T eatBytes(ArrayRef<uint8_t>& Bytes) { return Res; } -DecodeStatus AMDGPUDisassembler::tryDecodeInst(const uint8_t* Table, - MCInst &MI, - uint64_t Inst, - uint64_t Address) const { - assert(MI.getOpcode() == 0); - assert(MI.getNumOperands() == 0); - MCInst TmpInst; - HasLiteral = false; - const auto SavedBytes = Bytes; - if (decodeInstruction(Table, TmpInst, Inst, Address, this, STI)) { - MI = TmpInst; - return MCDisassembler::Success; - } - Bytes = SavedBytes; - return MCDisassembler::Fail; +static inline DecoderUInt128 eat12Bytes(ArrayRef<uint8_t> &Bytes) { + assert(Bytes.size() >= 12); + uint64_t Lo = support::endian::read<uint64_t, support::endianness::little>( + Bytes.data()); + Bytes = Bytes.slice(8); + uint64_t Hi = support::endian::read<uint32_t, support::endianness::little>( + Bytes.data()); + Bytes = Bytes.slice(4); + return DecoderUInt128(Lo, Hi); } // The disassembler is greedy, so we need to check FI operand value to @@ -457,6 +438,29 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, // Try to decode DPP and SDWA first to solve conflict with VOP1 and VOP2 // encodings + if (isGFX11Plus() && Bytes.size() >= 12 ) { + DecoderUInt128 DecW = eat12Bytes(Bytes); + Res = tryDecodeInst(DecoderTableDPP8GFX1196, MI, DecW, + Address); + if (Res && convertDPP8Inst(MI) == MCDisassembler::Success) + break; + MI = MCInst(); // clear + Res = tryDecodeInst(DecoderTableDPPGFX1196, MI, DecW, + Address); + if (Res) { + if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOP3P) + convertVOP3PDPPInst(MI); + else if (AMDGPU::isVOPC64DPP(MI.getOpcode())) + convertVOPCDPPInst(MI); + break; + } + Res = tryDecodeInst(DecoderTableGFX1196, MI, DecW, Address); + if (Res) + break; + } + // Reinitialize Bytes + Bytes = Bytes_.slice(0, MaxInstBytesNum); + if (Bytes.size() >= 8) { const uint64_t QW = eatBytes<uint64_t>(Bytes); @@ -475,12 +479,23 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, Res = tryDecodeInst(DecoderTableDPP864, MI, QW, Address); if (Res && convertDPP8Inst(MI) == MCDisassembler::Success) break; + MI = MCInst(); // clear + Res = tryDecodeInst(DecoderTableDPP8GFX1164, MI, QW, Address); + if (Res && convertDPP8Inst(MI) == MCDisassembler::Success) + break; MI = MCInst(); // clear Res = tryDecodeInst(DecoderTableDPP64, MI, QW, Address); if (Res) break; + Res = tryDecodeInst(DecoderTableDPPGFX1164, MI, QW, Address); + if (Res) { + if (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VOPC) + convertVOPCDPPInst(MI); + break; + } + Res = tryDecodeInst(DecoderTableSDWA64, MI, QW, Address); if (Res) { IsSDWA = true; break; } @@ -535,6 +550,9 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, Res = tryDecodeInst(DecoderTableGFX1032, MI, DW, Address); if (Res) break; + Res = tryDecodeInst(DecoderTableGFX1132, MI, DW, Address); + if (Res) break; + if (Bytes.size() < 4) break; const uint64_t QW = ((uint64_t)eatBytes<uint32_t>(Bytes) << 32) | DW; @@ -554,6 +572,13 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, if (Res) break; Res = tryDecodeInst(DecoderTableGFX1064, MI, QW, Address); + if (Res) break; + + Res = tryDecodeInst(DecoderTableGFX1164, MI, QW, Address); + if (Res) + break; + + Res = tryDecodeInst(DecoderTableWMMAGFX1164, MI, QW, Address); } while (false); if (Res && (MI.getOpcode() == AMDGPU::V_MAC_F32_e64_vi || @@ -565,8 +590,11 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, MI.getOpcode() == AMDGPU::V_FMAC_F64_e64_gfx90a || MI.getOpcode() == AMDGPU::V_FMAC_F32_e64_vi || MI.getOpcode() == AMDGPU::V_FMAC_F32_e64_gfx10 || + MI.getOpcode() == AMDGPU::V_FMAC_F32_e64_gfx11 || MI.getOpcode() == AMDGPU::V_FMAC_LEGACY_F32_e64_gfx10 || - MI.getOpcode() == AMDGPU::V_FMAC_F16_e64_gfx10)) { + MI.getOpcode() == AMDGPU::V_FMAC_DX9_ZERO_F32_e64_gfx11 || + MI.getOpcode() == AMDGPU::V_FMAC_F16_e64_gfx10 || + MI.getOpcode() == AMDGPU::V_FMAC_F16_e64_gfx11)) { // Insert dummy unused src2_modifiers. insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::src2_modifiers); @@ -625,8 +653,10 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, Res = MCDisassembler::Fail; } else { for (unsigned i = 0; i < NSAArgs; ++i) { - MI.insert(MI.begin() + VAddr0Idx + 1 + i, - decodeOperand_VGPR_32(Bytes[i])); + const unsigned VAddrIdx = VAddr0Idx + 1 + i; + auto VAddrRCID = MCII->get(MI.getOpcode()).OpInfo[VAddrIdx].RegClass; + MI.insert(MI.begin() + VAddrIdx, + createRegOperand(VAddrRCID, Bytes[i])); } Bytes = Bytes.slice(4 * NSAWords); } @@ -636,6 +666,12 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, Res = convertMIMGInst(MI); } + if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::EXP)) + Res = convertEXPInst(MI); + + if (Res && (MCII->get(MI.getOpcode()).TSFlags & SIInstrFlags::VINTERP)) + Res = convertVINTERPInst(MI); + if (Res && IsSDWA) Res = convertSDWAInst(MI); @@ -667,6 +703,28 @@ DecodeStatus AMDGPUDisassembler::getInstruction(MCInst &MI, uint64_t &Size, return Res; } +DecodeStatus AMDGPUDisassembler::convertEXPInst(MCInst &MI) const { + if (STI.getFeatureBits()[AMDGPU::FeatureGFX11]) { + // The MCInst still has these fields even though they are no longer encoded + // in the GFX11 instruction. + insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vm); + insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::compr); + } + return MCDisassembler::Success; +} + +DecodeStatus AMDGPUDisassembler::convertVINTERPInst(MCInst &MI) const { + if (MI.getOpcode() == AMDGPU::V_INTERP_P10_F16_F32_inreg_gfx11 || + MI.getOpcode() == AMDGPU::V_INTERP_P10_RTZ_F16_F32_inreg_gfx11 || + MI.getOpcode() == AMDGPU::V_INTERP_P2_F16_F32_inreg_gfx11 || + MI.getOpcode() == AMDGPU::V_INTERP_P2_RTZ_F16_F32_inreg_gfx11) { + // The MCInst has this field that is not directly encoded in the + // instruction. + insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::op_sel); + } + return MCDisassembler::Success; +} + DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const { if (STI.getFeatureBits()[AMDGPU::FeatureGFX9] || STI.getFeatureBits()[AMDGPU::FeatureGFX10]) { @@ -692,18 +750,23 @@ DecodeStatus AMDGPUDisassembler::convertSDWAInst(MCInst &MI) const { DecodeStatus AMDGPUDisassembler::convertDPP8Inst(MCInst &MI) const { unsigned Opc = MI.getOpcode(); unsigned DescNumOps = MCII->get(Opc).getNumOperands(); - - // Insert dummy unused src modifiers. - if (MI.getNumOperands() < DescNumOps && - AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) - insertNamedMCOperand(MI, MCOperand::createImm(0), - AMDGPU::OpName::src0_modifiers); - - if (MI.getNumOperands() < DescNumOps && - AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1_modifiers) != -1) - insertNamedMCOperand(MI, MCOperand::createImm(0), - AMDGPU::OpName::src1_modifiers); - + if (MCII->get(Opc).TSFlags & SIInstrFlags::VOP3P) { + convertVOP3PDPPInst(MI); + } else if ((MCII->get(Opc).TSFlags & SIInstrFlags::VOPC) || + AMDGPU::isVOPC64DPP(Opc)) { + convertVOPCDPPInst(MI); + } else { + // Insert dummy unused src modifiers. + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(0), + AMDGPU::OpName::src0_modifiers); + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1_modifiers) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(0), + AMDGPU::OpName::src1_modifiers); + } return isValidDPP8(MI) ? MCDisassembler::Success : MCDisassembler::SoftFail; } @@ -745,7 +808,7 @@ DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { bool IsNSA = false; unsigned AddrSize = Info->VAddrDwords; - if (STI.getFeatureBits()[AMDGPU::FeatureGFX10]) { + if (isGFX10Plus()) { unsigned DimIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::dim); int A16Idx = @@ -757,7 +820,8 @@ DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { AddrSize = AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, AMDGPU::hasG16(STI)); - IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA; + IsNSA = Info->MIMGEncoding == AMDGPU::MIMGEncGfx10NSA || + Info->MIMGEncoding == AMDGPU::MIMGEncGfx11NSA; if (!IsNSA) { if (AddrSize > 8) AddrSize = 16; @@ -808,9 +872,9 @@ DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { } } + // If not using NSA on GFX10+, widen address register to correct size. unsigned NewVAddr0 = AMDGPU::NoRegister; - if (STI.getFeatureBits()[AMDGPU::FeatureGFX10] && !IsNSA && - AddrSize != Info->VAddrDwords) { + if (isGFX10Plus() && !IsNSA && AddrSize != Info->VAddrDwords) { unsigned VAddr0 = MI.getOperand(VAddr0Idx).getReg(); unsigned VAddrSub0 = MRI.getSubReg(VAddr0, AMDGPU::sub0); VAddr0 = (VAddrSub0 != 0) ? VAddrSub0 : VAddr0; @@ -844,11 +908,84 @@ DecodeStatus AMDGPUDisassembler::convertMIMGInst(MCInst &MI) const { return MCDisassembler::Success; } +// Opsel and neg bits are used in src_modifiers and standalone operands. Autogen +// decoder only adds to src_modifiers, so manually add the bits to the other +// operands. +DecodeStatus AMDGPUDisassembler::convertVOP3PDPPInst(MCInst &MI) const { + unsigned Opc = MI.getOpcode(); + unsigned DescNumOps = MCII->get(Opc).getNumOperands(); + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(0), AMDGPU::OpName::vdst_in); + + const int ModOps[] = {AMDGPU::OpName::src0_modifiers, + AMDGPU::OpName::src1_modifiers, + AMDGPU::OpName::src2_modifiers}; + unsigned OpSel = 0; + unsigned OpSelHi = 0; + unsigned NegLo = 0; + unsigned NegHi = 0; + for (int J = 0; J < 3; ++J) { + int OpIdx = AMDGPU::getNamedOperandIdx(Opc, ModOps[J]); + if (OpIdx == -1) + break; + unsigned Val = MI.getOperand(OpIdx).getImm(); + + OpSel |= !!(Val & SISrcMods::OP_SEL_0) << J; + OpSelHi |= !!(Val & SISrcMods::OP_SEL_1) << J; + NegLo |= !!(Val & SISrcMods::NEG) << J; + NegHi |= !!(Val & SISrcMods::NEG_HI) << J; + } + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(OpSel), + AMDGPU::OpName::op_sel); + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::op_sel_hi) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(OpSelHi), + AMDGPU::OpName::op_sel_hi); + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_lo) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(NegLo), + AMDGPU::OpName::neg_lo); + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::neg_hi) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(NegHi), + AMDGPU::OpName::neg_hi); + + return MCDisassembler::Success; +} + +// Create dummy old operand and insert optional operands +DecodeStatus AMDGPUDisassembler::convertVOPCDPPInst(MCInst &MI) const { + unsigned Opc = MI.getOpcode(); + unsigned DescNumOps = MCII->get(Opc).getNumOperands(); + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::old) != -1) + insertNamedMCOperand(MI, MCOperand::createReg(0), AMDGPU::OpName::old); + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0_modifiers) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(0), + AMDGPU::OpName::src0_modifiers); + + if (MI.getNumOperands() < DescNumOps && + AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1_modifiers) != -1) + insertNamedMCOperand(MI, MCOperand::createImm(0), + AMDGPU::OpName::src1_modifiers); + return MCDisassembler::Success; +} + DecodeStatus AMDGPUDisassembler::convertFMAanyK(MCInst &MI, int ImmLitIdx) const { assert(HasLiteral && "Should have decoded a literal"); const MCInstrDesc &Desc = MCII->get(MI.getOpcode()); unsigned DescNumOps = Desc.getNumOperands(); + insertNamedMCOperand(MI, MCOperand::createImm(Literal), + AMDGPU::OpName::immDeferred); assert(DescNumOps == MI.getNumOperands()); for (unsigned I = 0; I < DescNumOps; ++I) { auto &Op = MI.getOperand(I); @@ -1001,6 +1138,22 @@ MCOperand AMDGPUDisassembler::decodeOperand_AV_64(unsigned Val) const { return decodeSrcOp(OPW64, Val); } +MCOperand AMDGPUDisassembler::decodeOperand_AV_128(unsigned Val) const { + return decodeSrcOp(OPW128, Val); +} + +MCOperand AMDGPUDisassembler::decodeOperand_AVDst_128(unsigned Val) const { + using namespace AMDGPU::EncValues; + assert((Val & IS_VGPR) == 0); // Val{8} is not encoded but assumed to be 1. + return decodeSrcOp(OPW128, Val | IS_VGPR); +} + +MCOperand AMDGPUDisassembler::decodeOperand_AVDst_512(unsigned Val) const { + using namespace AMDGPU::EncValues; + assert((Val & IS_VGPR) == 0); // Val{8} is not encoded but assumed to be 1. + return decodeSrcOp(OPW512, Val | IS_VGPR); +} + MCOperand AMDGPUDisassembler::decodeOperand_VReg_64(unsigned Val) const { return createRegOperand(AMDGPU::VReg_64RegClassID, Val); } @@ -1075,6 +1228,9 @@ MCOperand AMDGPUDisassembler::decodeOperand_SReg_512(unsigned Val) const { MCOperand AMDGPUDisassembler::decodeMandatoryLiteralConstant(unsigned Val) const { if (HasLiteral) { + assert( + AMDGPU::hasVOPD(STI) && + "Should only decode multiple kimm with VOPD, check VSrc operand types"); if (Literal != Val) return errOperand(Val, "More than one unique literal is illegal"); } @@ -1367,6 +1523,20 @@ MCOperand AMDGPUDisassembler::decodeDstOp(const OpWidthTy Width, unsigned Val) c llvm_unreachable("unknown dst register"); } +// Bit 0 of DstY isn't stored in the instruction, because it's always the +// opposite of bit 0 of DstX. +MCOperand AMDGPUDisassembler::decodeVOPDDstYOp(MCInst &Inst, + unsigned Val) const { + int VDstXInd = + AMDGPU::getNamedOperandIdx(Inst.getOpcode(), AMDGPU::OpName::vdstX); + assert(VDstXInd != -1); + assert(Inst.getOperand(VDstXInd).isReg()); + unsigned XDstReg = MRI.getEncodingValue(Inst.getOperand(VDstXInd).getReg()); + Val |= ~XDstReg & 1; + auto Width = llvm::AMDGPUDisassembler::OPW32; + return createRegOperand(getVgprClassId(Width), Val); +} + MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { using namespace AMDGPU; @@ -1381,8 +1551,10 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg32(unsigned Val) const { case 109: return createRegOperand(TBA_HI); case 110: return createRegOperand(TMA_LO); case 111: return createRegOperand(TMA_HI); - case 124: return createRegOperand(M0); - case 125: return createRegOperand(SGPR_NULL); + case 124: + return isGFX11Plus() ? createRegOperand(SGPR_NULL) : createRegOperand(M0); + case 125: + return isGFX11Plus() ? createRegOperand(M0) : createRegOperand(SGPR_NULL); case 126: return createRegOperand(EXEC_LO); case 127: return createRegOperand(EXEC_HI); case 235: return createRegOperand(SRC_SHARED_BASE); @@ -1408,7 +1580,14 @@ MCOperand AMDGPUDisassembler::decodeSpecialReg64(unsigned Val) const { case 106: return createRegOperand(VCC); case 108: return createRegOperand(TBA); case 110: return createRegOperand(TMA); - case 125: return createRegOperand(SGPR_NULL); + case 124: + if (isGFX11Plus()) + return createRegOperand(SGPR_NULL); + break; + case 125: + if (!isGFX11Plus()) + return createRegOperand(SGPR_NULL); + break; case 126: return createRegOperand(EXEC); case 235: return createRegOperand(SRC_SHARED_BASE); case 236: return createRegOperand(SRC_SHARED_LIMIT); @@ -1522,6 +1701,15 @@ bool AMDGPUDisassembler::isGFX10Plus() const { return AMDGPU::isGFX10Plus(STI); } +bool AMDGPUDisassembler::isGFX11() const { + return STI.getFeatureBits()[AMDGPU::FeatureGFX11]; +} + +bool AMDGPUDisassembler::isGFX11Plus() const { + return AMDGPU::isGFX11Plus(STI); +} + + bool AMDGPUDisassembler::hasArchitectedFlatScratch() const { return STI.getFeatureBits()[AMDGPU::FeatureArchitectedFlatScratch]; } @@ -1888,10 +2076,10 @@ AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol, uint64_t &Size, //===----------------------------------------------------------------------===// // Try to find symbol name for specified label -bool AMDGPUSymbolizer::tryAddingSymbolicOperand(MCInst &Inst, - raw_ostream &/*cStream*/, int64_t Value, - uint64_t /*Address*/, bool IsBranch, - uint64_t /*Offset*/, uint64_t /*InstSize*/) { +bool AMDGPUSymbolizer::tryAddingSymbolicOperand( + MCInst &Inst, raw_ostream & /*cStream*/, int64_t Value, + uint64_t /*Address*/, bool IsBranch, uint64_t /*Offset*/, + uint64_t /*OpSize*/, uint64_t /*InstSize*/) { if (!IsBranch) { return false; |