SPU: Fix timer events

This commit is contained in:
Eladash 2020-08-20 20:36:49 +03:00 committed by Ivan
commit 841b8fad38
2 changed files with 13 additions and 19 deletions

View file

@ -1252,7 +1252,6 @@ void spu_recompiler::get_events()
Label label1 = c->newLabel(); Label label1 = c->newLabel();
Label rcheck = c->newLabel(); Label rcheck = c->newLabel();
Label tcheck = c->newLabel(); Label tcheck = c->newLabel();
Label treset = c->newLabel();
Label label2 = c->newLabel(); Label label2 = c->newLabel();
// Check if reservation exists // Check if reservation exists
@ -1323,17 +1322,21 @@ void spu_recompiler::get_events()
}); });
c->bind(label1); c->bind(label1);
c->cmp(SPU_OFF_32(ch_dec_value), 0); c->jmp(tcheck);
c->jnz(tcheck);
// Check decrementer event (unlikely) // Check decrementer event (unlikely)
after.emplace_back([=, this]() after.emplace_back([=, this]()
{ {
auto sub = [](spu_thread* _spu) 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); 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(); Label fail = c->newLabel();
after.emplace_back([=, this]() after.emplace_back([=, this]()

View file

@ -2362,9 +2362,12 @@ u32 spu_thread::get_events(bool waiting)
raddr = 0; raddr = 0;
} }
// SPU Decrementer Event // SPU Decrementer Event on underflow (use the upper 32-bits to determine it)
if (!ch_dec_value || (ch_dec_value - (get_timebased_time() - ch_dec_start_timestamp)) >> 31) 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) if ((ch_event_stat & SPU_EVENT_TM) == 0)
{ {
ch_event_stat |= SPU_EVENT_TM; ch_event_stat |= SPU_EVENT_TM;