From 5736b1be2a760970b082d5106faeb4e16ac62d9f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 31 Mar 2019 13:06:12 -0700 Subject: [PATCH] interp: Correct some negative invalid zero cases. In these cases, the input value wires to +0. Also, transposed the values in a comment (oops.) --- Core/MIPS/MIPSIntVFPU.cpp | 11 ++++++++--- Core/MIPS/MIPSVFPUUtils.h | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 65659e0603..b9bb5e2d2e 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -774,8 +774,9 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); ReadVector(s, sz, vs); // Swizzle can cause V_Single to properly write both components. - // TODO: Minor, but negate shouldn't apply to invalid here. Maybe always? ApplySwizzleS(s, V_Quad); + // Negate should not actually apply to invalid swizzle. + RetainInvalidSwizzleST(s, V_Quad); VectorSize outsize = V_Single; switch (sz) { @@ -1393,13 +1394,17 @@ namespace MIPSInt float s[4]{}; ReadVector(s, V_Single, vs); u32 sprefixRemove = VFPU_NEGATE(1, 0, 0, 0); - u32 sprefixAdd = VFPU_NEGATE(negSin, 0, 0, 0); - // TODO: Minor, but negate shouldn't apply to invalid here. Maybe always? + // We apply negSin later, not here. This handles zero a bit better. + u32 sprefixAdd = VFPU_NEGATE(0, 0, 0, 0); ApplyPrefixST(s, VFPURewritePrefix(VFPU_CTRL_SPREFIX, sprefixRemove, sprefixAdd), V_Single); // Cosine ignores all prefixes, so take the original. cosine = vfpu_cos(V(vs)); sine = vfpu_sin(s[0]); + + if (negSin) + sine = -sine; + RetainInvalidSwizzleST(&sine, V_Single); } if (sineLane == cosineLane) { diff --git a/Core/MIPS/MIPSVFPUUtils.h b/Core/MIPS/MIPSVFPUUtils.h index 34863a222b..5a9c59ae70 100644 --- a/Core/MIPS/MIPSVFPUUtils.h +++ b/Core/MIPS/MIPSVFPUUtils.h @@ -35,7 +35,7 @@ inline int Xpose(int v) { // Some games depend on exact values, but sinf() and cosf() aren't always precise. // Stepping down to [0, 2pi) helps, but we also check common exact-result values. -// TODO: cos(2) and sin(1) should be -0.0, but doing that gives wrong results (possibly from floorf.) +// TODO: cos(1) and sin(2) should be -0.0, but doing that gives wrong results (possibly from floorf.) inline float vfpu_sin(float angle) { angle -= floorf(angle * 0.25f) * 4.f;