debugger: Fix single stepping (#9793)

This commit is contained in:
Eladash 2021-02-19 13:53:09 +02:00 committed by GitHub
parent e76d8eb046
commit 20eb4352fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 58 additions and 11 deletions

View File

@ -667,6 +667,26 @@ bool cpu_thread::check_state() noexcept
store = true;
}
// Can't process dbg_step if we only paused temporarily
if (cpu_can_stop && flags & cpu_flag::dbg_step)
{
if (u32 pc = get_pc(), *pc2 = get_pc2(); pc != umax && pc2)
{
if (pc != *pc2)
{
flags -= cpu_flag::dbg_step;
flags += cpu_flag::dbg_pause;
store = true;
}
}
else
{
// Can't test, ignore flag
flags -= cpu_flag::dbg_step;
store = true;
}
}
// Atomically clean wait flag and escape
if (!(flags & (cpu_flag::exit + cpu_flag::ret + cpu_flag::stop)))
{
@ -703,14 +723,6 @@ bool cpu_thread::check_state() noexcept
retval = cpu_can_stop;
}
if (cpu_can_stop && flags & cpu_flag::dbg_step)
{
// Can't process dbg_step if we only paused temporarily
flags += cpu_flag::dbg_pause;
flags -= cpu_flag::dbg_step;
store = true;
}
escape = true;
state1 = flags;
return store;
@ -876,6 +888,29 @@ u32 cpu_thread::get_pc() const
return pc ? atomic_storage<u32>::load(*pc) : UINT32_MAX;
}
u32* cpu_thread::get_pc2()
{
switch (id_type())
{
case 1:
{
return &static_cast<ppu_thread*>(this)->dbg_step_pc;
}
case 2:
{
return &static_cast<spu_thread*>(this)->dbg_step_pc;
}
case 0x55:
{
const auto ctrl = static_cast<rsx::thread*>(this)->ctrl;
return ctrl ? &static_cast<rsx::thread*>(this)->dbg_step_pc : nullptr;
}
default: break;
}
return nullptr;
}
std::string cpu_thread::dump_all() const
{
std::string ret = cpu_thread::dump_misc();

View File

@ -105,6 +105,7 @@ public:
}
u32 get_pc() const;
u32* get_pc2(); // Last PC before stepping for the debugger (may be null)
void notify();

View File

@ -455,7 +455,7 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_function_t ptr)
static bool ppu_break(ppu_thread& ppu, ppu_opcode_t op)
{
// Pause
ppu.state += cpu_flag::dbg_pause;
ppu.state.atomic_op([](bs_t<cpu_flag>& state) { if (!(state & cpu_flag::dbg_step)) state += cpu_flag::dbg_pause; });
if (ppu.check_state())
{

View File

@ -277,6 +277,8 @@ public:
u64 last_fail = 0;
u64 last_succ = 0;
u32 dbg_step_pc = 0;
be_t<u64>* get_stack_arg(s32 i, u64 align = alignof(u64));
void exec_task();
void fast_call(u32 addr, u32 rtoc);

View File

@ -643,6 +643,7 @@ public:
spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false, u32 option = 0);
u32 pc = 0;
u32 dbg_step_pc = 0;
// May be used internally by recompilers.
u32 base_pc = 0;

View File

@ -648,6 +648,7 @@ namespace rsx
u32 dma_address{0};
rsx_iomap_table iomap_table;
u32 restore_point = 0;
u32 dbg_step_pc = 0;
atomic_t<u32> external_interrupt_lock{ 0 };
atomic_t<bool> external_interrupt_ack{ false };
bool is_fifo_idle() const;

View File

@ -825,7 +825,7 @@ void debugger_frame::DoStep(bool stepOver)
{
bool should_step_over = stepOver && cpu->id_type() == 1;
if (cpu->state & s_pause_flags)
if (auto _state = +cpu->state; _state & s_pause_flags && _state & cpu_flag::wait && !(_state & cpu_flag::dbg_step))
{
if (should_step_over)
{
@ -849,7 +849,14 @@ void debugger_frame::DoStep(bool stepOver)
{
state -= s_pause_flags;
if (!should_step_over) state += cpu_flag::dbg_step;
if (!should_step_over)
{
if (u32* ptr = cpu->get_pc2())
{
state += cpu_flag::dbg_step;
*ptr = cpu->get_pc();
}
}
});
cpu->state.notify_one(s_pause_flags);