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:
Lioncash 2018-04-01 21:18:09 -04:00
parent bf8ffe5bfb
commit c1b78106e7
No known key found for this signature in database
GPG Key ID: 4E3C3CC1031BA9C7
2 changed files with 37 additions and 5 deletions

View File

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

View File

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