From c0280b43f26e8178c3cb5cc1f3e7d5a0c4e0319e Mon Sep 17 00:00:00 2001 From: Eladash Date: Wed, 12 Jul 2023 11:02:12 +0300 Subject: [PATCH] PPU/Debugger: View the currently used CR field content in register panel --- rpcs3/Emu/CPU/CPUThread.cpp | 6 ++- rpcs3/Emu/CPU/CPUThread.h | 3 +- rpcs3/Emu/Cell/PPUThread.cpp | 74 ++++++++++++++++++++++++++++++-- rpcs3/Emu/Cell/PPUThread.h | 2 +- rpcs3/Emu/Cell/SPUThread.cpp | 2 +- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- rpcs3/Emu/RSX/RSXThread.h | 2 +- rpcs3/rpcs3qt/debugger_frame.cpp | 2 +- rpcs3/rpcs3qt/debugger_frame.h | 2 + 10 files changed, 85 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 7098776a53..d0cf1e100e 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -1093,9 +1093,11 @@ std::shared_ptr make_disasm(const cpu_thread* cpu); void cpu_thread::dump_all(std::string& ret) const { + std::any func_data; + ret += dump_misc(); ret += '\n'; - dump_regs(ret); + dump_regs(ret, func_data); ret += '\n'; ret += dump_callstack(); ret += '\n'; @@ -1118,7 +1120,7 @@ void cpu_thread::dump_all(std::string& ret) const } } -void cpu_thread::dump_regs(std::string&) const +void cpu_thread::dump_regs(std::string&, std::any&) const { } diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 8885969a6f..cfdee6db4b 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -4,6 +4,7 @@ #include "../Utilities/bit_set.h" #include +#include template concept DerivedFrom = std::is_base_of_v && @@ -159,7 +160,7 @@ public: virtual void dump_all(std::string&) const; // Get CPU register dump - virtual void dump_regs(std::string&) const; + virtual void dump_regs(std::string& ret, std::any& custom_data) const; // Get CPU call stack dump virtual std::string dump_callstack() const; diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 9565357a59..c73395a931 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -1235,7 +1235,7 @@ std::array op_branch_targets(u32 pc, ppu_opcode_t op) return res; } -void ppu_thread::dump_regs(std::string& ret) const +void ppu_thread::dump_regs(std::string& ret, std::any& custom_data) const { const system_state emu_state = Emu.GetStatus(false); const bool is_stopped_or_frozen = state & cpu_flag::exit || emu_state == system_state::frozen || emu_state <= system_state::stopping; @@ -1243,6 +1243,22 @@ void ppu_thread::dump_regs(std::string& ret) const const bool is_decimal = !is_stopped_or_frozen && mode == ppu_debugger_mode::is_decimal; + struct dump_registers_data_t + { + u32 preferred_cr_field_index = 7; + }; + + dump_registers_data_t* func_data = nullptr; + + func_data = std::any_cast(&custom_data); + + if (!func_data) + { + custom_data.reset(); + custom_data = std::make_any(); + func_data = ensure(std::any_cast(&custom_data)); + } + PPUDisAsm dis_asm(cpu_disasm_mode::normal, vm::g_sudo_addr); for (uint i = 0; i < 32; ++i) @@ -1367,6 +1383,59 @@ void ppu_thread::dump_regs(std::string& ret) const ret += '\n'; } + const u32 current_cia = cia; + const u32 cr_packed = cr.pack(); + + for (u32 addr : + { + current_cia, + current_cia + 4, + current_cia + 8, + current_cia - 4, + current_cia + 12, + }) + { + dis_asm.disasm(addr); + + if (dis_asm.last_opcode.size() <= 4) + { + continue; + } + + if (usz index = dis_asm.last_opcode.rfind(",cr"); index < dis_asm.last_opcode.size() - 4) + { + const char result = dis_asm.last_opcode[index + 3]; + + if (result >= '0' && result <= '7') + { + func_data->preferred_cr_field_index = result - '0'; + break; + } + } + + if (usz index = dis_asm.last_opcode.rfind(" cr"); index < dis_asm.last_opcode.size() - 4) + { + const char result = dis_asm.last_opcode[index + 3]; + + if (result >= '0' && result <= '7') + { + func_data->preferred_cr_field_index = result - '0'; + break; + } + } + + if (dis_asm.last_opcode.find("stdcx.") != umax || dis_asm.last_opcode.find("stwcx.") != umax) + { + // Modifying CR0 + func_data->preferred_cr_field_index = 0; + break; + } + } + + const u32 displayed_cr_field = (cr_packed >> ((7 - func_data->preferred_cr_field_index) * 4)) & 0xf; + + fmt::append(ret, "CR: 0x%08x, CR%d: [LT=%u GT=%u EQ=%u SO=%u]\n", cr_packed, func_data->preferred_cr_field_index, displayed_cr_field >> 3, (displayed_cr_field >> 2) & 1, (displayed_cr_field >> 1) & 1, displayed_cr_field & 1); + for (uint i = 0; i < 32; ++i) { const f64 r = fpr[i]; @@ -1400,8 +1469,7 @@ void ppu_thread::dump_regs(std::string& ret) const } } - fmt::append(ret, "CIA: 0x%x\n", cia); - fmt::append(ret, "CR: 0x%08x\n", cr.pack()); + fmt::append(ret, "CIA: 0x%x\n", current_cia); fmt::append(ret, "LR: 0x%llx\n", lr); fmt::append(ret, "CTR: 0x%llx\n", ctr); fmt::append(ret, "VRSAVE: 0x%08x\n", vrsave); diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index acff6e6bfa..2bb03c412c 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -141,7 +141,7 @@ public: static const u32 id_count = 100; static constexpr std::pair id_invl_range = {12, 12}; - virtual void dump_regs(std::string&) const override; + virtual void dump_regs(std::string&, std::any& custom_data) const override; virtual std::string dump_callstack() const override; virtual std::vector> dump_callstack_list() const override; virtual std::string dump_misc() const override; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 8906136558..805751a8de 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1017,7 +1017,7 @@ spu_imm_table_t::spu_imm_table_t() } } -void spu_thread::dump_regs(std::string& ret) const +void spu_thread::dump_regs(std::string& ret, std::any& /*custom_data*/) const { const system_state emu_state = Emu.GetStatus(false); const bool is_stopped_or_frozen = state & cpu_flag::exit || emu_state == system_state::frozen || emu_state <= system_state::stopping; diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 0c59344dd1..4801c7671c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -620,7 +620,7 @@ enum class spu_debugger_mode : u32 class spu_thread : public cpu_thread { public: - virtual void dump_regs(std::string&) const override; + virtual void dump_regs(std::string&, std::any& custom_data) const override; virtual std::string dump_callstack() const override; virtual std::vector> dump_callstack_list() const override; virtual std::string dump_misc() const override; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 12437359e0..0b6b8efe9b 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -3164,7 +3164,7 @@ namespace rsx void invalid_method(thread*, u32, u32); - void thread::dump_regs(std::string& result) const + void thread::dump_regs(std::string& result, std::any& /*custom_data*/) const { if (ctrl) { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index ddd45213ee..dde75f3e53 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -228,7 +228,7 @@ namespace rsx static void fifo_wake_delay(u64 div = 1); u32 get_fifo_cmd() const; - void dump_regs(std::string&) const override; + void dump_regs(std::string&, std::any& custom_data) const override; void cpu_wait(bs_t old) override; static constexpr u32 id_base = 0x5555'5555; // See get_current_cpu_thread() diff --git a/rpcs3/rpcs3qt/debugger_frame.cpp b/rpcs3/rpcs3qt/debugger_frame.cpp index 964bdbe8ca..4769c99f18 100644 --- a/rpcs3/rpcs3qt/debugger_frame.cpp +++ b/rpcs3/rpcs3qt/debugger_frame.cpp @@ -1155,7 +1155,7 @@ void debugger_frame::WritePanels() hloc = m_regs->horizontalScrollBar()->value(); m_regs->clear(); m_last_reg_state.clear(); - cpu->dump_regs(m_last_reg_state); + cpu->dump_regs(m_last_reg_state, m_dump_reg_func_data); m_regs->setText(qstr(m_last_reg_state)); m_regs->verticalScrollBar()->setValue(loc); m_regs->horizontalScrollBar()->setValue(hloc); diff --git a/rpcs3/rpcs3qt/debugger_frame.h b/rpcs3/rpcs3qt/debugger_frame.h index db81cae343..4ccc62a1f3 100644 --- a/rpcs3/rpcs3qt/debugger_frame.h +++ b/rpcs3/rpcs3qt/debugger_frame.h @@ -11,6 +11,7 @@ #include #include +#include class CPUDisAsm; class cpu_thread; @@ -58,6 +59,7 @@ class debugger_frame : public custom_dock_widget u32 m_last_pc = -1; std::vector m_last_query_state; std::string m_last_reg_state; + std::any m_dump_reg_func_data; u32 m_last_step_over_breakpoint = -1; u64 m_ui_update_ctr = 0; u64 m_ui_fast_update_permission_deadline = 0;