mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-27 18:41:10 +00:00
spu: Fix interrupt jump check - also change interrupt variable to atomic bool for ease of setting/checking
This commit is contained in:
parent
34e01ba3d8
commit
d17093e65b
@ -21,7 +21,7 @@ void RawSPUThread::cpu_task()
|
|||||||
SPUThread::cpu_task();
|
SPUThread::cpu_task();
|
||||||
|
|
||||||
// save next PC and current SPU Interrupt status
|
// save next PC and current SPU Interrupt status
|
||||||
npc = pc | ((ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0);
|
npc = pc | (interrupts_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawSPUThread::on_init(const std::shared_ptr<void>& _this)
|
void RawSPUThread::on_init(const std::shared_ptr<void>& _this)
|
||||||
|
@ -376,12 +376,12 @@ void spu_recompiler::FunctionCall()
|
|||||||
fmt::throw_exception("Undefined behaviour" HERE);
|
fmt::throw_exception("Undefined behaviour" HERE);
|
||||||
}
|
}
|
||||||
|
|
||||||
_spu->set_interrupt_status(true);
|
_spu->interrupts_enabled = true;
|
||||||
_spu->pc &= ~0x4000000;
|
_spu->pc &= ~0x4000000;
|
||||||
}
|
}
|
||||||
else if (_spu->pc & 0x8000000)
|
else if (_spu->pc & 0x8000000)
|
||||||
{
|
{
|
||||||
_spu->set_interrupt_status(false);
|
_spu->interrupts_enabled = false;
|
||||||
_spu->pc &= ~0x8000000;
|
_spu->pc &= ~0x8000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,9 +50,9 @@ void spu_interpreter::set_interrupt_status(SPUThread& spu, spu_opcode_t op)
|
|||||||
spu.set_interrupt_status(false);
|
spu.set_interrupt_status(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((spu.ch_event_stat & SPU_EVENT_INTR_TEST & spu.ch_event_mask) > SPU_EVENT_INTR_ENABLED)
|
if (spu.interrupts_enabled && (spu.ch_event_mask & spu.ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0)
|
||||||
{
|
{
|
||||||
spu.ch_event_stat &= ~SPU_EVENT_INTR_ENABLED;
|
spu.interrupts_enabled = false;
|
||||||
spu.srr0 = std::exchange(spu.pc, -4) + 4;
|
spu.srr0 = std::exchange(spu.pc, -4) + 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,9 @@ void spu_recompiler_base::enter(SPUThread& spu)
|
|||||||
|
|
||||||
spu.pc = res & 0x3fffc;
|
spu.pc = res & 0x3fffc;
|
||||||
|
|
||||||
if ((spu.ch_event_stat & SPU_EVENT_INTR_TEST & spu.ch_event_mask) > SPU_EVENT_INTR_ENABLED)
|
if (spu.interrupts_enabled && (spu.ch_event_mask & spu.ch_event_stat & SPU_EVENT_INTR_IMPLEMENTED) > 0)
|
||||||
{
|
{
|
||||||
spu.ch_event_stat &= ~SPU_EVENT_INTR_ENABLED;
|
spu.interrupts_enabled = false;
|
||||||
spu.srr0 = std::exchange(spu.pc, 0);
|
spu.srr0 = std::exchange(spu.pc, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,7 @@ void SPUThread::cpu_init()
|
|||||||
|
|
||||||
ch_event_mask = 0;
|
ch_event_mask = 0;
|
||||||
ch_event_stat = 0;
|
ch_event_stat = 0;
|
||||||
|
interrupts_enabled = false;
|
||||||
raddr = 0;
|
raddr = 0;
|
||||||
|
|
||||||
ch_dec_start_timestamp = get_timebased_time(); // ???
|
ch_dec_start_timestamp = get_timebased_time(); // ???
|
||||||
@ -974,12 +975,11 @@ void SPUThread::set_interrupt_status(bool enable)
|
|||||||
{
|
{
|
||||||
fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, mask);
|
fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, mask);
|
||||||
}
|
}
|
||||||
|
interrupts_enabled = true;
|
||||||
ch_event_stat |= SPU_EVENT_INTR_ENABLED;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ch_event_stat &= ~SPU_EVENT_INTR_ENABLED;
|
interrupts_enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,7 +1165,7 @@ bool SPUThread::get_ch_value(u32 ch, u32& out)
|
|||||||
{
|
{
|
||||||
// HACK: "Not isolated" status
|
// HACK: "Not isolated" status
|
||||||
// Return SPU Interrupt status in LSB
|
// Return SPU Interrupt status in LSB
|
||||||
out = (ch_event_stat & SPU_EVENT_INTR_ENABLED) != 0;
|
out = interrupts_enabled == true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1467,7 +1467,7 @@ bool SPUThread::set_ch_value(u32 ch, u32 value)
|
|||||||
case SPU_WrEventMask:
|
case SPU_WrEventMask:
|
||||||
{
|
{
|
||||||
// detect masking events with enabled interrupt status
|
// detect masking events with enabled interrupt status
|
||||||
if (value & ~SPU_EVENT_INTR_IMPLEMENTED && ch_event_stat & SPU_EVENT_INTR_ENABLED)
|
if (value & ~SPU_EVENT_INTR_IMPLEMENTED && interrupts_enabled)
|
||||||
{
|
{
|
||||||
fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, value);
|
fmt::throw_exception("SPU Interrupts not implemented (mask=0x%x)" HERE, value);
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,9 @@ enum : u32
|
|||||||
|
|
||||||
SPU_EVENT_WAITING = 0x80000000, // Originally unused, set when SPU thread starts waiting on ch_event_stat
|
SPU_EVENT_WAITING = 0x80000000, // Originally unused, set when SPU thread starts waiting on ch_event_stat
|
||||||
//SPU_EVENT_AVAILABLE = 0x40000000, // Originally unused, channel count of the SPU_RdEventStat channel
|
//SPU_EVENT_AVAILABLE = 0x40000000, // Originally unused, channel count of the SPU_RdEventStat channel
|
||||||
SPU_EVENT_INTR_ENABLED = 0x20000000, // Originally unused, represents "SPU Interrupts Enabled" status
|
//SPU_EVENT_INTR_ENABLED = 0x20000000, // Originally unused, represents "SPU Interrupts Enabled" status
|
||||||
|
|
||||||
SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_ENABLED | SPU_EVENT_INTR_IMPLEMENTED
|
SPU_EVENT_INTR_TEST = SPU_EVENT_INTR_IMPLEMENTED
|
||||||
};
|
};
|
||||||
|
|
||||||
// SPU Class 0 Interrupts
|
// SPU Class 0 Interrupts
|
||||||
@ -562,6 +562,7 @@ public:
|
|||||||
|
|
||||||
atomic_t<u32> ch_event_mask;
|
atomic_t<u32> ch_event_mask;
|
||||||
atomic_t<u32> ch_event_stat;
|
atomic_t<u32> ch_event_stat;
|
||||||
|
atomic_t<bool> interrupts_enabled;
|
||||||
|
|
||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user