mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
Debugger/Disasm: Name PPU Syscalls
This commit is contained in:
parent
2821eb7397
commit
34c36c73ee
3 changed files with 150 additions and 1 deletions
|
@ -1,11 +1,16 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "PPUDisAsm.h"
|
#include "PPUDisAsm.h"
|
||||||
#include "PPUFunction.h"
|
#include "PPUFunction.h"
|
||||||
|
#include "PPUAnalyser.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
|
||||||
const ppu_decoder<PPUDisAsm> s_ppu_disasm;
|
const ppu_decoder<PPUDisAsm> s_ppu_disasm;
|
||||||
|
const ppu_decoder<ppu_itype> s_ppu_itype;
|
||||||
|
|
||||||
extern const std::unordered_map<u32, std::string_view>& get_exported_function_names_as_addr_indexed_map();
|
extern const std::unordered_map<u32, std::string_view>& get_exported_function_names_as_addr_indexed_map();
|
||||||
|
|
||||||
|
enum class ppu_syscall_code : u64;
|
||||||
|
|
||||||
u32 PPUDisAsm::disasm(u32 pc)
|
u32 PPUDisAsm::disasm(u32 pc)
|
||||||
{
|
{
|
||||||
dump_pc = pc;
|
dump_pc = pc;
|
||||||
|
@ -14,6 +19,11 @@ u32 PPUDisAsm::disasm(u32 pc)
|
||||||
m_op = op;
|
m_op = op;
|
||||||
(this->*(s_ppu_disasm.decode(m_op)))({ m_op });
|
(this->*(s_ppu_disasm.decode(m_op)))({ m_op });
|
||||||
|
|
||||||
|
if (m_mode != cpu_disasm_mode::interpreter && m_mode != cpu_disasm_mode::normal)
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
const auto& map = get_exported_function_names_as_addr_indexed_map();
|
const auto& map = get_exported_function_names_as_addr_indexed_map();
|
||||||
|
|
||||||
if (auto it = map.find(pc); it != map.end())
|
if (auto it = map.find(pc); it != map.end())
|
||||||
|
@ -25,6 +35,137 @@ u32 PPUDisAsm::disasm(u32 pc)
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<bool, u64> PPUDisAsm::try_get_const_gpr_value(u32 reg, u32 pc) const
|
||||||
|
{
|
||||||
|
if (m_mode != cpu_disasm_mode::interpreter && m_mode != cpu_disasm_mode::normal)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc == umax)
|
||||||
|
{
|
||||||
|
pc = dump_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vm::check_addr(pc, vm::page_executable))
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan PPU executable memory backwards until unmapped or non-executable memory block is encountered
|
||||||
|
|
||||||
|
for (u32 i = pc - 4; vm::check_addr(i, vm::page_executable); i -= 4)
|
||||||
|
{
|
||||||
|
const u32 opcode = *reinterpret_cast<const be_t<u32>*>(m_offset + i);
|
||||||
|
const ppu_opcode_t op{ opcode };
|
||||||
|
|
||||||
|
const auto type = s_ppu_itype.decode(opcode);
|
||||||
|
|
||||||
|
auto is_branch = [](enum ppu_itype::type itype)
|
||||||
|
{
|
||||||
|
return itype == ppu_itype::BC || itype == ppu_itype::B || itype == ppu_itype::BCLR || itype == ppu_itype::BCCTR;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (is_branch(type) || type == ppu_itype::UNK)
|
||||||
|
{
|
||||||
|
// TODO: Detect calls, ignore them if reg is a non-volatile register
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get constant register value
|
||||||
|
#define GET_CONST_REG(var, reg) \
|
||||||
|
{\
|
||||||
|
/* Search for the constant value of the register*/\
|
||||||
|
const auto [is_const, value] = try_get_const_gpr_value(reg, i);\
|
||||||
|
\
|
||||||
|
if (!is_const)\
|
||||||
|
{\
|
||||||
|
/* Cannot compute constant value if register is not constant*/\
|
||||||
|
return {};\
|
||||||
|
}\
|
||||||
|
\
|
||||||
|
var = value;\
|
||||||
|
} void() /*<- Require a semicolon*/
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ppu_itype::ADDI:
|
||||||
|
{
|
||||||
|
if (op.rd != reg)
|
||||||
|
{
|
||||||
|
// Destination register is not relevant to us
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 reg_ra = 0;
|
||||||
|
|
||||||
|
if (op.ra)
|
||||||
|
{
|
||||||
|
GET_CONST_REG(reg_ra, op.ra);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { true, reg_ra + op.simm16 };
|
||||||
|
}
|
||||||
|
case ppu_itype::ADDIS:
|
||||||
|
{
|
||||||
|
if (op.rd != reg)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 reg_ra = 0;
|
||||||
|
|
||||||
|
if (op.ra)
|
||||||
|
{
|
||||||
|
GET_CONST_REG(reg_ra, op.ra);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { true, reg_ra + op.simm16 * 65536 };
|
||||||
|
}
|
||||||
|
case ppu_itype::ORI:
|
||||||
|
{
|
||||||
|
if (op.ra != reg)
|
||||||
|
{
|
||||||
|
// Destination register is not relevant to us
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 reg_rs = 0;
|
||||||
|
|
||||||
|
GET_CONST_REG(reg_rs, op.rs);
|
||||||
|
|
||||||
|
return { true, reg_rs | op.uimm16 };
|
||||||
|
}
|
||||||
|
case ppu_itype::ORIS:
|
||||||
|
{
|
||||||
|
if (op.ra != reg)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 reg_rs = 0;
|
||||||
|
|
||||||
|
GET_CONST_REG(reg_rs, op.rs);
|
||||||
|
|
||||||
|
return { true, reg_rs | (u64{op.uimm16} << 16)};
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// Ordinary test
|
||||||
|
// TODO: Proper detection of destination register(s) modification (if there are any)
|
||||||
|
if (op.ra == reg || op.rd == reg)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
constexpr std::pair<const char*, char> get_BC_info(u32 bo, u32 bi)
|
constexpr std::pair<const char*, char> get_BC_info(u32 bo, u32 bi)
|
||||||
{
|
{
|
||||||
std::pair<const char*, char> info{};
|
std::pair<const char*, char> info{};
|
||||||
|
@ -999,6 +1140,13 @@ void PPUDisAsm::SC(ppu_opcode_t op)
|
||||||
return UNK(op);
|
return UNK(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to get constant syscall index
|
||||||
|
if (auto [is_const, index] = try_get_const_gpr_value(11); is_const && index < 1024u)
|
||||||
|
{
|
||||||
|
Write(fmt::format("sc #%s", ppu_syscall_code{index}));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Write("sc");
|
Write("sc");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -287,6 +287,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
u32 disasm(u32 pc) override;
|
u32 disasm(u32 pc) override;
|
||||||
|
std::pair<bool, u64> try_get_const_gpr_value(u32 reg, u32 pc = -1) const;
|
||||||
|
|
||||||
void MFVSCR(ppu_opcode_t op);
|
void MFVSCR(ppu_opcode_t op);
|
||||||
void MTVSCR(ppu_opcode_t op);
|
void MTVSCR(ppu_opcode_t op);
|
||||||
|
|
|
@ -22,7 +22,7 @@ u32 SPUDisAsm::disasm(u32 pc)
|
||||||
|
|
||||||
std::pair<bool, v128> SPUDisAsm::try_get_const_value(u32 reg, u32 pc) const
|
std::pair<bool, v128> SPUDisAsm::try_get_const_value(u32 reg, u32 pc) const
|
||||||
{
|
{
|
||||||
if (m_mode != cpu_disasm_mode::interpreter)
|
if (m_mode != cpu_disasm_mode::interpreter && m_mode != cpu_disasm_mode::normal)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue