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
This commit is contained in:
Shawn Hoffman 2009-03-23 07:58:59 +00:00
parent 813b864a5e
commit 32b983ef83
4 changed files with 108 additions and 66 deletions

View File

@ -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);}

View File

@ -113,7 +113,7 @@ void CompiledBlock(UGeckoInstruction _inst)
void rfi(UGeckoInstruction _inst)
{
//Bits SRR1[0,5-9,16<EFBFBD>23, 25<32>27, 30<33>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);

View File

@ -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)

View File

@ -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
}