Alexandre Julliard : webservices: Use _control87() instead of directly manipulating the FPU register.

Alexandre Julliard julliard at winehq.org
Thu Oct 31 17:39:30 CDT 2019


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Oct 31 22:18:32 2019 +0100

webservices: Use _control87() instead of directly manipulating the FPU register.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c              | 32 ++++-----------------------
 dlls/webservices/tests/writer.c        | 40 +++++++---------------------------
 dlls/webservices/webservices_private.h |  2 --
 dlls/webservices/writer.c              |  7 +++---
 4 files changed, 16 insertions(+), 65 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index 664bfbeb63..181739650e 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -18,6 +18,7 @@
 
 #include <stdarg.h>
 #include <assert.h>
+#include <float.h>
 
 #include "windef.h"
 #include "winbase.h"
@@ -3723,31 +3724,6 @@ static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, U
     return S_OK;
 }
 
-BOOL set_fpword( unsigned short new, unsigned short *old )
-{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-    unsigned short fpword;
-
-    __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
-    *old = fpword;
-    fpword = new;
-    __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
-    return TRUE;
-#else
-    FIXME( "not implemented\n" );
-    return FALSE;
-#endif
-}
-
-void restore_fpword( unsigned short fpword )
-{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-    __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
-#else
-    FIXME( "not implemented\n" );
-#endif
-}
-
 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
 {
     static const unsigned __int64 nan = 0xfff8000000000000;
@@ -3758,7 +3734,7 @@ static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
     int sign = 1, exp_sign = 1, exp = 0, exp_tmp = 0, neg_exp, i, nb_digits, have_digits;
     unsigned __int64 val = 0, tmp;
     long double exp_val = 1.0, exp_mul = 10.0;
-    unsigned short fpword;
+    unsigned int fpword = _control87( 0, 0 );
 
     while (len && read_isspace( *p )) { p++; len--; }
     while (len && read_isspace( p[len - 1] )) { len--; }
@@ -3789,7 +3765,7 @@ static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
     else if (*p == '+') { p++; len--; };
     if (!len) return S_OK;
 
-    if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
+    _control87( _MCW_EM | _RC_NEAR | _PC_64, _MCW_EM | _MCW_RC | _MCW_PC );
 
     q = p;
     while (len && isdigit( *q )) { q++; len--; }
@@ -3860,7 +3836,7 @@ static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
     hr = S_OK;
 
 done:
-    restore_fpword( fpword );
+    _control87( fpword, _MCW_EM | _MCW_RC | _MCW_PC );
     return hr;
 }
 
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 18c4b7e284..65e672a424 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -18,6 +18,7 @@
 
 #include <stdio.h>
 #include <math.h>
+#include <float.h>
 #include "windows.h"
 #include "rpc.h"
 #include "webservices.h"
@@ -2220,28 +2221,10 @@ static void test_text_types(void)
     WsFreeWriter( writer );
 }
 
-static BOOL get_fpword( unsigned short *ret )
-{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-    unsigned short fpword;
-    __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
-    *ret = fpword;
-    return TRUE;
-#endif
-    return FALSE;
-}
-
-static void set_fpword( unsigned short fpword )
-{
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-    __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
-#endif
-}
-
 static void test_double(void)
 {
     WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
-    unsigned short fpword;
+    unsigned int fpword, fpword_orig;
     static const struct
     {
         double      val;
@@ -2329,16 +2312,9 @@ static void test_double(void)
     ok( hr == S_OK, "got %08x\n", hr );
     check_output( writer, "<t>-INF</t>", __LINE__ );
 
-    if (!get_fpword( &fpword ))
-    {
-        skip( "can't get floating point control word\n" );
-        WsFreeWriter( writer );
-        return;
-    }
-    ok( fpword == 0x27f, "got %04x\n", fpword );
-    set_fpword( 0x1f7f );
-    get_fpword( &fpword );
-    ok( fpword == 0x1f7f, "got %04x\n", fpword );
+    fpword_orig = _control87( 0, 0 );
+    fpword = _control87( _MCW_EM | _RC_CHOP | _PC_64, _MCW_EM | _MCW_RC | _MCW_PC );
+    ok( fpword == (_MCW_EM | _RC_CHOP | _PC_64), "got %08x\n", fpword );
 
     hr = set_output( writer );
     ok( hr == S_OK, "got %08x\n", hr );
@@ -2353,9 +2329,9 @@ static void test_double(void)
     ok( hr == S_OK, "got %08x\n", hr );
     check_output( writer, "<t>100000000000000</t>", __LINE__ );
 
-    get_fpword( &fpword );
-    ok( fpword == 0x1f7f, "got %04x\n", fpword );
-    set_fpword( 0x27f );
+    fpword = _control87( 0, 0 );
+    ok( fpword == (_MCW_EM | _RC_CHOP | _PC_64), "got %08x\n", fpword );
+    _control87( fpword_orig, _MCW_EM | _MCW_RC | _MCW_PC );
 
     WsFreeWriter( writer );
 }
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index 9ca470c82b..b12032060f 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -65,8 +65,6 @@ void free_xml_string( WS_XML_STRING * ) DECLSPEC_HIDDEN;
 HRESULT append_attribute( WS_XML_ELEMENT_NODE *, WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
 void free_attribute( WS_XML_ATTRIBUTE * ) DECLSPEC_HIDDEN;
 WS_TYPE map_value_type( WS_VALUE_TYPE ) DECLSPEC_HIDDEN;
-BOOL set_fpword( unsigned short, unsigned short * ) DECLSPEC_HIDDEN;
-void restore_fpword( unsigned short ) DECLSPEC_HIDDEN;
 ULONG get_type_size( WS_TYPE, const void * ) DECLSPEC_HIDDEN;
 HRESULT read_header( WS_XML_READER *, const WS_XML_STRING *, const WS_XML_STRING *, WS_TYPE,
                      const void *, WS_READ_OPTION, WS_HEAP *, void *, ULONG ) DECLSPEC_HIDDEN;
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index f750859fbc..021c961c94 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -19,6 +19,7 @@
 #include <assert.h>
 #include <stdarg.h>
 #include <stdio.h>
+#include <float.h>
 #include <math.h>
 
 #include "windef.h"
@@ -1193,12 +1194,12 @@ HRESULT text_to_utf8text( const WS_XML_TEXT *text, const WS_XML_UTF8_TEXT *old,
     {
         const WS_XML_DOUBLE_TEXT *double_text = (const WS_XML_DOUBLE_TEXT *)text;
         unsigned char buf[32]; /* "-1.1111111111111111E-308", oversized to address Valgrind limitations */
-        unsigned short fpword;
+        unsigned int fpword = _control87( 0, 0 );
         ULONG len;
 
-        if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
+        _control87( _MCW_EM | _RC_NEAR | _PC_64, _MCW_EM | _MCW_RC | _MCW_PC );
         len = format_double( &double_text->value, buf );
-        restore_fpword( fpword );
+        _control87( fpword, _MCW_EM | _MCW_RC | _MCW_PC );
         if (!len) return E_NOTIMPL;
 
         if (!(*ret = alloc_utf8_text( NULL, len_old + len ))) return E_OUTOFMEMORY;




More information about the wine-cvs mailing list