From fd1b01b5735c5773896f744672ffd20a1f79c13c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 1 Sep 2014 22:33:01 -0700 Subject: [PATCH] Fix the vrndi.s output range. Was previously outputting only valid positive float values, but should use a much wider range of a u32. Might've affected randomness in some games. --- Core/MIPS/MIPSIntVFPU.cpp | 37 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 0531f9835d..d69b0666ff 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -70,6 +70,12 @@ #define M_SQRT1_2 0.707106781186547524401f #endif +union FloatBits { + float f[4]; + u32 u[4]; + int i[4]; +}; + // Preserves NaN in first param, takes sign of equal second param. // Technically, std::max may do this but it's undefined. inline float nanmax(float f, float cst) @@ -1177,7 +1183,8 @@ namespace MIPSInt ReadVector(s, sz, vs); ApplySwizzleS(s, sz); ReadVector(t, sz, vt); - // TODO: Does t have swizzle? + // TODO: The swizzle on t behaves oddly with constants, but sign changes seem to work. + // Also, seems to round in a non-standard way (sometimes toward zero, not always.) d[0] = s[0] * t[1] - s[1] * t[0]; ApplyPrefixD(d, sz); WriteVector(d, V_Single, vd); @@ -1267,7 +1274,7 @@ namespace MIPSInt void Int_VrndX(MIPSOpcode op) { - float d[4]; + FloatBits d; int vd = _VD; VectorSize sz = GetVecSize(op); int n = GetNumVectorElements(sz); @@ -1275,14 +1282,14 @@ namespace MIPSInt { switch ((op >> 16) & 0x1f) { - case 1: d[i] = (float)currentMIPS->rng.R32(); break; // vrndi - TODO: copy bits instead? - case 2: d[i] = 1.0f + ((float)currentMIPS->rng.R32() / 0xFFFFFFFF); break; // vrndf1 TODO: make more accurate - case 3: d[i] = 2.0f + 2 * ((float)currentMIPS->rng.R32() / 0xFFFFFFFF); break; // vrndf2 TODO: make more accurate + case 1: d.u[i] = currentMIPS->rng.R32(); break; // vrndi + case 2: d.f[i] = 1.0f + ((float)currentMIPS->rng.R32() / 0xFFFFFFFF); break; // vrndf1 TODO: make more accurate + case 3: d.f[i] = 2.0f + 2 * ((float)currentMIPS->rng.R32() / 0xFFFFFFFF); break; // vrndf2 TODO: make more accurate default: _dbg_assert_msg_(CPU,0,"Trying to interpret instruction that can't be interpreted"); } } - ApplyPrefixD(d, sz); - WriteVector(d, sz, vd); + ApplyPrefixD(d.f, sz); + WriteVector(d.f, sz, vd); PC += 4; EatPrefixes(); } @@ -1531,12 +1538,6 @@ namespace MIPSInt VectorSize sz = GetVecSize(op); int numElements = GetNumVectorElements(sz); - union FloatBits { - float f[4]; - u32 u[4]; - int i[4]; - }; - FloatBits s; FloatBits t; FloatBits d; @@ -1810,11 +1811,6 @@ bad: int vs = _VS; VectorSize sz = GetVecSize(op); - union FloatBits { - float f[4]; - u32 u[4]; - }; - FloatBits d; FloatBits s; u8 exp = (u8)((op >> 16) & 0xFF); @@ -1856,11 +1852,6 @@ bad: int vt = _VT; VectorSize sz = GetVecSize(op); - union FloatBits { - float f[4]; - u32 u[4]; - }; - FloatBits d; FloatBits s; u8 exp = (u8)(127 + VI(vt));