Interpreter: consolidate fdiv/fdivs/ps_div

This commit is contained in:
Tillmann Karras 2015-06-25 05:24:07 +02:00
parent da7ec75350
commit ca36ff0551
3 changed files with 26 additions and 158 deletions

View File

@ -95,6 +95,28 @@ inline double NI_mul(double a, double b)
return t; return t;
} }
inline double NI_div(double a, double b)
{
double t = a / b;
if (std::isnan(t))
{
if (std::isnan(a)) return a;
if (std::isnan(b)) return b;
if (b == 0.0)
{
SetFPException(FPSCR_ZX);
if (a == 0.0)
SetFPException(FPSCR_VXZDZ);
}
else if (std::isinf(a) && std::isinf(b))
{
SetFPException(FPSCR_VXIDI);
}
return PPC_NAN;
}
return t;
}
inline double NI_add(double a, double b) inline double NI_add(double a, double b)
{ {
double t = a + b; double t = a + b;

View File

@ -351,38 +351,7 @@ void Interpreter::faddsx(UGeckoInstruction _inst)
void Interpreter::fdivx(UGeckoInstruction _inst) void Interpreter::fdivx(UGeckoInstruction _inst)
{ {
double a = rPS0(_inst.FA); rPS0(_inst.FD) = ForceDouble(NI_div(rPS0(_inst.FA), rPS0(_inst.FB)));
double b = rPS0(_inst.FB);
if (a != a)
{
rPS0(_inst.FD) = a;
}
else if (b != b)
{
rPS0(_inst.FD) = b;
}
else
{
rPS0(_inst.FD) = ForceDouble(a / b);
if (b == 0.0)
{
if (a == 0.0)
{
SetFPException(FPSCR_VXZDZ);
rPS0(_inst.FD) = PPC_NAN;
}
SetFPException(FPSCR_ZX);
}
else
{
if (IsINF(a) && IsINF(b))
{
SetFPException(FPSCR_VXIDI);
rPS0(_inst.FD) = PPC_NAN;
}
}
}
UpdateFPRF(rPS0(_inst.FD)); UpdateFPRF(rPS0(_inst.FD));
// FR,FI,OX,UX??? // FR,FI,OX,UX???
@ -391,41 +360,7 @@ void Interpreter::fdivx(UGeckoInstruction _inst)
} }
void Interpreter::fdivsx(UGeckoInstruction _inst) void Interpreter::fdivsx(UGeckoInstruction _inst)
{ {
double a = rPS0(_inst.FA); rPS0(_inst.FD) = rPS1(_inst.FD) = ForceSingle(NI_div(rPS0(_inst.FA), rPS0(_inst.FB)));
double b = rPS0(_inst.FB);
double res;
if (a != a)
{
res = a;
}
else if (b != b)
{
res = b;
}
else
{
res = ForceSingle(a / b);
if (b == 0.0)
{
if (a == 0.0)
{
SetFPException(FPSCR_VXZDZ);
res = PPC_NAN;
}
SetFPException(FPSCR_ZX);
}
else
{
if (IsINF(a) && IsINF(b))
{
SetFPException(FPSCR_VXIDI);
res = PPC_NAN;
}
}
}
rPS0(_inst.FD) = rPS1(_inst.FD) = res;
UpdateFPRF(rPS0(_inst.FD)); UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc) if (_inst.Rc)

View File

@ -104,97 +104,8 @@ void Interpreter::ps_merge11(UGeckoInstruction _inst)
// From here on, the real deal. // From here on, the real deal.
void Interpreter::ps_div(UGeckoInstruction _inst) void Interpreter::ps_div(UGeckoInstruction _inst)
{ {
u32 ex_mask = 0; rPS0(_inst.FD) = ForceSingle(NI_div(rPS0(_inst.FA), rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(NI_div(rPS1(_inst.FA), rPS1(_inst.FB)));
// PS0
{
double a = rPS0(_inst.FA);
double b = rPS0(_inst.FB);
double &res = rPS0(_inst.FD);
if (a != a)
{
res = a;
}
else if (b != b)
{
res = b;
}
else
{
if (b == 0.0)
{
ex_mask |= FPSCR_ZX;
if (rPS0(_inst.FA) == 0.0)
{
ex_mask |= FPSCR_VXZDZ;
res = PPC_NAN;
}
else
{
res = ForceSingle(a / b);
}
}
else
{
if (IsINF(a) && IsINF(b))
{
ex_mask |= FPSCR_VXIDI;
res = PPC_NAN;
}
else
{
res = ForceSingle(a / b);
}
}
}
}
// PS1
{
double a = rPS1(_inst.FA);
double b = rPS1(_inst.FB);
double &res = rPS1(_inst.FD);
if (a != a)
{
res = a;
}
else if (b != b)
{
res = b;
}
else
{
if (b == 0.0)
{
ex_mask |= FPSCR_ZX;
if (rPS0(_inst.FA) == 0.0)
{
ex_mask |= FPSCR_VXZDZ;
res = PPC_NAN;
}
else
{
res = ForceSingle(a / b);
}
}
else
{
if (IsINF(a) && IsINF(b))
{
ex_mask |= FPSCR_VXIDI;
res = PPC_NAN;
}
else
{
res = ForceSingle(a / b);
}
}
}
}
SetFPException(ex_mask);
UpdateFPRF(rPS0(_inst.FD)); UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc) if (_inst.Rc)