Piotr Caban : msvcrt: Set mxcsr denormal flag in sqrtf if needed.
Module: wine Branch: master Commit: 0cd71776f474a6d8df7dc1198c50a3c31bacb635 URL: https://source.winehq.org/git/wine.git/?a=commit;h=0cd71776f474a6d8df7dc1198... Author: Piotr Caban <piotr(a)codeweavers.com> Date: Fri Feb 5 16:06:47 2021 +0100 msvcrt: Set mxcsr denormal flag in sqrtf if needed. Signed-off-by: Piotr Caban <piotr(a)codeweavers.com> Signed-off-by: Alexandre Julliard <julliard(a)winehq.org> --- dlls/msvcrt/math.c | 85 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 0f41cbac468..d0cc87d2c8e 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -82,6 +82,13 @@ static inline float fp_barrierf(float x) return y; } +static inline double CDECL ret_nan( BOOL update_sw ) +{ + double x = 1.0; + if (!update_sw) return -NAN; + return (x - x) / (x - x); +} + /********************************************************************* * _matherr (CRTDLL.@) */ @@ -613,6 +620,28 @@ float CDECL sinhf( float x ) return ret; } +static BOOL sqrtf_validate( float *x ) +{ + short c = _fdclass(*x); + + if (c == FP_ZERO) return FALSE; + if (c == FP_NAN) return FALSE; + if (signbit(*x)) + { + *x = math_error(_DOMAIN, "sqrtf", *x, 0, ret_nan(TRUE)); + return FALSE; + } + if (c == FP_INFINITE) return FALSE; + return TRUE; +} + +#if defined(__x86_64__) || defined(__i386__) +float CDECL sse2_sqrtf(float); +__ASM_GLOBAL_FUNC( sse2_sqrtf, + "sqrtss %xmm0, %xmm0\n\t" + "ret" ) +#endif + /********************************************************************* * sqrtf (MSVCRT.@) * @@ -620,25 +649,23 @@ float CDECL sinhf( float x ) */ float CDECL sqrtf( float x ) { +#ifdef __x86_64__ + if (!sqrtf_validate(&x)) + return x; + + return sse2_sqrtf(x); +#else static const float tiny = 1.0e-30; float z; - int sign = 0x80000000; int ix,s,q,m,t,i; unsigned int r; ix = *(int*)&x; - /* take care of Inf and NaN */ - if ((ix & 0x7f800000) == 0x7f800000 && (ix == 0x7f800000 || ix & 0x7fffff)) + if (!sqrtf_validate(&x)) return x; - /* take care of zero */ - if (ix <= 0) { - if ((ix & ~sign) == 0) - return x; /* sqrt(+-0) = +-0 */ - return math_error(_DOMAIN, "sqrtf", x, 0, (x - x) / (x - x)); /* sqrt(-ve) = sNaN */ - } /* normalize x */ m = ix >> 23; if (m == 0) { /* subnormal x */ @@ -683,6 +710,7 @@ float CDECL sqrtf( float x ) r = ix + ((unsigned int)m << 23); z = *(float*)&r; return z; +#endif } /********************************************************************* @@ -1165,14 +1193,7 @@ double CDECL sinh( double x ) return ret; } -static inline double CDECL ret_nan( BOOL update_sw ) -{ - double x = 1.0; - if (!update_sw) return -NAN; - return (x - x) / (x - x); -} - -BOOL sqrt_validate( double *x, BOOL update_sw ) +static BOOL sqrt_validate( double *x, BOOL update_sw ) { short c = _dclass(*x); @@ -3511,6 +3532,21 @@ __int64 CDECL llrintf(float x) return unix_funcs->llrintf( x ); } +/********************************************************************* + * _fdclass (MSVCR120.@) + * + * Copied from musl: src/math/__fpclassifyf.c + */ +short CDECL _fdclass(float x) +{ + union { float f; UINT32 i; } u = { x }; + int e = u.i >> 23 & 0xff; + + if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO; + if (e == 0xff) return u.i << 9 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; +} + /********************************************************************* * _dclass (MSVCR120.@) * @@ -3592,21 +3628,6 @@ float CDECL truncf(float x) return unix_funcs->truncf(x); } -/********************************************************************* - * _fdclass (MSVCR120.@) - * - * Copied from musl: src/math/__fpclassifyf.c - */ -short CDECL _fdclass(float x) -{ - union { float f; UINT32 i; } u = { x }; - int e = u.i >> 23 & 0xff; - - if (!e) return u.i << 1 ? FP_SUBNORMAL : FP_ZERO; - if (e == 0xff) return u.i << 9 ? FP_NAN : FP_INFINITE; - return FP_NORMAL; -} - /********************************************************************* * _dtest (MSVCR120.@) */
participants (1)
-
Alexandre Julliard