From 84c95526bc325fa8013d500e7a2fe37635542584 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Feb 2013 14:38:37 -0800 Subject: [PATCH 1/3] Mark more instructions which eat prefixes. --- Core/MIPS/MIPSTables.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 2d6ec44494..a27774bd3d 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -492,7 +492,7 @@ const MIPSInstruction tableVFPU1[8] = INSTR("vdot",&Jit::Comp_VDot, Dis_VectorDot, Int_VDot, IS_VFPU|OUT_EAT_PREFIX), INSTR("vscl",&Jit::Comp_Generic, Dis_VScl, Int_VScl, IS_VFPU|OUT_EAT_PREFIX), {-2}, - INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU), + INSTR("vhdp",&Jit::Comp_Generic, Dis_Generic, Int_VHdp, IS_VFPU|OUT_EAT_PREFIX), INSTR("vcrs",&Jit::Comp_Generic, Dis_Vcrs, Int_Vcrs, IS_VFPU), INSTR("vdet",&Jit::Comp_Generic, Dis_Generic, Int_Vdet, IS_VFPU), {-2}, @@ -619,8 +619,8 @@ MIPSInstruction tableVFPU5[8] = //110111 xxx INSTR("vpfxt",&Jit::Comp_VPFX, Dis_VPFXST, Int_VPFX, IS_VFPU), INSTR("vpfxd", &Jit::Comp_VPFX, Dis_VPFXD, Int_VPFX, IS_VFPU), INSTR("vpfxd", &Jit::Comp_VPFX, Dis_VPFXD, Int_VPFX, IS_VFPU), - INSTR("viim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU), - INSTR("vfim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU), + INSTR("viim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vfim.s",&Jit::Comp_Generic, Dis_Viim,Int_Viim, IS_VFPU|OUT_EAT_PREFIX), }; const MIPSInstruction tableVFPU6[32] = //111100 xxx @@ -690,14 +690,14 @@ const MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx INSTR("vbfy1", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX), INSTR("vbfy2", &Jit::Comp_Generic, Dis_Vbfy, Int_Vbfy, IS_VFPU|OUT_EAT_PREFIX), //4 - INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU), // one's complement - INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU), + INSTR("vocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vocp, IS_VFPU|OUT_EAT_PREFIX), // one's complement + INSTR("vsocp", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsocp, IS_VFPU|OUT_EAT_PREFIX), INSTR("vfad", &Jit::Comp_Generic, Dis_Vfad, Int_Vfad, IS_VFPU|OUT_EAT_PREFIX), INSTR("vavg", &Jit::Comp_Generic, Dis_Vfad, Int_Vavg, IS_VFPU), //8 INSTR("vsrt3", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt3, IS_VFPU), INSTR("vsrt4", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsrt4, IS_VFPU), - INSTR("vsgn", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsgn, IS_VFPU), + INSTR("vsgn", &Jit::Comp_Generic, Dis_Vbfy, Int_Vsgn, IS_VFPU|OUT_EAT_PREFIX), {-2}, //12 {-2}, @@ -715,9 +715,9 @@ const MIPSInstruction tableVFPU9[32] = //110100 00010 xxxxx {-2},{-2},{-2},{-2}, //24 {-2}, - INSTR("vt4444", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU), - INSTR("vt5551", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU), - INSTR("vt5650", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU), + INSTR("vt4444", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vt5551", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU|OUT_EAT_PREFIX), + INSTR("vt5650", &Jit::Comp_Generic, Dis_Generic, Int_ColorConv, IS_VFPU|OUT_EAT_PREFIX), //28 {-2},{-2},{-2},{-2}, From 4d1f07990a13f0e27cf815db0ee18862689d2765 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Feb 2013 14:39:13 -0800 Subject: [PATCH 2/3] Fix some NaN handling in a few funcs. --- Core/MIPS/MIPSIntVFPU.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index 4cc701ece9..d2e2e281fc 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -89,6 +89,25 @@ using std::isnan; #define isnan _isnan #endif +// 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) +{ + return f <= cst ? cst : f; +} + +// Preserves NaN in first param, takes sign of equal second param. +inline float nanmin(float f, float cst) +{ + return f >= cst ? cst : f; +} + +// Preserves NaN in first param, takes sign of equal value in others. +inline float nanclamp(float f, float lower, float upper) +{ + return nanmin(nanmax(f, lower), upper); +} + void ApplyPrefixST(float *v, u32 data, VectorSize size) { // Possible optimization shortcut: @@ -523,7 +542,8 @@ namespace MIPSInt ReadVector(s, sz, vs); for (int i = 0; i < GetNumVectorElements(sz); i++) { - d[i] = 1.0f - s[i]; + // Always positive NaN. + d[i] = isnan(s[i]) ? fabsf(s[i]) : 1.0f - s[i]; } ApplyPrefixD(d, sz); WriteVector(d, sz, vd); @@ -540,13 +560,13 @@ namespace MIPSInt ReadVector(s, sz, vs); int n = GetNumVectorElements(sz); float x = s[0]; - d[0] = std::min(std::max(0.0f, 1.0f - x), 1.0f); - d[1] = std::min(std::max(0.0f, x), 1.0f); + d[0] = nanclamp(1.0f - x, 0.0f, 1.0f); + d[1] = nanclamp(x, 0.0f, 1.0f); VectorSize outSize = V_Pair; if (n > 1) { float y = s[1]; - d[2] = std::min(std::max(0.0f, 1.0f - y), 1.0f); - d[3] = std::min(std::max(0.0f, y), 1.0f); + d[2] = nanclamp(1.0f - y, 0.0f, 1.0f); + d[3] = nanclamp(y, 0.0f, 1.0f); outSize = V_Quad; } WriteVector(d, outSize, vd); @@ -1001,7 +1021,7 @@ namespace MIPSInt { sum += (i == n - 1) ? t[i] : s[i]*t[i]; } - d = sum; + d = isnan(sum) ? fabsf(sum) : sum; ApplyPrefixD(&d,V_Single); V(vd) = d; PC += 4; From 06425ae9e7e074c76321b996b3a33e84b3e8f6db Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 24 Feb 2013 15:07:29 -0800 Subject: [PATCH 3/3] Correct the more obscure vcmp cases. --- Core/MIPS/MIPSIntVFPU.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Core/MIPS/MIPSIntVFPU.cpp b/Core/MIPS/MIPSIntVFPU.cpp index d2e2e281fc..0267af829e 100644 --- a/Core/MIPS/MIPSIntVFPU.cpp +++ b/Core/MIPS/MIPSIntVFPU.cpp @@ -84,9 +84,11 @@ #ifdef __APPLE__ using std::isnan; +using std::isinf; #endif #ifdef _MSC_VER #define isnan _isnan +#define isinf(x) (!_finite(x) && !_isnan(x)) #endif // Preserves NaN in first param, takes sign of equal second param. @@ -1554,16 +1556,18 @@ namespace MIPSInt case VC_EZ: c = s[i] == 0.0f || s[i] == -0.0f; break; case VC_EN: c = isnan(s[i]); break; - case VC_EI: c = 0; break; - case VC_ES: c = (s[i] != s[i]) || (s[i] == std::numeric_limits::infinity()); break; // Tekken Dark Resurrection + case VC_EI: c = isinf(s[i]); break; + case VC_ES: c = isnan(s[i]) || isinf(s[i]); break; // Tekken Dark Resurrection case VC_NZ: c = s[i] != 0; break; - case VC_NN: c = s[i] != 0; break; - case VC_NI: c = s[i] != 0; break; - case VC_NS: c = s[i] != 0; break; + case VC_NN: c = !isnan(s[i]); break; + case VC_NI: c = !isinf(s[i]); break; + case VC_NS: c = !isnan(s[i]) && !isinf(s[i]); break; + default: _dbg_assert_msg_(CPU,0,"Unsupported vcmp condition code %d", cond); PC += 4; + EatPrefixes(); return; } cc |= (c<