Fixed some race conditions with PPC exceptions and external interrupts.

This may help fixing issues related to video interrupts handling.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6157 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
dok.slade 2010-09-01 22:03:51 +00:00
parent 625d78fb59
commit 8d6f98439e
16 changed files with 64 additions and 48 deletions

View File

@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "Atomic.h"
#include "GPFifo.h" #include "GPFifo.h"
#include "Memmap.h" #include "Memmap.h"
@ -605,7 +606,7 @@ void GenerateDSIException(u32 _EffectiveAddress, bool _bWrite)
PowerPC::ppcState.spr[SPR_DAR] = _EffectiveAddress; PowerPC::ppcState.spr[SPR_DAR] = _EffectiveAddress;
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
} }
@ -615,7 +616,7 @@ void GenerateISIException(u32 _EffectiveAddress)
SRR1 = (1 << 30) | (MSR & 0x3fffff); SRR1 = (1 << 30) | (MSR & 0x3fffff);
NPC = _EffectiveAddress; NPC = _EffectiveAddress;
PowerPC::ppcState.Exceptions |= EXCEPTION_ISI; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_ISI);
} }

View File

@ -17,6 +17,7 @@
#include <stdio.h> #include <stdio.h>
#include "Common.h" #include "Common.h"
#include "Atomic.h"
#include "ChunkFile.h" #include "ChunkFile.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
@ -155,7 +156,7 @@ void Write32(const u32 _uValue, const u32 _iAddress)
switch(_iAddress & 0xFFF) switch(_iAddress & 0xFFF)
{ {
case PI_INTERRUPT_CAUSE: case PI_INTERRUPT_CAUSE:
m_InterruptCause &= ~_uValue; // writes turn them off Common::AtomicAnd(m_InterruptCause, ~_uValue); // writes turn them off
UpdateException(); UpdateException();
return; return;
@ -203,9 +204,9 @@ void Write32(const u32 _uValue, const u32 _iAddress)
void UpdateException() void UpdateException()
{ {
if ((m_InterruptCause & m_InterruptMask) != 0) if ((m_InterruptCause & m_InterruptMask) != 0)
PowerPC::ppcState.Exceptions |= EXCEPTION_EXTERNAL_INT; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_EXTERNAL_INT);
else else
PowerPC::ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; Common::AtomicAnd(PowerPC::ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
} }
static const char *Debug_GetInterruptName(u32 _causemask) static const char *Debug_GetInterruptName(u32 _causemask)
@ -247,9 +248,9 @@ void SetInterrupt(u32 _causemask, bool _bSet)
} }
if (_bSet) if (_bSet)
m_InterruptCause |= _causemask; Common::AtomicOr(m_InterruptCause, _causemask);
else else
m_InterruptCause &= ~_causemask;// is there any reason to have this possibility? Common::AtomicAnd(m_InterruptCause, ~_causemask);// is there any reason to have this possibility?
// F|RES: i think the hw devices reset the interrupt in the PI to 0 // F|RES: i think the hw devices reset the interrupt in the PI to 0
// if the interrupt cause is eliminated. that isnt done by software (afaik) // if the interrupt cause is eliminated. that isnt done by software (afaik)
UpdateException(); UpdateException();
@ -258,9 +259,9 @@ void SetInterrupt(u32 _causemask, bool _bSet)
void SetResetButton(bool _bSet) void SetResetButton(bool _bSet)
{ {
if (_bSet) if (_bSet)
m_InterruptCause &= ~INT_CAUSE_RST_BUTTON; Common::AtomicAnd(m_InterruptCause, ~INT_CAUSE_RST_BUTTON);
else else
m_InterruptCause |= INT_CAUSE_RST_BUTTON; Common::AtomicOr(m_InterruptCause, INT_CAUSE_RST_BUTTON);
} }
void ToggleResetButtonCallback(u64 userdata, int cyclesLate) void ToggleResetButtonCallback(u64 userdata, int cyclesLate)

View File

@ -58,6 +58,7 @@ IPC_HLE_PERIOD: For the Wiimote this is the call schedule:
#include "Common.h" #include "Common.h"
#include "Atomic.h"
#include "../PatchEngine.h" #include "../PatchEngine.h"
#include "SystemTimers.h" #include "SystemTimers.h"
#include "../PluginManager.h" #include "../PluginManager.h"
@ -192,7 +193,7 @@ void DecrementerCallback(u64 userdata, int cyclesLate)
// A: Because it's 64bit (0xffffffffffffffff)...? // A: Because it's 64bit (0xffffffffffffffff)...?
fakeDec = -1; fakeDec = -1;
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF; PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
} }
void DecrementerSet() void DecrementerSet()

View File

