Merge pull request #1987 from magumagu/thread-safety
Cleanup usage of atomic/threadsafe functions
This commit is contained in:
commit
d9988ee9b5
|
@ -224,6 +224,7 @@ u64 GetIdleTicks()
|
||||||
// schedule things to be executed on the main thread.
|
// schedule things to be executed on the main thread.
|
||||||
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata)
|
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata)
|
||||||
{
|
{
|
||||||
|
_assert_msg_(POWERPC, !Core::IsCPUThread(), "ScheduleEvent_Threadsafe from wrong thread");
|
||||||
std::lock_guard<std::mutex> lk(tsWriteLock);
|
std::lock_guard<std::mutex> lk(tsWriteLock);
|
||||||
Event ne;
|
Event ne;
|
||||||
ne.time = globalTimer + cyclesIntoFuture;
|
ne.time = globalTimer + cyclesIntoFuture;
|
||||||
|
@ -279,6 +280,7 @@ static void AddEventToQueue(Event* ne)
|
||||||
// than Advance
|
// than Advance
|
||||||
void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
|
void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
|
||||||
{
|
{
|
||||||
|
_assert_msg_(POWERPC, Core::IsCPUThread(), "ScheduleEvent from wrong thread");
|
||||||
Event *ne = GetNewEvent();
|
Event *ne = GetNewEvent();
|
||||||
ne->userdata = userdata;
|
ne->userdata = userdata;
|
||||||
ne->type = event_type;
|
ne->type = event_type;
|
||||||
|
|
|
@ -427,7 +427,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
// We make the samples ready as soon as possible
|
// We make the samples ready as soon as possible
|
||||||
void *address = Memory::GetPointer(g_audioDMA.SourceAddress);
|
void *address = Memory::GetPointer(g_audioDMA.SourceAddress);
|
||||||
AudioCommon::SendAIBuffer((short*)address, g_audioDMA.AudioDMAControl.NumBlocks * 8);
|
AudioCommon::SendAIBuffer((short*)address, g_audioDMA.AudioDMAControl.NumBlocks * 8);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(80, et_GenerateDSPInterrupt, INT_AID);
|
CoreTiming::ScheduleEvent(80, et_GenerateDSPInterrupt, INT_AID);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -477,6 +477,7 @@ static void GenerateDSPInterrupt(u64 DSPIntType, int cyclesLate)
|
||||||
// CALLED FROM DSP EMULATOR, POSSIBLY THREADED
|
// CALLED FROM DSP EMULATOR, POSSIBLY THREADED
|
||||||
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type)
|
void GenerateDSPInterruptFromDSPEmu(DSPInterruptType type)
|
||||||
{
|
{
|
||||||
|
// TODO: Maybe rethink this? ScheduleEvent_Threadsafe has unpredictable timing.
|
||||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(et_GenerateDSPInterrupt, type);
|
CoreTiming::ScheduleEvent_Threadsafe_Immediate(et_GenerateDSPInterrupt, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +544,7 @@ static void Do_ARAM_DMA()
|
||||||
if (instant_dma)
|
if (instant_dma)
|
||||||
ticksToTransfer = 0;
|
ticksToTransfer = 0;
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(ticksToTransfer, et_CompleteARAM);
|
CoreTiming::ScheduleEvent(ticksToTransfer, et_CompleteARAM);
|
||||||
|
|
||||||
if (instant_dma)
|
if (instant_dma)
|
||||||
CoreTiming::ForceExceptionCheck(100);
|
CoreTiming::ForceExceptionCheck(100);
|
||||||
|
|
|
@ -447,6 +447,7 @@ void ChangeDisc(const std::string& newFileName)
|
||||||
std::string* _FileName = new std::string(newFileName);
|
std::string* _FileName = new std::string(newFileName);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, ejectDisc);
|
CoreTiming::ScheduleEvent_Threadsafe(0, ejectDisc);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(500000000, insertDisc, (u64)_FileName);
|
CoreTiming::ScheduleEvent_Threadsafe(500000000, insertDisc, (u64)_FileName);
|
||||||
|
// TODO: We shouldn't be modifying movie state from the GUI thread.
|
||||||
if (Movie::IsRecordingInput())
|
if (Movie::IsRecordingInput())
|
||||||
{
|
{
|
||||||
Movie::g_bDiscChange = true;
|
Movie::g_bDiscChange = true;
|
||||||
|
|
|
@ -647,7 +647,7 @@ static void GenerateDSIException(u32 effectiveAddress, bool write)
|
||||||
|
|
||||||
PowerPC::ppcState.spr[SPR_DAR] = effectiveAddress;
|
PowerPC::ppcState.spr[SPR_DAR] = effectiveAddress;
|
||||||
|
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -656,7 +656,7 @@ static void GenerateISIException(u32 _EffectiveAddress)
|
||||||
// Address of instruction could not be translated
|
// Address of instruction could not be translated
|
||||||
NPC = _EffectiveAddress;
|
NPC = _EffectiveAddress;
|
||||||
|
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ISI);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
|
|
||||||
|
#include "Core/Core.h"
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/CPU.h"
|
#include "Core/HW/CPU.h"
|
||||||
#include "Core/HW/GPFifo.h"
|
#include "Core/HW/GPFifo.h"
|
||||||
|
@ -159,9 +160,9 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
void UpdateException()
|
void UpdateException()
|
||||||
{
|
{
|
||||||
if ((m_InterruptCause & m_InterruptMask) != 0)
|
if ((m_InterruptCause & m_InterruptMask) != 0)
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_EXTERNAL_INT);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_EXTERNAL_INT;
|
||||||
else
|
else
|
||||||
Common::AtomicAnd(PowerPC::ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
|
PowerPC::ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *Debug_GetInterruptName(u32 _causemask)
|
static const char *Debug_GetInterruptName(u32 _causemask)
|
||||||
|
@ -190,7 +191,7 @@ static const char *Debug_GetInterruptName(u32 _causemask)
|
||||||
|
|
||||||
void SetInterrupt(u32 _causemask, bool _bSet)
|
void SetInterrupt(u32 _causemask, bool _bSet)
|
||||||
{
|
{
|
||||||
// TODO(ector): add sanity check that current thread id is CPU thread
|
_assert_msg_(POWERPC, Core::IsCPUThread(), "SetInterrupt from wrong thread");
|
||||||
|
|
||||||
if (_bSet && !(m_InterruptCause & _causemask))
|
if (_bSet && !(m_InterruptCause & _causemask))
|
||||||
{
|
{
|
||||||
|
|
|
@ -492,6 +492,7 @@ void ChangeDevice(SIDevices device, int channel)
|
||||||
{
|
{
|
||||||
// Called from GUI, so we need to make it thread safe.
|
// Called from GUI, so we need to make it thread safe.
|
||||||
// Let the hardware see no device for .5b cycles
|
// Let the hardware see no device for .5b cycles
|
||||||
|
// TODO: Calling GetDeviceType here isn't threadsafe.
|
||||||
if (GetDeviceType(channel) != device)
|
if (GetDeviceType(channel) != device)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
|
CoreTiming::ScheduleEvent_Threadsafe(0, changeDevice, ((u64)channel << 32) | SIDEVICE_NONE);
|
||||||
|
|
|
@ -157,7 +157,7 @@ static void CPCallback(u64 userdata, int cyclesLate)
|
||||||
static void DecrementerCallback(u64 userdata, int cyclesLate)
|
static void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecrementerSet()
|
void DecrementerSet()
|
||||||
|
|
|
@ -162,7 +162,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
if (ctrl.X1)
|
if (ctrl.X1)
|
||||||
WII_IPC_HLE_Interface::EnqueueRequest(ppc_msg);
|
WII_IPC_HLE_Interface::EnqueueRequest(ppc_msg);
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::Update();
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -176,7 +176,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
MMIO::ComplexWrite<u32>([](u32, u32 val) {
|
||||||
ppc_irq_flags &= ~val;
|
ppc_irq_flags &= ~val;
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::Update();
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
|
||||||
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
|
if (ppc_irq_masks & INT_CAUSE_IPC_BROADWAY) // wtf?
|
||||||
Reset();
|
Reset();
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::Update();
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ void GenerateAck(u32 _Address)
|
||||||
ctrl.Y2 = 1;
|
ctrl.Y2 = 1;
|
||||||
INFO_LOG(WII_IPC, "GenerateAck: %08x | %08x [R:%i A:%i E:%i]",
|
INFO_LOG(WII_IPC, "GenerateAck: %08x | %08x [R:%i A:%i E:%i]",
|
||||||
ppc_msg,_Address, ctrl.Y1, ctrl.Y2, ctrl.X1);
|
ppc_msg,_Address, ctrl.Y1, ctrl.Y2, ctrl.X1);
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, updateInterrupts, 0);
|
CoreTiming::ScheduleEvent(0, updateInterrupts, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateReply(u32 _Address)
|
void GenerateReply(u32 _Address)
|
||||||
|
|
|
@ -146,7 +146,7 @@ int Interpreter::SingleStepInner()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
m_EndBlock = true;
|
m_EndBlock = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ void Interpreter::rfid(UGeckoInstruction _inst)
|
||||||
// We do it anyway, though :P
|
// We do it anyway, though :P
|
||||||
void Interpreter::sc(UGeckoInstruction _inst)
|
void Interpreter::sc(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_SYSCALL);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_SYSCALL;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
m_EndBlock = true;
|
m_EndBlock = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ void Interpreter::twi(UGeckoInstruction _inst)
|
||||||
(((u32)a <(u32)b) && (TO & 0x02)) ||
|
(((u32)a <(u32)b) && (TO & 0x02)) ||
|
||||||
(((u32)a >(u32)b) && (TO & 0x01)))
|
(((u32)a >(u32)b) && (TO & 0x01)))
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
m_EndBlock = true; // Dunno about this
|
m_EndBlock = true; // Dunno about this
|
||||||
}
|
}
|
||||||
|
@ -423,7 +423,7 @@ void Interpreter::tw(UGeckoInstruction _inst)
|
||||||
(((u32)a <(u32)b) && (TO & 0x02)) ||
|
(((u32)a <(u32)b) && (TO & 0x02)) ||
|
||||||
(((u32)a >(u32)b) && (TO & 0x01)))
|
(((u32)a >(u32)b) && (TO & 0x01)))
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM;
|
||||||
PowerPC::CheckExceptions();
|
PowerPC::CheckExceptions();
|
||||||
m_EndBlock = true; // Dunno about this
|
m_EndBlock = true; // Dunno about this
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,10 +395,10 @@ void Interpreter::eciwx(UGeckoInstruction _inst)
|
||||||
|
|
||||||
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||||
}
|
}
|
||||||
if (EA & 3)
|
if (EA & 3)
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ALIGNMENT);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
|
||||||
|
|
||||||
// _assert_msg_(POWERPC,0,"eciwx - fill r%i with word @ %08x from device %02x",
|
// _assert_msg_(POWERPC,0,"eciwx - fill r%i with word @ %08x from device %02x",
|
||||||
// _inst.RS, EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
// _inst.RS, EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
||||||
|
@ -417,10 +417,10 @@ void Interpreter::ecowx(UGeckoInstruction _inst)
|
||||||
|
|
||||||
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
||||||
{
|
{
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||||
}
|
}
|
||||||
if (EA & 3)
|
if (EA & 3)
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ALIGNMENT);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
|
||||||
|
|
||||||
// _assert_msg_(POWERPC,0,"ecowx - send stw request (%08x@%08x) to device %02x",
|
// _assert_msg_(POWERPC,0,"ecowx - send stw request (%08x@%08x) to device %02x",
|
||||||
// rGPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
// rGPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);
|
||||||
|
|
|
@ -344,7 +344,7 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
||||||
if (!(oldValue >> 31) && (rGPR[_inst.RD]>>31)) //top bit from 0 to 1
|
if (!(oldValue >> 31) && (rGPR[_inst.RD]>>31)) //top bit from 0 to 1
|
||||||
{
|
{
|
||||||
PanicAlert("Interesting - Software triggered Decrementer exception");
|
PanicAlert("Interesting - Software triggered Decrementer exception");
|
||||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER;
|
||||||
}
|
}
|
||||||
SystemTimers::DecrementerSet();
|
SystemTimers::DecrementerSet();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under GPLv2
|
// Licensed under GPLv2
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "Common/Atomic.h"
|
|
||||||
#include "Common/ChunkFile.h"
|
#include "Common/ChunkFile.h"
|
||||||
#include "Common/CommonTypes.h"
|
#include "Common/CommonTypes.h"
|
||||||
#include "Common/FPURoundMode.h"
|
#include "Common/FPURoundMode.h"
|
||||||
|
@ -311,7 +310,6 @@ void UpdatePerformanceMonitor(u32 cycles, u32 num_load_stores, u32 num_fp_inst)
|
||||||
|
|
||||||
void CheckExceptions()
|
void CheckExceptions()
|
||||||
{
|
{
|
||||||
// Read volatile data once
|
|
||||||
u32 exceptions = ppcState.Exceptions;
|
u32 exceptions = ppcState.Exceptions;
|
||||||
|
|
||||||
// Example procedure:
|
// Example procedure:
|
||||||
|
@ -341,7 +339,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000400;
|
PC = NPC = 0x00000400;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_ISI");
|
INFO_LOG(POWERPC, "EXCEPTION_ISI");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_ISI);
|
ppcState.Exceptions &= ~EXCEPTION_ISI;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_PROGRAM)
|
else if (exceptions & EXCEPTION_PROGRAM)
|
||||||
{
|
{
|
||||||
|
@ -353,7 +351,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000700;
|
PC = NPC = 0x00000700;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_PROGRAM");
|
INFO_LOG(POWERPC, "EXCEPTION_PROGRAM");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PROGRAM);
|
ppcState.Exceptions &= ~EXCEPTION_PROGRAM;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_SYSCALL)
|
else if (exceptions & EXCEPTION_SYSCALL)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +362,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000C00;
|
PC = NPC = 0x00000C00;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
|
INFO_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_SYSCALL);
|
ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_FPU_UNAVAILABLE)
|
else if (exceptions & EXCEPTION_FPU_UNAVAILABLE)
|
||||||
{
|
{
|
||||||
|
@ -376,7 +374,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000800;
|
PC = NPC = 0x00000800;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_FPU_UNAVAILABLE);
|
ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_DSI)
|
else if (exceptions & EXCEPTION_DSI)
|
||||||
{
|
{
|
||||||
|
@ -388,7 +386,7 @@ void CheckExceptions()
|
||||||
//DSISR and DAR regs are changed in GenerateDSIException()
|
//DSISR and DAR regs are changed in GenerateDSIException()
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_DSI");
|
INFO_LOG(POWERPC, "EXCEPTION_DSI");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DSI);
|
ppcState.Exceptions &= ~EXCEPTION_DSI;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_ALIGNMENT)
|
else if (exceptions & EXCEPTION_ALIGNMENT)
|
||||||
{
|
{
|
||||||
|
@ -403,7 +401,7 @@ void CheckExceptions()
|
||||||
//TODO crazy amount of DSISR options to check out
|
//TODO crazy amount of DSISR options to check out
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_ALIGNMENT");
|
INFO_LOG(POWERPC, "EXCEPTION_ALIGNMENT");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_ALIGNMENT);
|
ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXTERNAL INTERRUPT
|
// EXTERNAL INTERRUPT
|
||||||
|
@ -419,7 +417,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000500;
|
PC = NPC = 0x00000500;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
|
ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT;
|
||||||
|
|
||||||
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
|
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
|
||||||
}
|
}
|
||||||
|
@ -432,7 +430,7 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000F00;
|
PC = NPC = 0x00000F00;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PERFORMANCE_MONITOR);
|
ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_DECREMENTER)
|
else if (exceptions & EXCEPTION_DECREMENTER)
|
||||||
{
|
{
|
||||||
|
@ -443,14 +441,13 @@ void CheckExceptions()
|
||||||
PC = NPC = 0x00000900;
|
PC = NPC = 0x00000900;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DECREMENTER);
|
ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckExternalExceptions()
|
void CheckExternalExceptions()
|
||||||
{
|
{
|
||||||
// Read volatile data once
|
|
||||||
u32 exceptions = ppcState.Exceptions;
|
u32 exceptions = ppcState.Exceptions;
|
||||||
|
|
||||||
// EXTERNAL INTERRUPT
|
// EXTERNAL INTERRUPT
|
||||||
|
@ -466,7 +463,7 @@ void CheckExternalExceptions()
|
||||||
PC = NPC = 0x00000500;
|
PC = NPC = 0x00000500;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
|
ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT;
|
||||||
|
|
||||||
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
|
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "EXTERNAL_INT unrecoverable???");
|
||||||
}
|
}
|
||||||
|
@ -479,7 +476,7 @@ void CheckExternalExceptions()
|
||||||
PC = NPC = 0x00000F00;
|
PC = NPC = 0x00000F00;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
INFO_LOG(POWERPC, "EXCEPTION_PERFORMANCE_MONITOR");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PERFORMANCE_MONITOR);
|
ppcState.Exceptions &= ~EXCEPTION_PERFORMANCE_MONITOR;
|
||||||
}
|
}
|
||||||
else if (exceptions & EXCEPTION_DECREMENTER)
|
else if (exceptions & EXCEPTION_DECREMENTER)
|
||||||
{
|
{
|
||||||
|
@ -490,7 +487,7 @@ void CheckExternalExceptions()
|
||||||
PC = NPC = 0x00000900;
|
PC = NPC = 0x00000900;
|
||||||
|
|
||||||
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
|
||||||
Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DECREMENTER);
|
ppcState.Exceptions &= ~EXCEPTION_DECREMENTER;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,7 +73,7 @@ struct GC_ALIGNED64(PowerPCState)
|
||||||
u32 fpscr; // floating point flags/status bits
|
u32 fpscr; // floating point flags/status bits
|
||||||
|
|
||||||
// Exception management.
|
// Exception management.
|
||||||
volatile u32 Exceptions;
|
u32 Exceptions;
|
||||||
|
|
||||||
// Downcount for determining when we need to do timing
|
// Downcount for determining when we need to do timing
|
||||||
// This isn't quite the right location for it, but it is here to accelerate the ARM JIT
|
// This isn't quite the right location for it, but it is here to accelerate the ARM JIT
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "Core/HW/ProcessorInterface.h"
|
#include "Core/HW/ProcessorInterface.h"
|
||||||
#include "VideoCommon/BoundingBox.h"
|
#include "VideoCommon/BoundingBox.h"
|
||||||
#include "VideoCommon/CommandProcessor.h"
|
#include "VideoCommon/CommandProcessor.h"
|
||||||
|
#include "VideoCommon/Fifo.h"
|
||||||
#include "VideoCommon/PixelEngine.h"
|
#include "VideoCommon/PixelEngine.h"
|
||||||
#include "VideoCommon/RenderBase.h"
|
#include "VideoCommon/RenderBase.h"
|
||||||
#include "VideoCommon/VideoCommon.h"
|
#include "VideoCommon/VideoCommon.h"
|
||||||
|
@ -299,7 +300,10 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandProcessor::interruptTokenWaiting = true;
|
CommandProcessor::interruptTokenWaiting = true;
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread || g_use_deterministic_gpu_thread)
|
||||||
|
CoreTiming::ScheduleEvent(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
|
else
|
||||||
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFinish
|
// SetFinish
|
||||||
|
@ -307,7 +311,10 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||||
void SetFinish()
|
void SetFinish()
|
||||||
{
|
{
|
||||||
CommandProcessor::interruptFinishWaiting = true;
|
CommandProcessor::interruptFinishWaiting = true;
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread || g_use_deterministic_gpu_thread)
|
||||||
|
CoreTiming::ScheduleEvent(0, et_SetFinishOnMainThread, 0);
|
||||||
|
else
|
||||||
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetFinishOnMainThread, 0);
|
||||||
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
INFO_LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue