aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-04 19:20:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-08 19:02:26 +0000
commit81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch)
tree311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
parent5fff09660e06a66bed6482da9c70df328e16bbb6 (diff)
parent145449b1e420787bb99721a429341fa6be3adfb6 (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.cpp470
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;