@ -25,6 +25,7 @@
#include "../../ConfigManager.h" #include "../../ConfigManager.h"
#include "PowerPCDisasm.h" #include "PowerPCDisasm.h"
#include "../../IPC_HLE/WII_IPC_HLE.h" #include "../../IPC_HLE/WII_IPC_HLE.h"
#include "Atomic.h"
namespace { namespace {
@ -107,7 +108,7 @@ void Interpreter::SingleStepInner(void)
} }
else else
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_FPU_UNAVAILABLE; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_EndBlock = true; m_EndBlock = true;
} }

View File

@ -19,6 +19,7 @@
#include "../../HW/CPU.h" #include "../../HW/CPU.h"
#include "../../HLE/HLE.h" #include "../../HLE/HLE.h"
#include "../PPCAnalyst.h" #include "../PPCAnalyst.h"
#include "Atomic.h"
void Interpreter::bx(UGeckoInstruction _inst) void Interpreter::bx(UGeckoInstruction _inst)
{ {
@ -134,7 +135,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)
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_SYSCALL; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_SYSCALL);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_EndBlock = true; m_EndBlock = true;
} }

View File

@ -17,6 +17,7 @@
#include "Interpreter.h" #include "Interpreter.h"
#include "../../Core.h" #include "../../Core.h"
#include "Atomic.h"
void Interpreter::Helper_UpdateCR0(u32 _uValue) void Interpreter::Helper_UpdateCR0(u32 _uValue)
{ {
@ -174,7 +175,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)))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_EndBlock = true; // Dunno about this m_EndBlock = true; // Dunno about this
} }
@ -402,7 +403,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)))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_PROGRAM);
PowerPC::CheckExceptions(); PowerPC::CheckExceptions();
m_EndBlock = true; // Dunno about this m_EndBlock = true; // Dunno about this
} }

View File

@ -16,6 +16,7 @@
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "Atomic.h"
#include "MathUtil.h" #include "MathUtil.h"
#include "../../HW/Memmap.h" #include "../../HW/Memmap.h"
@ -405,10 +406,10 @@ void Interpreter::eciwx(UGeckoInstruction _inst)
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
} }
if (EA & 3) if (EA & 3)
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; Common::AtomicOr(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);
@ -427,10 +428,10 @@ void Interpreter::ecowx(UGeckoInstruction _inst)
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000)) if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
{ {
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DSI);
} }
if (EA & 3) if (EA & 3)
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT; Common::AtomicOr(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",
// m_GPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f); // m_GPR[_inst.RS], EA, PowerPC::ppcState.spr[SPR_EAR] & 0x1f);

View File

@ -36,6 +36,7 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10;
#endif #endif
#include "CPUDetect.h" #include "CPUDetect.h"
#include "Atomic.h"
#include "../../CoreTiming.h" #include "../../CoreTiming.h"
#include "../../HW/Memmap.h" #include "../../HW/Memmap.h"
#include "../../HW/GPFifo.h" #include "../../HW/GPFifo.h"
@ -413,7 +414,7 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
if (!(oldValue >> 31) && (m_GPR[_inst.RD]>>31)) //top bit from 0 to 1 if (!(oldValue >> 31) && (m_GPR[_inst.RD]>>31)) //top bit from 0 to 1
{ {
PanicAlert("Interesting - Software triggered Decrementer exception"); PanicAlert("Interesting - Software triggered Decrementer exception");
PowerPC::ppcState.Exceptions |= EXCEPTION_DECREMENTER; Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
} }
else else
{ {

View File

@ -562,7 +562,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = J_CC(CC_Z); FixupBranch noMemException = J_CC(CC_Z);
// If a memory exception occurs, the exception handler will read // If a memory exception occurs, the exception handler will read

View File

@ -55,7 +55,7 @@
#define MEMCHECK_START \ #define MEMCHECK_START \
FixupBranch memException; \ FixupBranch memException; \
if (js.memcheck) \ if (js.memcheck) \
{ TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); \ { TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); \
memException = J_CC(CC_NZ); } memException = J_CC(CC_NZ); }
#define MEMCHECK_END \ #define MEMCHECK_END \

View File

@ -193,7 +193,8 @@ void Jit64AsmRoutineManager::Generate()
//FP blocks test for FPU available, jump here if false //FP blocks test for FPU available, jump here if false
fpException = AlignCode4(); fpException = AlignCode4();
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions)); ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC)); MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX)); MOV(32, M(&PC), R(EAX));
@ -205,7 +206,7 @@ void Jit64AsmRoutineManager::Generate()
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance)); ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
testExceptions = GetCodePtr(); testExceptions = GetCodePtr();
TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF)); TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
FixupBranch skipExceptions = J_CC(CC_Z); FixupBranch skipExceptions = J_CC(CC_Z);
MOV(32, R(EAX), M(&PC)); MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX)); MOV(32, M(&NPC), R(EAX));

View File

