Hans Leidekker : webservices: Set and restore the full floating point control word.

Alexandre Julliard julliard at winehq.org
Fri Jan 27 14:12:23 CST 2017


Module: wine
Branch: master
Commit: 35c09b52d97c91db1736e39d2756bb944a91f9c0
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=35c09b52d97c91db1736e39d2756bb944a91f9c0

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jan 27 10:28:42 2017 +0100

webservices: Set and restore the full floating point control word.

Signed-off-by: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/webservices/reader.c              | 31 +++++++---------------
 dlls/webservices/tests/writer.c        | 47 ++++++++++++++++++++++++++++++++++
 dlls/webservices/webservices_private.h |  4 +--
 dlls/webservices/writer.c              |  4 +--
 4 files changed, 60 insertions(+), 26 deletions(-)

diff --git a/dlls/webservices/reader.c b/dlls/webservices/reader.c
index d67c47a..9e68cb4 100644
--- a/dlls/webservices/reader.c
+++ b/dlls/webservices/reader.c
@@ -2294,17 +2294,14 @@ static HRESULT str_to_uint64( const unsigned char *str, ULONG len, UINT64 max, U
     return S_OK;
 }
 
-#if defined(__i386__) || defined(__x86_64__)
-
-#define RC_DOWN 0x100;
-BOOL set_fp_rounding( unsigned short *save )
+BOOL set_fpword( unsigned short new, unsigned short *old )
 {
-#ifdef __GNUC__
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
     unsigned short fpword;
 
     __asm__ __volatile__( "fstcw %0" : "=m" (fpword) );
-    *save = fpword;
-    fpword |= RC_DOWN;
+    *old = fpword;
+    fpword = new;
     __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
     return TRUE;
 #else
@@ -2312,25 +2309,15 @@ BOOL set_fp_rounding( unsigned short *save )
     return FALSE;
 #endif
 }
-void restore_fp_rounding( unsigned short fpword )
+
+void restore_fpword( unsigned short fpword )
 {
-#ifdef __GNUC__
+#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
     __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
 #else
     FIXME( "not implemented\n" );
 #endif
 }
-#else
-BOOL set_fp_rounding( unsigned short *save )
-{
-    FIXME( "not implemented\n" );
-    return FALSE;
-}
-void restore_fp_rounding( unsigned short fpword )
-{
-    FIXME( "not implemented\n" );
-}
-#endif
 
 static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
 {
@@ -2373,7 +2360,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_fp_rounding( &fpword )) return E_NOTIMPL;
+    if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
 
     q = p;
     while (len && isdigit( *q )) { q++; len--; }
@@ -2444,7 +2431,7 @@ static HRESULT str_to_double( const unsigned char *str, ULONG len, double *ret )
     hr = S_OK;
 
 done:
-    restore_fp_rounding( fpword );
+    restore_fpword( fpword );
     return hr;
 }
 
diff --git a/dlls/webservices/tests/writer.c b/dlls/webservices/tests/writer.c
index 6ad691f..039de55 100644
--- a/dlls/webservices/tests/writer.c
+++ b/dlls/webservices/tests/writer.c
@@ -2065,9 +2065,28 @@ 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;
     static const struct
     {
         double      val;
@@ -2155,6 +2174,34 @@ 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 );
+
+    hr = set_output( writer );
+    ok( hr == S_OK, "got %08x\n", hr );
+    hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    text.value = 100000000000000;
+    hr = WsWriteText( writer, &text.text, NULL );
+    ok( hr == S_OK, "got %08x\n", hr );
+
+    hr = WsWriteEndElement( writer, NULL );
+    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 );
+
     WsFreeWriter( writer );
 }
 
diff --git a/dlls/webservices/webservices_private.h b/dlls/webservices/webservices_private.h
index b442838..3aafeb1 100644
--- a/dlls/webservices/webservices_private.h
+++ b/dlls/webservices/webservices_private.h
@@ -35,8 +35,8 @@ WS_XML_UTF8_TEXT *alloc_utf8_text( const unsigned char *, ULONG ) DECLSPEC_HIDDE
 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_fp_rounding( unsigned short * ) DECLSPEC_HIDDEN;
-void restore_fp_rounding( unsigned short ) DECLSPEC_HIDDEN;
+BOOL set_fpword( unsigned short, unsigned short * ) DECLSPEC_HIDDEN;
+void restore_fpword( unsigned short ) DECLSPEC_HIDDEN;
 HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN;
 HRESULT set_input( WS_XML_READER *, char *, ULONG ) DECLSPEC_HIDDEN;
 ULONG get_type_size( WS_TYPE, const WS_STRUCT_DESCRIPTION * ) DECLSPEC_HIDDEN;
diff --git a/dlls/webservices/writer.c b/dlls/webservices/writer.c
index 1ccac53..f01a5a0 100644
--- a/dlls/webservices/writer.c
+++ b/dlls/webservices/writer.c
@@ -1373,9 +1373,9 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
         unsigned short fpword;
         ULONG len;
 
-        if (!set_fp_rounding( &fpword )) return E_NOTIMPL;
+        if (!set_fpword( 0x37f, &fpword )) return E_NOTIMPL;
         len = format_double( &double_text->value, buf );
-        restore_fp_rounding( fpword );
+        restore_fpword( fpword );
         if (!len) return E_NOTIMPL;
         if (!(*ret = alloc_utf8_text( buf, len ))) return E_OUTOFMEMORY;
         return S_OK;




More information about the wine-cvs mailing list