diff --git a/crates/xenia-cpu/src/interpreter.rs b/crates/xenia-cpu/src/interpreter.rs index e4d88cd..051aa4f 100644 --- a/crates/xenia-cpu/src/interpreter.rs +++ b/crates/xenia-cpu/src/interpreter.rs @@ -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);