summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp')
-rw-r--r--llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
index 05063c6c321a..76a559c9443b 100644
--- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
+++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp
@@ -21,6 +21,7 @@
#include "SIDefines.h"
#include "SIRegisterInfo.h"
#include "TargetInfo/AMDGPUTargetInfo.h"
+#include "Utils/AMDGPUAsmUtils.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm-c/DisassemblerTypes.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -52,6 +53,13 @@ AMDGPUDisassembler::AMDGPUDisassembler(const MCSubtargetInfo &STI,
// ToDo: AMDGPUDisassembler supports only VI ISA.
if (!STI.hasFeature(AMDGPU::FeatureGCN3Encoding) && !isGFX10Plus())
report_fatal_error("Disassembly not yet supported for subtarget");
+
+ for (auto [Symbol, Code] : AMDGPU::UCVersion::getGFXVersions())
+ createConstantSymbolExpr(Symbol, Code);
+
+ UCVersionW64Expr = createConstantSymbolExpr("UC_VERSION_W64_BIT", 0x2000);
+ UCVersionW32Expr = createConstantSymbolExpr("UC_VERSION_W32_BIT", 0x4000);
+ UCVersionMDPExpr = createConstantSymbolExpr("UC_VERSION_MDP_BIT", 0x8000);
}
void AMDGPUDisassembler::setABIVersion(unsigned Version) {
@@ -421,6 +429,13 @@ DECODE_SDWA(Src32)
DECODE_SDWA(Src16)
DECODE_SDWA(VopcDst)
+static DecodeStatus decodeVersionImm(MCInst &Inst, unsigned Imm,
+ uint64_t /* Addr */,
+ const MCDisassembler *Decoder) {
+ auto DAsm = static_cast<const AMDGPUDisassembler *>(Decoder);
+ return addOperand(Inst, DAsm->decodeVersionImm(Imm));
+}
+
#include "AMDGPUGenDisassemblerTables.inc"
//===----------------------------------------------------------------------===//
@@ -1727,6 +1742,41 @@ MCOperand AMDGPUDisassembler::decodeDpp8FI(unsigned Val) const {
return MCOperand::createImm(Val);
}
+MCOperand AMDGPUDisassembler::decodeVersionImm(unsigned Imm) const {
+ using VersionField = AMDGPU::EncodingField<7, 0>;
+ using W64Bit = AMDGPU::EncodingBit<13>;
+ using W32Bit = AMDGPU::EncodingBit<14>;
+ using MDPBit = AMDGPU::EncodingBit<15>;
+ using Encoding = AMDGPU::EncodingFields<VersionField, W64Bit, W32Bit, MDPBit>;
+
+ auto [Version, W64, W32, MDP] = Encoding::decode(Imm);
+
+ // Decode into a plain immediate if any unused bits are raised.
+ if (Encoding::encode(Version, W64, W32, MDP) != Imm)
+ return MCOperand::createImm(Imm);
+
+ const auto &Versions = AMDGPU::UCVersion::getGFXVersions();
+ auto I = find_if(Versions,
+ [Version = Version](const AMDGPU::UCVersion::GFXVersion &V) {
+ return V.Code == Version;
+ });
+ MCContext &Ctx = getContext();
+ const MCExpr *E;
+ if (I == Versions.end())
+ E = MCConstantExpr::create(Version, Ctx);
+ else
+ E = MCSymbolRefExpr::create(Ctx.getOrCreateSymbol(I->Symbol), Ctx);
+
+ if (W64)
+ E = MCBinaryExpr::createOr(E, UCVersionW64Expr, Ctx);
+ if (W32)
+ E = MCBinaryExpr::createOr(E, UCVersionW32Expr, Ctx);
+ if (MDP)
+ E = MCBinaryExpr::createOr(E, UCVersionMDPExpr, Ctx);
+
+ return MCOperand::createExpr(E);
+}
+
bool AMDGPUDisassembler::isVI() const {
return STI.hasFeature(AMDGPU::FeatureVolcanicIslands);
}
@@ -2312,6 +2362,15 @@ Expected<bool> AMDGPUDisassembler::onSymbolStart(SymbolInfoTy &Symbol,
return false;
}
+const MCExpr *AMDGPUDisassembler::createConstantSymbolExpr(StringRef Id,
+ int64_t Val) {
+ MCContext &Ctx = getContext();
+ MCSymbol *Sym = Ctx.getOrCreateSymbol(Id);
+ assert(!Sym->isVariable());
+ Sym->setVariableValue(MCConstantExpr::create(Val, Ctx));
+ return MCSymbolRefExpr::create(Sym, Ctx);
+}
+
//===----------------------------------------------------------------------===//
// AMDGPUSymbolizer
//===----------------------------------------------------------------------===//