mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 06:51:26 +12:00
Debugger: Fix GOTO and intruction stepping
This commit is contained in:
parent
e851c044b5
commit
90ad129b83
4 changed files with 101 additions and 29 deletions
|
@ -43,6 +43,11 @@ u32 RSXDisAsm::disasm(u32 pc)
|
||||||
|
|
||||||
if (m_op & RSX_METHOD_NON_METHOD_CMD_MASK)
|
if (m_op & RSX_METHOD_NON_METHOD_CMD_MASK)
|
||||||
{
|
{
|
||||||
|
if (m_mode == cpu_disasm_mode::survey_cmd_size)
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
if ((m_op & RSX_METHOD_OLD_JUMP_CMD_MASK) == RSX_METHOD_OLD_JUMP_CMD)
|
if ((m_op & RSX_METHOD_OLD_JUMP_CMD_MASK) == RSX_METHOD_OLD_JUMP_CMD)
|
||||||
{
|
{
|
||||||
u32 jumpAddr = m_op & RSX_METHOD_OLD_JUMP_OFFSET_MASK;
|
u32 jumpAddr = m_op & RSX_METHOD_OLD_JUMP_OFFSET_MASK;
|
||||||
|
@ -86,10 +91,13 @@ u32 RSXDisAsm::disasm(u32 pc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_mode != cpu_disasm_mode::survey_cmd_size)
|
||||||
|
{
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
Write("nop", 0);
|
Write("nop", 0);
|
||||||
else
|
else
|
||||||
Write(fmt::format("nop x%u", i), 0);
|
Write(fmt::format("nop x%u", i), 0);
|
||||||
|
}
|
||||||
|
|
||||||
return i * 4;
|
return i * 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3106,9 +3106,9 @@ namespace rsx
|
||||||
fifo_ctrl->invalidate_cache();
|
fifo_ctrl->invalidate_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u32, u32> thread::try_get_pc_of_x_cmds_backwards(u32 count, u32 get) const
|
std::pair<u32, u32> thread::try_get_pc_of_x_cmds_backwards(s32 count, u32 get) const
|
||||||
{
|
{
|
||||||
if (!ctrl)
|
if (!ctrl || state & cpu_flag::exit)
|
||||||
{
|
{
|
||||||
return {0, umax};
|
return {0, umax};
|
||||||
}
|
}
|
||||||
|
@ -3124,31 +3124,61 @@ namespace rsx
|
||||||
RSXDisAsm disasm(cpu_disasm_mode::survey_cmd_size, vm::g_sudo_addr, 0, this);
|
RSXDisAsm disasm(cpu_disasm_mode::survey_cmd_size, vm::g_sudo_addr, 0, this);
|
||||||
|
|
||||||
std::vector<u32> pcs_of_valid_cmds;
|
std::vector<u32> pcs_of_valid_cmds;
|
||||||
|
|
||||||
|
if (get > start)
|
||||||
|
{
|
||||||
pcs_of_valid_cmds.reserve(std::min<u32>((get - start) / 16, 0x4000)); // Rough estimation of final array size
|
pcs_of_valid_cmds.reserve(std::min<u32>((get - start) / 16, 0x4000)); // Rough estimation of final array size
|
||||||
|
}
|
||||||
|
|
||||||
auto probe_code_region = [&](u32 probe_start) -> std::pair<u32, u32>
|
auto probe_code_region = [&](u32 probe_start) -> std::pair<u32, u32>
|
||||||
{
|
{
|
||||||
|
if (probe_start > get)
|
||||||
|
{
|
||||||
|
return {0, get};
|
||||||
|
}
|
||||||
|
|
||||||
pcs_of_valid_cmds.clear();
|
pcs_of_valid_cmds.clear();
|
||||||
pcs_of_valid_cmds.push_back(probe_start);
|
pcs_of_valid_cmds.push_back(probe_start);
|
||||||
|
|
||||||
while (pcs_of_valid_cmds.back() < get)
|
usz index_of_get = umax;
|
||||||
|
usz until = umax;
|
||||||
|
|
||||||
|
while (pcs_of_valid_cmds.size() < until)
|
||||||
{
|
{
|
||||||
if (u32 advance = disasm.disasm(pcs_of_valid_cmds.back()))
|
if (u32 advance = disasm.disasm(pcs_of_valid_cmds.back()))
|
||||||
{
|
{
|
||||||
pcs_of_valid_cmds.push_back(pcs_of_valid_cmds.back() + advance);
|
pcs_of_valid_cmds.push_back(utils::add_saturate<u32>(pcs_of_valid_cmds.back(), advance));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return {0, get};
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index_of_get == umax && pcs_of_valid_cmds.back() >= get)
|
||||||
|
{
|
||||||
|
index_of_get = pcs_of_valid_cmds.size() - 1;
|
||||||
|
until = index_of_get + 1;
|
||||||
|
|
||||||
|
if (count < 0 && pcs_of_valid_cmds.back() == get)
|
||||||
|
{
|
||||||
|
until -= count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pcs_of_valid_cmds.size() == 1u || pcs_of_valid_cmds.back() != get)
|
if (index_of_get == umax || pcs_of_valid_cmds[index_of_get] != get)
|
||||||
{
|
{
|
||||||
return {0, get};
|
return {0, get};
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 found_cmds_count = std::min(count, ::size32(pcs_of_valid_cmds) - 1);
|
if (count < 0)
|
||||||
|
{
|
||||||
|
const u32 found_cmds_count = std::min<u32>(-count, ::size32(pcs_of_valid_cmds) - 1 - index_of_get);
|
||||||
|
|
||||||
|
return {found_cmds_count, pcs_of_valid_cmds[index_of_get + found_cmds_count]};
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 found_cmds_count = std::min<u32>(count, ::size32(pcs_of_valid_cmds) - 1);
|
||||||
|
|
||||||
return {found_cmds_count, *(pcs_of_valid_cmds.end() - 1 - found_cmds_count)};
|
return {found_cmds_count, *(pcs_of_valid_cmds.end() - 1 - found_cmds_count)};
|
||||||
};
|
};
|
||||||
|
|
|
@ -219,7 +219,7 @@ namespace rsx
|
||||||
void flush_fifo();
|
void flush_fifo();
|
||||||
|
|
||||||
// Returns [count of found commands, PC of their start]
|
// Returns [count of found commands, PC of their start]
|
||||||
std::pair<u32, u32> try_get_pc_of_x_cmds_backwards(u32 count, u32 get) const;
|
std::pair<u32, u32> try_get_pc_of_x_cmds_backwards(s32 count, u32 get) const;
|
||||||
|
|
||||||
void recover_fifo(u32 line = __builtin_LINE(),
|
void recover_fifo(u32 line = __builtin_LINE(),
|
||||||
u32 col = __builtin_COLUMN(),
|
u32 col = __builtin_COLUMN(),
|
||||||
|
|
|
@ -71,8 +71,12 @@ void debugger_list::UpdateCPUData(cpu_thread* cpu, CPUDisAsm* disasm)
|
||||||
u32 debugger_list::GetStartAddress(u32 address)
|
u32 debugger_list::GetStartAddress(u32 address)
|
||||||
{
|
{
|
||||||
const u32 steps = m_item_count / 3;
|
const u32 steps = m_item_count / 3;
|
||||||
|
const u32 inst_count_jump_on_step = std::min<u32>(steps, 4);
|
||||||
|
|
||||||
u32 result = address;
|
const bool is_spu = m_cpu && m_cpu->id_type() == 2;
|
||||||
|
const u32 address_mask = (is_spu ? 0x3fffc : ~3);
|
||||||
|
|
||||||
|
u32 result = address & address_mask;
|
||||||
|
|
||||||
if (m_cpu && m_cpu->id_type() == 0x55)
|
if (m_cpu && m_cpu->id_type() == 0x55)
|
||||||
{
|
{
|
||||||
|
@ -83,14 +87,44 @@ u32 debugger_list::GetStartAddress(u32 address)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = address - (steps * 4);
|
result = (address - (steps * 4)) & address_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (address > m_pc || m_start_addr > address)
|
u32 upper_bound = (m_start_addr + (steps * 4)) & address_mask;
|
||||||
|
|
||||||
|
if (m_cpu && m_cpu->id_type() == 0x55)
|
||||||
|
{
|
||||||
|
if (auto [count, res] = static_cast<rsx::thread*>(m_cpu)->try_get_pc_of_x_cmds_backwards(0 - steps, m_start_addr); count == steps)
|
||||||
|
{
|
||||||
|
upper_bound = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool goto_addr = false;
|
||||||
|
|
||||||
|
if (upper_bound > m_start_addr)
|
||||||
|
{
|
||||||
|
goto_addr = address < m_start_addr || address >= upper_bound;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Overflowing bounds case
|
||||||
|
goto_addr = address < m_start_addr && address >= upper_bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (goto_addr)
|
||||||
{
|
{
|
||||||
m_pc = address;
|
m_pc = address;
|
||||||
|
|
||||||
|
if (address > upper_bound && address - upper_bound < inst_count_jump_on_step * 4)
|
||||||
|
{
|
||||||
|
m_start_addr = result + inst_count_jump_on_step * 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
m_start_addr = result;
|
m_start_addr = result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m_start_addr;
|
return m_start_addr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue