From c21cdb80556c8f3f1934f2a322c8eedf0240539e Mon Sep 17 00:00:00 2001 From: Eladash Date: Fri, 19 May 2023 18:41:17 +0300 Subject: [PATCH] Implement PPU LV2 debug --- rpcs3/Emu/Cell/PPUFunction.h | 5 +++++ rpcs3/Emu/Cell/PPUThread.cpp | 13 ++++++++----- rpcs3/Emu/Cell/PPUThread.h | 17 +++++++++++++++++ rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/rpcs3qt/debugger_frame.cpp | 22 +++++++++++++++++++--- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUFunction.h b/rpcs3/Emu/Cell/PPUFunction.h index f3232e9d35..b53659938d 100644 --- a/rpcs3/Emu/Cell/PPUFunction.h +++ b/rpcs3/Emu/Cell/PPUFunction.h @@ -14,6 +14,11 @@ std::memcpy(ppu.syscall_args, ppu.gpr + 3, sizeof(ppu.syscall_args)); \ ppu_func_detail::do_call(ppu, func);\ static_cast(ppu.test_stopped());\ + auto& history = ppu.syscall_history.data[ppu.syscall_history.index++ % ppu.syscall_history.data.size()];\ + history.cia = ppu.cia;\ + history.func_name = ppu.current_function;\ + history.error = ppu.gpr[3];\ + if (ppu.syscall_history.count_debug_arguments) std::copy_n(ppu.syscall_args, std::size(history.args), history.args.data());\ ppu.current_function = old_f;\ ppu.cia += 4;\ __VA_ARGS__;\ diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 9160697bfd..538d224ddd 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1593,7 +1593,7 @@ void ppu_thread::dump_all(std::string& ret) const { cpu_thread::dump_all(ret); - if (!call_history.data.empty()) + if (call_history.data.size() > 1) { ret += "\nCalling History:" @@ -1887,10 +1887,9 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3 state += cpu_flag::memory; } - if (g_cfg.core.ppu_call_history) - { - call_history.data.resize(call_history_max_size); - } + call_history.data.resize(g_cfg.core.ppu_call_history ? call_history_max_size : 1); + syscall_history.data.resize(g_cfg.core.ppu_call_history ? syscall_history_max_size : 1); + syscall_history.count_debug_arguments = static_cast(g_cfg.core.ppu_call_history ? std::size(syscall_history.data[0].args) : 0); #ifdef __APPLE__ pthread_jit_write_protect_np(true); @@ -1967,6 +1966,10 @@ ppu_thread::ppu_thread(utils::serial& ar) atomic_t inited = false; }; + call_history.data.resize(g_cfg.core.ppu_call_history ? call_history_max_size : 1); + syscall_history.data.resize(g_cfg.core.ppu_call_history ? syscall_history_max_size : 1); + syscall_history.count_debug_arguments = static_cast(g_cfg.core.ppu_call_history ? std::size(syscall_history.data[0].args) : 0); + serialize_common(ar); // Restore jm_mask diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 8e94252306..89543e168f 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -311,6 +311,23 @@ public: static constexpr u32 call_history_max_size = 4096; + struct syscall_history_t + { + struct entry_t + { + u64 cia; + const char* func_name; + u64 error; + std::array args; + }; + + std::vector data; + u64 index = 0; + u32 count_debug_arguments; + } syscall_history; + + static constexpr u32 syscall_history_max_size = 2048; + struct hle_func_call_with_toc_info_t { u32 cia; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 700c0c6165..c4d52d517e 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -782,7 +782,7 @@ public: std::vector mfc_history; u64 mfc_dump_idx = 0; - static constexpr u32 max_mfc_dump_idx = 2048; + static constexpr u32 max_mfc_dump_idx = 4096; bool in_cpu_work = false; bool allow_interrupts_in_cpu_work = false; diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 6fcfb9f35f..d2c54ecf39 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -462,6 +462,8 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) auto copy_overlapping_list = [&] (u64& index, u64 max, const std::vector& in, std::vector& out, bool& emptied) { + max = std::min(max, in.size()); + const u64 current_pos = index % in.size(); const u64 last_elements = std::min(current_pos, max); const u64 overlapped_old_elements = std::min(index, max) - last_elements; @@ -543,13 +545,16 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) // Preallocate in order to save execution time when inside suspend_all. std::vector copy(max); + std::vector sys_copy(ppu_thread::syscall_history_max_size); - bool emptied = false; + std::array emptied{}; cpu_thread::suspend_all(nullptr, {}, [&] { auto& list = static_cast(cpu)->call_history; - copy_overlapping_list(list.index, max, list.data, copy, emptied); + auto& sys_list = static_cast(cpu)->syscall_history; + copy_overlapping_list(list.index, max, list.data, copy, emptied[0]); + copy_overlapping_list(sys_list.index, max, sys_list.data, sys_copy, emptied[1]); }); std::string ret; @@ -563,16 +568,27 @@ void debugger_frame::keyPressEvent(QKeyEvent* event) fmt::append(ret, "\n(%u) 0x%08x: %s", i, *it, dis_asm.last_opcode); } + i = 0; + for (auto it = sys_copy.rbegin(); it != sys_copy.rend(); it++, i++) + { + fmt::append(ret, "\n(%u) 0x%08x: %s, 0x%x, r3=0x%x, r4=0x%x, r5=0x%x, r6=0x%x", i, it->cia, it->func_name, it->error, it->args[0], it->args[1], it->args[2], it->args[3]); + } + if (ret.empty()) { ret = "No PPU calls have been logged"; } - if (emptied) + if (emptied[0]) { ret += "\nPrevious call history has been emptied!"; } + if (emptied[1]) + { + ret += "\nPrevious HLE call history has been emptied!"; + } + ppu_log.success("PPU calling history dump of '%s': %s", cpu->get_name(), ret); }