diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index f91a3f00ac..cb4124c612 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -91,7 +91,7 @@ void spu_cache::initialize() } // SPU cache file (version + block size type) - const std::string loc = _main->cache + u8"spu-§" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v2.dat"; + const std::string loc = _main->cache + u8"spu-§" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v3.dat"; auto cache = std::make_shared(loc); @@ -814,14 +814,74 @@ std::vector spu_recompiler_base::block(const be_t* ls, u32 lsa) { bool reachable = false; - for (u32 pred : pair.second) + if (pair.first >= limit) { - if (pred >= lsa && pred < limit) + continue; + } + + // All (direct and indirect) predecessors to check + std::basic_string workload; + + // Bit array used to deduplicate workload list + workload.push_back(pair.first); + m_bits[pair.first / 4] = true; + + for (std::size_t i = 0; !reachable && i < workload.size(); i++) + { + for (u32 j = workload[i];; j -= 4) { - reachable = true; + // Go backward from an address until the entry point (=lsa) is reached + if (j == lsa) + { + reachable = true; + break; + } + + const auto found = m_preds.find(j); + + bool had_fallthrough = false; + + if (found != m_preds.end()) + { + for (u32 new_pred : found->second) + { + // Check whether the predecessor is previous instruction + if (new_pred == j - 4) + { + had_fallthrough = true; + continue; + } + + // Check whether in range and not already added + if (new_pred >= lsa && new_pred < limit && !m_bits[new_pred / 4]) + { + workload.push_back(new_pred); + m_bits[new_pred / 4] = true; + } + } + } + + // Check for possible fallthrough predecessor + if (!had_fallthrough) + { + if (result.at((j - lsa) / 4) == 0 || m_targets.count(j - 4)) + { + break; + } + } + + if (i == 0) + { + // TODO + } } } + for (u32 pred : workload) + { + m_bits[pred / 4] = false; + } + if (!reachable && pair.first < limit) { limit = pair.first; diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 0c880a4c97..d734013587 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -45,11 +45,15 @@ protected: // List of possible targets for the instruction ({} = next instruction, {-1} = no targets) std::unordered_map, value_hash> m_targets; - // List of block predecessors + // List of block predecessors (incomplete, doesn't include all fallthrough predecessors) std::unordered_map, value_hash> m_preds; std::shared_ptr m_cache; +private: + // For private use + std::bitset<0x10000> m_bits; + public: spu_recompiler_base();