From c1b78106e75e63804f7c795e708e7a5218a72ec7 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sun, 1 Apr 2018 21:18:09 -0400 Subject: [PATCH] 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. --- .../Interpreter/Interpreter_LoadStore.cpp | 40 +++++++++++++++++-- Source/Core/Core/PowerPC/PowerPC.cpp | 2 - 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 8000e6a949..4260339a1c 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -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); diff --git a/Source/Core/Core/PowerPC/PowerPC.cpp b/Source/Core/Core/PowerPC/PowerPC.cpp index 3167c4bcb3..b42f8cf91a 100644 --- a/Source/Core/Core/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/PowerPC/PowerPC.cpp @@ -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;