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
This commit is contained in:
parent
4edf1ea837
commit
7f2d4fc2c8
|
@ -59,33 +59,18 @@ void fcmpo(UGeckoInstruction _inst)
|
||||||
double fb = rPS0(_inst.FB);
|
double fb = rPS0(_inst.FB);
|
||||||
|
|
||||||
int compareResult;
|
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;
|
if (fa < fb) compareResult = 8;
|
||||||
else if (fa > fb) compareResult = 4;
|
else if (fa > fb) compareResult = 4;
|
||||||
else if (fa == fb) compareResult = 2;
|
else if (fa == fb) compareResult = 2;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// either fa or fb is NaN, or both,
|
|
||||||
FPSCR.FX = 1;
|
FPSCR.FX = 1;
|
||||||
compareResult = 1;
|
compareResult = 1;
|
||||||
if (IsSNAN(fa) || IsSNAN(fb))
|
if (IsSNAN(fa) || IsSNAN(fb))
|
||||||
{
|
|
||||||
FPSCR.VXSNAN = 1;
|
FPSCR.VXSNAN = 1;
|
||||||
if (!FPSCR.FEX || IsQNAN(fa) || IsQNAN(fb))
|
if (!FPSCR.FEX || IsQNAN(fa) || IsQNAN(fb))
|
||||||
FPSCR.VXVC = 1;
|
FPSCR.VXVC = 1;
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FPSCR.FPRF = compareResult;
|
FPSCR.FPRF = compareResult;
|
||||||
|
@ -100,22 +85,12 @@ void fcmpu(UGeckoInstruction _inst)
|
||||||
double fb = rPS0(_inst.FB);
|
double fb = rPS0(_inst.FB);
|
||||||
|
|
||||||
int compareResult;
|
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;
|
if (fa < fb) compareResult = 8;
|
||||||
else if (fa > fb) compareResult = 4;
|
else if (fa > fb) compareResult = 4;
|
||||||
else if (fa == fb) compareResult = 2;
|
else if (fa == fb) compareResult = 2;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// either fa or fb is NaN, or both
|
|
||||||
FPSCR.FX = 1;
|
FPSCR.FX = 1;
|
||||||
compareResult = 1;
|
compareResult = 1;
|
||||||
if (IsSNAN(fa) || IsSNAN(fb))
|
if (IsSNAN(fa) || IsSNAN(fb))
|
||||||
|
|
|
@ -29,12 +29,6 @@ namespace Interpreter
|
||||||
// These "binary instructions" do not alter FPSCR.
|
// These "binary instructions" do not alter FPSCR.
|
||||||
void ps_sel(UGeckoInstruction _inst)
|
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);
|
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);
|
rPS1(_inst.FD) = rPS1(_inst.FA) >= -0.0 ? rPS1(_inst.FC) : rPS1(_inst.FB);
|
||||||
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
||||||
|
@ -247,20 +241,46 @@ void ps_cmpu0(UGeckoInstruction _inst)
|
||||||
double fa = rPS0(_inst.FA);
|
double fa = rPS0(_inst.FA);
|
||||||
double fb = rPS0(_inst.FB);
|
double fb = rPS0(_inst.FB);
|
||||||
int compareResult;
|
int compareResult;
|
||||||
//if (IsNAN(fa) || IsNAN(fb)) compareResult = 1;
|
|
||||||
//else
|
|
||||||
if (fa < fb) compareResult = 8;
|
if (fa < fb) compareResult = 8;
|
||||||
else if (fa > fb) compareResult = 4;
|
else if (fa > fb) compareResult = 4;
|
||||||
else if (fa == fb) compareResult = 2;
|
else if (fa == fb) compareResult = 2;
|
||||||
else compareResult = 1;
|
else
|
||||||
|
{
|
||||||
|
compareResult = 1;
|
||||||
|
if (IsSNAN(fa) || IsSNAN(fb))
|
||||||
|
{
|
||||||
|
FPSCR.VXSNAN = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
SetCRField(_inst.CRFD, compareResult);
|
SetCRField(_inst.CRFD, compareResult);
|
||||||
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps_cmpo0(UGeckoInstruction _inst)
|
void ps_cmpo0(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
// for now HACK
|
// Ector, please check
|
||||||
ps_cmpu0(_inst);
|
//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)
|
void ps_cmpu1(UGeckoInstruction _inst)
|
||||||
|
@ -268,20 +288,46 @@ void ps_cmpu1(UGeckoInstruction _inst)
|
||||||
double fa = rPS1(_inst.FA);
|
double fa = rPS1(_inst.FA);
|
||||||
double fb = rPS1(_inst.FB);
|
double fb = rPS1(_inst.FB);
|
||||||
int compareResult;
|
int compareResult;
|
||||||
//if (IsNAN(fa) || IsNAN(fb)) compareResult = 1;
|
|
||||||
//else
|
|
||||||
if (fa < fb) compareResult = 8;
|
if (fa < fb) compareResult = 8;
|
||||||
else if (fa > fb) compareResult = 4;
|
else if (fa > fb) compareResult = 4;
|
||||||
else if (fa == fb) compareResult = 2;
|
else if (fa == fb) compareResult = 2;
|
||||||
else compareResult = 1;
|
else
|
||||||
|
{
|
||||||
|
compareResult = 1;
|
||||||
|
if (IsSNAN(fa) || IsSNAN(fb))
|
||||||
|
{
|
||||||
|
FPSCR.VXSNAN = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
SetCRField(_inst.CRFD, compareResult);
|
SetCRField(_inst.CRFD, compareResult);
|
||||||
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
if (_inst.Rc) Helper_UpdateCR1(rPS0(_inst.FD));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps_cmpo1(UGeckoInstruction _inst)
|
void ps_cmpo1(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
// for now HACK
|
// Ector, please check
|
||||||
ps_cmpu1(_inst);
|
//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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// __________________________________________________________________________________________________
|
// __________________________________________________________________________________________________
|
||||||
|
|
Loading…
Reference in New Issue