Add missing libc.prx symbols required by Unity IL2CPP runtime:
- Implement _Dtest double classification in Math.cpp
- Implement _Inf double constant in Math.cpp
- Implement sceLibcBacktraceGetBufferSize and sceLibcBacktraceSelf in Backtrace.cpp
- Implement _Cnd_signal in Threads.cpp
- Implement _ZNSt8ios_base7_AddstdEPS_ in RuntimeSupport.cpp
- Implement __pointer_type_info and __function_type_info vtables in TypeInfo.cpp
- Remove duplicate stubs from libSceAmpr/Export.cpp
- Add unit tests in GuestMath.cpp and GuestLibcThreads.cpp
- Document unverified behaviors in docs/dev/debt/libc.md
PPSA99611 imports ceilf, floorf, truncf, isnan and isinf from libc.prx and stops at start-up on main. Implement them next to the existing double forms: the rounding results delegate to the standard library like the other float exports, and isnan/isinf reuse the __isnan/__isinf helpers isnanf already uses.
The H+8UBOwfScI import was a throwing stub (libcCyberUnknown08). It is
the NID of "__powidf2", the double-precision integer-power helper that
complements __powisf2.
The previous commit replaced the out-of-range result with the default
quiet NaN 0x7fc00000, but main and FreeBSD e_acosf.c return 0xffc00000.
acosf now calls the host and restores errno, so only errno differs from
main. The guest test pins the result bits for 2.0f and -2.0f and keeps
the in-range case acosf(0.5f).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
acosf returned 0xffc00000 (errno 33) for 2.0 (0x40000000), where FreeBSD
lib/msun/src/math.h returns 0xffc00000 (errno 0).
It now returns the FreeBSD result for that case. A guest test covers it
and fails on main.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Dusklight (PPSA99305) imports atanhf (cPGyc5FGjy0) from
libSceLibcInternal.prx; the libc.prx it bundles only has a zero-return
stub for it.
The implementation follows the atanhf of the libc.prx bundled with
PPSA28319 (0x438a0), read from its disassembly: FreeBSD msun's
e_atanhf.c calling msun's s_log1pf.c, both as of 59bc2f09 (stable/9,
the revision the sinhf port took expm1f and expf from). The log1pf
paths for the positive arguments atanhf passes are inlined, as the
exported log1pf is still the host's. For |x| > 1, the infinities and
NaN, Sony's error helper raises FE_INVALID and sets errno to EDOM
before returning (x - x) / (x - x); for |x| = 1 it sets errno to
ERANGE before returning x / 0. Other arguments leave errno alone.
Running that code from the title's libc.prx on a Windows host gives
the same bits, errno and floating-point exceptions as the built
libc.prx for all 2^32 arguments, and msun's own e_atanhf.c and
s_log1pf.c built with the host compiler give the same bits. With the
host log1pf instead of the msun one, 4.7% of the arguments in [0, 1)
differ. guest_math pins bits for every branch reachable from atanhf,
both signs, and the errno and exception behaviour.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
powf(1.0, nan) returned 0x7fc00001; FreeBSD msun (lib/msun/src/e_powf.c)
returns 0x3f800000. That case now follows FreeBSD; other inputs are
unchanged.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Kart PS5 (PPSA99611) stops on gacfOmO8hNs (ceil, per tools/nid_names.py)
from libc.prx once __umodti3 resolves (title run on #4519). ceil rounds
toward positive infinity whatever the rounding mode, keeps the sign of
zero and of results that round to zero, and returns infinities and NaNs
unchanged, as std::ceil does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
C17 7.22.1.3 and 7.29.4.1.1 interpret NAN(n-char-sequence) as a quiet
NaN. With MinGW-w64, std::strtod, strtof and strtold are mingw-w64's
gdtoa functions, which copy the hex digits into the significand
without the quiet bit, and for long double without the x87 integer
bit: strtod("nan(0x123)") returned the signaling NaN
0x7ff0000000000123 and strtold a pseudo-NaN. A payload whose only set
bit is the implicit or x87 integer bit gave infinity:
strtof("nan(0x800000)"), strtod("nan(0x10000000000000)") and
strtold("nan(0x8000000000000000)") returned +inf. glibc returns quiet
NaNs that keep the payload.
C17 7.12.11.2p2 makes nan("n-char-sequence") equivalent to
strtod("NAN(n-char-sequence)", NULL), and nan and nanf already return
the console's fixed quiet NaNs, ignoring the tag. ParseFloat, which
strtod, strtof, strtold, atof and the wide variants share, now returns
the same values, 0x7ff8000000000000 and 0x7fc00000, negated after a
minus sign, on Windows and Linux. strtold returns the x87 default
quiet NaN, since no console nanl was observed.
OutRun2006 (PPSA99106) imports nearbyintl and stops at start-up on main. Add the long double round-to-nearest-integer export next to nearbyintf; std::nearbyint rounds under the current direction and raises no inexact exception.
RetroArch 1.0.0-beta.1 (PPSA99169) stops on main 0f863c10 at
FAIL: unresolved ELF import Nx-F5v0-qU8 from libSceLibcInternal.prx
Nx-F5v0-qU8 is asinl (tools/nid_names.py, aerolib).
The implementation follows the asinl of the libc.prx bundled with
PPSA28319, read from its disassembly: FreeBSD msun's e_asinl.c with
the ld80 invtrig.c coefficients (9f043204), which the binary holds as
the same 80-bit constants, computed in the x87 long double the guest
uses. +-1 returns +-pi/2 rounded to 64 bits and +-0 keeps its sign.
For |x| > 1, the infinities and NaN, Sony's error helper raises
FE_INVALID and sets errno to EDOM before returning (x - x) / (x - x),
so a NaN argument sets EDOM too.
20 million random arguments in (-1, 1) plus the branch edges give the
same bits as that code from the title's libc.prx run on a Windows
host. guest_math pins a set of those bits and checks the domain
errors' errno and FE_INVALID, and that errno is untouched otherwise.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Ruffle Flash 1.2.0 (PPSA68091) stops on main 0f863c10 at
FAIL: unresolved ELF import 1t1-JoZ0sZQ from libSceLibcInternal.prx
1t1-JoZ0sZQ is sinhf (tools/nid_names.py, aerolib). RetroArch
1.0.0-beta.1 (PPSA99169) imports it as well.
The implementation follows the sinhf of the libc.prx bundled with
PPSA28319, read from its disassembly: FreeBSD msun's e_sinhf.c as of
5aa554c7 (before __ldexp_expf, so expf(|x| / 2) is squared between
logf(FLT_MAX) and the overflow threshold), calling msun stable/9
expm1f and expf (59bc2f09), whose paths for the arguments sinhf passes
are inlined. Past the threshold Sony's error helper sets errno to
ERANGE before returning x * 1e37; NaN and the infinities return x + x
and leave errno alone.
Running that code from the title's libc.prx on a Windows host gives
the same bits as this implementation for every finite argument up to
the threshold, both signs (2,238,032,378 inputs). guest_math pins a
set of those bits, the overflow errno and FE_OVERFLOW, and checks that
errno is untouched otherwise.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
exp2 set errno (34) for 1024.0. FreeBSD msun never sets errno and
reports errors through floating-point exceptions only, so errno is now
saved and restored around the host call.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
On main asin(2.0) returns 0x7ff8000000000000 and sets errno to 33;
FreeBSD msun (lib/msun/src/e_asin.c) returns 0xfff8000000000000 and
never sets errno. asin now handles |x| > 1 itself with quiet
comparisons, so a NaN input still raises no exception. For |x| <= 1
and for NaN the host function is still called.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
asinf returned 0xffc00000 (errno 33) for 2.0 (0x40000000), where FreeBSD
lib/msun/src/math.h returns 0xffc00000 (errno 0).
It now returns the FreeBSD result for that case. A guest test covers it
and fails on main.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
fmod set errno (33) for 1.0, 0.0. FreeBSD msun never sets errno and
reports errors through floating-point exceptions only, so errno is now
saved and restored around the host call.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
hypot(inf, NaN) returned a NaN on main. C Annex F returns +inf when
either operand is infinite, even if the other is a NaN, and FreeBSD
msun (lib/msun/src/e_hypot.c) does so for a signalling NaN too. The
infinite case is now checked before std::hypot; other inputs do not
change.
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Add standard quiet NaN generators nanf (DZU+K1wozGI) and nan (zck+6bVj5pA) to libc.
Resolves startup failure in VLC for PS5 (PPSA85300) where execution halts at nanf on Linux once strsep is available.
The original fix predates llroundf, which was added in #2933. Use the same guest range and exception behavior for the fourth wrapper and include it in the edge-case checks.
FreeBSD amd64 converts the rounded value with a plain cast, so NaN, infinities and values outside the 64-bit range give 0x8000000000000000 with FE_INVALID raised. The Windows host llround returns 0 for them.
(cherry picked from commit 0ee2741534bdfcc9d818b1d93f2eb793a68f111e)