Module: wine Branch: master Commit: 35c09b52d97c91db1736e39d2756bb944a91f9c0 URL: http://source.winehq.org/git/wine.git/?a=commit;h=35c09b52d97c91db1736e39d27...
Author: Hans Leidekker hans@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@codeweavers.com Signed-off-by: Alexandre Julliard julliard@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;