fix(cpu): PPCBUG-184 fresx pre-quantize input to f32 (canary parity)
Phase 5 batch 5 (5e): minimal-viable fix for the estimate-precision family. Hardware Xenon `fres` produces a ~12-bit LUT estimate; xenia and canary both produce a fully IEEE single reciprocal, but canary pre-quantizes the f64 input to f32 to at least match the input precision. Now matches canary. PPCBUG-428..431 (vrefp/vrsqrtefp/vexptefp/vlogefp) already operate on f32 inputs naturally (no f64 → f32 quantization step needed); the estimate-precision deviation is purely the output side. Newton-Raphson convergence is unaffected. Documented in audit-findings.md as LOW-impact full-fix-requires-LUT. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2777,12 +2777,18 @@ fn execute(ctx: &mut PpcContext, mem: &dyn MemoryAccess, instr: &DecodedInstr) -
|
||||
ctx.pc += 4;
|
||||
}
|
||||
PpcOpcode::fresx => {
|
||||
// Single-precision reciprocal estimate: frD = 1.0 / frB
|
||||
let b = ctx.fpr[instr.rb()];
|
||||
// Single-precision reciprocal estimate: frD = 1.0 / frB.
|
||||
// PPCBUG-184: pre-quantize input to f32 to match canary's
|
||||
// `f.Recip(f.Convert(frB, FLOAT32_TYPE))` behavior. Hardware
|
||||
// produces a ~12-bit LUT estimate; both emulators produce a
|
||||
// fully-IEEE single reciprocal, but the f32 quantization at
|
||||
// least makes the input precision match.
|
||||
let b_full = ctx.fpr[instr.rb()];
|
||||
let b = b_full as f32 as f64;
|
||||
if b == 0.0 {
|
||||
fpscr::set_exception(ctx, fpscr::ZX);
|
||||
}
|
||||
if fpscr::is_snan(b) {
|
||||
if fpscr::is_snan(b_full) {
|
||||
fpscr::set_exception(ctx, fpscr::VXSNAN);
|
||||
}
|
||||
let result = to_single(ctx, 1.0 / b);
|
||||
|
||||
Reference in New Issue
Block a user