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; | ... | ... |