Interpreter: less duplicate code in float compares
This commit is contained in:
parent
9ef64245fa
commit
16885d0f74
|
@ -410,7 +410,8 @@ union UReg_FPSCR
|
|||
u32 VXSOFT : 1;
|
||||
// reserved
|
||||
u32 : 1;
|
||||
// Floating point result flags (not sticky)
|
||||
// Floating point result flags (includes FPCC) (not sticky)
|
||||
// from more to less significand: class, <, >, =, ?
|
||||
u32 FPRF : 5;
|
||||
// Fraction inexact (not sticky)
|
||||
u32 FI : 1;
|
||||
|
|
|
@ -326,6 +326,9 @@ private:
|
|||
Interpreter(const Interpreter &);
|
||||
Interpreter & operator=(const Interpreter &);
|
||||
|
||||
static void Helper_FloatCompareOrdered(UGeckoInstruction _inst, double a, double b);
|
||||
static void Helper_FloatCompareUnordered(UGeckoInstruction _inst, double a, double b);
|
||||
|
||||
// TODO: These should really be in the save state, although it's unlikely to matter much.
|
||||
// They are for lwarx and its friend stwcxd.
|
||||
static bool g_bReserve;
|
||||
|
|
|
@ -40,6 +40,14 @@ const u32 FPSCR_ANY_X = FPSCR_OX | FPSCR_UX | FPSCR_ZX | FPSCR_XX | FPSCR_V
|
|||
const u64 PPC_NAN_U64 = 0x7ff8000000000000ull;
|
||||
const double PPC_NAN = *(double* const)&PPC_NAN_U64;
|
||||
|
||||
// the 4 less-significand bits in FPSCR[FPRF]
|
||||
enum FPCC {
|
||||
FL = 8, // <
|
||||
FG = 4, // >
|
||||
FE = 2, // =
|
||||
FU = 1, // ?
|
||||
};
|
||||
|
||||
inline void SetFPException(u32 mask)
|
||||
{
|
||||
if ((FPSCR.Hex & mask) != mask)
|
||||
|
|
|
@ -33,29 +33,36 @@ void Interpreter::Helper_UpdateCR1(double _fValue)
|
|||
SetCRField(1, (FPSCR.FX << 4) | (FPSCR.FEX << 3) | (FPSCR.VX << 2) | FPSCR.OX);
|
||||
}
|
||||
|
||||
void Interpreter::fcmpo(UGeckoInstruction _inst)
|
||||
void Interpreter::Helper_FloatCompareOrdered(UGeckoInstruction _inst, double fa, double fb)
|
||||
{
|
||||
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
|
||||
if (fa < fb)
|
||||
{
|
||||
compareResult = FPCC::FL;
|
||||
}
|
||||
else if (fa > fb)
|
||||
{
|
||||
compareResult = FPCC::FG;
|
||||
}
|
||||
else if (fa == fb)
|
||||
{
|
||||
compareResult = FPCC::FE;
|
||||
}
|
||||
else // NaN
|
||||
{
|
||||
FPSCR.FX = 1;
|
||||
compareResult = 1;
|
||||
compareResult = FPCC::FU;
|
||||
if (IsSNAN(fa) || IsSNAN(fb))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
if (FPSCR.VE == 0)
|
||||
{
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
}
|
||||
else
|
||||
else // QNaN
|
||||
{
|
||||
//if (IsQNAN(fa) || IsQNAN(fb)) // this is always true
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
}
|
||||
|
@ -64,21 +71,28 @@ void Interpreter::fcmpo(UGeckoInstruction _inst)
|
|||
SetCRField(_inst.CRFD, compareResult);
|
||||
}
|
||||
|
||||
void Interpreter::fcmpu(UGeckoInstruction _inst)
|
||||
void Interpreter::Helper_FloatCompareUnordered(UGeckoInstruction _inst, double fa, double fb)
|
||||
{
|
||||
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;
|
||||
if (fa < fb)
|
||||
{
|
||||
compareResult = FPCC::FL;
|
||||
}
|
||||
else if (fa > fb)
|
||||
{
|
||||
compareResult = FPCC::FG;
|
||||
}
|
||||
else if (fa == fb)
|
||||
{
|
||||
compareResult = FPCC::FE;
|
||||
}
|
||||
else
|
||||
{
|
||||
compareResult = 1;
|
||||
compareResult = FPCC::FU;
|
||||
if (IsSNAN(fa) || IsSNAN(fb))
|
||||
{
|
||||
FPSCR.FX = 1;
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +100,16 @@ void Interpreter::fcmpu(UGeckoInstruction _inst)
|
|||
SetCRField(_inst.CRFD, compareResult);
|
||||
}
|
||||
|
||||
void Interpreter::fcmpo(UGeckoInstruction _inst)
|
||||
{
|
||||
Helper_FloatCompareOrdered(_inst, rPS0(_inst.FA), rPS0(_inst.FB));
|
||||
}
|
||||
|
||||
void Interpreter::fcmpu(UGeckoInstruction _inst)
|
||||
{
|
||||
Helper_FloatCompareUnordered(_inst, rPS0(_inst.FA), rPS0(_inst.FB));
|
||||
}
|
||||
|
||||
// Apply current rounding mode
|
||||
void Interpreter::fctiwx(UGeckoInstruction _inst)
|
||||
{
|
||||
|
|
|
@ -354,100 +354,22 @@ void Interpreter::ps_madds1(UGeckoInstruction _inst)
|
|||
|
||||
void Interpreter::ps_cmpu0(UGeckoInstruction _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))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
}
|
||||
}
|
||||
FPSCR.FPRF = compareResult;
|
||||
SetCRField(_inst.CRFD, compareResult);
|
||||
Helper_FloatCompareUnordered(_inst, rPS0(_inst.FA), rPS0(_inst.FB));
|
||||
}
|
||||
|
||||
void Interpreter::ps_cmpo0(UGeckoInstruction _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))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
if (!FPSCR.VE)
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (IsQNAN(fa) || IsQNAN(fb)) // this is always true
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
}
|
||||
FPSCR.FPRF = compareResult;
|
||||
SetCRField(_inst.CRFD, compareResult);
|
||||
Helper_FloatCompareOrdered(_inst, rPS0(_inst.FA), rPS0(_inst.FB));
|
||||
}
|
||||
|
||||
void Interpreter::ps_cmpu1(UGeckoInstruction _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))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
}
|
||||
}
|
||||
FPSCR.FPRF = compareResult;
|
||||
SetCRField(_inst.CRFD, compareResult);
|
||||
Helper_FloatCompareUnordered(_inst, rPS1(_inst.FA), rPS1(_inst.FB));
|
||||
}
|
||||
|
||||
void Interpreter::ps_cmpo1(UGeckoInstruction _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))
|
||||
{
|
||||
SetFPException(FPSCR_VXSNAN);
|
||||
if (!FPSCR.VE)
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (IsQNAN(fa) || IsQNAN(fb)) // this is always true
|
||||
SetFPException(FPSCR_VXVC);
|
||||
}
|
||||
}
|
||||
FPSCR.FPRF = compareResult;
|
||||
SetCRField(_inst.CRFD, compareResult);
|
||||
Helper_FloatCompareOrdered(_inst, rPS1(_inst.FA), rPS1(_inst.FB));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
|
|
Loading…
Reference in New Issue