From 32b983ef8393bb0cab4d159a0c31def426a8922c Mon Sep 17 00:00:00 2001 From: Shawn Hoffman Date: Mon, 23 Mar 2009 07:58:59 +0000 Subject: [PATCH] beginning to take a look at the wonderful world of exceptions. try to implement tw/twi git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2738 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/PowerPC/Gekko.h | 5 +- .../Interpreter/Interpreter_Branch.cpp | 2 +- .../Interpreter/Interpreter_Integer.cpp | 39 ++++-- Source/Core/Core/Src/PowerPC/PowerPC.cpp | 128 ++++++++++-------- 4 files changed, 108 insertions(+), 66 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Gekko.h b/Source/Core/Core/Src/PowerPC/Gekko.h index 152539cc90..c8945b02c6 100644 --- a/Source/Core/Core/Src/PowerPC/Gekko.h +++ b/Source/Core/Core/Src/PowerPC/Gekko.h @@ -46,7 +46,7 @@ union UGeckoInstruction { signed SIMM_16 : 16; unsigned : 5; - unsigned : 5; + unsigned TO : 5; unsigned OPCD_2 : 6; }; struct @@ -152,7 +152,7 @@ union UGeckoInstruction struct { unsigned : 10; - unsigned OE : 1; + unsigned OE : 1; unsigned SPR : 10; unsigned : 11; }; @@ -604,6 +604,7 @@ enum #define EXCEPTION_ISI 0x00000010 #define EXCEPTION_ALIGNMENT 0x00000020 #define EXCEPTION_FPU_UNAVAILABLE 0x00000040 +#define EXCEPTION_PROGRAM 0x00000080 inline s32 SignExt16(s16 x) {return (s32)(s16)x;} inline s32 SignExt26(u32 x) {return x & 0x2000000 ? (s32)x | 0xFC000000 : (s32)(x);} diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp index 3ae22f197f..768ee05deb 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Branch.cpp @@ -113,7 +113,7 @@ void CompiledBlock(UGeckoInstruction _inst) void rfi(UGeckoInstruction _inst) { - //Bits SRR1[0,5-9,16�23, 25�27, 30�31] are placed into the corresponding bits of the MSR. + //Bits SRR1[0,5-9,16-23, 25-27, 30-31] are placed into the corresponding bits of the MSR. //MSR[13] is set to 0. const int mask = 0x87C0FF73; MSR = (MSR & ~mask) | (SRR1 & mask); diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp index 7ef208a121..593d8f6fd3 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Integer.cpp @@ -165,11 +165,22 @@ void subfic(UGeckoInstruction _inst) void twi(UGeckoInstruction _inst) { - bool bFirst = true; - if (bFirst) - PanicAlert("twi - Instruction unimplemented"); + s32 a = m_GPR[_inst.RA]; + s32 b = _inst.SIMM_16; + s32 TO = _inst.TO; - bFirst = false; + ERROR_LOG(GEKKO, "twi rA %x SIMM %x TO %0x", a, b, TO); + + if ( ((a < b) && (TO & 0x10)) + || ((a > b) && (TO & 0x08)) + || ((a ==b) && (TO & 0x04)) + || (((u32)a <(u32)b) && (TO & 0x02)) + || (((u32)a >(u32)b) && (TO & 0x01))) + { + PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; + PowerPC::CheckExceptions(); + m_EndBlock = true; // Dunno about this + } } void xori(UGeckoInstruction _inst) @@ -382,10 +393,22 @@ void srwx(UGeckoInstruction _inst) void tw(UGeckoInstruction _inst) { - static bool bFirst = true; - if (bFirst) - PanicAlert("tw - Instruction unimplemented"); - bFirst = false; + s32 a = m_GPR[_inst.RA]; + s32 b = m_GPR[_inst.RB]; + s32 TO = _inst.TO; + + ERROR_LOG(GEKKO, "tw rA %0x rB %0x TO %0x", a, b, TO); + + if ( ((a < b) && (TO & 0x10)) + || ((a > b) && (TO & 0x08)) + || ((a ==b) && (TO & 0x04)) + || (((u32)a <(u32)b) && (TO & 0x02)) + || (((u32)a >(u32)b) && (TO & 0x01))) + { + PowerPC::ppcState.Exceptions |= EXCEPTION_PROGRAM; + PowerPC::CheckExceptions(); + m_EndBlock = true; // Dunno about this + } } void xorx(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index ad22688e9d..2a041f031c 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -213,62 +213,12 @@ void CheckExceptions() // gcemu uses the mask 0x87C0FFFF instead of 0x0780FF77 // Investigate! - if (ppcState.Exceptions & EXCEPTION_FPU_UNAVAILABLE) - { - //This happens a lot - Gamecube OS uses deferred FPU context switching - SRR0 = PC; // re-execute the instruction - SRR1 = MSR & 0x0780FF77; - NPC = 0x80000800; - - INFO_LOG(GEKKO, "EXCEPTION_FPU_UNAVAILABLE"); - ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; - SRR1 |= 0x02; //recoverable - } - else if (ppcState.Exceptions & EXCEPTION_SYSCALL) - { - SRR0 = NPC; // execute next instruction when we come back from handler - SRR1 = MSR & 0x0780FF77; - NPC = 0x80000C00; - - INFO_LOG(GEKKO, "EXCEPTION_SYSCALL (PC=%08x)", PC); - ppcState.Exceptions &= ~EXCEPTION_SYSCALL; - SRR1 |= 0x02; //recoverable - } - else if (ppcState.Exceptions & EXCEPTION_DSI) - { - SRR0 = PC; // re-execute the instruction - SRR1 = MSR & 0x0780FF77; - NPC = 0x80000300; - - INFO_LOG(GEKKO, "EXCEPTION_DSI"); - ppcState.Exceptions &= ~EXCEPTION_DSI; - //SRR1 |= 0x02; //make recoverable ? - } - else if (ppcState.Exceptions & EXCEPTION_ISI) - { - SRR0 = PC; - SRR1 = (MSR & 0x0780FF77) | 0x40000000; - NPC = 0x80000400; - - INFO_LOG(GEKKO, "EXCEPTION_ISI"); - ppcState.Exceptions &= ~EXCEPTION_ISI; - //SRR1 |= 0x02; //make recoverable ? - } - else if (ppcState.Exceptions & EXCEPTION_ALIGNMENT) - { - //This never happens ATM - SRR0 = NPC; - SRR1 = MSR & 0x0780FF77; - NPC = 0x80000600; - - INFO_LOG(GEKKO, "EXCEPTION_ALIGNMENT"); - ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT; - //SRR1 |= 0x02; //make recoverable ? - } - // EXTERNAL INTTERUPT - else if (MSR & 0x0008000) + if (MSR & 0x0008000) { + // EXCEPTION_SYSRESET (hard) + // EXCEPTION_MACHINE_CHECK + // EXCEPTION_SYSRESET (soft) if (ppcState.Exceptions & EXCEPTION_EXTERNAL_INT) { // Pokemon gets this "too early", it hasn't a handler yet @@ -277,12 +227,13 @@ void CheckExceptions() SRR0 = NPC; NPC = 0x80000500; SRR1 = (MSR & 0x0780FF77); - + INFO_LOG(GEKKO, "EXCEPTION_EXTERNAL_INT"); SRR1 |= 0x02; //set it to recoverable _dbg_assert_msg_(GEKKO, (SRR1 & 0x02) != 0, "GEKKO", "EXTERNAL_INT unrecoverable???"); // unrecoverable exception !?! } + // EXCEPTION_PERF_MONITOR else if (ppcState.Exceptions & EXCEPTION_DECREMENTER) { SRR0 = NPC; @@ -300,6 +251,73 @@ void CheckExceptions() ERROR_LOG(GEKKO, "Unknown EXTERNAL INTERRUPT exception: Exceptions == %08x", ppcState.Exceptions); } } + else if (ppcState.Exceptions & EXCEPTION_ISI) + { + SRR0 = PC; + SRR1 = (MSR & 0x0780FF77) | 0x40000000; + NPC = 0x80000400; + + INFO_LOG(GEKKO, "EXCEPTION_ISI"); + ppcState.Exceptions &= ~EXCEPTION_ISI; + //SRR1 |= 0x02; //make recoverable ? + } + // EXCEPTION_ADDR_BREAKPOINT + else if (ppcState.Exceptions & EXCEPTION_PROGRAM) + { + SRR0 = NPC; // execute next instruction when we come back from handler + SRR1 = MSR & 0x0780FF77; + NPC = 0x80000700; + + INFO_LOG(GEKKO, "EXCEPTION_PROGRAM (PC=%08x)", PC); + ppcState.Exceptions &= ~EXCEPTION_PROGRAM; + SRR1 |= 0x02; //recoverable + } + else if (ppcState.Exceptions & EXCEPTION_SYSCALL) + { + SRR0 = NPC; // execute next instruction when we come back from handler + SRR1 = MSR & 0x0780FF77; + NPC = 0x80000C00; + + INFO_LOG(GEKKO, "EXCEPTION_SYSCALL (PC=%08x)", PC); + ppcState.Exceptions &= ~EXCEPTION_SYSCALL; + SRR1 |= 0x02; //recoverable + } + else if (ppcState.Exceptions & EXCEPTION_FPU_UNAVAILABLE) + { + //This happens a lot - Gamecube OS uses deferred FPU context switching + SRR0 = PC; // re-execute the instruction + SRR1 = MSR & 0x0780FF77; + NPC = 0x80000800; + + INFO_LOG(GEKKO, "EXCEPTION_FPU_UNAVAILABLE"); + ppcState.Exceptions &= ~EXCEPTION_FPU_UNAVAILABLE; + SRR1 |= 0x02; //recoverable + } + // EXCEPTION_PROGRAM (floating point) + else if (ppcState.Exceptions & EXCEPTION_DSI) + { + SRR0 = PC; // re-execute the instruction + SRR1 = MSR & 0x0780FF77; + NPC = 0x80000300; + + INFO_LOG(GEKKO, "EXCEPTION_DSI"); + ppcState.Exceptions &= ~EXCEPTION_DSI; + //SRR1 |= 0x02; //make recoverable ? + } + else if (ppcState.Exceptions & EXCEPTION_ALIGNMENT) + { + // Alignment exceptions have priorities + //This never happens ATM + SRR0 = NPC; + SRR1 = MSR & 0x0780FF77; + NPC = 0x80000600; + + INFO_LOG(GEKKO, "EXCEPTION_ALIGNMENT"); + ppcState.Exceptions &= ~EXCEPTION_ALIGNMENT; + //SRR1 |= 0x02; //make recoverable ? + } + // Other DSI exceptions + // EXCEPTION_TRACE MSR &= ~0x0008000; // clear EE-bit so interrupts aren't possible anymore }