rpcsx/rpcs3/Emu/CPU/CPUDisAsm.h

126 lines
2.5 KiB
C
Raw Normal View History

#pragma once
#include <string>
#include <limits>
#include "Utilities/StrFmt.h"
2021-01-22 09:11:54 +01:00
enum class cpu_disasm_mode
{
2021-01-22 09:11:54 +01:00
dump,
interpreter,
normal,
compiler_elf,
list, // RSX exclusive
};
2021-01-22 09:11:54 +01:00
class cpu_thread;
class CPUDisAsm
{
protected:
2021-03-30 17:31:46 +02:00
const cpu_disasm_mode m_mode{};
const std::add_pointer_t<const u8> m_offset{};
const std::add_pointer_t<const cpu_thread> m_cpu{};
u32 m_op = 0;
void Write(const std::string& value)
{
switch (m_mode)
{
2021-01-22 09:11:54 +01:00
case cpu_disasm_mode::dump:
2020-11-10 15:57:06 +01:00
{
last_opcode = fmt::format("\t%08x:\t%02x %02x %02x %02x\t%s\n", dump_pc,
static_cast<u8>(m_op >> 24),
static_cast<u8>(m_op >> 16),
static_cast<u8>(m_op >> 8),
static_cast<u8>(m_op >> 0), value);
2020-11-10 15:57:06 +01:00
break;
}
2021-01-22 09:11:54 +01:00
case cpu_disasm_mode::interpreter:
2020-11-10 15:57:06 +01:00
{
last_opcode = fmt::format("[%08x] %02x %02x %02x %02x: %s", dump_pc,
static_cast<u8>(m_op >> 24),
static_cast<u8>(m_op >> 16),
static_cast<u8>(m_op >> 8),
static_cast<u8>(m_op >> 0), value);
2020-11-10 15:57:06 +01:00
break;
}
2021-01-22 09:11:54 +01:00
case cpu_disasm_mode::compiler_elf:
2020-11-10 15:57:06 +01:00
{
last_opcode = value + '\n';
break;
}
2021-01-22 09:11:54 +01:00
case cpu_disasm_mode::normal:
2020-11-10 15:57:06 +01:00
{
last_opcode = value;
break;
}
default: fmt::throw_exception("Unreachable");
}
}
public:
2021-03-30 17:31:46 +02:00
std::string last_opcode{};
u32 dump_pc{};
2021-01-22 09:11:54 +01:00
template <typename T, std::enable_if_t<std::is_base_of_v<CPUDisAsm, T>, int> = 0>
static T copy_and_change_mode(const T& dis, cpu_disasm_mode mode)
{
return T{mode, dis.m_offset, dis.m_cpu};
}
protected:
2021-01-22 09:11:54 +01:00
CPUDisAsm(cpu_disasm_mode mode, const u8* offset, const cpu_thread* cpu = nullptr)
: m_mode(mode)
2020-12-16 07:53:59 +01:00
, m_offset(offset)
2021-01-22 09:11:54 +01:00
, m_cpu(cpu)
{
}
2021-03-30 17:31:46 +02:00
CPUDisAsm(const CPUDisAsm&) = delete;
CPUDisAsm& operator=(const CPUDisAsm&) = delete;
virtual ~CPUDisAsm() = default;
virtual u32 DisAsmBranchTarget(s32 /*imm*/);
// TODO: Add builtin fmt helpper for best performance
template <typename T, std::enable_if_t<std::is_integral_v<T>, int> = 0>
static std::string SignedHex(T value)
{
const auto v = static_cast<std::make_signed_t<T>>(value);
if (v == std::numeric_limits<std::make_signed_t<T>>::min())
{
// for INTx_MIN
return fmt::format("-0x%x", v);
}
const auto av = std::abs(v);
if (av < 10)
{
// Does not need hex
return fmt::format("%d", v);
}
return fmt::format("%s%s", v < 0 ? "-" : "", av);
}
2020-11-10 15:57:06 +01:00
std::string FixOp(std::string op) const
{
2021-01-22 09:11:54 +01:00
if (m_mode != cpu_disasm_mode::normal)
2020-11-10 15:57:06 +01:00
{
2020-12-18 08:39:54 +01:00
op.resize(std::max<usz>(op.length(), 10), ' ');
2020-11-10 15:57:06 +01:00
}
return op;
}
2016-04-14 00:59:00 +02:00
public:
virtual u32 disasm(u32 pc) = 0;
2013-11-19 11:30:58 +01:00
};