Module: wine Branch: master Commit: 6b6f3406f4be92287f8f097803fd96811d785a05 URL: http://source.winehq.org/git/wine.git/?a=commit;h=6b6f3406f4be92287f8f097803...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Jun 13 11:34:49 2016 +0200
ucrtbase: Add __fpe_flt_rounds implementation.
Based on a patch by Alex Henrie.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
.../api-ms-win-crt-runtime-l1-1-0.spec | 2 +- dlls/msvcrt/math.c | 22 +++++++++++ dlls/ucrtbase/tests/misc.c | 45 +++++++++++++++++++++- dlls/ucrtbase/ucrtbase.spec | 2 +- 4 files changed, 67 insertions(+), 4 deletions(-)
diff --git a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec index 9864c6c..8d96f98 100644 --- a/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec +++ b/dlls/api-ms-win-crt-runtime-l1-1-0/api-ms-win-crt-runtime-l1-1-0.spec @@ -1,7 +1,7 @@ @ stub _Exit @ cdecl -arch=i386 __control87_2(long long ptr ptr) ucrtbase.__control87_2 @ cdecl __doserrno() ucrtbase.__doserrno -@ stub __fpe_flt_rounds +@ cdecl __fpe_flt_rounds() ucrtbase.__fpe_flt_rounds @ cdecl __fpecode() ucrtbase.__fpecode @ cdecl __p___argc() ucrtbase.__p___argc @ cdecl __p___argv() ucrtbase.__p___argv diff --git a/dlls/msvcrt/math.c b/dlls/msvcrt/math.c index 402e8b2..3d2104b 100644 --- a/dlls/msvcrt/math.c +++ b/dlls/msvcrt/math.c @@ -1199,6 +1199,28 @@ int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask }
/********************************************************************* + * __fpe_flt_rounds (UCRTBASE.@) + */ +int CDECL __fpe_flt_rounds(void) +{ + unsigned int fpc = _controlfp(0, 0) & MSVCRT__RC_CHOP; + + TRACE("()\n"); + + switch(fpc) { + case MSVCRT__RC_CHOP: return 0; + case MSVCRT__RC_NEAR: return 1; +#ifdef _WIN64 + case MSVCRT__RC_UP: return 3; + default: return 2; +#else + case MSVCRT__RC_UP: return 2; + default: return 3; +#endif + } +} + +/********************************************************************* * _copysign (MSVCRT.@) */ double CDECL MSVCRT__copysign(double num, double sign) diff --git a/dlls/ucrtbase/tests/misc.c b/dlls/ucrtbase/tests/misc.c index 63ea465..bfdf3c1 100644 --- a/dlls/ucrtbase/tests/misc.c +++ b/dlls/ucrtbase/tests/misc.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <wchar.h> #include <stdio.h> +#include <float.h>
#include <windef.h> #include <winbase.h> @@ -38,6 +39,8 @@ typedef struct MSVCRT__onexit_table_t static int (CDECL *p_initialize_onexit_table)(MSVCRT__onexit_table_t *table); static int (CDECL *p_register_onexit_function)(MSVCRT__onexit_table_t *table, MSVCRT__onexit_t func); static int (CDECL *p_execute_onexit_table)(MSVCRT__onexit_table_t *table); +static int (CDECL *p___fpe_flt_rounds)(void); +static unsigned int (CDECL *p__controlfp)(unsigned int, unsigned int);
static void test__initialize_onexit_table(void) { @@ -211,20 +214,58 @@ static void test__execute_onexit_table(void) ok(g_onexit_called == 2, "got %d\n", g_onexit_called); }
-static void init(void) +static void test___fpe_flt_rounds(void) +{ + unsigned int cfp = p__controlfp(0, 0); + int ret; + + if(!cfp) { + skip("_controlfp not supported\n"); + return; + } + + ok((p__controlfp(_RC_NEAR, _RC_CHOP) & _RC_CHOP) == _RC_NEAR, "_controlfp(_RC_NEAR, _RC_CHOP) failed\n"); + ret = p___fpe_flt_rounds(); + ok(ret == 1, "__fpe_flt_rounds returned %d\n", ret); + + ok((p__controlfp(_RC_UP, _RC_CHOP) & _RC_CHOP) == _RC_UP, "_controlfp(_RC_UP, _RC_CHOP) failed\n"); + ret = p___fpe_flt_rounds(); + ok(ret == 2 + (sizeof(void*)>sizeof(int)), "__fpe_flt_rounds returned %d\n", ret); + + ok((p__controlfp(_RC_DOWN, _RC_CHOP) & _RC_CHOP) == _RC_DOWN, "_controlfp(_RC_DOWN, _RC_CHOP) failed\n"); + ret = p___fpe_flt_rounds(); + ok(ret == 3 - (sizeof(void*)>sizeof(int)), "__fpe_flt_rounds returned %d\n", ret); + + ok((p__controlfp(_RC_CHOP, _RC_CHOP) & _RC_CHOP) == _RC_CHOP, "_controlfp(_RC_CHOP, _RC_CHOP) failed\n"); + ret = p___fpe_flt_rounds(); + ok(ret == 0, "__fpe_flt_rounds returned %d\n", ret); +} + +static BOOL init(void) { HMODULE module = LoadLibraryA("ucrtbase.dll");
+ if(!module) { + win_skip("ucrtbase.dll not available\n"); + return FALSE; + } + p_initialize_onexit_table = (void*)GetProcAddress(module, "_initialize_onexit_table"); p_register_onexit_function = (void*)GetProcAddress(module, "_register_onexit_function"); p_execute_onexit_table = (void*)GetProcAddress(module, "_execute_onexit_table"); + p___fpe_flt_rounds = (void*)GetProcAddress(module, "__fpe_flt_rounds"); + p__controlfp = (void*)GetProcAddress(module, "_controlfp"); + + return TRUE; }
START_TEST(misc) { - init(); + if(!init()) + return;
test__initialize_onexit_table(); test__register_onexit_function(); test__execute_onexit_table(); + test___fpe_flt_rounds(); } diff --git a/dlls/ucrtbase/ucrtbase.spec b/dlls/ucrtbase/ucrtbase.spec index 9d65d3c..14ffa63 100644 --- a/dlls/ucrtbase/ucrtbase.spec +++ b/dlls/ucrtbase/ucrtbase.spec @@ -89,7 +89,7 @@ @ stub __dcrt_initial_narrow_environment @ cdecl __doserrno() MSVCRT___doserrno @ cdecl __dstbias() MSVCRT___p__dstbias -@ stub __fpe_flt_rounds +@ cdecl __fpe_flt_rounds() @ cdecl __fpecode() @ stub __initialize_lconv_for_unsigned_char @ stub __intrinsic_abnormal_termination