mirror of
https://github.com/ARMSX2/ARMSX2.git
synced 2026-08-24 16:50:16 -07:00
Fix: ESQRT/ERSQRT take the operand's magnitude
The EFU square root roots a negative operand as if it were positive; the interpreter's `p >= 0` guard returned the operand unchanged instead, so ESQRT and ERSQRT of -1.0 gave -1.0 where the console gives 1.0, and ESQRT of -0.0 gave -0.0 where the console gives +0.0. Both recompilers already AND the raw bits with absclip before FSQRT (mVU_ESQRT, mVU_ERSQRT), so masking the sign off before vuDouble puts the interpreter on the same order of operations rather than on a new one. Clears bad_interp on ERSQRT CVF_NEGONE, ESQRT CVF_NEGZERO and ESQRT CVF_NEGONE; kEfuBadInterp 119 -> 116. The remaining negative-operand rows (CVF_MIN, CVF_GARBAGE2, ...) still fail on BOTH engines and are untouched here: they are Inf/NaN inputs that vuDouble only clamps to fMax under CHECK_VU_OVERFLOW, which ships off. That is a separate, all-engines-wrong defect. Idea by pstef.
This commit is contained in:
committed by
Brian Degenhardt
parent
bcf55312d4
commit
4a7284ea4a
+12
-12
@@ -1776,29 +1776,29 @@ static __ri void _vuERCPR(VURegs* VU)
|
||||
VU->p.F = p;
|
||||
}
|
||||
|
||||
// The EFU square root takes the operand's MAGNITUDE: a negative input is rooted
|
||||
// as if positive, it is not passed through unchanged. Both recompilers do this
|
||||
// by ANDing the raw bits with absclip before FSQRT (mVU_ESQRT / mVU_ERSQRT);
|
||||
// the `p >= 0` guard here returned the operand untouched instead, so ESQRT and
|
||||
// ERSQRT of -1.0 gave -1.0 where the console gives 1.0. Masking the sign off the
|
||||
// raw bits before vuDouble is the same order the recompilers use.
|
||||
static __ri void _vuESQRT(VURegs* VU)
|
||||
{
|
||||
float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]);
|
||||
float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_] & 0x7FFFFFFF);
|
||||
|
||||
if (p >= 0)
|
||||
{
|
||||
p = sqrt(p);
|
||||
}
|
||||
p = sqrt(p);
|
||||
|
||||
VU->p.F = p;
|
||||
}
|
||||
|
||||
static __ri void _vuERSQRT(VURegs* VU)
|
||||
{
|
||||
float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_]);
|
||||
float p = vuDouble(VU->VF[_Fs_].UL[_Fsf_] & 0x7FFFFFFF);
|
||||
|
||||
if (p >= 0)
|
||||
p = sqrt(p);
|
||||
if (p)
|
||||
{
|
||||
p = sqrt(p);
|
||||
if (p)
|
||||
{
|
||||
p = 1.0f / p;
|
||||
}
|
||||
p = 1.0f / p;
|
||||
}
|
||||
|
||||
VU->p.F = p;
|
||||
|
||||
@@ -151,7 +151,7 @@ inline constexpr EfuCase kEfuCases[] = {
|
||||
{"ERSQRT", "CVF_MAX_EXP", "ERSQRT CVF_MAX_EXP", true, {0x7F800001u, 0x7F800001u, 0x7F800001u, 0x7F800001u}, 0x1F800000u, false, true},
|
||||
{"ERSQRT", "CVF_MIN_EXP", "ERSQRT CVF_MIN_EXP", true, {0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u}, 0x7FFFFFFFu, true, true},
|
||||
{"ERSQRT", "CVF_ONE", "ERSQRT CVF_ONE", true, {0x3F800000u, 0x3F800000u, 0x3F800000u, 0x3F800000u}, 0x3F800000u, false, false},
|
||||
{"ERSQRT", "CVF_NEGONE", "ERSQRT CVF_NEGONE", true, {0xBF800000u, 0xBF800000u, 0xBF800000u, 0xBF800000u}, 0x3F800000u, true, false},
|
||||
{"ERSQRT", "CVF_NEGONE", "ERSQRT CVF_NEGONE", true, {0xBF800000u, 0xBF800000u, 0xBF800000u, 0xBF800000u}, 0x3F800000u, false, false},
|
||||
{"ERSQRT", "CVF_GARBAGE1", "ERSQRT CVF_GARBAGE1", true, {0x00001337u, 0x00001337u, 0x00001337u, 0x00001337u}, 0x7FFFFFFFu, true, true},
|
||||
{"ERSQRT", "CVF_GARBAGE2", "ERSQRT CVF_GARBAGE2", true, {0xDEADBEEFu, 0xDEADBEEFu, 0xDEADBEEFu, 0xDEADBEEFu}, 0x2FDBBAACu, true, true},
|
||||
{"ERSQRT", "CVF_INCREASING", "ERSQRT CVF_INCREASING", true, {0x3F800000u, 0x40000000u, 0x40400000u, 0x40800000u}, 0x3F13CD3Au, false, false},
|
||||
@@ -192,14 +192,14 @@ inline constexpr EfuCase kEfuCases[] = {
|
||||
{"ESIN", "CVF_PI", "ESIN CVF_PI", true, {0x40490FDBu, 0x40490FDBu, 0x40490FDBu, 0x40490FDBu}, 0x3B565DE0u, true, false},
|
||||
{"ESIN", "CVF_3PI_OVER2", "ESIN CVF_3PI_OVER2", true, {0x4096CBE4u, 0x4096CBE4u, 0x4096CBE4u, 0x4096CBE4u}, 0xBF1A9934u, true, false},
|
||||
{"ESQRT", "CVF_ZERO", "ESQRT CVF_ZERO", true, {0x00000000u, 0x00000000u, 0x00000000u, 0x00000000u}, 0x00000000u, false, false},
|
||||
{"ESQRT", "CVF_NEGZERO", "ESQRT CVF_NEGZERO", true, {0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u}, 0x00000000u, true, false},
|
||||
{"ESQRT", "CVF_NEGZERO", "ESQRT CVF_NEGZERO", true, {0x80000000u, 0x80000000u, 0x80000000u, 0x80000000u}, 0x00000000u, false, false},
|
||||
{"ESQRT", "CVF_MAX", "ESQRT CVF_MAX", true, {0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu, 0x7FFFFFFFu}, 0x5FB504F3u, true, true},
|
||||
{"ESQRT", "CVF_MIN", "ESQRT CVF_MIN", true, {0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu}, 0x5FB504F3u, true, true},
|
||||
{"ESQRT", "CVF_MAX_MANTISSA", "ESQRT CVF_MAX_MANTISSA", true, {0x3FFFFFFFu, 0x3FFFFFFFu, 0x3FFFFFFFu, 0x3FFFFFFFu}, 0x3FB504F3u, true, true},
|
||||
{"ESQRT", "CVF_MAX_EXP", "ESQRT CVF_MAX_EXP", true, {0x7F800001u, 0x7F800001u, 0x7F800001u, 0x7F800001u}, 0x5F800000u, true, true},
|
||||
{"ESQRT", "CVF_MIN_EXP", "ESQRT CVF_MIN_EXP", true, {0x00000001u, 0x00000001u, 0x00000001u, 0x00000001u}, 0x00000000u, false, false},
|
||||
{"ESQRT", "CVF_ONE", "ESQRT CVF_ONE", true, {0x3F800000u, 0x3F800000u, 0x3F800000u, 0x3F800000u}, 0x3F800000u, false, false},
|
||||
{"ESQRT", "CVF_NEGONE", "ESQRT CVF_NEGONE", true, {0xBF800000u, 0xBF800000u, 0xBF800000u, 0xBF800000u}, 0x3F800000u, true, false},
|
||||
{"ESQRT", "CVF_NEGONE", "ESQRT CVF_NEGONE", true, {0xBF800000u, 0xBF800000u, 0xBF800000u, 0xBF800000u}, 0x3F800000u, false, false},
|
||||
{"ESQRT", "CVF_GARBAGE1", "ESQRT CVF_GARBAGE1", true, {0x00001337u, 0x00001337u, 0x00001337u, 0x00001337u}, 0x00000000u, false, false},
|
||||
{"ESQRT", "CVF_GARBAGE2", "ESQRT CVF_GARBAGE2", true, {0xDEADBEEFu, 0xDEADBEEFu, 0xDEADBEEFu, 0xDEADBEEFu}, 0x4F152108u, true, true},
|
||||
{"ESQRT", "CVF_INCREASING", "ESQRT CVF_INCREASING", true, {0x3F800000u, 0x40000000u, 0x40400000u, 0x40800000u}, 0x3FDDB3D7u, false, false},
|
||||
@@ -226,7 +226,7 @@ inline constexpr EfuCase kEfuCases[] = {
|
||||
};
|
||||
|
||||
inline constexpr int kEfuCaseCount = 208;
|
||||
inline constexpr int kEfuBadInterp = 119;
|
||||
inline constexpr int kEfuBadInterp = 116;
|
||||
inline constexpr int kEfuBadJit = 126;
|
||||
|
||||
} // namespace ps2auto_efu
|
||||
|
||||
Reference in New Issue
Block a user