From e1eae3ee4959ca7373f999350e7b562d17f212db Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Sun, 8 Mar 2026 14:54:58 +0200 Subject: [PATCH] Add floating ppoint hint --- rpcs3/Emu/Cell/SPUAnalyser.h | 24 ++++++++++++------------ rpcs3/Emu/Cell/SPUCommonRecompiler.cpp | 21 +++++++++++++-------- rpcs3/Emu/Cell/SPURecompiler.h | 7 +++++-- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUAnalyser.h b/rpcs3/Emu/Cell/SPUAnalyser.h index 59560cd182..a6c788faad 100644 --- a/rpcs3/Emu/Cell/SPUAnalyser.h +++ b/rpcs3/Emu/Cell/SPUAnalyser.h @@ -158,6 +158,15 @@ struct spu_itype CUFLT, FRDS, // xfloat_tag last + CFLTS, + CFLTU, + FCEQ, + FCMEQ, + FCGT, + FCMGT, // floating_tag last + FSCRWR, + FSCRRD, + DFA, DFS, DFM, @@ -167,20 +176,11 @@ struct spu_itype DFNMA, FESD, - CFLTS, - CFLTU, - FCEQ, - FCMEQ, - FCGT, - FCMGT, - FSCRWR, - FSCRRD, - DFCEQ, DFCMEQ, DFCGT, DFCMGT, - DFTSV, // floating_tag last + DFTSV, SHLH, // shiftrot_tag first SHLHI, @@ -248,10 +248,10 @@ struct spu_itype return value >= BR && value <= BISL; } - // Test for floating point instruction + // Test for floating point instruction (32-bit float) friend constexpr bool operator &(type value, floating_tag) { - return value >= FMA && value <= DFTSV; + return value >= FMA && value <= FCMGT; } // Test for 4-op instruction diff --git a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp index eff272753a..9da576f009 100644 --- a/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUCommonRecompiler.cpp @@ -3933,7 +3933,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s const auto type = g_spu_itype.decode(op.opcode); - u8 reg_save = 255; + u8 reg_save = s_reg_max; if (type == spu_itype::STQD && op.ra == s_reg_sp && !block.reg_mod[op.rt] && !block.reg_use[op.rt]) { @@ -3953,7 +3953,12 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s // Register reg use only if it happens before reg mod if (!block.reg_mod[reg]) { - block.reg_use.set(reg); + if (type & spu_itype::floating) + { + block.reg_maybe_float.set(reg); + } + + block.reg_use[reg]++; if (reg_save != reg && block.reg_save_dom[reg]) { @@ -3970,7 +3975,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s for (u8 reg : {s_reg_mfc_lsa, s_reg_mfc_tag, s_reg_mfc_size}) { if (!block.reg_mod[reg]) - block.reg_use.set(reg); + block.reg_use[reg]++; } } @@ -4024,7 +4029,7 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (i == s_reg_lr || (i >= 2 && i < s_reg_80) || i > s_reg_127) { if (!block.reg_mod[i]) - block.reg_use.set(i); + block.reg_use[i]++; if (!is_tail) { @@ -6353,9 +6358,9 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (!reduced_loop->loop_dicts.test(i)) { - if (b.reg_use.test(i) || (!b.reg_mod.test(i) && b2.reg_use.test(i))) + if (b.reg_use[i] || (!b.reg_mod.test(i) && b2.reg_use[i])) { - if ((b.reg_use.test(i) && b.reg_mod.test(i)) || b2.reg_mod.test(i)) + if ((b.reg_use[i] && b.reg_mod.test(i)) || b2.reg_mod.test(i)) { reduced_loop->is_constant_expression = false; reduced_loop->loop_writes.set(i); @@ -7032,9 +7037,9 @@ spu_program spu_recompiler_base::analyse(const be_t* ls, u32 entry_point, s if (!reduced_loop->loop_dicts.test(i)) { - if (b.reg_use.test(i) || (!b.reg_mod.test(i) && b2.reg_use.test(i))) + if (b.reg_use[i] || (!b.reg_mod.test(i) && b2.reg_use[i])) { - if ((b.reg_use.test(i) && b.reg_mod.test(i)) || b2.reg_mod.test(i)) + if ((b.reg_use[i] && b.reg_mod.test(i)) || b2.reg_mod.test(i)) { reduced_loop->is_constant_expression = false; reduced_loop->loop_writes.set(i); diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 4348e7e08a..00d89127d6 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -739,8 +739,11 @@ protected: // Set if the initial register value in this block may be xfloat std::bitset reg_maybe_xf{}; - // Bit mask of the registers used (before modified) - std::bitset reg_use{}; + // Set if register is used in floating pont instruction + std::bitset reg_maybe_float{}; + + // Number of times registers are used (before modified) + std::array reg_use{}; // Bit mask of the trivial (u32 x 4) constant value resulting in this block std::bitset reg_const{};