mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-20 22:05:12 +00:00
Debugger: Implement SPU breakpoints
This commit is contained in:
parent
ec6d6adebc
commit
ccb2724fc4
10 changed files with 136 additions and 32 deletions
|
|
@ -52,6 +52,7 @@ void fmt_class_string<cpu_flag>::format(std::string& out, u64 arg)
|
|||
case cpu_flag::signal: return "sig";
|
||||
case cpu_flag::memory: return "mem";
|
||||
case cpu_flag::pending: return "pend";
|
||||
case cpu_flag::pending_recheck: return "pend-re";
|
||||
case cpu_flag::dbg_global_pause: return "G-PAUSE";
|
||||
case cpu_flag::dbg_pause: return "PAUSE";
|
||||
case cpu_flag::dbg_step: return "STEP";
|
||||
|
|
@ -624,6 +625,11 @@ cpu_thread::cpu_thread(u32 id)
|
|||
}
|
||||
|
||||
g_threads_created++;
|
||||
|
||||
if (u32* pc2 = get_pc2())
|
||||
{
|
||||
*pc2 = umax;
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_thread::cpu_wait(bs_t<cpu_flag> old)
|
||||
|
|
@ -762,10 +768,18 @@ bool cpu_thread::check_state() noexcept
|
|||
cpu_counter::add(this);
|
||||
}
|
||||
|
||||
if ((state0 & (cpu_flag::pending + cpu_flag::temp)) == cpu_flag::pending)
|
||||
constexpr auto pending_and_temp = (cpu_flag::pending + cpu_flag::temp);
|
||||
|
||||
if ((state0 & pending_and_temp) == cpu_flag::pending)
|
||||
{
|
||||
// Execute pending work
|
||||
cpu_work();
|
||||
|
||||
if ((state1 ^ state) - pending_and_temp)
|
||||
{
|
||||
// Work could have changed flags
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ enum class cpu_flag : u32
|
|||
signal, // Thread received a signal (HLE)
|
||||
memory, // Thread must unlock memory mutex
|
||||
pending, // Thread has postponed work
|
||||
pending_recheck, // Thread needs to recheck if there is pending work before ::pending removal
|
||||
|
||||
dbg_global_pause, // Emulation paused
|
||||
dbg_pause, // Thread paused
|
||||
|
|
|
|||
|
|
@ -1503,10 +1503,30 @@ void spu_thread::cpu_work()
|
|||
|
||||
const u32 old_iter_count = cpu_work_iteration_count++;
|
||||
|
||||
const auto timeout = +g_cfg.core.mfc_transfers_timeout;
|
||||
|
||||
bool work_left = false;
|
||||
|
||||
if (has_active_local_bps)
|
||||
{
|
||||
if (local_breakpoints[pc / 4])
|
||||
{
|
||||
// Ignore repeatations until a different instruction is issued
|
||||
if (pc != current_bp_pc)
|
||||
{
|
||||
// Breakpoint hit
|
||||
state += cpu_flag::dbg_pause;
|
||||
}
|
||||
}
|
||||
|
||||
current_bp_pc = pc;
|
||||
work_left = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_bp_pc = umax;
|
||||
}
|
||||
|
||||
const auto timeout = +g_cfg.core.mfc_transfers_timeout;
|
||||
|
||||
if (u32 shuffle_count = g_cfg.core.mfc_transfers_shuffling)
|
||||
{
|
||||
// If either MFC size exceeds limit or timeout has been reached execute pending MFC commands
|
||||
|
|
@ -1544,7 +1564,19 @@ void spu_thread::cpu_work()
|
|||
|
||||
if (!work_left)
|
||||
{
|
||||
state -= cpu_flag::pending;
|
||||
// No more pending work
|
||||
state.atomic_op([](bs_t<cpu_flag>& flags)
|
||||
{
|
||||
if (flags & cpu_flag::pending_recheck)
|
||||
{
|
||||
// Do not really remove ::pending because external thread may have pushed more pending work
|
||||
flags -= cpu_flag::pending_recheck;
|
||||
}
|
||||
else
|
||||
{
|
||||
flags -= cpu_flag::pending;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (gen_interrupt)
|
||||
|
|
|
|||
|
|
@ -843,6 +843,11 @@ public:
|
|||
|
||||
atomic_t<u8> debugger_float_mode = 0;
|
||||
|
||||
// PC-based breakpoint list
|
||||
std::array<atomic_t<bool>, SPU_LS_SIZE / 4> local_breakpoints{};
|
||||
atomic_t<bool> has_active_local_bps = false;
|
||||
u32 current_bp_pc = umax;
|
||||
|
||||
void push_snr(u32 number, u32 value);
|
||||
static void do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8* ls);
|
||||
bool do_dma_check(const spu_mfc_cmd& args);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue