mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Correct the FpuMulHack comment: the constant is pi, not pi/2
0x40490fdb is 3.14159274, and 0.25 * that is pi/4 == 0x3f490fdb. The
comment called the multiplicand pi/2 and did not say what the patched
value 0x3f490fda is, which left it reading as an arbitrary magic number
lifted from x86.
It is not arbitrary: 0x3f490fda is pi/4 one ULP low, and one ULP low is
what the EE's multiplier returns here. Its Booth recoding drops one ULP
when ft's significand has an odd digit pair (ft & 0x2AA -- 0x490fdb & 0x2AA
== 0x28a, so it fires) and the exact product carries no tail below the
single ULP -- fs = 0.25 = 2^-2 has significand 2^23 exactly, so the product
is exact and the deficit reaches the result. The gamefix is a hardcoded
instance of a general defect, not a game-specific fudge.
Checked by executing the general widened model (cmtst/fmul/fcmeq/bic/add on
doubles under FZ|RZ) on both operand orders:
model(0.25, pi) = 0x3f490fda gamefix patches to 0x3f490fda
model(pi, 0.25) = 0x3f490fdb gamefix leaves alone (host value)
so the model agrees with the gamefix on the asymmetry too -- the predicate
reads ft's significand alone, and 0.25's is zero. That is the same
asymmetry the Cmp sequence below has, where s must be 0.25 and t must be pi.
Comment also records why the general model is not being pulled into this
fast path: here it costs ~9 instructions on every multiply in every game,
against 1 today. It belongs in iFPUd-arm64.cpp, where the operands are
already doubles and it costs 4 -- and where every eeClampMode:3 title gets
it, rather than the one title that needs the hack. Extending it to this
path needs its own measured case.
Comment-only change; no emitted code moves.
Idea by pstef.
This commit is contained in:
committed by
Brian Degenhardt
parent
c5a6c7cb0a
commit
fca3e9074b
@@ -593,12 +593,24 @@ static void fpuEmitGuardedAddSub(const a64::VRegister& dst,
|
||||
|
||||
// FpuMulHack (Tales of Destiny Remake gamefix, EmuConfig.Gamefixes.FpuMulHack).
|
||||
// x86 routes every FPU multiply (MUL/MULA/MADD/MSUB) through FPU_MUL, which —
|
||||
// when the gamefix is on — patches the single specific product 0.25 * (π/2)
|
||||
// (0x3e800000 * 0x40490fdb) to 0x3f490fda so the game stops hanging in one
|
||||
// late-game room. Emit `dst = (hit) ? 0x3f490fda : s*t`; callers clamp/accumulate
|
||||
// dst as they normally would (the magic value is an ordinary small float, so a
|
||||
// following fpuClampResult is a no-op). In the default config (gamefix off) this
|
||||
// is a bare Fmul — zero added cost.
|
||||
// when the gamefix is on — patches the single specific product 0.25 * π
|
||||
// (0x3e800000 * 0x40490fdb) from the correctly-rounded 0x3f490fdb to 0x3f490fda
|
||||
// so the game stops hanging in one late-game room. Emit
|
||||
// `dst = (hit) ? 0x3f490fda : s*t`; callers clamp/accumulate dst as they normally
|
||||
// would (the magic value is an ordinary small float, so a following
|
||||
// fpuClampResult is a no-op). In the default config (gamefix off) this is a bare
|
||||
// Fmul — zero added cost.
|
||||
//
|
||||
// The patched value is not arbitrary: 0x3f490fda is π/4 one ULP low, which is
|
||||
// what the EE's multiplier actually returns. Its Booth recoding drops one ULP
|
||||
// when ft's significand has an odd digit pair (ft & 0x2AA) and the exact product
|
||||
// has no tail below the single ULP — here fs = 2^-2, so the product is exact and
|
||||
// the deficit reaches the result. The general model reproduces this pair (and
|
||||
// leaves the swapped operand order alone, exactly as the check below does).
|
||||
// It is NOT generalized here: in this fast path it costs ~9 instructions on every
|
||||
// multiply in every game, against 1 today. Its home is iFPUd-arm64.cpp, where the
|
||||
// double product already exists and it costs 4 — extending it to this path needs
|
||||
// its own measured case.
|
||||
static void emitFpuMul(const a64::VRegister& dst, const a64::VRegister& s, const a64::VRegister& t)
|
||||
{
|
||||
if (!CHECK_FPUMULHACK)
|
||||
|
||||
Reference in New Issue
Block a user