SPU Debugger: Improve registers panel

This commit is contained in:
Eladash 2020-11-10 16:57:06 +02:00 committed by kd-11
parent a83df01bfd
commit 52fa69d93d
5 changed files with 106 additions and 13 deletions

View File

@ -7,7 +7,7 @@ enum CPUDisAsmMode
{
CPUDisAsm_DumpMode,
CPUDisAsm_InterpreterMode,
//CPUDisAsm_NormalMode,
CPUDisAsm_NormalMode,
CPUDisAsm_CompilerElfMode,
};
@ -21,25 +21,37 @@ protected:
switch(m_mode)
{
case CPUDisAsm_DumpMode:
{
last_opcode = fmt::format("\t%08x:\t%02x %02x %02x %02x\t%s\n", dump_pc,
offset[dump_pc],
offset[dump_pc + 1],
offset[dump_pc + 2],
offset[dump_pc + 3], value);
break;
}
case CPUDisAsm_InterpreterMode:
{
last_opcode = fmt::format("[%08x] %02x %02x %02x %02x: %s", dump_pc,
offset[dump_pc],
offset[dump_pc + 1],
offset[dump_pc + 2],
offset[dump_pc + 3], value);
break;
}
case CPUDisAsm_CompilerElfMode:
last_opcode = value + "\n";
{
last_opcode = value + '\n';
break;
}
case CPUDisAsm_NormalMode:
{
last_opcode = value;
break;
}
default: ASSUME(0);
}
}
public:
@ -79,9 +91,13 @@ protected:
return fmt::format("%s%s", v < 0 ? "-" : "", av);
}
static std::string FixOp(std::string op)
std::string FixOp(std::string op) const
{
if (m_mode != CPUDisAsm_NormalMode)
{
op.resize(std::max<std::size_t>(op.length(), 10), ' ');
}
return op;
}

View File

@ -11,6 +11,7 @@
#include "PPUInterpreter.h"
#include "PPUAnalyser.h"
#include "PPUModule.h"
#include "PPUDisAsm.h"
#include "SPURecompiler.h"
#include "lv2/sys_sync.h"
#include "lv2/sys_prx.h"
@ -482,7 +483,11 @@ std::string ppu_thread::dump_regs() const
}
else
{
fmt::append(ret, " -> function-code");
PPUDisAsm dis_asm(CPUDisAsm_NormalMode);
dis_asm.offset = vm::g_sudo_addr;
dis_asm.dump_pc = reg;
dis_asm.disasm(reg);
fmt::append(ret, " -> %s", dis_asm.last_opcode);
}
}
else if (std::isprint(static_cast<u8>(buf_tmp[0])) && std::isprint(static_cast<u8>(buf_tmp[1])) && std::isprint(static_cast<u8>(buf_tmp[2])))

View File

@ -97,7 +97,11 @@ private:
private:
std::string& FixOp(std::string& op)
{
op.append(std::max<int>(10 - ::narrow<int>(op.size()), 0),' ');
if (m_mode != CPUDisAsm_NormalMode)
{
op.append(std::max<int>(10 - ::narrow<int>(op.size()), 0), ' ');
}
return op;
}
void DisAsm(const char* op)

View File

@ -1194,9 +1194,49 @@ std::string spu_thread::dump_regs() const
{
std::string ret;
for (u32 i = 0; i < 128; i++)
for (u32 i = 0; i < 128; i++, ret += '\n')
{
fmt::append(ret, "r%d: %s\n", i, gpr[i]);
fmt::append(ret, "r%d: ", i);
const auto r = gpr[i];
if (auto [size, dst, src] = SPUDisAsm::try_get_insert_mask_info(r); size)
{
// Special: insertation masks
const std::string_view type =
size == 1 ? "byte" :
size == 2 ? "half" :
size == 4 ? "word" :
size == 8 ? "dword" : "error";
if ((size >= 4u && !src) || (size == 2u && src == 1u) || (size == 1u && src == 3u))
{
fmt::append(ret, "insert -> %s[%u]", type, dst);
continue;
}
}
const u32 i3 = r._u32[3];
if (v128::from32p(i3) == r)
{
// Shortand formatting
fmt::append(ret, "0x%08x$", i3);
}
else
{
fmt::append(ret, "%s", r);
}
if (i3 >= 0x80 && is_exec_code(i3))
{
SPUDisAsm dis_asm(CPUDisAsm_NormalMode);
dis_asm.offset = ls;
dis_asm.dump_pc = i3;
dis_asm.disasm(i3);
fmt::append(ret, " -> %s", dis_asm.last_opcode);
}
}
const auto events = ch_events.load();
@ -1264,8 +1304,7 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
return true;
}
const u32 op = _ref<u32>(addr);
return s_spu_itype.decode(op) == spu_itype::UNK || !op || !addr;
return !addr || !is_exec_code(addr);
};
if (is_invalid(lr))
@ -2863,6 +2902,34 @@ bool spu_thread::check_mfc_interrupts(u32 next_pc)
return false;
}
bool spu_thread::is_exec_code(u32 addr) const
{
if (addr & ~0x3FFFC)
{
return false;
}
for (u32 i = 0; i < 30; i++)
{
const u32 addr0 = addr + (i * 4);
const u32 op = _ref<u32>(addr0);
const auto type = s_spu_itype.decode(op);
if (type == spu_itype::UNK || !op)
{
return false;
}
if (type & spu_itype::branch)
{
// TODO
break;
}
}
return true;
}
u32 spu_thread::get_mfc_completed()
{
return ch_tag_mask & ~mfc_fence;

View File

@ -778,6 +778,7 @@ public:
void set_events(u32 bits);
void set_interrupt_status(bool enable);
bool check_mfc_interrupts(u32 nex_pc);
bool is_exec_code(u32 addr) const; // Only a hint, do not rely on it other than debugging purposes
u32 get_ch_count(u32 ch);
s64 get_ch_value(u32 ch);
bool set_ch_value(u32 ch, u32 value);