From 7f2d4fc2c8bca315b8b6aa2136f9ad3b7ad6fd43 Mon Sep 17 00:00:00 2001 From: rice1964 Date: Thu, 17 Sep 2009 04:05:14 +0000 Subject: [PATCH] FPU: some fixes about NaN, SNaN, QNan in related opcodes, according to the CPU manual. Ector, please double check. I don't see any side effects yet. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4288 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Interpreter/Interpreter_FloatingPoint.cpp | 35 ++------- .../Interpreter/Interpreter_Paired.cpp | 78 +++++++++++++++---- 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp index 7ecd40db3a..902c7c11f6 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp @@ -59,33 +59,18 @@ void fcmpo(UGeckoInstruction _inst) double fb = rPS0(_inst.FB); int compareResult; - //if (IsNAN(fa) || IsNAN(fb)) - //{ - // FPSCR.FX = 1; - // compareResult = 1; - // if (IsSNAN(fa) || IsSNAN(fb)) - // { - // FPSCR.VXSNAN = 1; - // if (!FPSCR.FEX || IsQNAN(fa) || IsQNAN(fb)) - // FPSCR.VXVC = 1; - // } - //} - //else + if (fa < fb) compareResult = 8; else if (fa > fb) compareResult = 4; else if (fa == fb) compareResult = 2; else { - // either fa or fb is NaN, or both, FPSCR.FX = 1; compareResult = 1; - if (IsSNAN(fa) || IsSNAN(fb)) - { + if (IsSNAN(fa) || IsSNAN(fb)) FPSCR.VXSNAN = 1; - if (!FPSCR.FEX || IsQNAN(fa) || IsQNAN(fb)) - FPSCR.VXVC = 1; - } - + if (!FPSCR.FEX || IsQNAN(fa) || IsQNAN(fb)) + FPSCR.VXVC = 1; } FPSCR.FPRF = compareResult; @@ -100,22 +85,12 @@ void fcmpu(UGeckoInstruction _inst) double fb = rPS0(_inst.FB); int compareResult; - //if (IsNAN(fa) || IsNAN(fb)) - //{ - // FPSCR.FX = 1; - // compareResult = 1; - // if (IsSNAN(fa) || IsSNAN(fb)) - // { - // FPSCR.VXSNAN = 1; - // } - //} - //else + if (fa < fb) compareResult = 8; else if (fa > fb) compareResult = 4; else if (fa == fb) compareResult = 2; else { - // either fa or fb is NaN, or both FPSCR.FX = 1; compareResult = 1; if (IsSNAN(fa) || IsSNAN(fb)) diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp index 36120cfeab..e6c1816a1f 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp @@ -29,12 +29,6 @@ namespace Interpreter // These "binary instructions" do not alter FPSCR. void ps_sel(UGeckoInstruction _inst) { - //rPS0(_inst.FD) = !IsNAN(rPS0(_inst.FA)) && rPS0(_inst.FA) >= -0.0 ? - // rPS0(_inst.FC) : rPS0(_inst.FB); - //rPS1(_inst.FD) = !IsNAN(rPS1(_inst.FA)) && rPS1(_inst.FA) >= -0.0 ? - // rPS1(_inst.FC) : rPS1(_inst.FB); - - // no need to check isNaN rPS0(_inst.FD) = rPS0(_inst.FA) >= -0.0 ? rPS0(_inst.FC) : rPS0(_inst.FB); rPS1(_inst.FD) = rPS1(_inst.FA) >= -0.0 ? rPS1(_inst.FC) : rPS1(_inst.FB); if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); @@ -247,20 +241,46 @@ void ps_cmpu0(UGeckoInstruction _inst) double fa = rPS0(_inst.FA); double fb = rPS0(_inst.FB); int compareResult; - //if (IsNAN(fa) || IsNAN(fb)) compareResult = 1; - //else + if (fa < fb) compareResult = 8; else if (fa > fb) compareResult = 4; else if (fa == fb) compareResult = 2; - else compareResult = 1; + else + { + compareResult = 1; + if (IsSNAN(fa) || IsSNAN(fb)) + { + FPSCR.VXSNAN = 1; + } + } SetCRField(_inst.CRFD, compareResult); if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); } void ps_cmpo0(UGeckoInstruction _inst) { - // for now HACK - ps_cmpu0(_inst); + // Ector, please check + //ps_cmpu0(_inst); + double fa = rPS0(_inst.FA); + double fb = rPS0(_inst.FB); + int compareResult; + + if (fa < fb) compareResult = 8; + else if (fa > fb) compareResult = 4; + else if (fa == fb) compareResult = 2; + else + { + compareResult = 1; + if (IsSNAN(fa) || IsSNAN(fb)) + { + FPSCR.VXSNAN = 1; + if (!FPSCR.FEX) FPSCR.VXVC = 1; + } + else if (IsQNAN(fa) || IsQNAN(fb)) + FPSCR.VXVC = 1; + } + SetCRField(_inst.CRFD, compareResult); + if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); } void ps_cmpu1(UGeckoInstruction _inst) @@ -268,20 +288,46 @@ void ps_cmpu1(UGeckoInstruction _inst) double fa = rPS1(_inst.FA); double fb = rPS1(_inst.FB); int compareResult; - //if (IsNAN(fa) || IsNAN(fb)) compareResult = 1; - //else + if (fa < fb) compareResult = 8; else if (fa > fb) compareResult = 4; else if (fa == fb) compareResult = 2; - else compareResult = 1; + else + { + compareResult = 1; + if (IsSNAN(fa) || IsSNAN(fb)) + { + FPSCR.VXSNAN = 1; + } + } SetCRField(_inst.CRFD, compareResult); if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); } void ps_cmpo1(UGeckoInstruction _inst) { - // for now HACK - ps_cmpu1(_inst); + // Ector, please check + //ps_cmpu1(_inst); + double fa = rPS1(_inst.FA); + double fb = rPS1(_inst.FB); + int compareResult; + + if (fa < fb) compareResult = 8; + else if (fa > fb) compareResult = 4; + else if (fa == fb) compareResult = 2; + else + { + compareResult = 1; + if (IsSNAN(fa) || IsSNAN(fb)) + { + FPSCR.VXSNAN = 1; + if (!FPSCR.FEX) FPSCR.VXVC = 1; + } + else if (IsQNAN(fa) || IsQNAN(fb)) + FPSCR.VXVC = 1; + } + SetCRField(_inst.CRFD, compareResult); + if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD)); } // __________________________________________________________________________________________________