From 912c9490c0e7225cdc7fa3581d8eb10e2b592259 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Thu, 5 Apr 2018 00:22:57 -0400 Subject: [PATCH] Interpreter_LoadStore: Generate alignment exceptions if an FP load/store instruction's effective address is not word aligned This is one of the conditions for an alignment exception documented in the 750CL architecture reference manual in section 4.5.6, which also applies to the Gekko microprocessor. --- .../Interpreter/Interpreter_LoadStore.cpp | 138 +++++++++++++++++- 1 file changed, 130 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 4ada0b3c3c..98b04f4bc2 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -74,7 +74,15 @@ void Interpreter::lbzu(UGeckoInstruction inst) void Interpreter::lfd(UGeckoInstruction inst) { - const u64 temp = PowerPC::Read_U64(Helper_Get_EA(inst)); + const u32 address = Helper_Get_EA(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + const u64 temp = PowerPC::Read_U64(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) riPS0(inst.FD) = temp; @@ -83,6 +91,13 @@ void Interpreter::lfd(UGeckoInstruction inst) void Interpreter::lfdu(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_U(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + const u64 temp = PowerPC::Read_U64(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) @@ -95,6 +110,13 @@ void Interpreter::lfdu(UGeckoInstruction inst) void Interpreter::lfdux(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_UX(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + const u64 temp = PowerPC::Read_U64(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) @@ -106,7 +128,15 @@ void Interpreter::lfdux(UGeckoInstruction inst) void Interpreter::lfdx(UGeckoInstruction inst) { - const u64 temp = PowerPC::Read_U64(Helper_Get_EA_X(inst)); + const u32 address = Helper_Get_EA_X(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + const u64 temp = PowerPC::Read_U64(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) riPS0(inst.FD) = temp; @@ -114,7 +144,15 @@ void Interpreter::lfdx(UGeckoInstruction inst) void Interpreter::lfs(UGeckoInstruction inst) { - const u32 temp = PowerPC::Read_U32(Helper_Get_EA(inst)); + const u32 address = Helper_Get_EA(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + const u32 temp = PowerPC::Read_U32(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { @@ -127,6 +165,13 @@ void Interpreter::lfs(UGeckoInstruction inst) void Interpreter::lfsu(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_U(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + const u32 temp = PowerPC::Read_U32(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) @@ -141,6 +186,13 @@ void Interpreter::lfsu(UGeckoInstruction inst) void Interpreter::lfsux(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_UX(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + const u32 temp = PowerPC::Read_U32(address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) @@ -154,7 +206,15 @@ void Interpreter::lfsux(UGeckoInstruction inst) void Interpreter::lfsx(UGeckoInstruction inst) { - const u32 temp = PowerPC::Read_U32(Helper_Get_EA_X(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)) { @@ -300,13 +360,27 @@ void Interpreter::stbu(UGeckoInstruction inst) void Interpreter::stfd(UGeckoInstruction inst) { - PowerPC::Write_U64(riPS0(inst.FS), Helper_Get_EA(inst)); + const u32 address = Helper_Get_EA(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + PowerPC::Write_U64(riPS0(inst.FS), address); } void Interpreter::stfdu(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_U(inst); + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + PowerPC::Write_U64(riPS0(inst.FS), address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { @@ -316,13 +390,27 @@ void Interpreter::stfdu(UGeckoInstruction inst) void Interpreter::stfs(UGeckoInstruction inst) { - PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), Helper_Get_EA(inst)); + const u32 address = Helper_Get_EA(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), address); } void Interpreter::stfsu(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_U(inst); + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { @@ -646,6 +734,12 @@ void Interpreter::stfdux(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_UX(inst); + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + PowerPC::Write_U64(riPS0(inst.FS), address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { @@ -655,7 +749,15 @@ void Interpreter::stfdux(UGeckoInstruction inst) void Interpreter::stfdx(UGeckoInstruction inst) { - PowerPC::Write_U64(riPS0(inst.FS), Helper_Get_EA_X(inst)); + const u32 address = Helper_Get_EA_X(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + PowerPC::Write_U64(riPS0(inst.FS), address); } // Stores Floating points into Integers indeXed @@ -663,6 +765,12 @@ void Interpreter::stfiwx(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_X(inst); + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + PowerPC::Write_U32((u32)riPS0(inst.FS), address); } @@ -670,6 +778,12 @@ void Interpreter::stfsux(UGeckoInstruction inst) { const u32 address = Helper_Get_EA_UX(inst); + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), address); if (!(PowerPC::ppcState.Exceptions & EXCEPTION_DSI)) { @@ -679,7 +793,15 @@ void Interpreter::stfsux(UGeckoInstruction inst) void Interpreter::stfsx(UGeckoInstruction inst) { - PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), Helper_Get_EA_X(inst)); + const u32 address = Helper_Get_EA_X(inst); + + if ((address & 0b11) != 0) + { + GenerateAlignmentException(address); + return; + } + + PowerPC::Write_U32(ConvertToSingle(riPS0(inst.FS)), address); } void Interpreter::sthbrx(UGeckoInstruction inst)