From 5b47635b3ff490965d60b4d813442c681c6c3a08 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 27 Aug 2016 10:07:14 +1200 Subject: [PATCH 1/4] Fix bug in interpreter's lswx. Was overwriting extra register. When n was a multiple of 4, the old implementation would overwrite the following register with 0. This was causing Not64 to crash. Thanks to Extrems for spotting this. --- .../Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index e197fd37a2..2505a4eafc 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -509,7 +509,7 @@ void Interpreter::lswx(UGeckoInstruction _inst) if (n > 0) { rGPR[r] = 0; - do + while (true) { u32 TempValue = PowerPC::Read_U8(EA) << (24 - i); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) @@ -520,8 +520,10 @@ void Interpreter::lswx(UGeckoInstruction _inst) } rGPR[r] |= TempValue; + if (--n == 0) + return; + EA++; - n--; i += 8; if (i == 32) { @@ -529,7 +531,7 @@ void Interpreter::lswx(UGeckoInstruction _inst) r = (r + 1) & 31; rGPR[r] = 0; } - } while (n > 0); + } } } From ab3eedcc331559e651fe1ffa7c56167921a7f51f Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 27 Aug 2016 10:33:39 +1200 Subject: [PATCH 2/4] While I'm here, stswx should wrap too. --- Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 2505a4eafc..0df1c338b5 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -742,7 +742,7 @@ void Interpreter::stswx(UGeckoInstruction _inst) if (i == 32) { i = 0; - r++; + r = (r + 1) & 0x1f; // wrap } } } From 967c371d7a8695e60cf52da22f3952f23b031359 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 28 Aug 2016 09:48:29 +1200 Subject: [PATCH 3/4] Zero case behaviour confirmed by hardware test Modify comments to reflect this --- Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 0df1c338b5..e3e1f4fcd6 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -497,7 +497,6 @@ void Interpreter::lhzx(UGeckoInstruction _inst) } } -// TODO: is this right? // FIXME: Should rollback if a DSI occurs void Interpreter::lswx(UGeckoInstruction _inst) { @@ -506,6 +505,7 @@ void Interpreter::lswx(UGeckoInstruction _inst) int r = _inst.RD; int i = 0; + // Confirmed by hardware test that the zero case doesn't zero rGPR[r] if (n > 0) { rGPR[r] = 0; From fc2b0e0f451b61bacd4b24b2a531edbaeb34292b Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Mon, 29 Aug 2016 22:57:37 +1200 Subject: [PATCH 4/4] Simplify lswx loop. --- .../Interpreter/Interpreter_LoadStore.cpp | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp index e3e1f4fcd6..1d9f49d582 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -501,37 +501,25 @@ void Interpreter::lhzx(UGeckoInstruction _inst) void Interpreter::lswx(UGeckoInstruction _inst) { u32 EA = Helper_Get_EA_X(_inst); - u32 n = (u8)PowerPC::ppcState.xer_stringctrl; - int r = _inst.RD; - int i = 0; // Confirmed by hardware test that the zero case doesn't zero rGPR[r] - if (n > 0) + for (u32 n = 0; n < static_cast(PowerPC::ppcState.xer_stringctrl); n++) { - rGPR[r] = 0; - while (true) + int reg = (_inst.RD + (n >> 2)) & 0x1f; + int offset = (n & 3) << 3; + if ((n & 3) == 0) + rGPR[reg] = 0; + + u32 TempValue = PowerPC::Read_U8(EA) << (24 - offset); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) { - u32 TempValue = PowerPC::Read_U8(EA) << (24 - i); - if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) - { - PanicAlert("DSI exception in lswx."); - NOTICE_LOG(POWERPC, "DSI exception in lswx"); - return; - } - rGPR[r] |= TempValue; - - if (--n == 0) - return; - - EA++; - i += 8; - if (i == 32) - { - i = 0; - r = (r + 1) & 31; - rGPR[r] = 0; - } + PanicAlert("DSI exception in lswx."); + NOTICE_LOG(POWERPC, "DSI exception in lswx"); + return; } + rGPR[reg] |= TempValue; + + EA++; } }