SPU: Fix SPU_WrEventAck

This commit is contained in:
Elad 2025-12-02 08:18:26 +02:00
parent 7e8ed5ecc1
commit 834612a6e2

View file

@ -3378,7 +3378,7 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
if (raddr) if (raddr)
{ {
// Last check for event before we clear the reservation // Last check for event before we clear the reservation
if (~ch_events.load().events & SPU_EVENT_LR) if (!ch_events.load().count || ~ch_events.load().events & SPU_EVENT_LR)
{ {
if (raddr == addr) if (raddr == addr)
{ {
@ -3551,7 +3551,7 @@ void spu_thread::do_putlluc(const spu_mfc_cmd& args)
// Try to process PUTLLUC using PUTLLC when a reservation is active: // Try to process PUTLLUC using PUTLLC when a reservation is active:
// If it fails the reservation is cleared, LR event is set and we fallback to the main implementation // If it fails the reservation is cleared, LR event is set and we fallback to the main implementation
// All of this is done atomically in PUTLLC // All of this is done atomically in PUTLLC
if (!(ch_events.load().events & SPU_EVENT_LR) && do_putllc(args)) if ((!ch_events.load().count || !(ch_events.load().events & SPU_EVENT_LR)) && do_putllc(args))
{ {
// Success, return as our job was done here // Success, return as our job was done here
return; return;
@ -4125,7 +4125,7 @@ bool spu_thread::process_mfc_cmd()
if (raddr != addr) if (raddr != addr)
{ {
// Last check for event before we replace the reservation with a new one // Last check for event before we replace the reservation with a new one
if (~ch_events.load().events & SPU_EVENT_LR && reservation_check(raddr, rdata, addr)) if ((!ch_events.load().count || ~ch_events.load().events & SPU_EVENT_LR) && reservation_check(raddr, rdata, addr))
{ {
set_events(SPU_EVENT_LR); set_events(SPU_EVENT_LR);
} }
@ -6241,24 +6241,21 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
case SPU_WrEventAck: case SPU_WrEventAck:
{ {
if (!value)
{
return true;
}
// "Collect" events before final acknowledgment // "Collect" events before final acknowledgment
get_events(value | static_cast<u32>(ch_events.load().mask)); get_events(value | static_cast<u32>(ch_events.load().mask));
bool freeze_dec = false; bool freeze_dec = false;
const bool check_intr = ch_events.atomic_op([&](ch_events_t& events) ch_events.atomic_op([&](ch_events_t& events)
{ {
events.events &= ~value; events.events &= ~value;
freeze_dec = !!((value & SPU_EVENT_TM) & ~events.mask); freeze_dec = !!((value & SPU_EVENT_TM) & ~events.mask);
if (events.events & events.mask)
{
events.count = true;
return true;
}
return !!events.count;
}); });
if (!is_dec_frozen && freeze_dec) if (!is_dec_frozen && freeze_dec)
@ -6268,15 +6265,6 @@ bool spu_thread::set_ch_value(u32 ch, u32 value)
is_dec_frozen = true; is_dec_frozen = true;
} }
if (check_intr)
{
// Check interrupts in case count is 1
if (check_mfc_interrupts(pc + 4))
{
spu_runtime::g_escape(this);
}
}
return true; return true;
} }