Merge pull request #6585 from lioncash/exception
Interpreter_LoadStore: Handle alignment exceptions in lmw, lwarx, stmw, and stwcx + fixes for eciwx and ecowx
This commit is contained in:
commit
1e0f72f2da
|
@ -17,6 +17,21 @@
|
|||
bool Interpreter::m_reserve;
|
||||
u32 Interpreter::m_reserve_address;
|
||||
|
||||
namespace
|
||||
{
|
||||
void GenerateAlignmentException(u32 address)
|
||||
{
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
|
||||
PowerPC::ppcState.spr[SPR_DAR] = address;
|
||||
}
|
||||
|
||||
void GenerateDSIException(u32 address)
|
||||
{
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||
PowerPC::ppcState.spr[SPR_DAR] = address;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Interpreter::Helper_Get_EA(const UGeckoInstruction inst)
|
||||
{
|
||||
return inst.RA ? (rGPR[inst.RA] + inst.SIMM_16) : (u32)inst.SIMM_16;
|
||||
|
@ -198,6 +213,12 @@ void Interpreter::lmw(UGeckoInstruction inst)
|
|||
{
|
||||
u32 address = Helper_Get_EA(inst);
|
||||
|
||||
if ((address & 0b11) != 0)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = inst.RD; i <= 31; i++, address += 4)
|
||||
{
|
||||
const u32 temp_reg = PowerPC::Read_U32(address);
|
||||
|
@ -220,6 +241,12 @@ void Interpreter::stmw(UGeckoInstruction inst)
|
|||
{
|
||||
u32 address = Helper_Get_EA(inst);
|
||||
|
||||
if ((address & 0b11) != 0)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = inst.RS; i <= 31; i++, address += 4)
|
||||
{
|
||||
PowerPC::Write_U32(rGPR[i], address);
|
||||
|
@ -410,10 +437,15 @@ void Interpreter::eciwx(UGeckoInstruction inst)
|
|||
|
||||
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
||||
{
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||
GenerateDSIException(EA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (EA & 3)
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
}
|
||||
|
||||
rGPR[inst.RD] = PowerPC::Read_U32(EA);
|
||||
}
|
||||
|
@ -424,10 +456,15 @@ void Interpreter::ecowx(UGeckoInstruction inst)
|
|||
|
||||
if (!(PowerPC::ppcState.spr[SPR_EAR] & 0x80000000))
|
||||
{
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_DSI;
|
||||
GenerateDSIException(EA);
|
||||
return;
|
||||
}
|
||||
|
||||
if (EA & 3)
|
||||
PowerPC::ppcState.Exceptions |= EXCEPTION_ALIGNMENT;
|
||||
{
|
||||
GenerateAlignmentException(EA);
|
||||
return;
|
||||
}
|
||||
|
||||
PowerPC::Write_U32(rGPR[inst.RS], EA);
|
||||
}
|
||||
|
@ -780,6 +817,13 @@ void Interpreter::stwbrx(UGeckoInstruction inst)
|
|||
void Interpreter::lwarx(UGeckoInstruction inst)
|
||||
{
|
||||
const u32 address = Helper_Get_EA_X(inst);
|
||||
|
||||
if ((address & 0b11) != 0)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 temp = PowerPC::Read_U32(address);
|
||||
|
||||
if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI))
|
||||
|
@ -790,13 +834,19 @@ void Interpreter::lwarx(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
// Stores Word Conditional indeXed
|
||||
void Interpreter::stwcxd(UGeckoInstruction inst)
|
||||
{
|
||||
// Stores Word Conditional indeXed
|
||||
if (m_reserve)
|
||||
{
|
||||
const u32 address = Helper_Get_EA_X(inst);
|
||||
|
||||
if ((address & 0b11) != 0)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_reserve)
|
||||
{
|
||||
if (address == m_reserve_address)
|
||||
{
|
||||
PowerPC::Write_U32(rGPR[inst.RS], address);
|
||||
|
|
|
@ -474,8 +474,6 @@ void CheckExceptions()
|
|||
}
|
||||
else if (exceptions & EXCEPTION_ALIGNMENT)
|
||||
{
|
||||
// This never happens ATM
|
||||
// perhaps we can get dcb* instructions to use this :p
|
||||
SRR0 = PC;
|
||||
SRR1 = MSR & 0x87C0FFFF;
|
||||
MSR |= (MSR >> 16) & 1;
|
||||
|
|
Loading…
Reference in New Issue