summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2014-12-28 06:07:24 -0500
committerGravatar Lioncash2014-12-28 06:09:43 -0500
commit059c65a27af538cba40aa43d2eeb3a544661a9b8 (patch)
tree250facd7671854ca8818c7900515813a3b7d94de /src
parentMerge pull request #349 from lioncash/uhdync (diff)
downloadyuzu-059c65a27af538cba40aa43d2eeb3a544661a9b8.tar.gz
yuzu-059c65a27af538cba40aa43d2eeb3a544661a9b8.tar.xz
yuzu-059c65a27af538cba40aa43d2eeb3a544661a9b8.zip
armemu: Fix underflows in USAD8/USADA8
Initially reported by xdec.
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/interpreter/armemu.cpp8
-rw-r--r--src/core/arm/interpreter/armsupp.cpp9
-rw-r--r--src/core/arm/skyeye_common/armemu.h1
3 files changed, 14 insertions, 4 deletions
diff --git a/src/core/arm/interpreter/armemu.cpp b/src/core/arm/interpreter/armemu.cpp
index 9b680c1e2..404012b2a 100644
--- a/src/core/arm/interpreter/armemu.cpp
+++ b/src/core/arm/interpreter/armemu.cpp
@@ -6643,10 +6643,10 @@ L_stm_s_takeabort:
6643 const u32 rm_val = state->Reg[rm_idx]; 6643 const u32 rm_val = state->Reg[rm_idx];
6644 const u32 rn_val = state->Reg[rn_idx]; 6644 const u32 rn_val = state->Reg[rn_idx];
6645 6645
6646 const u8 diff1 = (u8)std::labs((rn_val & 0xFF) - (rm_val & 0xFF)); 6646 const u8 diff1 = ARMul_UnsignedAbsoluteDifference(rn_val & 0xFF, rm_val & 0xFF);
6647 const u8 diff2 = (u8)std::labs(((rn_val >> 8) & 0xFF) - ((rm_val >> 8) & 0xFF)); 6647 const u8 diff2 = ARMul_UnsignedAbsoluteDifference((rn_val >> 8) & 0xFF, (rm_val >> 8) & 0xFF);
6648 const u8 diff3 = (u8)std::labs(((rn_val >> 16) & 0xFF) - ((rm_val >> 16) & 0xFF)); 6648 const u8 diff3 = ARMul_UnsignedAbsoluteDifference((rn_val >> 16) & 0xFF, (rm_val >> 16) & 0xFF);
6649 const u8 diff4 = (u8)std::labs(((rn_val >> 24) & 0xFF) - ((rm_val >> 24) & 0xFF)); 6649 const u8 diff4 = ARMul_UnsignedAbsoluteDifference((rn_val >> 24) & 0xFF, (rm_val >> 24) & 0xFF);
6650 6650
6651 u32 finalDif = (diff1 + diff2 + diff3 + diff4); 6651 u32 finalDif = (diff1 + diff2 + diff3 + diff4);
6652 6652
diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp
index 6774f8a74..61639d156 100644
--- a/src/core/arm/interpreter/armsupp.cpp
+++ b/src/core/arm/interpreter/armsupp.cpp
@@ -392,6 +392,15 @@ ARMul_NthReg (ARMword instr, unsigned number)
392 return (bit - 1); 392 return (bit - 1);
393} 393}
394 394
395/* Unsigned sum of absolute difference */
396u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right)
397{
398 if (left > right)
399 return left - right;
400
401 return right - left;
402}
403
395/* Assigns the N and Z flags depending on the value of result. */ 404/* Assigns the N and Z flags depending on the value of result. */
396 405
397void 406void
diff --git a/src/core/arm/skyeye_common/armemu.h b/src/core/arm/skyeye_common/armemu.h
index 3ea14b5a3..04c5d2e1a 100644
--- a/src/core/arm/skyeye_common/armemu.h
+++ b/src/core/arm/skyeye_common/armemu.h
@@ -600,6 +600,7 @@ extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
600extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword); 600extern ARMword ARMul_Align (ARMul_State *, ARMword, ARMword);
601extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword); 601extern ARMword ARMul_SwitchMode (ARMul_State *, ARMword, ARMword);
602extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword); 602extern void ARMul_MSRCpsr (ARMul_State *, ARMword, ARMword);
603extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
603extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword); 604extern void ARMul_SubOverflow (ARMul_State *, ARMword, ARMword, ARMword);
604extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword); 605extern void ARMul_AddOverflow (ARMul_State *, ARMword, ARMword, ARMword);
605extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword); 606extern void ARMul_AddOverflowQ(ARMul_State*, ARMword, ARMword);