SPU: Fix timer events

This commit is contained in:
Eladash 2020-08-20 20:36:49 +03:00 committed by Ivan
parent ab0df0a0f5
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 rcheck = c->newLabel();
Label tcheck = c->newLabel();
Label treset = c->newLabel();
Label label2 = c->newLabel();
// Check if reservation exists
@ -1323,18 +1322,22 @@ 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_dec_start_timestamp -= res << 32;
if (!(_spu->ch_event_stat & SPU_EVENT_TM))
{
_spu->ch_event_stat |= SPU_EVENT_TM;
}
}
};
c->bind(tcheck);
@ -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]()

View File

@ -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;