mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
SPU Interrupt Enable Status implemented
SPU Interrupts are still NOT implemented
This commit is contained in:
parent
1519a2b468
commit
5bd83516ba
@ -224,9 +224,15 @@ bool RawSPUThread::WriteReg(const u32 addr, const u32 value)
|
|||||||
|
|
||||||
void RawSPUThread::Task()
|
void RawSPUThread::Task()
|
||||||
{
|
{
|
||||||
PC = npc.exchange(0) & ~3;
|
// get next PC and SPU Interrupt status
|
||||||
|
PC = npc.exchange(0);
|
||||||
|
|
||||||
|
set_interrupt_status((PC & 1) != 0);
|
||||||
|
|
||||||
|
PC &= 0x3FFFC;
|
||||||
|
|
||||||
SPUThread::Task();
|
SPUThread::Task();
|
||||||
|
|
||||||
npc.store(PC | 1);
|
// save next PC and current SPU Interrupt status
|
||||||
|
npc.store(PC | ((ch_event_stat.load() & SPU_EVENT_INTR_ENABLED) != 0));
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,24 @@ void spu_interpreter::DEFAULT(SPUThread& CPU, spu_opcode_t op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void spu_interpreter::set_interrupt_status(SPUThread& CPU, spu_opcode_t op)
|
||||||
|
{
|
||||||
|
if (op.e)
|
||||||
|
{
|
||||||
|
CPU.set_interrupt_status(true);
|
||||||
|
|
||||||
|
if (op.d)
|
||||||
|
{
|
||||||
|
throw EXCEPTION("Undefined behaviour");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op.d)
|
||||||
|
{
|
||||||
|
CPU.set_interrupt_status(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void spu_interpreter::STOP(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::STOP(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
CPU.stop_and_signal(op.opcode & 0x3fff);
|
CPU.stop_and_signal(op.opcode & 0x3fff);
|
||||||
@ -272,53 +290,37 @@ void spu_interpreter::WRCH(SPUThread& CPU, spu_opcode_t op)
|
|||||||
|
|
||||||
void spu_interpreter::BIZ(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BIZ(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CPU.GPR[op.rt]._u32[3] == 0)
|
if (CPU.GPR[op.rt]._u32[3] == 0)
|
||||||
{
|
{
|
||||||
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_interpreter::BINZ(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BINZ(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CPU.GPR[op.rt]._u32[3] != 0)
|
if (CPU.GPR[op.rt]._u32[3] != 0)
|
||||||
{
|
{
|
||||||
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_interpreter::BIHZ(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BIHZ(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CPU.GPR[op.rt]._u16[6] == 0)
|
if (CPU.GPR[op.rt]._u16[6] == 0)
|
||||||
{
|
{
|
||||||
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_interpreter::BIHNZ(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BIHNZ(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CPU.GPR[op.rt]._u16[6] != 0)
|
if (CPU.GPR[op.rt]._u16[6] != 0)
|
||||||
{
|
{
|
||||||
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,24 +336,16 @@ void spu_interpreter::STQX(SPUThread& CPU, spu_opcode_t op)
|
|||||||
|
|
||||||
void spu_interpreter::BI(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BI(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
CPU.PC = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0) - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_interpreter::BISL(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::BISL(SPUThread& CPU, spu_opcode_t op)
|
||||||
{
|
{
|
||||||
if (op.d || op.e)
|
|
||||||
{
|
|
||||||
throw EXCEPTION("Unimplemented interrupt flags (d=%d, e=%d)", op.d, op.e);
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 target = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0);
|
const u32 target = SPUOpcodes::branchTarget(CPU.GPR[op.ra]._u32[3], 0);
|
||||||
CPU.GPR[op.rt] = u128::from32r(CPU.PC + 4);
|
CPU.GPR[op.rt] = u128::from32r(CPU.PC + 4);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
set_interrupt_status(CPU, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spu_interpreter::IRET(SPUThread& CPU, spu_opcode_t op)
|
void spu_interpreter::IRET(SPUThread& CPU, spu_opcode_t op)
|
||||||
|
@ -315,17 +315,19 @@ private:
|
|||||||
}
|
}
|
||||||
void BIZ(u32 intr, u32 rt, u32 ra)
|
void BIZ(u32 intr, u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
switch (intr & 0x30)
|
|
||||||
{
|
|
||||||
case 0: break;
|
|
||||||
default: UNIMPLEMENTED(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
if (CPU.GPR[rt]._u32[3] == 0)
|
if (CPU.GPR[rt]._u32[3] == 0)
|
||||||
{
|
{
|
||||||
LOG5_OPCODE("taken (0x%x)", target);
|
LOG5_OPCODE("taken (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
|
||||||
|
switch (intr & 0x30)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
|
default: UNIMPLEMENTED(); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -334,17 +336,19 @@ private:
|
|||||||
}
|
}
|
||||||
void BINZ(u32 intr, u32 rt, u32 ra)
|
void BINZ(u32 intr, u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
switch (intr & 0x30)
|
|
||||||
{
|
|
||||||
case 0: break;
|
|
||||||
default: UNIMPLEMENTED(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
if (CPU.GPR[rt]._u32[3] != 0)
|
if (CPU.GPR[rt]._u32[3] != 0)
|
||||||
{
|
{
|
||||||
LOG5_OPCODE("taken (0x%x)", target);
|
LOG5_OPCODE("taken (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
|
||||||
|
switch (intr & 0x30)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
|
default: UNIMPLEMENTED(); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -353,17 +357,19 @@ private:
|
|||||||
}
|
}
|
||||||
void BIHZ(u32 intr, u32 rt, u32 ra)
|
void BIHZ(u32 intr, u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
switch (intr & 0x30)
|
|
||||||
{
|
|
||||||
case 0: break;
|
|
||||||
default: UNIMPLEMENTED(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
if (CPU.GPR[rt]._u16[6] == 0)
|
if (CPU.GPR[rt]._u16[6] == 0)
|
||||||
{
|
{
|
||||||
LOG5_OPCODE("taken (0x%x)", target);
|
LOG5_OPCODE("taken (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
|
||||||
|
switch (intr & 0x30)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
|
default: UNIMPLEMENTED(); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -372,17 +378,19 @@ private:
|
|||||||
}
|
}
|
||||||
void BIHNZ(u32 intr, u32 rt, u32 ra)
|
void BIHNZ(u32 intr, u32 rt, u32 ra)
|
||||||
{
|
{
|
||||||
switch (intr & 0x30)
|
|
||||||
{
|
|
||||||
case 0: break;
|
|
||||||
default: UNIMPLEMENTED(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
if (CPU.GPR[rt]._u16[6] != 0)
|
if (CPU.GPR[rt]._u16[6] != 0)
|
||||||
{
|
{
|
||||||
LOG5_OPCODE("taken (0x%x)", target);
|
LOG5_OPCODE("taken (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
|
||||||
|
switch (intr & 0x30)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
|
default: UNIMPLEMENTED(); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -401,28 +409,32 @@ private:
|
|||||||
}
|
}
|
||||||
void BI(u32 intr, u32 ra)
|
void BI(u32 intr, u32 ra)
|
||||||
{
|
{
|
||||||
switch (intr & 0x30)
|
|
||||||
{
|
|
||||||
case 0: break;
|
|
||||||
default: UNIMPLEMENTED(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
LOG5_OPCODE("branch (0x%x)", target);
|
LOG5_OPCODE("branch (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
}
|
|
||||||
void BISL(u32 intr, u32 rt, u32 ra)
|
|
||||||
{
|
|
||||||
switch (intr & 0x30)
|
switch (intr & 0x30)
|
||||||
{
|
{
|
||||||
case 0: break;
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
default: UNIMPLEMENTED(); return;
|
default: UNIMPLEMENTED(); return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
void BISL(u32 intr, u32 rt, u32 ra)
|
||||||
|
{
|
||||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||||
CPU.GPR[rt] = u128::from32r(CPU.PC + 4);
|
CPU.GPR[rt] = u128::from32r(CPU.PC + 4);
|
||||||
LOG5_OPCODE("branch (0x%x)", target);
|
LOG5_OPCODE("branch (0x%x)", target);
|
||||||
CPU.PC = target - 4;
|
CPU.PC = target - 4;
|
||||||
|
|
||||||
|
switch (intr & 0x30)
|
||||||
|
{
|
||||||
|
case 0: break;
|
||||||
|
case 0x10: CPU.set_interrupt_status(true);
|
||||||
|
case 0x20: CPU.set_interrupt_status(false);
|
||||||
|
default: UNIMPLEMENTED(); return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void IRET(u32 ra)
|
void IRET(u32 ra)
|
||||||
{
|
{
|
||||||
|
@ -88,6 +88,8 @@ namespace spu_interpreter
|
|||||||
{
|
{
|
||||||
void DEFAULT(SPUThread& CPU, spu_opcode_t op);
|
void DEFAULT(SPUThread& CPU, spu_opcode_t op);
|
||||||
|
|
||||||
|
void set_interrupt_status(SPUThread& CPU, spu_opcode_t op);
|
||||||
|
|
||||||
void STOP(SPUThread& CPU, spu_opcode_t op);
|
void STOP(SPUThread& CPU, spu_opcode_t op);
|
||||||
void LNOP(SPUThread& CPU, spu_opcode_t op);
|
void LNOP(SPUThread& CPU, spu_opcode_t op);
|
||||||
void SYNC(SPUThread& CPU, spu_opcode_t op);
|
void SYNC(SPUThread& CPU, spu_opcode_t op);
|
||||||
|
@ -208,7 +208,7 @@ void SPUThread::InitRegs()
|
|||||||
ch_snr1 = {};
|
ch_snr1 = {};
|
||||||
ch_snr2 = {};
|
ch_snr2 = {};
|
||||||
|
|
||||||
ch_event_mask = 0;
|
ch_event_mask = {};
|
||||||
ch_event_stat = {};
|
ch_event_stat = {};
|
||||||
last_raddr = 0;
|
last_raddr = 0;
|
||||||
|
|
||||||
@ -548,7 +548,7 @@ u32 SPUThread::get_events(bool waiting)
|
|||||||
// polling with atomically set/removed SPU_EVENT_WAITING flag
|
// polling with atomically set/removed SPU_EVENT_WAITING flag
|
||||||
return ch_event_stat.atomic_op([this](u32& stat) -> u32
|
return ch_event_stat.atomic_op([this](u32& stat) -> u32
|
||||||
{
|
{
|
||||||
if (u32 res = stat & ch_event_mask)
|
if (u32 res = stat & ch_event_mask.load())
|
||||||
{
|
{
|
||||||
stat &= ~SPU_EVENT_WAITING;
|
stat &= ~SPU_EVENT_WAITING;
|
||||||
return res;
|
return res;
|
||||||
@ -562,7 +562,7 @@ u32 SPUThread::get_events(bool waiting)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// simple polling
|
// simple polling
|
||||||
return ch_event_stat.load() & ch_event_mask;
|
return ch_event_stat.load() & ch_event_mask.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPUThread::set_events(u32 mask)
|
void SPUThread::set_events(u32 mask)
|
||||||
@ -587,6 +587,24 @@ void SPUThread::set_events(u32 mask)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SPUThread::set_interrupt_status(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
// detect enabling interrupts with events masked
|
||||||
|
if (u32 mask = ch_event_mask.load())
|
||||||
|
{
|
||||||
|
throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
ch_event_stat |= SPU_EVENT_INTR_ENABLED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ch_event_stat &= ~SPU_EVENT_INTR_ENABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 SPUThread::get_ch_count(u32 ch)
|
u32 SPUThread::get_ch_count(u32 ch)
|
||||||
{
|
{
|
||||||
if (Ini.HLELogging.GetValue())
|
if (Ini.HLELogging.GetValue())
|
||||||
@ -716,7 +734,7 @@ u32 SPUThread::get_ch_value(u32 ch)
|
|||||||
|
|
||||||
case SPU_RdEventMask:
|
case SPU_RdEventMask:
|
||||||
{
|
{
|
||||||
return ch_event_mask;
|
return ch_event_mask.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
case SPU_RdEventStat:
|
case SPU_RdEventStat:
|
||||||
@ -729,7 +747,7 @@ u32 SPUThread::get_ch_value(u32 ch)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch_event_mask & SPU_EVENT_LR)
|
if (ch_event_mask.load() & SPU_EVENT_LR)
|
||||||
{
|
{
|
||||||
// register waiter if polling reservation status is required
|
// register waiter if polling reservation status is required
|
||||||
vm::wait_op(*this, last_raddr, 128, WRAP_EXPR(get_events(true) || IsStopped()));
|
vm::wait_op(*this, last_raddr, 128, WRAP_EXPR(get_events(true) || IsStopped()));
|
||||||
@ -756,7 +774,9 @@ u32 SPUThread::get_ch_value(u32 ch)
|
|||||||
|
|
||||||
case SPU_RdMachStat:
|
case SPU_RdMachStat:
|
||||||
{
|
{
|
||||||
return 0; // hack (not isolated, interrupts disabled)
|
// HACK: "Not isolated" status
|
||||||
|
// Return SPU Interrupt status in LSB
|
||||||
|
return (ch_event_stat.load() & SPU_EVENT_INTR_ENABLED) != 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,12 +1127,19 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
|
|||||||
|
|
||||||
case SPU_WrEventMask:
|
case SPU_WrEventMask:
|
||||||
{
|
{
|
||||||
|
// detect masking events with enabled interrupt status
|
||||||
|
if (value && ch_event_stat.load() & SPU_EVENT_INTR_ENABLED)
|
||||||
|
{
|
||||||
|
throw EXCEPTION("SPU Interrupts not implemented (mask=0x%x)", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// detect masking unimplemented events
|
||||||
if (value & ~SPU_EVENT_IMPLEMENTED)
|
if (value & ~SPU_EVENT_IMPLEMENTED)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ch_event_mask = value;
|
ch_event_mask.store(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,9 @@ enum : u32
|
|||||||
|
|
||||||
SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR, // Mask of implemented events
|
SPU_EVENT_IMPLEMENTED = SPU_EVENT_LR, // Mask of implemented events
|
||||||
|
|
||||||
SPU_EVENT_WAITING = 0x80000000, // This bit is 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_INTR_ENABLED = 0x20000000, // Originally unused, represents "SPU Interrupts Enabled" status
|
||||||
};
|
};
|
||||||
|
|
||||||
// SPU Class 0 Interrupts
|
// SPU Class 0 Interrupts
|
||||||
@ -502,7 +504,7 @@ public:
|
|||||||
spu_channel_t ch_snr1; // SPU Signal Notification Register 1
|
spu_channel_t ch_snr1; // SPU Signal Notification Register 1
|
||||||
spu_channel_t ch_snr2; // SPU Signal Notification Register 2
|
spu_channel_t ch_snr2; // SPU Signal Notification Register 2
|
||||||
|
|
||||||
u32 ch_event_mask;
|
atomic_t<u32> ch_event_mask;
|
||||||
atomic_t<u32> ch_event_stat;
|
atomic_t<u32> ch_event_stat;
|
||||||
u32 last_raddr; // Last Reservation Address (0 if not set)
|
u32 last_raddr; // Last Reservation Address (0 if not set)
|
||||||
|
|
||||||
@ -558,6 +560,7 @@ public:
|
|||||||
|
|
||||||
u32 get_events(bool waiting = false);
|
u32 get_events(bool waiting = false);
|
||||||
void set_events(u32 mask);
|
void set_events(u32 mask);
|
||||||
|
void set_interrupt_status(bool enable);
|
||||||
u32 get_ch_count(u32 ch);
|
u32 get_ch_count(u32 ch);
|
||||||
u32 get_ch_value(u32 ch);
|
u32 get_ch_value(u32 ch);
|
||||||
void set_ch_value(u32 ch, u32 value);
|
void set_ch_value(u32 ch, u32 value);
|
||||||
|
@ -222,13 +222,12 @@ namespace vm
|
|||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
// catch exception thrown by predicate
|
// capture any exception possibly thrown by predicate
|
||||||
auto exception = std::current_exception();
|
auto exception = std::current_exception();
|
||||||
|
|
||||||
// set new predicate that will throw this exception from the original thread
|
// set new predicate that will throw this exception from the original thread
|
||||||
pred = [exception]() -> bool
|
pred = [exception]() -> bool
|
||||||
{
|
{
|
||||||
// rethrow exception
|
|
||||||
std::rethrow_exception(exception);
|
std::rethrow_exception(exception);
|
||||||
|
|
||||||
// dummy return value
|
// dummy return value
|
||||||
@ -241,10 +240,9 @@ namespace vm
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear predicate if succeeded
|
// clear predicate and signal
|
||||||
pred = nullptr;
|
pred = nullptr;
|
||||||
|
|
||||||
// signal if succeeded or an exception thrown
|
|
||||||
if (!thread->Signal())
|
if (!thread->Signal())
|
||||||
{
|
{
|
||||||
throw EXCEPTION("Thread already signaled");
|
throw EXCEPTION("Thread already signaled");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user