Correct the COP2 FPCR comment: FZ is set in a default game

The comment 882c0d40ea left behind says "FPCR.FZ is NOT set while these
run". That was read off the test harness, which sets FPCR to 0 --
RecompilerTestEnvironment mirrors CPUThreadInitialize and stops before
the VM applies FPUFPCR. A real boot says otherwise. Printing FPCR from
recExecute before entering recompiled code, God of War II:

    FPCRPROBE live=0x1c00000 FPUFPCR=0x1c00000 VU0FPCR=0x1c00000 FZ=1

0x1c00000 is FZ plus RMode=ChopZero, from EmuConfig.Cpu.FPUFPCR, whose
default is DAZ+FTZ+ChopZero. On aarch64 DAZ and FTZ are the same bit, so
that flushes denormal operands and results alike.

No code change: the software flush stays, and the reason it stays is now
the accurate one. FZ is a per-unit user setting (EmuCore/CPU:
FPU/VU0/VU1.DenormalsAreZero), so it cannot be assumed either way; and it
could not supply the flag half regardless, since it erases the mantissa
that U is defined on. What the flush actually buys is that the two
engines agree in both environments -- redundant when FZ is on, load
bearing when it is not.

Idea by pstef.
This commit is contained in:
bmdhacks
2026-08-02 17:03:02 -07:00
committed by Brian Degenhardt
parent 3d15e04c6c
commit 63f12f4009
+14
View File
@@ -447,6 +447,20 @@ static void cop2ApplyDestMaskACC(const a64::VRegister& result)
// PS2 VU has no infinities — overflow clamps to ±FLT_MAX (0x7f7fffff).
// NEON FPCR has FZ=1 (denormals flushed to zero), so only post-op clamping is needed.
// FMINNM/FMAXNM match x86 MINPS/MAXPS semantics: NaN → non-NaN operand.
//
// FPCR.FZ here is measured, not assumed: a real boot logs FPCR = 0x1c00000
// inside the EE dispatcher -- FZ set and RMode = ChopZero, from
// EmuConfig.Cpu.FPUFPCR, whose default is DAZ+FTZ+ChopZero (Pcsx2Config.cpp
// DEFAULT_FPU_FP_CONTROL_REGISTER). The recompiler test harness runs FPCR = 0
// instead (RecompilerTestEnvironment.cpp mirrors CPUThreadInitialize and stops
// before the VM applies FPUFPCR), so denormals survive there and not in a
// default game.
//
// That is not a licence to depend on the hardware: DenormalsAreZero is a
// per-unit user setting (EmuCore/CPU: FPU/VU0/VU1.DenormalsAreZero), so FZ can
// be off in production too. Modelling the FZ-off case in software is deferred
// to the pending COP2 U/O redesign; the DISABLED tripwires in
// vu_sticky_console_conformance_tests.cpp record what it owes.
alignas(16) static const u32 s_cop2MaxFloat[4] = {0x7f7fffff, 0x7f7fffff, 0x7f7fffff, 0x7f7fffff};