Interpreter: Avoid ppcState global (Interpreter_Paired.cpp).

This commit is contained in:
Admiral H. Curtiss 2023-03-17 01:36:50 +01:00
parent 514a7af473
commit c582aad0c7
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
1 changed files with 231 additions and 225 deletions

View File

@ -13,485 +13,491 @@
// These "binary instructions" do not alter FPSCR.
void Interpreter::ps_sel(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
PowerPC::ppcState.ps[inst.FD].SetBoth(a.PS0AsDouble() >= -0.0 ? c.PS0AsDouble() : b.PS0AsDouble(),
a.PS1AsDouble() >= -0.0 ? c.PS1AsDouble() :
b.PS1AsDouble());
ppc_state.ps[inst.FD].SetBoth(a.PS0AsDouble() >= -0.0 ? c.PS0AsDouble() : b.PS0AsDouble(),
a.PS1AsDouble() >= -0.0 ? c.PS1AsDouble() : b.PS1AsDouble());
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_neg(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(b.PS0AsU64() ^ (UINT64_C(1) << 63),
b.PS1AsU64() ^ (UINT64_C(1) << 63));
ppc_state.ps[inst.FD].SetBoth(b.PS0AsU64() ^ (UINT64_C(1) << 63),
b.PS1AsU64() ^ (UINT64_C(1) << 63));
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_mr(Interpreter& interpreter, UGeckoInstruction inst)
{
PowerPC::ppcState.ps[inst.FD] = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
ppc_state.ps[inst.FD] = ppc_state.ps[inst.FB];
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_nabs(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(b.PS0AsU64() | (UINT64_C(1) << 63),
b.PS1AsU64() | (UINT64_C(1) << 63));
ppc_state.ps[inst.FD].SetBoth(b.PS0AsU64() | (UINT64_C(1) << 63),
b.PS1AsU64() | (UINT64_C(1) << 63));
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_abs(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(b.PS0AsU64() & ~(UINT64_C(1) << 63),
b.PS1AsU64() & ~(UINT64_C(1) << 63));
ppc_state.ps[inst.FD].SetBoth(b.PS0AsU64() & ~(UINT64_C(1) << 63),
b.PS1AsU64() & ~(UINT64_C(1) << 63));
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
// These are just moves, double is OK.
void Interpreter::ps_merge00(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(a.PS0AsDouble(), b.PS0AsDouble());
ppc_state.ps[inst.FD].SetBoth(a.PS0AsDouble(), b.PS0AsDouble());
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_merge01(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(a.PS0AsDouble(), b.PS1AsDouble());
ppc_state.ps[inst.FD].SetBoth(a.PS0AsDouble(), b.PS1AsDouble());
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_merge10(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(a.PS1AsDouble(), b.PS0AsDouble());
ppc_state.ps[inst.FD].SetBoth(a.PS1AsDouble(), b.PS0AsDouble());
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_merge11(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
PowerPC::ppcState.ps[inst.FD].SetBoth(a.PS1AsDouble(), b.PS1AsDouble());
ppc_state.ps[inst.FD].SetBoth(a.PS1AsDouble(), b.PS1AsDouble());
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
// From here on, the real deal.
void Interpreter::ps_div(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_div(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_div(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
const float ps0 = ForceSingle(ppc_state.fpscr,
NI_div(&ppc_state.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 = ForceSingle(ppc_state.fpscr,
NI_div(&ppc_state.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_res(Interpreter& interpreter, UGeckoInstruction inst)
{
// this code is based on the real hardware tests
const double a = PowerPC::ppcState.ps[inst.FB].PS0AsDouble();
const double b = PowerPC::ppcState.ps[inst.FB].PS1AsDouble();
auto& ppc_state = interpreter.m_ppc_state;
const double a = ppc_state.ps[inst.FB].PS0AsDouble();
const double b = ppc_state.ps[inst.FB].PS1AsDouble();
if (a == 0.0 || b == 0.0)
{
SetFPException(&PowerPC::ppcState.fpscr, FPSCR_ZX);
PowerPC::ppcState.fpscr.ClearFIFR();
SetFPException(&ppc_state.fpscr, FPSCR_ZX);
ppc_state.fpscr.ClearFIFR();
}
if (std::isnan(a) || std::isinf(a) || std::isnan(b) || std::isinf(b))
PowerPC::ppcState.fpscr.ClearFIFR();
ppc_state.fpscr.ClearFIFR();
if (Common::IsSNAN(a) || Common::IsSNAN(b))
SetFPException(&PowerPC::ppcState.fpscr, FPSCR_VXSNAN);
SetFPException(&ppc_state.fpscr, FPSCR_VXSNAN);
const double ps0 = Common::ApproximateReciprocal(a);
const double ps1 = Common::ApproximateReciprocal(b);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(float(ps0));
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(float(ps0));
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_rsqrte(Interpreter& interpreter, UGeckoInstruction inst)
{
const double ps0 = PowerPC::ppcState.ps[inst.FB].PS0AsDouble();
const double ps1 = PowerPC::ppcState.ps[inst.FB].PS1AsDouble();
auto& ppc_state = interpreter.m_ppc_state;
const double ps0 = ppc_state.ps[inst.FB].PS0AsDouble();
const double ps1 = ppc_state.ps[inst.FB].PS1AsDouble();
if (ps0 == 0.0 || ps1 == 0.0)
{
SetFPException(&PowerPC::ppcState.fpscr, FPSCR_ZX);
PowerPC::ppcState.fpscr.ClearFIFR();
SetFPException(&ppc_state.fpscr, FPSCR_ZX);
ppc_state.fpscr.ClearFIFR();
}
if (ps0 < 0.0 || ps1 < 0.0)
{
SetFPException(&PowerPC::ppcState.fpscr, FPSCR_VXSQRT);
PowerPC::ppcState.fpscr.ClearFIFR();
SetFPException(&ppc_state.fpscr, FPSCR_VXSQRT);
ppc_state.fpscr.ClearFIFR();
}
if (std::isnan(ps0) || std::isinf(ps0) || std::isnan(ps1) || std::isinf(ps1))
PowerPC::ppcState.fpscr.ClearFIFR();
ppc_state.fpscr.ClearFIFR();
if (Common::IsSNAN(ps0) || Common::IsSNAN(ps1))
SetFPException(&PowerPC::ppcState.fpscr, FPSCR_VXSNAN);
SetFPException(&ppc_state.fpscr, FPSCR_VXSNAN);
const float dst_ps0 =
ForceSingle(PowerPC::ppcState.fpscr, Common::ApproximateReciprocalSquareRoot(ps0));
const float dst_ps1 =
ForceSingle(PowerPC::ppcState.fpscr, Common::ApproximateReciprocalSquareRoot(ps1));
const float dst_ps0 = ForceSingle(ppc_state.fpscr, Common::ApproximateReciprocalSquareRoot(ps0));
const float dst_ps1 = ForceSingle(ppc_state.fpscr, Common::ApproximateReciprocalSquareRoot(ps1));
PowerPC::ppcState.ps[inst.FD].SetBoth(dst_ps0, dst_ps1);
PowerPC::ppcState.UpdateFPRFSingle(dst_ps0);
ppc_state.ps[inst.FD].SetBoth(dst_ps0, dst_ps1);
ppc_state.UpdateFPRFSingle(dst_ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_sub(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_sub(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_sub(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
const float ps0 = ForceSingle(ppc_state.fpscr,
NI_sub(&ppc_state.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 = ForceSingle(ppc_state.fpscr,
NI_sub(&ppc_state.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_add(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_add(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_add(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
const float ps0 = ForceSingle(ppc_state.fpscr,
NI_add(&ppc_state.fpscr, a.PS0AsDouble(), b.PS0AsDouble()).value);
const float ps1 = ForceSingle(ppc_state.fpscr,
NI_add(&ppc_state.fpscr, a.PS1AsDouble(), b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_mul(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble());
const float ps0 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0).value);
const float ps1 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1).value);
const float ps0 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS0AsDouble(), c0).value);
const float ps1 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS1AsDouble(), c1).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_msub(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble());
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_msub(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_msub(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float ps0 = ForceSingle(
ppc_state.fpscr, NI_msub(&ppc_state.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 = ForceSingle(
ppc_state.fpscr, NI_msub(&ppc_state.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_madd(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble());
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float ps0 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_nmsub(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble());
const float tmp0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_msub(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float tmp1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_msub(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float tmp0 = ForceSingle(
ppc_state.fpscr, NI_msub(&ppc_state.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float tmp1 = ForceSingle(
ppc_state.fpscr, NI_msub(&ppc_state.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float ps0 = std::isnan(tmp0) ? tmp0 : -tmp0;
const float ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_nmadd(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const double c1 = Force25Bit(c.PS1AsDouble());
const float tmp0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float tmp1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float tmp0 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float tmp1 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float ps0 = std::isnan(tmp0) ? tmp0 : -tmp0;
const float ps1 = std::isnan(tmp1) ? tmp1 : -tmp1;
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_sum0(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_add(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), b.PS1AsDouble()).value);
const float ps1 = ForceSingle(PowerPC::ppcState.fpscr, c.PS1AsDouble());
const float ps0 = ForceSingle(ppc_state.fpscr,
NI_add(&ppc_state.fpscr, a.PS0AsDouble(), b.PS1AsDouble()).value);
const float ps1 = ForceSingle(ppc_state.fpscr, c.PS1AsDouble());
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_sum1(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const float ps0 = ForceSingle(PowerPC::ppcState.fpscr, c.PS0AsDouble());
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_add(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), b.PS1AsDouble()).value);
const float ps0 = ForceSingle(ppc_state.fpscr, c.PS0AsDouble());
const float ps1 = ForceSingle(ppc_state.fpscr,
NI_add(&ppc_state.fpscr, a.PS0AsDouble(), b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps1);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps1);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_muls0(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const float ps0 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0).value);
const float ps1 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c0).value);
const float ps0 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS0AsDouble(), c0).value);
const float ps1 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS1AsDouble(), c0).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_muls1(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& c = ppc_state.ps[inst.FC];
const double c1 = Force25Bit(c.PS1AsDouble());
const float ps0 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c1).value);
const float ps1 = ForceSingle(PowerPC::ppcState.fpscr,
NI_mul(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1).value);
const float ps0 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS0AsDouble(), c1).value);
const float ps1 =
ForceSingle(ppc_state.fpscr, NI_mul(&ppc_state.fpscr, a.PS1AsDouble(), c1).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_madds0(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c0 = Force25Bit(c.PS0AsDouble());
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c0, b.PS1AsDouble()).value);
const float ps0 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS0AsDouble(), c0, b.PS0AsDouble()).value);
const float ps1 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS1AsDouble(), c0, b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_madds1(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
const auto& c = PowerPC::ppcState.ps[inst.FC];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
const auto& c = ppc_state.ps[inst.FC];
const double c1 = Force25Bit(c.PS1AsDouble());
const float ps0 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS0AsDouble(), c1, b.PS0AsDouble()).value);
const float ps1 =
ForceSingle(PowerPC::ppcState.fpscr,
NI_madd(&PowerPC::ppcState.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
const float ps0 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS0AsDouble(), c1, b.PS0AsDouble()).value);
const float ps1 = ForceSingle(
ppc_state.fpscr, NI_madd(&ppc_state.fpscr, a.PS1AsDouble(), c1, b.PS1AsDouble()).value);
PowerPC::ppcState.ps[inst.FD].SetBoth(ps0, ps1);
PowerPC::ppcState.UpdateFPRFSingle(ps0);
ppc_state.ps[inst.FD].SetBoth(ps0, ps1);
ppc_state.UpdateFPRFSingle(ps0);
if (inst.Rc)
PowerPC::ppcState.UpdateCR1();
ppc_state.UpdateCR1();
}
void Interpreter::ps_cmpu0(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
Helper_FloatCompareUnordered(PowerPC::ppcState, inst, a.PS0AsDouble(), b.PS0AsDouble());
Helper_FloatCompareUnordered(ppc_state, inst, a.PS0AsDouble(), b.PS0AsDouble());
}
void Interpreter::ps_cmpo0(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
Helper_FloatCompareOrdered(PowerPC::ppcState, inst, a.PS0AsDouble(), b.PS0AsDouble());
Helper_FloatCompareOrdered(ppc_state, inst, a.PS0AsDouble(), b.PS0AsDouble());
}
void Interpreter::ps_cmpu1(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
Helper_FloatCompareUnordered(PowerPC::ppcState, inst, a.PS1AsDouble(), b.PS1AsDouble());
Helper_FloatCompareUnordered(ppc_state, inst, a.PS1AsDouble(), b.PS1AsDouble());
}
void Interpreter::ps_cmpo1(Interpreter& interpreter, UGeckoInstruction inst)
{
const auto& a = PowerPC::ppcState.ps[inst.FA];
const auto& b = PowerPC::ppcState.ps[inst.FB];
auto& ppc_state = interpreter.m_ppc_state;
const auto& a = ppc_state.ps[inst.FA];
const auto& b = ppc_state.ps[inst.FB];
Helper_FloatCompareOrdered(PowerPC::ppcState, inst, a.PS1AsDouble(), b.PS1AsDouble());
Helper_FloatCompareOrdered(ppc_state, inst, a.PS1AsDouble(), b.PS1AsDouble());
}