// 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); } }