Piotr Caban : msvcrt: Set mxcsr denormal flag in sqrtf if needed.

Alexandre Julliard julliard at winehq.org
Fri Feb 5 16:50:49 CST 2021


Module: wine
Branch: master
Commit: 0cd71776f474a6d8df7dc1198c50a3c31bacb635
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=0cd71776f474a6d8df7dc1198c50a3c31bacb635

Author: Piotr Caban <piotr at 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 at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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.@)
  */




More information about the wine-cvs mailing list