diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 3e34d762ae..e8f3df2afc 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1252,7 +1252,6 @@ void spu_recompiler::get_events() Label label1 = c->newLabel(); Label rcheck = c->newLabel(); Label tcheck = c->newLabel(); - Label treset = c->newLabel(); Label label2 = c->newLabel(); // Check if reservation exists @@ -1323,17 +1322,21 @@ void spu_recompiler::get_events() }); c->bind(label1); - c->cmp(SPU_OFF_32(ch_dec_value), 0); - c->jnz(tcheck); + c->jmp(tcheck); // Check decrementer event (unlikely) after.emplace_back([=, this]() { auto sub = [](spu_thread* _spu) { - if ((_spu->ch_dec_value - (get_timebased_time() - _spu->ch_dec_start_timestamp)) >> 31) + if (const u64 res = (_spu->ch_dec_value - (get_timebased_time() - _spu->ch_dec_start_timestamp)) >> 32) { - _spu->ch_event_stat |= SPU_EVENT_TM; + _spu->ch_dec_start_timestamp -= res << 32; + + if (!(_spu->ch_event_stat & SPU_EVENT_TM)) + { + _spu->ch_event_stat |= SPU_EVENT_TM; + } } }; @@ -1343,18 +1346,6 @@ void spu_recompiler::get_events() c->jmp(label2); }); - // Check whether SPU_EVENT_TM is already set - c->bt(SPU_OFF_32(ch_event_stat), 5); - c->jnc(treset); - - // Set SPU_EVENT_TM (unlikely) - after.emplace_back([=, this]() - { - c->bind(treset); - c->lock().bts(SPU_OFF_32(ch_event_stat), 5); - c->jmp(label2); - }); - Label fail = c->newLabel(); after.emplace_back([=, this]() diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 7d83130ed3..8e7ebc043b 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -2362,9 +2362,12 @@ u32 spu_thread::get_events(bool waiting) raddr = 0; } - // SPU Decrementer Event - if (!ch_dec_value || (ch_dec_value - (get_timebased_time() - ch_dec_start_timestamp)) >> 31) + // SPU Decrementer Event on underflow (use the upper 32-bits to determine it) + if (const u64 res = (ch_dec_value - (get_timebased_time() - ch_dec_start_timestamp)) >> 32) { + // Set next event to the next time the decrementer underflows + ch_dec_start_timestamp -= res << 32; + if ((ch_event_stat & SPU_EVENT_TM) == 0) { ch_event_stat |= SPU_EVENT_TM;