From 64e244eb703346f22d8e6703499e51c16f52b055 Mon Sep 17 00:00:00 2001 From: Alex <270190108+CouchRiv@users.noreply.github.com> Date: Sun, 11 Oct 2026 11:19:22 -0400 Subject: [PATCH 1/2] fix(libc): match FreeBSD acosf errno 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 --- core/libs/prx/libc/src/Math.cpp | 8 +++++++- core/libs/tests/GuestMath.cpp | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index 90c19cb5f..f6ccc2b03 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -182,7 +182,13 @@ float APS5_VABI asinf_nid_postfix(float x) { errno = saved_errno; return result; } -float APS5_VABI acosf_nid_postfix(float x) { return std::acos(x); } +float APS5_VABI acosf_nid_postfix(float x) { + if (x < -1.0f || x > 1.0f) { + std::feraiseexcept(FE_INVALID); + return std::numeric_limits::quiet_NaN(); + } + return std::acos(x); +} float APS5_VABI atan2f_nid_postfix(float y, float x) { return std::atan2(y, x); } float APS5_VABI hypotf_nid_postfix(float x, float y) { return static_cast(std::hypot(static_cast(x), static_cast(y))); } double APS5_VABI hypot_nid_postfix(double x, double y) { diff --git a/core/libs/tests/GuestMath.cpp b/core/libs/tests/GuestMath.cpp index 2f09ac820..64c693895 100644 --- a/core/libs/tests/GuestMath.cpp +++ b/core/libs/tests/GuestMath.cpp @@ -214,6 +214,18 @@ static void CheckPowfSpecialValue() { Require(std::bit_cast(powf_nid_postfix(1.0f, std::bit_cast(0x7f800001u))) == 0x3f800000u); } +static void CheckAcosfErrno() { + errno = 0; + (void)acosf_nid_postfix(2.0f); + Require(errno == 0); + errno = 0; + (void)acosf_nid_postfix(-2.0f); + Require(errno == 0); + errno = 0; + (void)acosf_nid_postfix(0.5f); + Require(errno == 0); +} + static void CheckLongDouble() { Require(ExtendedBits(acosl_nid_postfix(-1.0L), 0xc90fdaa22168c235ull, 0x4000)); Require(ExtendedBits(acosl_nid_postfix(0.0L), 0xc90fdaa22168c235ull, 0x3fff)); @@ -839,6 +851,7 @@ int main() { Require(minimum.quot == -214748364 && minimum.rem == -8); CheckPowfSpecialValue(); Require(abs_nid_postfix(0) == 0); + CheckAcosfErrno(); Require(abs_nid_postfix(42) == 42); Require(abs_nid_postfix(-42) == 42); Require(abs_nid_postfix(std::numeric_limits::max()) == std::numeric_limits::max()); From 988d304c5ce1882b553503df6e8577b4856f7171 Mon Sep 17 00:00:00 2001 From: Alex <270190108+CouchRiv@users.noreply.github.com> Date: Sun, 11 Oct 2026 11:42:42 -0400 Subject: [PATCH 2/2] fix(libc): keep the acosf result and leave errno unchanged 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 --- core/libs/prx/libc/src/Math.cpp | 9 ++++----- core/libs/tests/GuestMath.cpp | 8 +++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/core/libs/prx/libc/src/Math.cpp b/core/libs/prx/libc/src/Math.cpp index f6ccc2b03..f127140ab 100644 --- a/core/libs/prx/libc/src/Math.cpp +++ b/core/libs/prx/libc/src/Math.cpp @@ -183,11 +183,10 @@ float APS5_VABI asinf_nid_postfix(float x) { return result; } float APS5_VABI acosf_nid_postfix(float x) { - if (x < -1.0f || x > 1.0f) { - std::feraiseexcept(FE_INVALID); - return std::numeric_limits::quiet_NaN(); - } - return std::acos(x); + const int saved_errno = errno; + const float result = std::acos(x); + errno = saved_errno; + return result; } float APS5_VABI atan2f_nid_postfix(float y, float x) { return std::atan2(y, x); } float APS5_VABI hypotf_nid_postfix(float x, float y) { return static_cast(std::hypot(static_cast(x), static_cast(y))); } diff --git a/core/libs/tests/GuestMath.cpp b/core/libs/tests/GuestMath.cpp index 64c693895..cc1760c60 100644 --- a/core/libs/tests/GuestMath.cpp +++ b/core/libs/tests/GuestMath.cpp @@ -216,13 +216,11 @@ static void CheckPowfSpecialValue() { static void CheckAcosfErrno() { errno = 0; - (void)acosf_nid_postfix(2.0f); + Require(std::bit_cast(acosf_nid_postfix(2.0f)) == 0xffc00000u); Require(errno == 0); - errno = 0; - (void)acosf_nid_postfix(-2.0f); + Require(std::bit_cast(acosf_nid_postfix(-2.0f)) == 0xffc00000u); Require(errno == 0); - errno = 0; - (void)acosf_nid_postfix(0.5f); + Require(std::bit_cast(acosf_nid_postfix(0.5f)) == 0x3f860a92u); Require(errno == 0); }