summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorrice1964 <rice1964@gmail.com>2009-09-17 04:05:14 +0000
committerrice1964 <rice1964@gmail.com>2009-09-17 04:05:14 +0000
commit7f2d4fc2c8bca315b8b6aa2136f9ad3b7ad6fd43 (patch)
treeedd66d35615286ce82d9c1d85a49dbc7f3bfec2d /Source/Core
parent4edf1ea837029fa5aa254d69561daec0dd82c049 (diff)
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
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FloatingPoint.cpp35
-rw-r--r--Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_Paired.cpp78
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));
}
// __________________________________________________________________________________________________