mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-13 07:14:49 +00:00
debugger: Fix single stepping (#9793)
This commit is contained in:
parent
e76d8eb046
commit
20eb4352fb
@ -667,6 +667,26 @@ bool cpu_thread::check_state() noexcept
|
|||||||
store = true;
|
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
|
// Atomically clean wait flag and escape
|
||||||
if (!(flags & (cpu_flag::exit + cpu_flag::ret + cpu_flag::stop)))
|
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;
|
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;
|
escape = true;
|
||||||
state1 = flags;
|
state1 = flags;
|
||||||
return store;
|
return store;
|
||||||
@ -876,6 +888,29 @@ u32 cpu_thread::get_pc() const
|
|||||||
return pc ? atomic_storage<u32>::load(*pc) : UINT32_MAX;
|
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 cpu_thread::dump_all() const
|
||||||
{
|
{
|
||||||
std::string ret = cpu_thread::dump_misc();
|
std::string ret = cpu_thread::dump_misc();
|
||||||
|
@ -105,6 +105,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 get_pc() const;
|
u32 get_pc() const;
|
||||||
|
u32* get_pc2(); // Last PC before stepping for the debugger (may be null)
|
||||||
|
|
||||||
void notify();
|
void notify();
|
||||||
|
|
||||||
|
@ -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)
|
static bool ppu_break(ppu_thread& ppu, ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
// Pause
|
// 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())
|
if (ppu.check_state())
|
||||||
{
|
{
|
||||||
|
@ -277,6 +277,8 @@ public:
|
|||||||
u64 last_fail = 0;
|
u64 last_fail = 0;
|
||||||
u64 last_succ = 0;
|
u64 last_succ = 0;
|
||||||
|
|
||||||
|
u32 dbg_step_pc = 0;
|
||||||
|
|
||||||
be_t<u64>* get_stack_arg(s32 i, u64 align = alignof(u64));
|
be_t<u64>* get_stack_arg(s32 i, u64 align = alignof(u64));
|
||||||
void exec_task();
|
void exec_task();
|
||||||
void fast_call(u32 addr, u32 rtoc);
|
void fast_call(u32 addr, u32 rtoc);
|
||||||
|
@ -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);
|
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 pc = 0;
|
||||||
|
u32 dbg_step_pc = 0;
|
||||||
|
|
||||||
// May be used internally by recompilers.
|
// May be used internally by recompilers.
|
||||||
u32 base_pc = 0;
|
u32 base_pc = 0;
|
||||||
|
@ -648,6 +648,7 @@ namespace rsx
|
|||||||
u32 dma_address{0};
|
u32 dma_address{0};
|
||||||
rsx_iomap_table iomap_table;
|
rsx_iomap_table iomap_table;
|
||||||
u32 restore_point = 0;
|
u32 restore_point = 0;
|
||||||
|
u32 dbg_step_pc = 0;
|
||||||
atomic_t<u32> external_interrupt_lock{ 0 };
|
atomic_t<u32> external_interrupt_lock{ 0 };
|
||||||
atomic_t<bool> external_interrupt_ack{ false };
|
atomic_t<bool> external_interrupt_ack{ false };
|
||||||
bool is_fifo_idle() const;
|
bool is_fifo_idle() const;
|
||||||
|
@ -825,7 +825,7 @@ void debugger_frame::DoStep(bool stepOver)
|
|||||||
{
|
{
|
||||||
bool should_step_over = stepOver && cpu->id_type() == 1;
|
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)
|
if (should_step_over)
|
||||||
{
|
{
|
||||||
@ -849,7 +849,14 @@ void debugger_frame::DoStep(bool stepOver)
|
|||||||
{
|
{
|
||||||
state -= s_pause_flags;
|
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);
|
cpu->state.notify_one(s_pause_flags);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user