FPU: saturate float-to-int in the interpreters

The C cast is undefined past the int32 range, and x86 makes it INT_MIN, so
round/trunc/ceil/floor/cvt.w.s of anything from 2^31 up gave 0x80000000 on
x86 hosts while the PSP saturates to 0x7fffffff (cpu/fpu/roundmode). Route
all of them through SaturatedFloatToInt, which also covers NaN and inf, and
drop the special cases that did.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Henrik RydgårdandClaude Fable 5.1 committed 2026-09-22 14:25:41 -06:00
1 parent dc983bb1c5
commit fc9dbf5ff5
3 files changed
+30 -83

No files matched your search

+13
View File
@@ -127,6 +127,19 @@ inline int is_even(float d) {
return 2.0f * int_part == d;
}
// Float to int the way the PSP's FPU does it: at or past the int32 range the result is the nearest
// limit, and a NaN gives INT_MAX whatever its sign (cpu/fpu/roundmode). The plain cast is undefined
// there, and x86 makes it INT_MIN. Takes a value that's already been rounded.
inline int32_t SaturatedFloatToInt(double d) {
if (d >= 2147483648.0)
return 0x7FFFFFFF;
if (d <= -2147483648.0)
return (int32_t)0x80000000;
if (d != d)
return 0x7FFFFFFF;
return (int32_t)d;
}
// Rounds *.5 to closest even number
inline double round_ieee_754(double d) {
float i = (float)floor(d);