Module: wine Branch: master Commit: 0cd71776f474a6d8df7dc1198c50a3c31bacb635 URL: https://source.winehq.org/git/wine.git/?a=commit;h=0cd71776f474a6d8df7dc1198...
Author: Piotr Caban piotr@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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.@) */