Rollback on a DSI exception, for the instructions that need it.
Not a good thing to say, but this isn't properly tested, since I don't know of any game that generates a DSI exception. I'll try to write some homebrew to test this, but I'm pretty confident it's ok. Anyway, please take a look at it and tell me if you find some mistake :-) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6172 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ae309405a5
commit
f4a6e585be
|
@ -195,39 +195,65 @@ void Interpreter::lhzu(UGeckoInstruction _inst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: lmw should do a total rollback if a DSI occurs
|
|
||||||
void Interpreter::lmw(UGeckoInstruction _inst)
|
void Interpreter::lmw(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
u32 uAddress = Helper_Get_EA(_inst);
|
u32 EA = Helper_Get_EA(_inst);
|
||||||
for (int iReg = _inst.RD; iReg <= 31; iReg++, uAddress += 4)
|
int r = _inst.RD;
|
||||||
|
|
||||||
|
const int rb_r = r;
|
||||||
|
static u32 rb_GPR[32];
|
||||||
|
|
||||||
|
while (r <= 31)
|
||||||
{
|
{
|
||||||
u32 TempReg = Memory::Read_U32(uAddress);
|
u32 TempReg = Memory::Read_U32(EA);
|
||||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||||
{
|
{
|
||||||
PanicAlert("DSI exception in lmw");
|
PanicAlert("DSI exception in lmw");
|
||||||
NOTICE_LOG(POWERPC, "DSI exception in lmw");
|
NOTICE_LOG(POWERPC, "DSI exception in lmw");
|
||||||
|
|
||||||
|
while (r > rb_r)
|
||||||
|
{
|
||||||
|
m_GPR[r] = rb_GPR[r];
|
||||||
|
r--;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
rb_GPR[r] = m_GPR[r];
|
||||||
{
|
m_GPR[r] = TempReg;
|
||||||
m_GPR[iReg] = TempReg;
|
|
||||||
}
|
r++;
|
||||||
|
EA += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: stmw should do a total rollback if a DSI occurs
|
|
||||||
void Interpreter::stmw(UGeckoInstruction _inst)
|
void Interpreter::stmw(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
u32 uAddress = Helper_Get_EA(_inst);
|
u32 EA = Helper_Get_EA(_inst);
|
||||||
for (int iReg = _inst.RS; iReg <= 31; iReg++, uAddress+=4)
|
int r = _inst.RS;
|
||||||
|
|
||||||
|
const int rb_r = r;
|
||||||
|
static u32 rb_mem[32];
|
||||||
|
|
||||||
|
while (r <= 31)
|
||||||
{
|
{
|
||||||
Memory::Write_U32(m_GPR[iReg], uAddress);
|
rb_mem[r] = Memory::ReadUnchecked_U32(EA);
|
||||||
|
Memory::Write_U32(m_GPR[r], EA);
|
||||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||||
{
|
{
|
||||||
PanicAlert("DSI exception in stmw");
|
PanicAlert("DSI exception in stmw");
|
||||||
NOTICE_LOG(POWERPC, "DSI exception in stmw");
|
NOTICE_LOG(POWERPC, "DSI exception in stmw");
|
||||||
|
|
||||||
|
while (r > rb_r)
|
||||||
|
{
|
||||||
|
Memory::WriteUnchecked_U32(rb_mem[r], EA);
|
||||||
|
r--;
|
||||||
|
EA -= 4;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
r++;
|
||||||
|
EA += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,7 +549,6 @@ void Interpreter::lhzx(UGeckoInstruction _inst)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: is this right?
|
// TODO: is this right?
|
||||||
// FIXME: Should rollback if a DSI occurs
|
|
||||||
void Interpreter::lswx(UGeckoInstruction _inst)
|
void Interpreter::lswx(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
u32 EA = Helper_Get_EA_X(_inst);
|
u32 EA = Helper_Get_EA_X(_inst);
|
||||||
|
@ -531,8 +556,13 @@ void Interpreter::lswx(UGeckoInstruction _inst)
|
||||||
int r = _inst.RD;
|
int r = _inst.RD;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
const u32 rb_EA = EA;
|
||||||
|
const int rb_r = r;
|
||||||
|
static u32 rb_GPR[32];
|
||||||
|
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
{
|
{
|
||||||
|
rb_GPR[r] = m_GPR[r];
|
||||||
m_GPR[r] = 0;
|
m_GPR[r] = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -541,6 +571,17 @@ void Interpreter::lswx(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
PanicAlert("DSI exception in lswx.");
|
PanicAlert("DSI exception in lswx.");
|
||||||
NOTICE_LOG(POWERPC, "DSI exception in lswx");
|
NOTICE_LOG(POWERPC, "DSI exception in lswx");
|
||||||
|
|
||||||
|
n = ((EA - rb_EA) / 4) + 1;
|
||||||
|
EA = rb_EA;
|
||||||
|
r = rb_r;
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
m_GPR[r] = rb_GPR[r];
|
||||||
|
r = (r + 1) & 31;
|
||||||
|
EA += 4;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_GPR[r] |= TempValue;
|
m_GPR[r] |= TempValue;
|
||||||
|
@ -552,6 +593,7 @@ void Interpreter::lswx(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
i = 0;
|
i = 0;
|
||||||
r = (r + 1) & 31;
|
r = (r + 1) & 31;
|
||||||
|
rb_GPR[r] = m_GPR[r];
|
||||||
m_GPR[r] = 0;
|
m_GPR[r] = 0;
|
||||||
}
|
}
|
||||||
} while (n > 0);
|
} while (n > 0);
|
||||||
|
@ -667,7 +709,6 @@ void Interpreter::sthx(UGeckoInstruction _inst)
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
// lswi - bizarro string instruction
|
// lswi - bizarro string instruction
|
||||||
// FIXME: Should rollback if a DSI occurs
|
|
||||||
void Interpreter::lswi(UGeckoInstruction _inst)
|
void Interpreter::lswi(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
u32 EA;
|
u32 EA;
|
||||||
|
@ -682,38 +723,55 @@ void Interpreter::lswi(UGeckoInstruction _inst)
|
||||||
else
|
else
|
||||||
n = _inst.NB;
|
n = _inst.NB;
|
||||||
|
|
||||||
int r = _inst.RD - 1;
|
int r = _inst.RD;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (n>0)
|
|
||||||
|
const u32 rb_EA = EA;
|
||||||
|
const int rb_r = r;
|
||||||
|
static u32 rb_GPR[32];
|
||||||
|
|
||||||
|
if (n > 0)
|
||||||
{
|
{
|
||||||
if (i==0)
|
rb_GPR[r] = m_GPR[r];
|
||||||
|
m_GPR[r] = 0;
|
||||||
|
do
|
||||||
{
|
{
|
||||||
r++;
|
u32 TempValue = Memory::Read_U8(EA) << (24 - i);
|
||||||
r &= 31;
|
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||||
m_GPR[r] = 0;
|
{
|
||||||
}
|
PanicAlert("DSI exception in lswi.");
|
||||||
|
|
||||||
u32 TempValue = Memory::Read_U8(EA) << (24 - i);
|
n = ((EA - rb_EA) / 4) + 1;
|
||||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
EA = rb_EA;
|
||||||
{
|
r = rb_r;
|
||||||
PanicAlert("DSI exception in lsw.");
|
while (n > 0)
|
||||||
return;
|
{
|
||||||
}
|
m_GPR[r] = rb_GPR[r];
|
||||||
|
r = (r + 1) & 31;
|
||||||
|
EA += 4;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_GPR[r] |= TempValue;
|
||||||
|
|
||||||
m_GPR[r] |= TempValue;
|
EA++;
|
||||||
|
n--;
|
||||||
i += 8;
|
i += 8;
|
||||||
if (i == 32)
|
if (i == 32)
|
||||||
i = 0;
|
{
|
||||||
EA++;
|
i = 0;
|
||||||
n--;
|
r = (r + 1) & 31;
|
||||||
|
rb_GPR[r] = m_GPR[r];
|
||||||
|
m_GPR[r] = 0;
|
||||||
|
}
|
||||||
|
} while (n > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo : optimize ?
|
// todo : optimize ?
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
// stswi - bizarro string instruction
|
// stswi - bizarro string instruction
|
||||||
// FIXME: Should rollback if a DSI occurs
|
|
||||||
void Interpreter::stswi(UGeckoInstruction _inst)
|
void Interpreter::stswi(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
u32 EA;
|
u32 EA;
|
||||||
|
@ -728,26 +786,47 @@ void Interpreter::stswi(UGeckoInstruction _inst)
|
||||||
else
|
else
|
||||||
n = _inst.NB;
|
n = _inst.NB;
|
||||||
|
|
||||||
int r = _inst.RS - 1;
|
int r = _inst.RS;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while (n > 0)
|
|
||||||
{
|
const u32 rb_EA = EA;
|
||||||
if (i == 0)
|
const int rb_r = r;
|
||||||
{
|
static u32 rb_mem[32];
|
||||||
r++;
|
|
||||||
r &= 31;
|
while (n > 0) {
|
||||||
}
|
rb_mem[r] |= Memory::ReadUnchecked_U8(EA) << (24 - i);
|
||||||
Memory::Write_U8((m_GPR[r] >> (24 - i)) & 0xFF, EA);
|
Memory::Write_U8((m_GPR[r] >> (24 - i)) & 0xFF, EA);
|
||||||
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
|
||||||
{
|
{
|
||||||
|
PanicAlert("DSI exception in stswi.");
|
||||||
|
|
||||||
|
n = EA - rb_EA;
|
||||||
|
EA = rb_EA;
|
||||||
|
r = rb_r;
|
||||||
|
i = 0;
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
Memory::WriteUnchecked_U8((rb_mem[r] >> (24 - i)) & 0xFF, EA);
|
||||||
|
EA++;
|
||||||
|
i += 8;
|
||||||
|
if (i == 32)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
r = (r + 1) & 31;
|
||||||
|
}
|
||||||
|
n--;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
i += 8;
|
|
||||||
if (i == 32)
|
|
||||||
i = 0;
|
|
||||||
EA++;
|
EA++;
|
||||||
n--;
|
n--;
|
||||||
|
i += 8;
|
||||||
|
if (i == 32)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
r = (r + 1) & 31;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue