summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2017-05-08 16:24:08 -0500
committerGravatar Subv2017-05-13 18:03:41 -0500
commita0874a7a687ac2ff606aca832f5dd21b14d75053 (patch)
treebdfb920bf747a28273bb1336c2d8431baca60048 /src
parentMerge pull request #2682 from nicoboss/filter (diff)
downloadyuzu-a0874a7a687ac2ff606aca832f5dd21b14d75053.tar.gz
yuzu-a0874a7a687ac2ff606aca832f5dd21b14d75053.tar.xz
yuzu-a0874a7a687ac2ff606aca832f5dd21b14d75053.zip
Dyncom/VFP: Perform flush-to-zero on the second operand of vsub before sending it to vadd.
Previously we were letting vadd flush the value to positive 0, but there are cases where this behavior is wrong, for example, vsub: -0 - +0 = -0 vadd: -0 + +0 = +0 Now we'll flush the value to +0 inside vsub, and then negate it.
Diffstat (limited to 'src')
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpsingle.cpp14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
index 1590d89a4..8034d8398 100644
--- a/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
+++ b/src/core/arm/skyeye_common/vfp/vfpsingle.cpp
@@ -1062,12 +1062,22 @@ static u32 vfp_single_fadd(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr)
1062static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) { 1062static u32 vfp_single_fsub(ARMul_State* state, int sd, int sn, s32 m, u32 fpscr) {
1063 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd); 1063 LOG_TRACE(Core_ARM11, "s%u = %08x", sn, sd);
1064 /* 1064 /*
1065 * Subtraction is addition with one sign inverted. 1065 * Subtraction is addition with one sign inverted. Unpack the second operand to perform FTZ if
1066 * necessary, we can't let fadd do this because a denormal in m might get flushed to +0 in FTZ
1067 * mode, and the resulting sign of 0 OP +0 differs between fadd and fsub. We do not need to do
1068 * this for n because +0 OP 0 is always +0 for both fadd and fsub.
1066 */ 1069 */
1070 struct vfp_single vsm;
1071 u32 exceptions = vfp_single_unpack(&vsm, m, fpscr);
1072 if (exceptions & FPSCR_IDC) {
1073 // The value was flushed to zero, re-pack it.
1074 m = vfp_single_pack(&vsm);
1075 }
1076
1067 if (m != 0x7FC00000) // Only negate if m isn't NaN. 1077 if (m != 0x7FC00000) // Only negate if m isn't NaN.
1068 m = vfp_single_packed_negate(m); 1078 m = vfp_single_packed_negate(m);
1069 1079
1070 return vfp_single_fadd(state, sd, sn, m, fpscr); 1080 return vfp_single_fadd(state, sd, sn, m, fpscr) | exceptions;
1071} 1081}
1072 1082
1073/* 1083/*