[PATCH] msvcr120/tests: Add tests for _statusfp[2].
Signed-off-by: Daniel Lehman <dlehman25(a)gmail.com> --- 2 test failures (f = 23.000000) are existing failures specific to Arabic locale: http://test.winehq.org/data/2201ca08fb03d069fa2ccf46773c150a6f7988bc/win10_n... --- dlls/msvcr120/tests/msvcr120.c | 63 ++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/dlls/msvcr120/tests/msvcr120.c b/dlls/msvcr120/tests/msvcr120.c index b3e3828156b..bccce182bed 100644 --- a/dlls/msvcr120/tests/msvcr120.c +++ b/dlls/msvcr120/tests/msvcr120.c @@ -86,6 +86,14 @@ static void init_thiscall_thunk(void) #define __thiscall __cdecl #endif +#if defined(__clang__) +#define DISABLE_OPT __attribute__((optnone)) +#elif defined(__GNUC__) +#define DISABLE_OPT __attribute__((optimize(0))) +#else +#define DISABLE_OPT +#endif + typedef unsigned char MSVCRT_bool; typedef struct cs_queue @@ -182,6 +190,8 @@ static int (CDECL *p_fegetenv)(fenv_t*); static int (CDECL *p_fesetenv)(const fenv_t*); static int (CDECL *p_fegetround)(void); static int (CDECL *p_fesetround)(int); +static unsigned int (CDECL *p__statusfp)(void); +static void (CDECL *p__statusfp2)(unsigned int*,unsigned int*); static int (CDECL *p__clearfp)(void); static _locale_t (__cdecl *p_wcreate_locale)(int, const wchar_t *); static void (__cdecl *p_free_locale)(_locale_t); @@ -258,6 +268,7 @@ static BOOL init(void) SET(p_fegetround, "fegetround"); SET(p_fesetround, "fesetround"); + SET(p__statusfp, "_statusfp"); SET(p__clearfp, "_clearfp"); SET(p_vsscanf, "vsscanf"); SET(p__Cbuild, "_Cbuild"); @@ -334,6 +345,8 @@ static BOOL init(void) SET(p__Condition_variable_notify_all, "?notify_all(a)_Condition_variable@details(a)Concurrency@@QAAXXZ"); #else + SET(p__statusfp2, "_statusfp2"); + SET(p_critical_section_ctor, "??0critical_section(a)Concurrency@@QAE(a)XZ"); SET(p_critical_section_dtor, @@ -785,10 +798,22 @@ static void test_critical_section(void) call_func1(p_critical_section_dtor, &cs); } -static void test_feenv(void) +static DISABLE_OPT void test_feenv(void) { + static const struct { + double num, denom; + int flag; + } tests[] = { + { 1.0, 10.0, FE_INEXACT }, + { DBL_MIN, DBL_MAX, FE_UNDERFLOW }, + { DBL_MAX, DBL_MIN, FE_OVERFLOW }, + { 1.0, 0.0, FE_DIVBYZERO }, + { 0.0, 0.0, FE_INVALID }, + }; + unsigned int x86f, sse2f; fenv_t env, env2; - int ret; + int i, ret, flags; + double res; p__clearfp(); @@ -806,6 +831,40 @@ static void test_feenv(void) ok(!ret, "fesetenv returned %x\n", ret); ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); + + if(p__statusfp2) { + x86f = sse2f = 0; + p__statusfp2(NULL, NULL); + + p__statusfp2(&x86f, NULL); + p__statusfp2(NULL, &sse2f); + + ok(!x86f, "p__statusfp2 set x86 %x\n", x86f); + ok(!sse2f, "p__statusfp2 set sse2 %x\n", sse2f); + } + + flags = 0; + for(i=0; i<ARRAY_SIZE(tests); i++) { + res = tests[i].num / tests[i].denom; + + flags |= tests[i].flag; + ret = p__statusfp(); + ok(ret == flags, "%d: p__statusfp returned %x\n", i, ret); + + if(p__statusfp2) { + x86f = sse2f = 0; + p__statusfp2(&x86f, &sse2f); + if(!sse2f) { + ok(!sse2f, "%d: p__statusfp2 set x86 %x\n", i, x86f); + ok(x86f == flags, "%d: p__statusfp2 set x86 %x\n", i, x86f); + }else { + ok(!x86f, "%d: p__statusfp2 set x86 %x\n", i, x86f); + ok(sse2f == flags, "%d: p__statusfp2 set sse2 %x\n", i, sse2f); + } + } + } + + p__clearfp(); } static void test__wcreate_locale(void) -- 2.25.1
Hi Daniel, On 2/4/21 8:17 AM, Daniel Lehman wrote:
-static void test_feenv(void) +static DISABLE_OPT void test_feenv(void) { + static const struct { + double num, denom; + int flag; + } tests[] = { + { 1.0, 10.0, FE_INEXACT }, + { DBL_MIN, DBL_MAX, FE_UNDERFLOW }, + { DBL_MAX, DBL_MIN, FE_OVERFLOW }, + { 1.0, 0.0, FE_DIVBYZERO }, + { 0.0, 0.0, FE_INVALID }, + }; + unsigned int x86f, sse2f; fenv_t env, env2; - int ret; + int i, ret, flags; + double res;
p__clearfp();
@@ -806,6 +831,40 @@ static void test_feenv(void) ok(!ret, "fesetenv returned %x\n", ret); ret = p_fegetround(); ok(ret == FE_TONEAREST, "Got unexpected round mode %#x.\n", ret); + + if(p__statusfp2) { + x86f = sse2f = 0; + p__statusfp2(NULL, NULL); + + p__statusfp2(&x86f, NULL); + p__statusfp2(NULL, &sse2f); + + ok(!x86f, "p__statusfp2 set x86 %x\n", x86f); + ok(!sse2f, "p__statusfp2 set sse2 %x\n", sse2f); + } + + flags = 0; + for(i=0; i<ARRAY_SIZE(tests); i++) { + res = tests[i].num / tests[i].denom; This doesn't look reliable. I guess you will need to go with some kind of assembly function to do the computation (or set status word directly). I'm not sure if it's worth it.
Thanks, Piotr
participants (2)
-
Daniel Lehman -
Piotr Caban