Interpreter: apply the same odd rounding to single multiplies as the JIT

This commit is contained in:
Fiora 2014-08-19 11:00:47 -07:00
parent 4f18f6078f
commit 4d7b1275c9
3 changed files with 45 additions and 20 deletions

View File

@ -94,6 +94,13 @@ inline double ForceDouble(double d)
return d;
}
inline double Force25Bit(double d)
{
u64 di = *(u64*)&d;
di = (di & 0xFFFFFFFFF8000000ULL) + (di & 0x8000000);
return *(double*)&di;
}
// these functions allow globally modify operations behaviour
// also, these may be used to set flags like FR, FI, OX, UX

View File

@ -297,7 +297,8 @@ void Interpreter::fmulx(UGeckoInstruction _inst)
}
void Interpreter::fmulsx(UGeckoInstruction _inst)
{
double d_value = NI_mul(rPS0(_inst.FA), rPS0(_inst.FC));
double c_value = Force25Bit(rPS0(_inst.FC));
double d_value = NI_mul(rPS0(_inst.FA), c_value);
rPS0(_inst.FD) = rPS1(_inst.FD) = ForceSingle(d_value);
//FPSCR.FI = d_value != rPS0(_inst.FD);
FPSCR.FI = 0;
@ -320,7 +321,8 @@ void Interpreter::fmaddx(UGeckoInstruction _inst)
void Interpreter::fmaddsx(UGeckoInstruction _inst)
{
double d_value = NI_madd( rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB) );
double c_value = Force25Bit(rPS0(_inst.FC));
double d_value = NI_madd(rPS0(_inst.FA), c_value, rPS0(_inst.FB));
rPS0(_inst.FD) = rPS1(_inst.FD) = ForceSingle(d_value);
FPSCR.FI = d_value != rPS0(_inst.FD);
FPSCR.FR = 0;

View File

@ -264,8 +264,10 @@ void Interpreter::ps_add(UGeckoInstruction _inst)
void Interpreter::ps_mul(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = ForceSingle(NI_mul(rPS0(_inst.FA), rPS0(_inst.FC)));
rPS1(_inst.FD) = ForceSingle(NI_mul(rPS1(_inst.FA), rPS1(_inst.FC)));
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
rPS0(_inst.FD) = ForceSingle(NI_mul(rPS0(_inst.FA), c0));
rPS1(_inst.FD) = ForceSingle(NI_mul(rPS1(_inst.FA), c1));
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc)
@ -275,8 +277,10 @@ void Interpreter::ps_mul(UGeckoInstruction _inst)
void Interpreter::ps_msub(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = ForceSingle(NI_msub(rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(NI_msub(rPS1(_inst.FA), rPS1(_inst.FC), rPS1(_inst.FB)));
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
rPS0(_inst.FD) = ForceSingle(NI_msub(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(NI_msub(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc)
@ -285,8 +289,10 @@ void Interpreter::ps_msub(UGeckoInstruction _inst)
void Interpreter::ps_madd(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = ForceSingle(NI_madd(rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(NI_madd(rPS1(_inst.FA), rPS1(_inst.FC), rPS1(_inst.FB)));
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
rPS0(_inst.FD) = ForceSingle(NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc)
@ -295,8 +301,10 @@ void Interpreter::ps_madd(UGeckoInstruction _inst)
void Interpreter::ps_nmsub(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = ForceSingle( -NI_msub( rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB) ) );
rPS1(_inst.FD) = ForceSingle( -NI_msub( rPS1(_inst.FA), rPS1(_inst.FC), rPS1(_inst.FB) ) );
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
rPS0(_inst.FD) = ForceSingle(-NI_msub(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(-NI_msub(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc)
@ -305,8 +313,10 @@ void Interpreter::ps_nmsub(UGeckoInstruction _inst)
void Interpreter::ps_nmadd(UGeckoInstruction _inst)
{
rPS0(_inst.FD) = ForceSingle( -NI_madd( rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB) ) );
rPS1(_inst.FD) = ForceSingle( -NI_madd( rPS1(_inst.FA), rPS1(_inst.FC), rPS1(_inst.FB) ) );
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
rPS0(_inst.FD) = ForceSingle(-NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
rPS1(_inst.FD) = ForceSingle(-NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
UpdateFPRF(rPS0(_inst.FD));
if (_inst.Rc)
@ -339,8 +349,9 @@ void Interpreter::ps_sum1(UGeckoInstruction _inst)
void Interpreter::ps_muls0(UGeckoInstruction _inst)
{
double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), rPS0(_inst.FC)));
double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), rPS0(_inst.FC)));
double c0 = Force25Bit(rPS1(_inst.FC));
double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), c0));
double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), c0));
rPS0(_inst.FD) = p0;
rPS1(_inst.FD) = p1;
UpdateFPRF(rPS0(_inst.FD));
@ -351,8 +362,9 @@ void Interpreter::ps_muls0(UGeckoInstruction _inst)
void Interpreter::ps_muls1(UGeckoInstruction _inst)
{
double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), rPS1(_inst.FC)));
double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), rPS1(_inst.FC)));
double c1 = Force25Bit(rPS1(_inst.FC));
double p0 = ForceSingle(NI_mul(rPS0(_inst.FA), c1));
double p1 = ForceSingle(NI_mul(rPS1(_inst.FA), c1));
rPS0(_inst.FD) = p0;
rPS1(_inst.FD) = p1;
UpdateFPRF(rPS0(_inst.FD));
@ -363,8 +375,10 @@ void Interpreter::ps_muls1(UGeckoInstruction _inst)
void Interpreter::ps_madds0(UGeckoInstruction _inst)
{
double p0 = ForceSingle( NI_madd( rPS0(_inst.FA), rPS0(_inst.FC), rPS0(_inst.FB)) );
double p1 = ForceSingle( NI_madd( rPS1(_inst.FA), rPS0(_inst.FC), rPS1(_inst.FB)) );
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
double p0 = ForceSingle(NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
double p1 = ForceSingle(NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
rPS0(_inst.FD) = p0;
rPS1(_inst.FD) = p1;
UpdateFPRF(rPS0(_inst.FD));
@ -375,8 +389,10 @@ void Interpreter::ps_madds0(UGeckoInstruction _inst)
void Interpreter::ps_madds1(UGeckoInstruction _inst)
{
double p0 = ForceSingle( NI_madd( rPS0(_inst.FA), rPS1(_inst.FC), rPS0(_inst.FB)) );
double p1 = ForceSingle( NI_madd( rPS1(_inst.FA), rPS1(_inst.FC), rPS1(_inst.FB)) );
double c0 = Force25Bit(rPS0(_inst.FC));
double c1 = Force25Bit(rPS1(_inst.FC));
double p0 = ForceSingle(NI_madd(rPS0(_inst.FA), c0, rPS0(_inst.FB)));
double p1 = ForceSingle(NI_madd(rPS1(_inst.FA), c1, rPS1(_inst.FB)));
rPS0(_inst.FD) = p0;
rPS1(_inst.FD) = p1;
UpdateFPRF(rPS0(_inst.FD));