Signed-off-by: Daniel Lehman dlehman25@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@_Condition_variable@details@Concurrency@@QAAXXZ"); #else + SET(p__statusfp2, "_statusfp2"); + SET(p_critical_section_ctor, "??0critical_section@Concurrency@@QAE@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)
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