// Reciprocal
static void
ps_res(cpu::Core *state, Instruction instr)
{
   const double b0 = state->fpr[instr.frB].paired0;
   const double b1 = state->fpr[instr.frB].paired1;

   const bool vxsnan0 = is_signalling_nan(b0);
   const bool vxsnan1 = is_signalling_nan(b1);
   const bool zx0 = is_zero(b0);
   const bool zx1 = is_zero(b1);

   const uint32_t oldFPSCR = state->fpscr.value;
   state->fpscr.vxsnan |= vxsnan0 || vxsnan1;
   state->fpscr.zx |= zx0 || zx1;

   float d0, d1;
   auto write = true;

   if ((vxsnan0 && state->fpscr.ve) || (zx0 && state->fpscr.ze)) {
      write = false;
   } else {
      d0 = ppc_estimate_reciprocal(truncate_double(b0));
      updateFPRF(state, d0);
   }

   if ((vxsnan1 && state->fpscr.ve) || (zx1 && state->fpscr.ze)) {
      write = false;
   } else {
      d1 = ppc_estimate_reciprocal(truncate_double(b1));
   }

   if (write) {
      state->fpr[instr.frD].paired0 = extend_float(d0);
      state->fpr[instr.frD].paired1 = extend_float(d1);
   }

   if (std::fetestexcept(FE_INEXACT)) {
      // On inexact result, ps_res sets FPSCR[FI] without also setting
      // FPSCR[XX] (like fres).
      std::feclearexcept(FE_INEXACT);
      updateFPSCR(state, oldFPSCR);
      state->fpscr.fi = 1;
   } else {
      updateFPSCR(state, oldFPSCR);
   }

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}
// Floating Reciprocal Estimate Single
static void
fres(ThreadState *state, Instruction instr)
{
   double b, d;
   b = state->fpr[instr.frB].paired0;

   state->fpscr.vxsnan |= is_signalling_nan(b);

   d = ppc_estimate_reciprocal(b);

   updateFPSCR(state);
   updateFPRF(state, d);
   state->fpr[instr.frD].paired0 = d;

   if (instr.rc) {
      updateFloatConditionRegister(state);
   }
}