@ -48,7 +48,8 @@ void Jit64::sc(UGeckoInstruction inst)
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
MOV(32, M(&PC), Imm32(js.compilerPC + 4)); MOV(32, M(&PC), Imm32(js.compilerPC + 4));
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL)); LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL));
WriteExceptionExit(); WriteExceptionExit();
} }

View File

@ -1716,7 +1716,8 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
} }
case SystemCall: { case SystemCall: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL)); Jit->LOCK();
Jit->OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_SYSCALL));
Jit->MOV(32, M(&PC), Imm32(InstLoc + 4)); Jit->MOV(32, M(&PC), Imm32(InstLoc + 4));
Jit->WriteExceptionExit(); Jit->WriteExceptionExit();
break; break;
@ -1759,7 +1760,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, bool UseProfile, bool Mak
} }
case FPExceptionCheckEnd: { case FPExceptionCheckEnd: {
unsigned InstLoc = ibuild->GetImmValue(getOp1(I)); unsigned InstLoc = ibuild->GetImmValue(getOp1(I));
Jit->TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI)); Jit->TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_DSI));
FixupBranch noMemException = Jit->J_CC(CC_Z); FixupBranch noMemException = Jit->J_CC(CC_Z);
// If a memory exception occurs, the exception handler will read // If a memory exception occurs, the exception handler will read

View File

@ -197,7 +197,8 @@ void JitILAsmRoutineManager::Generate()
fpException = AlignCode4(); fpException = AlignCode4();
MOV(32, R(EAX), M(&PC)); MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX)); MOV(32, M(&NPC), R(EAX));
OR(32, M(&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE)); LOCK();
OR(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(EXCEPTION_FPU_UNAVAILABLE));
ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions)); ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckExceptions));
MOV(32, R(EAX), M(&NPC)); MOV(32, R(EAX), M(&NPC));
MOV(32, M(&PC), R(EAX)); MOV(32, M(&PC), R(EAX));
@ -209,7 +210,7 @@ void JitILAsmRoutineManager::Generate()
ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance)); ABI_CallFunction(reinterpret_cast<void *>(&CoreTiming::Advance));
testExceptions = GetCodePtr(); testExceptions = GetCodePtr();
TEST(32, M(&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF)); TEST(32, M((void *)&PowerPC::ppcState.Exceptions), Imm32(0xFFFFFFFF));
FixupBranch skipExceptions = J_CC(CC_Z); FixupBranch skipExceptions = J_CC(CC_Z);
MOV(32, R(EAX), M(&PC)); MOV(32, R(EAX), M(&PC));
MOV(32, M(&NPC), R(EAX)); MOV(32, M(&NPC), R(EAX));

View File

