SPU: fixup for STOP 0w0

This commit is contained in:
Nekotekina 2020-01-21 15:51:55 +03:00
parent 9993df9b8b
commit ddda09607d
2 changed files with 18 additions and 2 deletions

View File

@ -1073,6 +1073,7 @@ void spu_thread::cpu_init()
run_ctrl.raw() = 0; run_ctrl.raw() = 0;
status.raw() = 0; status.raw() = 0;
npc.raw() = 0; npc.raw() = 0;
skip_npc_set = false;
int_ctrl[0].clear(); int_ctrl[0].clear();
int_ctrl[1].clear(); int_ctrl[1].clear();
@ -1086,7 +1087,14 @@ void spu_thread::cpu_stop()
if (!group && offset >= RAW_SPU_BASE_ADDR) if (!group && offset >= RAW_SPU_BASE_ADDR)
{ {
// Save next PC and current SPU Interrupt Status // Save next PC and current SPU Interrupt Status
npc = pc | (interrupts_enabled); if (skip_npc_set)
{
skip_npc_set = false;
}
else
{
npc = pc | interrupts_enabled;
}
} }
else if (group && is_stopped()) else if (group && is_stopped())
{ {
@ -1126,6 +1134,8 @@ void spu_thread::cpu_task()
// Get next PC and SPU Interrupt status // Get next PC and SPU Interrupt status
pc = npc.exchange(0); pc = npc.exchange(0);
skip_npc_set = false;
set_interrupt_status((pc & 1) != 0); set_interrupt_status((pc & 1) != 0);
pc &= 0x3fffc; pc &= 0x3fffc;
@ -1150,7 +1160,8 @@ void spu_thread::cpu_task()
if (_ref<u32>(pc) == 0x0) if (_ref<u32>(pc) == 0x0)
{ {
spu_thread::stop_and_signal(0x0); if (spu_thread::stop_and_signal(0x0))
pc += 4;
continue; continue;
} }
@ -2773,6 +2784,9 @@ bool spu_thread::stop_and_signal(u32 code)
if (offset >= RAW_SPU_BASE_ADDR) if (offset >= RAW_SPU_BASE_ADDR)
{ {
// Save next PC and current SPU Interrupt Status
npc = (pc + 4) | (interrupts_enabled);
skip_npc_set = true;
state += cpu_flag::stop + cpu_flag::wait; state += cpu_flag::stop + cpu_flag::wait;
status.atomic_op([code](u32& status) status.atomic_op([code](u32& status)
{ {

View File

@ -560,6 +560,8 @@ public:
atomic_t<u32> ch_event_stat; atomic_t<u32> ch_event_stat;
atomic_t<bool> interrupts_enabled; atomic_t<bool> interrupts_enabled;
bool skip_npc_set = false;
u64 ch_dec_start_timestamp; // timestamp of writing decrementer value u64 ch_dec_start_timestamp; // timestamp of writing decrementer value
u32 ch_dec_value; // written decrementer value u32 ch_dec_value; // written decrementer value