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;
|
ctx.pc += 4;
|
||||||
}
|
}
|
||||||
PpcOpcode::fresx => {
|
PpcOpcode::fresx => {
|
||||||
// Single-precision reciprocal estimate: frD = 1.0 / frB
|
// Single-precision reciprocal estimate: frD = 1.0 / frB.
|
||||||
let b = ctx.fpr[instr.rb()];
|
// 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 {
|
if b == 0.0 {
|
||||||
fpscr::set_exception(ctx, fpscr::ZX);
|
fpscr::set_exception(ctx, fpscr::ZX);
|
||||||
}
|
}
|
||||||
if fpscr::is_snan(b) {
|
if fpscr::is_snan(b_full) {
|
||||||
fpscr::set_exception(ctx, fpscr::VXSNAN);
|
fpscr::set_exception(ctx, fpscr::VXSNAN);
|
||||||
}
|
}
|
||||||
let result = to_single(ctx, 1.0 / b);
|
let result = to_single(ctx, 1.0 / b);
|
||||||
|
|||||||
Reference in New Issue
Block a user