mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-03 21:41:26 +12:00
SPU/Savestates: Remove reservation hack, allow its saving
This commit is contained in:
parent
e209dc1229
commit
9f6c5381a1
2 changed files with 52 additions and 16 deletions
|
@ -4521,6 +4521,18 @@ class spu_llvm_recompiler : public spu_recompiler_base, public cpu_translator
|
||||||
std::array<usz, s_reg_max> store_context_last_id = fill_array<usz>(0); // Protects against illegal forward ordering
|
std::array<usz, s_reg_max> store_context_last_id = fill_array<usz>(0); // Protects against illegal forward ordering
|
||||||
std::array<usz, s_reg_max> store_context_first_id = fill_array<usz>(usz{umax}); // Protects against illegal past store elimination (backwards ordering is not implemented)
|
std::array<usz, s_reg_max> store_context_first_id = fill_array<usz>(usz{umax}); // Protects against illegal past store elimination (backwards ordering is not implemented)
|
||||||
std::array<usz, s_reg_max> store_context_ctr = fill_array<usz>(1); // Store barrier cointer
|
std::array<usz, s_reg_max> store_context_ctr = fill_array<usz>(1); // Store barrier cointer
|
||||||
|
|
||||||
|
bool does_gpr_barrier_proceed_last_store(u32 i) const noexcept
|
||||||
|
{
|
||||||
|
const usz counter = store_context_ctr[i];
|
||||||
|
return counter != 1 && counter > store_context_last_id[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool does_gpr_barrier_preceed_first_store(u32 i) const noexcept
|
||||||
|
{
|
||||||
|
const usz counter = store_context_ctr[i];
|
||||||
|
return counter != 1 && counter < store_context_first_id[i];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct function_info
|
struct function_info
|
||||||
|
@ -6019,7 +6031,7 @@ public:
|
||||||
for (u32 i = 0; i < 128; i++)
|
for (u32 i = 0; i < 128; i++)
|
||||||
{
|
{
|
||||||
// Check if the store is beyond the last barrier
|
// Check if the store is beyond the last barrier
|
||||||
if (auto& bs = bqbi->store[i]; bs && bqbi->store_context_last_id[i] == bqbi->store_context_ctr[i])
|
if (auto& bs = bqbi->store[i]; bs && !bqbi->does_gpr_barrier_proceed_last_store(i))
|
||||||
{
|
{
|
||||||
for (auto& [a, b] : m_blocks)
|
for (auto& [a, b] : m_blocks)
|
||||||
{
|
{
|
||||||
|
@ -6107,7 +6119,7 @@ public:
|
||||||
auto* cur = work_list[wi];
|
auto* cur = work_list[wi];
|
||||||
if (std::count(killers.begin(), killers.end(), cur))
|
if (std::count(killers.begin(), killers.end(), cur))
|
||||||
{
|
{
|
||||||
work2_list.emplace_back(cur, bb_to_info[cur] && bb_to_info[cur]->store_context_first_id[i] > 1);
|
work2_list.emplace_back(cur, bb_to_info[cur] && bb_to_info[cur]->does_gpr_barrier_preceed_first_store(i));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6145,17 +6157,7 @@ public:
|
||||||
{
|
{
|
||||||
auto [cur, found_user] = work2_list[wi];
|
auto [cur, found_user] = work2_list[wi];
|
||||||
|
|
||||||
if (cur == bs->getParent())
|
ensure(cur != bs->getParent());
|
||||||
{
|
|
||||||
if (found_user)
|
|
||||||
{
|
|
||||||
// Reset: store is being used and preserved by ensure_gpr_stores()
|
|
||||||
killers.clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found_user && wi >= work_list_tail_blocks_max_index)
|
if (!found_user && wi >= work_list_tail_blocks_max_index)
|
||||||
{
|
{
|
||||||
|
@ -6170,6 +6172,18 @@ public:
|
||||||
|
|
||||||
for (auto* p : llvm::predecessors(cur))
|
for (auto* p : llvm::predecessors(cur))
|
||||||
{
|
{
|
||||||
|
if (p == bs->getParent())
|
||||||
|
{
|
||||||
|
if (found_user)
|
||||||
|
{
|
||||||
|
// Reset: store is being used and preserved by ensure_gpr_stores()
|
||||||
|
killers.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!worked_on[p])
|
if (!worked_on[p])
|
||||||
{
|
{
|
||||||
worked_on[p] = true;
|
worked_on[p] = true;
|
||||||
|
@ -6181,6 +6195,11 @@ public:
|
||||||
work2_list.push_back(std::make_pair(p, true));
|
work2_list.push_back(std::make_pair(p, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (killers.empty())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally erase the dead store
|
// Finally erase the dead store
|
||||||
|
@ -6207,7 +6226,7 @@ public:
|
||||||
for (u32 i = 0; i < 128; i++)
|
for (u32 i = 0; i < 128; i++)
|
||||||
{
|
{
|
||||||
// If store isn't erased, try to sink it
|
// If store isn't erased, try to sink it
|
||||||
if (auto& bs = block_q[bi]->store[i]; bs && block_q[bi]->bb->targets.size() > 1 && block_q[bi]->store_context_last_id[i] == block_q[bi]->store_context_ctr[i])
|
if (auto& bs = block_q[bi]->store[i]; bs && block_q[bi]->bb->targets.size() > 1 && !block_q[bi]->does_gpr_barrier_proceed_last_store(i))
|
||||||
{
|
{
|
||||||
std::map<u32, block_info*, std::greater<>> sucs;
|
std::map<u32, block_info*, std::greater<>> sucs;
|
||||||
|
|
||||||
|
|
|
@ -2022,6 +2022,20 @@ spu_thread::spu_thread(utils::serial& ar, lv2_spu_group* group)
|
||||||
|
|
||||||
serialize_common(ar);
|
serialize_common(ar);
|
||||||
|
|
||||||
|
raddr = ::narrow<u32>(ar.pop<u64>());
|
||||||
|
|
||||||
|
if (raddr)
|
||||||
|
{
|
||||||
|
// Acquire reservation
|
||||||
|
if (!vm::check_addr(raddr))
|
||||||
|
{
|
||||||
|
fmt::throw_exception("SPU Serialization: Reservation address is not accessible! (addr=0x%x)", raddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtime = vm::reservation_acquire(raddr);
|
||||||
|
mov_rdata(rdata, *vm::get_super_ptr<spu_rdata_t>(raddr));
|
||||||
|
}
|
||||||
|
|
||||||
status_npc.raw().npc = pc | u8{interrupts_enabled};
|
status_npc.raw().npc = pc | u8{interrupts_enabled};
|
||||||
|
|
||||||
if (get_type() == spu_type::threaded)
|
if (get_type() == spu_type::threaded)
|
||||||
|
@ -2058,8 +2072,8 @@ void spu_thread::save(utils::serial& ar)
|
||||||
|
|
||||||
if (raddr)
|
if (raddr)
|
||||||
{
|
{
|
||||||
// Lose reservation at savestate load with an event if one existed at savestate save
|
// Last check for reservation-lost event
|
||||||
set_events(SPU_EVENT_LR);
|
get_events(SPU_EVENT_LR);
|
||||||
}
|
}
|
||||||
|
|
||||||
ar(index);
|
ar(index);
|
||||||
|
@ -2073,6 +2087,9 @@ void spu_thread::save(utils::serial& ar)
|
||||||
|
|
||||||
serialize_common(ar);
|
serialize_common(ar);
|
||||||
|
|
||||||
|
// Let's save it as u64 for future proofing
|
||||||
|
ar(u64{raddr});
|
||||||
|
|
||||||
if (get_type() == spu_type::threaded)
|
if (get_type() == spu_type::threaded)
|
||||||
{
|
{
|
||||||
for (const auto& [key, q] : spuq)
|
for (const auto& [key, q] : spuq)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue