Interpreter_LoadStore: Flag alignment exceptions on misaligned addresses in lwarx, lmw, stmw, and stwcx
The effective address given to these instructions must be word (4 byte) aligned, and if the address is not aligned like that, then an alignment exception gets triggered. We currently don't update the DSISR in this case properly, since we didn't really handle alignment exceptions outside of ecowx and eciwx, and even then the handling of it isn't really that great, considering the DAR isn't updated with the address that caused the exception to occur. The DSISR will eventually be amended to be properly updated.
This commit is contained in:
parent
bf8ffe5bfb
commit
c1b78106e7
|
@ -17,6 +17,15 @@
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
u32 Interpreter::Helper_Get_EA(const UGeckoInstruction inst)
|
||||
{
|
||||
return inst.RA ? (rGPR[inst.RA] + inst.SIMM_16) : (u32)inst.SIMM_16;
|
||||
|
@ -198,6 +207,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 +235,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);
|
||||
|
@ -780,6 +801,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 +818,19 @@ void Interpreter::lwarx(UGeckoInstruction inst)
|
|||
}
|
||||
}
|
||||
|
||||
// Stores Word Conditional indeXed
|
||||
void Interpreter::stwcxd(UGeckoInstruction inst)
|
||||
{
|
||||
// Stores Word Conditional indeXed
|
||||
const u32 address = Helper_Get_EA_X(inst);
|
||||
|
||||
if ((address & 0b11) != 0)
|
||||
{
|
||||
GenerateAlignmentException(address);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_reserve)
|
||||
{
|
||||
const u32 address = Helper_Get_EA_X(inst);
|
||||
|
||||
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