@ -18,6 +18,7 @@
#include <float.h> #include <float.h>
#include "Common.h" #include "Common.h"
#include "Atomic.h"
#include "MathUtil.h" #include "MathUtil.h"
#include "ChunkFile.h" #include "ChunkFile.h"
@ -262,8 +263,11 @@ void Stop()
void CheckExceptions() void CheckExceptions()
{ {
// Read volatile data once
u32 exceptions = ppcState.Exceptions;
// This check is unnecessary in JIT mode. However, it probably doesn't really hurt. // This check is unnecessary in JIT mode. However, it probably doesn't really hurt.
if (!ppcState.Exceptions) if (!exceptions)
return; return;
// gcemu uses the mask 0x87C0FFFF instead of 0x0780FF77 // gcemu uses the mask 0x87C0FFFF instead of 0x0780FF77
@ -285,7 +289,7 @@ void CheckExceptions()
// set to exception type entry point // set to exception type entry point
//NPC = 0x80000x00; //NPC = 0x80000x00;
if (ppcState.Exceptions & EXCEPTION_ISI) if (exceptions & EXCEPTION_ISI)
{ {
SRR0 = NPC; SRR0 = NPC;
//GenerateISIException() sets up SRR1 //GenerateISIException() sets up SRR1
@ -294,9 +298,9 @@ void CheckExceptions()
NPC = 0x80000400; NPC = 0x80000400;
INFO_LOG(POWERPC, "EXCEPTION_ISI"); INFO_LOG(POWERPC, "EXCEPTION_ISI");
ppcState.Exceptions &= ~EXCEPTION_ISI; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_ISI);
} }
else if (ppcState.Exceptions & EXCEPTION_PROGRAM) else if (exceptions & EXCEPTION_PROGRAM)
{ {
SRR0 = PC; SRR0 = PC;
SRR1 = MSR & 0x87C0FFFF; SRR1 = MSR & 0x87C0FFFF;
@ -307,9 +311,9 @@ void CheckExceptions()
NPC = 0x80000700; NPC = 0x80000700;
INFO_LOG(POWERPC, "EXCEPTION_PROGRAM"); INFO_LOG(POWERPC, "EXCEPTION_PROGRAM");
ppcState.Exceptions &= ~EXCEPTION_PROGRAM; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_PROGRAM);
} }
else if (ppcState.Exceptions & EXCEPTION_SYSCALL) else if (exceptions & EXCEPTION_SYSCALL)
{ {
SRR0 = NPC; SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF; SRR1 = MSR & 0x87C0FFFF;
@ -318,9 +322,9 @@ void CheckExceptions()
NPC = 0x80000C00; NPC = 0x80000C00;
INFO_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC); INFO_LOG(POWERPC, "EXCEPTION_SYSCALL (PC=%08x)", PC);
ppcState.Exceptions &= ~EXCEPTION_SYSCALL; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_SYSCALL);
} }
else if (ppcState.Exceptions & EXCEPTION_FPU_UNAVAILABLE) else if (exceptions & EXCEPTION_FPU_UNAVAILABLE)
{ {
//This happens a lot - Gamecube OS uses deferred FPU context switching //This happens a lot - Gamecube OS uses deferred FPU context switching
SRR0 = PC; // re-execute the instruction SRR0 = PC; // re-execute the instruction
@ -334,9 +338,9 @@ void CheckExceptions()
NPC = 0x80000800; NPC = 0x80000800;
INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE"); INFO_LOG(POWERPC, "EXCEPTION_FPU_UNAVAILABLE");
ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_FPU_UNAVAILABLE);
} }
else if (ppcState.Exceptions & EXCEPTION_DSI) else if (exceptions & EXCEPTION_DSI)
{ {
SRR0 = PC; SRR0 = PC;
SRR1 = MSR & 0x87C0FFFF; SRR1 = MSR & 0x87C0FFFF;
@ -346,9 +350,9 @@ 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");
ppcState.Exceptions &= ~EXCEPTION_DSI; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DSI);
} }
else if (ppcState.Exceptions & EXCEPTION_ALIGNMENT) else if (exceptions & EXCEPTION_ALIGNMENT)
{ {
//This never happens ATM //This never happens ATM
// perhaps we can get dcb* instructions to use this :p // perhaps we can get dcb* instructions to use this :p
@ -361,13 +365,13 @@ 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");
ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_ALIGNMENT);
} }
// EXTERNAL INTERRUPT // EXTERNAL INTERRUPT
else if (MSR & 0x0008000) //hacky...the exception shouldn't be generated if EE isn't set... else if (MSR & 0x0008000) //hacky...the exception shouldn't be generated if EE isn't set...
{ {
if (ppcState.Exceptions & EXCEPTION_EXTERNAL_INT) if (exceptions & EXCEPTION_EXTERNAL_INT)
{ {
// Pokemon gets this "too early", it hasn't a handler yet // Pokemon gets this "too early", it hasn't a handler yet
SRR0 = NPC; SRR0 = NPC;
@ -377,11 +381,11 @@ void CheckExceptions()
NPC = 0x80000500; NPC = 0x80000500;
INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT"); INFO_LOG(POWERPC, "EXCEPTION_EXTERNAL_INT");
ppcState.Exceptions &= ~EXCEPTION_EXTERNAL_INT; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_EXTERNAL_INT);
_dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???"); _dbg_assert_msg_(POWERPC, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???");
} }
else if (ppcState.Exceptions & EXCEPTION_DECREMENTER) else if (exceptions & EXCEPTION_DECREMENTER)
{ {
SRR0 = NPC; SRR0 = NPC;
SRR1 = MSR & 0x87C0FFFF; SRR1 = MSR & 0x87C0FFFF;
@ -390,12 +394,12 @@ void CheckExceptions()
NPC = 0x80000900; NPC = 0x80000900;
INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER"); INFO_LOG(POWERPC, "EXCEPTION_DECREMENTER");
ppcState.Exceptions &= ~EXCEPTION_DECREMENTER; Common::AtomicAnd(ppcState.Exceptions, ~EXCEPTION_DECREMENTER);
} }
else else
{ {
_dbg_assert_msg_(POWERPC, 0, "Unknown EXT interrupt: Exceptions == %08x", ppcState.Exceptions); _dbg_assert_msg_(POWERPC, 0, "Unknown EXT interrupt: Exceptions == %08x", exceptions);
ERROR_LOG(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", ppcState.Exceptions); ERROR_LOG(POWERPC, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", exceptions);
} }
} }
} }

View File

@ -59,7 +59,7 @@ struct GC_ALIGNED64(PowerPCState)
u32 fpscr; // floating point flags/status bits u32 fpscr; // floating point flags/status bits
// Exception management. // Exception management.
u32 Exceptions; volatile u32 Exceptions;
u32 sr[16]; // Segment registers. u32 sr[16]; // Segment registers.