Commit 86bd2ca58a99c5dec1372809236640bcc8ede2cd
1 parent
8422b113
NaN tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1342 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
124 additions
and
58 deletions
tests/test-i386.c
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | #define TEST_CMOV 1 |
41 | 41 | #define TEST_FCOMI 1 |
42 | 42 | #else |
43 | +//#define TEST_SSE | |
43 | 44 | #define TEST_CMOV 0 |
44 | 45 | #define TEST_FCOMI 0 |
45 | 46 | #endif |
... | ... | @@ -697,6 +698,14 @@ void test_bsx(void) |
697 | 698 | |
698 | 699 | /**********************************************/ |
699 | 700 | |
701 | +union float64u { | |
702 | + double d; | |
703 | + uint64_t l; | |
704 | +}; | |
705 | + | |
706 | +union float64u q_nan = { .l = 0xFFF8000000000000 }; | |
707 | +union float64u s_nan = { .l = 0xFFF0000000000000 }; | |
708 | + | |
700 | 709 | void test_fops(double a, double b) |
701 | 710 | { |
702 | 711 | printf("a=%f b=%f a+b=%f\n", a, b, a + b); |
... | ... | @@ -718,28 +727,68 @@ void test_fops(double a, double b) |
718 | 727 | |
719 | 728 | } |
720 | 729 | |
730 | +void fpu_clear_exceptions(void) | |
731 | +{ | |
732 | + struct __attribute__((packed)) { | |
733 | + uint16_t fpuc; | |
734 | + uint16_t dummy1; | |
735 | + uint16_t fpus; | |
736 | + uint16_t dummy2; | |
737 | + uint16_t fptag; | |
738 | + uint16_t dummy3; | |
739 | + uint32_t ignored[4]; | |
740 | + long double fpregs[8]; | |
741 | + } float_env32; | |
742 | + | |
743 | + asm volatile ("fnstenv %0\n" : : "m" (float_env32)); | |
744 | + float_env32.fpus &= ~0x7f; | |
745 | + asm volatile ("fldenv %0\n" : : "m" (float_env32)); | |
746 | +} | |
747 | + | |
748 | +/* XXX: display exception bits when supported */ | |
749 | +#define FPUS_EMASK 0x0000 | |
750 | +//#define FPUS_EMASK 0x007f | |
751 | + | |
721 | 752 | void test_fcmp(double a, double b) |
722 | 753 | { |
723 | - printf("(%f<%f)=%d\n", | |
724 | - a, b, a < b); | |
725 | - printf("(%f<=%f)=%d\n", | |
726 | - a, b, a <= b); | |
727 | - printf("(%f==%f)=%d\n", | |
728 | - a, b, a == b); | |
729 | - printf("(%f>%f)=%d\n", | |
730 | - a, b, a > b); | |
731 | - printf("(%f<=%f)=%d\n", | |
732 | - a, b, a >= b); | |
754 | + long eflags, fpus; | |
755 | + | |
756 | + fpu_clear_exceptions(); | |
757 | + asm("fcom %2\n" | |
758 | + "fstsw %%ax\n" | |
759 | + : "=a" (fpus) | |
760 | + : "t" (a), "u" (b)); | |
761 | + printf("fcom(%f %f)=%04lx \n", | |
762 | + a, b, fpus & (0x4500 | FPUS_EMASK)); | |
763 | + fpu_clear_exceptions(); | |
764 | + asm("fucom %2\n" | |
765 | + "fstsw %%ax\n" | |
766 | + : "=a" (fpus) | |
767 | + : "t" (a), "u" (b)); | |
768 | + printf("fucom(%f %f)=%04lx\n", | |
769 | + a, b, fpus & (0x4500 | FPUS_EMASK)); | |
733 | 770 | if (TEST_FCOMI) { |
734 | - long eflags; | |
735 | 771 | /* test f(u)comi instruction */ |
736 | - asm("fcomi %2, %1\n" | |
772 | + fpu_clear_exceptions(); | |
773 | + asm("fcomi %3, %2\n" | |
774 | + "fstsw %%ax\n" | |
737 | 775 | "pushf\n" |
738 | 776 | "pop %0\n" |
739 | - : "=r" (eflags) | |
777 | + : "=r" (eflags), "=a" (fpus) | |
740 | 778 | : "t" (a), "u" (b)); |
741 | - printf("fcomi(%f %f)=%08lx\n", a, b, eflags & (CC_Z | CC_P | CC_C)); | |
779 | + printf("fcomi(%f %f)=%04lx %02lx\n", | |
780 | + a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); | |
781 | + fpu_clear_exceptions(); | |
782 | + asm("fucomi %3, %2\n" | |
783 | + "fstsw %%ax\n" | |
784 | + "pushf\n" | |
785 | + "pop %0\n" | |
786 | + : "=r" (eflags), "=a" (fpus) | |
787 | + : "t" (a), "u" (b)); | |
788 | + printf("fucomi(%f %f)=%04lx %02lx\n", | |
789 | + a, b, fpus & FPUS_EMASK, eflags & (CC_Z | CC_P | CC_C)); | |
742 | 790 | } |
791 | + fpu_clear_exceptions(); | |
743 | 792 | } |
744 | 793 | |
745 | 794 | void test_fcvt(double a) |
... | ... | @@ -907,6 +956,8 @@ void test_floats(void) |
907 | 956 | test_fcmp(2, -1); |
908 | 957 | test_fcmp(2, 2); |
909 | 958 | test_fcmp(2, 3); |
959 | + test_fcmp(2, q_nan.d); | |
960 | + test_fcmp(q_nan.d, -1); | |
910 | 961 | test_fcvt(0.5); |
911 | 962 | test_fcvt(-0.5); |
912 | 963 | test_fcvt(1.0/7.0); |
... | ... | @@ -2191,6 +2242,7 @@ void test_fxsave(void) |
2191 | 2242 | void test_sse(void) |
2192 | 2243 | { |
2193 | 2244 | XMMReg r, a, b; |
2245 | + int i; | |
2194 | 2246 | |
2195 | 2247 | MMX_OP2(punpcklbw); |
2196 | 2248 | MMX_OP2(punpcklwd); |
... | ... | @@ -2354,51 +2406,65 @@ void test_sse(void) |
2354 | 2406 | test_sse_comi(2, -1); |
2355 | 2407 | test_sse_comi(2, 2); |
2356 | 2408 | test_sse_comi(2, 3); |
2409 | + test_sse_comi(2, q_nan.d); | |
2410 | + test_sse_comi(q_nan.d, -1); | |
2411 | + | |
2412 | + for(i = 0; i < 2; i++) { | |
2413 | + a.s[0] = 2.7; | |
2414 | + a.s[1] = 3.4; | |
2415 | + a.s[2] = 4; | |
2416 | + a.s[3] = -6.3; | |
2417 | + b.s[0] = 45.7; | |
2418 | + b.s[1] = 353.4; | |
2419 | + b.s[2] = 4; | |
2420 | + b.s[3] = 56.3; | |
2421 | + if (i == 1) { | |
2422 | + a.s[0] = q_nan.d; | |
2423 | + b.s[3] = q_nan.d; | |
2424 | + } | |
2425 | + | |
2426 | + SSE_OPS(add); | |
2427 | + SSE_OPS(mul); | |
2428 | + SSE_OPS(sub); | |
2429 | + SSE_OPS(min); | |
2430 | + SSE_OPS(div); | |
2431 | + SSE_OPS(max); | |
2432 | + SSE_OPS(sqrt); | |
2433 | + SSE_OPS(cmpeq); | |
2434 | + SSE_OPS(cmplt); | |
2435 | + SSE_OPS(cmple); | |
2436 | + SSE_OPS(cmpunord); | |
2437 | + SSE_OPS(cmpneq); | |
2438 | + SSE_OPS(cmpnlt); | |
2439 | + SSE_OPS(cmpnle); | |
2440 | + SSE_OPS(cmpord); | |
2441 | + | |
2442 | + | |
2443 | + a.d[0] = 2.7; | |
2444 | + a.d[1] = -3.4; | |
2445 | + b.d[0] = 45.7; | |
2446 | + b.d[1] = -53.4; | |
2447 | + if (i == 1) { | |
2448 | + a.d[0] = q_nan.d; | |
2449 | + b.d[1] = q_nan.d; | |
2450 | + } | |
2451 | + SSE_OPD(add); | |
2452 | + SSE_OPD(mul); | |
2453 | + SSE_OPD(sub); | |
2454 | + SSE_OPD(min); | |
2455 | + SSE_OPD(div); | |
2456 | + SSE_OPD(max); | |
2457 | + SSE_OPD(sqrt); | |
2458 | + SSE_OPD(cmpeq); | |
2459 | + SSE_OPD(cmplt); | |
2460 | + SSE_OPD(cmple); | |
2461 | + SSE_OPD(cmpunord); | |
2462 | + SSE_OPD(cmpneq); | |
2463 | + SSE_OPD(cmpnlt); | |
2464 | + SSE_OPD(cmpnle); | |
2465 | + SSE_OPD(cmpord); | |
2466 | + } | |
2357 | 2467 | |
2358 | - a.s[0] = 2.7; | |
2359 | - a.s[1] = 3.4; | |
2360 | - a.s[2] = 4; | |
2361 | - a.s[3] = -6.3; | |
2362 | - b.s[0] = 45.7; | |
2363 | - b.s[1] = 353.4; | |
2364 | - b.s[2] = 4; | |
2365 | - b.s[3] = 56.3; | |
2366 | - SSE_OPS(add); | |
2367 | - SSE_OPS(mul); | |
2368 | - SSE_OPS(sub); | |
2369 | - SSE_OPS(min); | |
2370 | - SSE_OPS(div); | |
2371 | - SSE_OPS(max); | |
2372 | - SSE_OPS(sqrt); | |
2373 | - SSE_OPS(cmpeq); | |
2374 | - SSE_OPS(cmplt); | |
2375 | - SSE_OPS(cmple); | |
2376 | - SSE_OPS(cmpunord); | |
2377 | - SSE_OPS(cmpneq); | |
2378 | - SSE_OPS(cmpnlt); | |
2379 | - SSE_OPS(cmpnle); | |
2380 | - SSE_OPS(cmpord); | |
2381 | - | |
2382 | - a.d[0] = 2.7; | |
2383 | - a.d[1] = -3.4; | |
2384 | - b.d[0] = 45.7; | |
2385 | - b.d[1] = -53.4; | |
2386 | - SSE_OPD(add); | |
2387 | - SSE_OPD(mul); | |
2388 | - SSE_OPD(sub); | |
2389 | - SSE_OPD(min); | |
2390 | - SSE_OPD(div); | |
2391 | - SSE_OPD(max); | |
2392 | - SSE_OPD(sqrt); | |
2393 | - SSE_OPD(cmpeq); | |
2394 | - SSE_OPD(cmplt); | |
2395 | - SSE_OPD(cmple); | |
2396 | - SSE_OPD(cmpunord); | |
2397 | - SSE_OPD(cmpneq); | |
2398 | - SSE_OPD(cmpnlt); | |
2399 | - SSE_OPD(cmpnle); | |
2400 | - SSE_OPD(cmpord); | |
2401 | - | |
2402 | 2468 | /* float to float/int */ |
2403 | 2469 | a.s[0] = 2.7; |
2404 | 2470 | a.s[1] = 3.4; | ... | ... |