Interpreter: refactor the rsqrte code, and use it for ps_rsqrte.
This commit is contained in:
parent
567724b2f8
commit
129e76e60d
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "Common/CPUDetect.h"
|
#include "Common/CPUDetect.h"
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
|
#include "Core/PowerPC/LUT_frsqrtex.h"
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
||||||
|
|
||||||
using namespace MathUtil;
|
using namespace MathUtil;
|
||||||
|
@ -329,3 +330,34 @@ inline double ApproximateReciprocal(double val)
|
||||||
vali |= (long long)(expected_base[i / 1024] - (expected_dec[i / 1024] * (i % 1024) + 1) / 2) << 29;
|
vali |= (long long)(expected_base[i / 1024] - (expected_dec[i / 1024] * (i % 1024) + 1) / 2) << 29;
|
||||||
return valf;
|
return valf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double ApproximateReciprocalSquareRoot(double val)
|
||||||
|
{
|
||||||
|
if (val < 0)
|
||||||
|
return PPC_NAN;
|
||||||
|
if (val == 0.0)
|
||||||
|
return INFINITY;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
double valf;
|
||||||
|
u64 vali;
|
||||||
|
};
|
||||||
|
valf = val;
|
||||||
|
|
||||||
|
u32 fsa = vali >> 32;
|
||||||
|
u32 idx = (fsa >> 5) % (sizeof(frsqrtex_lut) / sizeof(frsqrtex_lut[0]));
|
||||||
|
|
||||||
|
s32 e = fsa >> (32 - 12);
|
||||||
|
e &= 2047;
|
||||||
|
e -= 1023;
|
||||||
|
s32 oe = -((e + 1) / 2);
|
||||||
|
oe -= ((e + 1) & 1);
|
||||||
|
|
||||||
|
u32 outb = frsqrtex_lut[idx] << 20;
|
||||||
|
u32 outa = ((oe + 1023) & 2047) << 20;
|
||||||
|
outa |= frsqrtex_lut[idx] >> 12;
|
||||||
|
|
||||||
|
vali = ((u64)outa << 32) + (u64)outb;
|
||||||
|
return valf;
|
||||||
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Common/MathUtil.h"
|
#include "Common/MathUtil.h"
|
||||||
#include "Core/PowerPC/LUT_frsqrtex.h"
|
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
#include "Core/PowerPC/Interpreter/Interpreter.h"
|
||||||
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
#include "Core/PowerPC/Interpreter/Interpreter_FPUtils.h"
|
||||||
|
|
||||||
|
@ -403,33 +402,12 @@ void Interpreter::frsqrtex(UGeckoInstruction _inst)
|
||||||
if (b < 0.0)
|
if (b < 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_VXSQRT);
|
SetFPException(FPSCR_VXSQRT);
|
||||||
rPS0(_inst.FD) = PPC_NAN;
|
|
||||||
}
|
}
|
||||||
else
|
else if (b == 0.0)
|
||||||
{
|
{
|
||||||
if (b == 0.0)
|
SetFPException(FPSCR_ZX);
|
||||||
{
|
|
||||||
SetFPException(FPSCR_ZX);
|
|
||||||
riPS0(_inst.FD) = 0x7ff0000000000000;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u32 fsa = Common::swap32(Common::swap64(riPS0(_inst.FB)));
|
|
||||||
u32 fsb = Common::swap32(Common::swap64(riPS0(_inst.FB)) >> 32);
|
|
||||||
u32 idx=(fsa >> 5) % (sizeof(frsqrtex_lut) / sizeof(frsqrtex_lut[0]));
|
|
||||||
|
|
||||||
s32 e = fsa >> (32-12);
|
|
||||||
e &= 2047;
|
|
||||||
e -= 1023;
|
|
||||||
s32 oe =- ((e + 1) / 2);
|
|
||||||
oe -= ((e + 1) & 1);
|
|
||||||
|
|
||||||
u32 outb = frsqrtex_lut[idx] << 20;
|
|
||||||
u32 outa = ((oe + 1023) & 2047) << 20;
|
|
||||||
outa |= frsqrtex_lut[idx] >> 12;
|
|
||||||
riPS0(_inst.FD) = ((u64)outa << 32) + (u64)outb;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
rPS0(_inst.FD) = ApproximateReciprocalSquareRoot(b);
|
||||||
UpdateFPRF(rPS0(_inst.FD));
|
UpdateFPRF(rPS0(_inst.FD));
|
||||||
if (_inst.Rc) Helper_UpdateCR1();
|
if (_inst.Rc) Helper_UpdateCR1();
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,36 +186,19 @@ void Interpreter::ps_res(UGeckoInstruction _inst)
|
||||||
|
|
||||||
void Interpreter::ps_rsqrte(UGeckoInstruction _inst)
|
void Interpreter::ps_rsqrte(UGeckoInstruction _inst)
|
||||||
{
|
{
|
||||||
// this code is based on the real hardware tests
|
|
||||||
if (rPS0(_inst.FB) == 0.0 || rPS1(_inst.FB) == 0.0)
|
if (rPS0(_inst.FB) == 0.0 || rPS1(_inst.FB) == 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_ZX);
|
SetFPException(FPSCR_ZX);
|
||||||
}
|
}
|
||||||
// PS0
|
|
||||||
if (rPS0(_inst.FB) < 0.0)
|
if (rPS0(_inst.FB) < 0.0 || rPS1(_inst.FB) < 0.0)
|
||||||
{
|
{
|
||||||
SetFPException(FPSCR_VXSQRT);
|
SetFPException(FPSCR_VXSQRT);
|
||||||
rPS0(_inst.FD) = PPC_NAN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rPS0(_inst.FD) = 1.0 / sqrt(rPS0(_inst.FB));
|
|
||||||
u32 t = ConvertToSingle(riPS0(_inst.FD));
|
|
||||||
rPS0(_inst.FD) = *(float*)&t;
|
|
||||||
}
|
|
||||||
// PS1
|
|
||||||
if (rPS1(_inst.FB) < 0.0)
|
|
||||||
{
|
|
||||||
SetFPException(FPSCR_VXSQRT);
|
|
||||||
rPS1(_inst.FD) = PPC_NAN;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rPS1(_inst.FD) = 1.0 / sqrt(rPS1(_inst.FB));
|
|
||||||
u32 t = ConvertToSingle(riPS1(_inst.FD));
|
|
||||||
rPS1(_inst.FD) = *(float*)&t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rPS0(_inst.FD) = ApproximateReciprocalSquareRoot(rPS0(_inst.FB));
|
||||||
|
rPS1(_inst.FD) = ApproximateReciprocalSquareRoot(rPS1(_inst.FB));
|
||||||
|
|
||||||
UpdateFPRF(rPS0(_inst.FD));
|
UpdateFPRF(rPS0(_inst.FD));
|
||||||
if (_inst.Rc) Helper_UpdateCR1();
|
if (_inst.Rc) Helper_UpdateCR1();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue