From 772de2a63b573acccecea7f9e5568e584f5a86e6 Mon Sep 17 00:00:00 2001 From: Eladash <18193363+elad335@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:35:28 +0300 Subject: [PATCH 1/2] SPU: Use bitset to reduce memory for compiler instance --- rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 26 ++++++++++++-------------- rpcs3/Emu/Cell/SPURecompiler.h | 6 +++--- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index f8882490bb04..39c308f5309d 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -2482,9 +2482,9 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s workload.push_back(entry_point); std::memset(m_regmod.data(), 0xff, sizeof(m_regmod)); - std::memset(m_use_ra.data(), 0xff, sizeof(m_use_ra)); - std::memset(m_use_rb.data(), 0xff, sizeof(m_use_rb)); - std::memset(m_use_rc.data(), 0xff, sizeof(m_use_rc)); + m_use_ra.reset(); + m_use_rb.reset(); + m_use_rc.reset(); m_targets.clear(); m_preds.clear(); m_preds[entry_point]; @@ -2579,11 +2579,11 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (auto iflags = g_spu_iflag.decode(data)) { if (+iflags & +spu_iflag::use_ra) - m_use_ra[pos / 4] = op.ra; + m_use_ra.set(pos / 4); if (+iflags & +spu_iflag::use_rb) - m_use_rb[pos / 4] = op.rb; + m_use_rb.set(pos / 4); if (+iflags & +spu_iflag::use_rc) - m_use_rc[pos / 4] = op.rc; + m_use_rc.set(pos / 4); } // Analyse instruction @@ -3010,11 +3010,6 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s m_regmod[pos / 4] = s_reg_mfc_size; break; } - case MFC_Cmd: - { - m_use_rb[pos / 4] = s_reg_mfc_eal; - break; - } default: break; } @@ -3461,10 +3456,13 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s reg_save = op.rt; } - for (auto* _use : {&m_use_ra, &m_use_rb, &m_use_rc}) + for (auto _use : std::initializer_list>{{op.ra, m_use_ra.test(ia / 4)} + , {op.rb, m_use_rb.test(ia / 4)}, {op.rc, m_use_rc.test(ia / 4)}}) { - if (u8 reg = (*_use)[ia / 4]; reg < s_reg_max) + if (_use.second) { + const u32 reg = _use.first; + // Register reg use only if it happens before reg mod if (!block.reg_mod[reg]) { @@ -3479,7 +3477,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s } } - if (m_use_rb[ia / 4] == s_reg_mfc_eal) + if (type == spu_itype::WRCH && op.ra == MFC_Cmd) { // Expand MFC_Cmd reg use for (u8 reg : {s_reg_mfc_lsa, s_reg_mfc_tag, s_reg_mfc_size}) diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 26f59cffb046..ba1dfce41258 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -202,9 +202,9 @@ class spu_recompiler_base // GPR modified by the instruction (-1 = not set) std::array m_regmod; - std::array m_use_ra; - std::array m_use_rb; - std::array m_use_rc; + std::bitset<0x10000> m_use_ra; + std::bitset<0x10000> m_use_rb; + std::bitset<0x10000> m_use_rc; // List of possible targets for the instruction (entry shouldn't exist for simple instructions) std::unordered_map, value_hash> m_targets; From bc6598dc075153014d776cb7a00bcc50d1060aa7 Mon Sep 17 00:00:00 2001 From: Eladash <18193363+elad335@users.noreply.github.com> Date: Fri, 12 Apr 2024 16:06:56 +0300 Subject: [PATCH 2/2] SPU/Debugger: Use bitset for breakpoints --- rpcs3/Emu/Cell/SPUThread.cpp | 5 ++++- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/rpcs3qt/breakpoint_list.cpp | 4 +++- rpcs3/rpcs3qt/debugger_list.cpp | 13 +++++++++++-- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 65dbc1dcfb92..725794b6e30b 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1839,7 +1839,10 @@ void spu_thread::cpu_work() if (has_active_local_bps) { - if (local_breakpoints[pc / 4]) + const u32 pos_at = pc / 4; + const u32 pos_bit = 1u << (pos_at % 8); + + if (local_breakpoints[pos_at] & pos_bit) { // Ignore repeatations until a different instruction is issued if (pc != current_bp_pc) diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 24914f70758b..82cf4bc1899c 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -816,7 +816,7 @@ class spu_thread : public cpu_thread atomic_t debugger_mode{}; // PC-based breakpoint list - std::array, SPU_LS_SIZE / 4> local_breakpoints{}; + std::array, SPU_LS_SIZE / 4 / 8> local_breakpoints{}; atomic_t has_active_local_bps = false; u32 current_bp_pc = umax; bool stop_flag_removal_protection = false; diff --git a/rpcs3/rpcs3qt/breakpoint_list.cpp b/rpcs3/rpcs3qt/breakpoint_list.cpp index 008ecc4df1df..2447e91e0312 100644 --- a/rpcs3/rpcs3qt/breakpoint_list.cpp +++ b/rpcs3/rpcs3qt/breakpoint_list.cpp @@ -125,8 +125,10 @@ void breakpoint_list::HandleBreakpointRequest(u32 loc, bool only_add) const auto spu = static_cast(m_cpu); auto& list = spu->local_breakpoints; + const u32 pos_at = loc / 4; + const u32 pos_bit = 1u << (pos_at % 8); - if (list[loc / 4].test_and_invert()) + if (list[pos_at / 8].fetch_xor(pos_bit) & pos_bit) { if (std::none_of(list.begin(), list.end(), [](auto& val){ return val.load(); })) { diff --git a/rpcs3/rpcs3qt/debugger_list.cpp b/rpcs3/rpcs3qt/debugger_list.cpp index 002ae1e0bb79..25b68f27a905 100644 --- a/rpcs3/rpcs3qt/debugger_list.cpp +++ b/rpcs3/rpcs3qt/debugger_list.cpp @@ -142,8 +142,17 @@ void debugger_list::ShowAddress(u32 addr, bool select_addr, bool direct) { switch (m_cpu ? m_cpu->id_type() : 0) { - case 1: return m_ppu_breakpoint_handler->HasBreakpoint(pc); - case 2: return (*spu_bps_list)[pc / 4].load(); + case 1: + { + return m_ppu_breakpoint_handler->HasBreakpoint(pc); + } + case 2: + { + const u32 pos_at = pc / 4; + const u32 pos_bit = 1u << (pos_at % 8); + + return !!((*spu_bps_list)[pos_at] & pos_bit); + } default: return false; } };