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,6 +40,7 @@ | ||
| 40 | #define TEST_CMOV 1 | 40 | #define TEST_CMOV 1 |
| 41 | #define TEST_FCOMI 1 | 41 | #define TEST_FCOMI 1 |
| 42 | #else | 42 | #else |
| 43 | +//#define TEST_SSE | ||
| 43 | #define TEST_CMOV 0 | 44 | #define TEST_CMOV 0 |
| 44 | #define TEST_FCOMI 0 | 45 | #define TEST_FCOMI 0 |
| 45 | #endif | 46 | #endif |
| @@ -697,6 +698,14 @@ void test_bsx(void) | @@ -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 | void test_fops(double a, double b) | 709 | void test_fops(double a, double b) |
| 701 | { | 710 | { |
| 702 | printf("a=%f b=%f a+b=%f\n", a, b, a + b); | 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,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 | void test_fcmp(double a, double b) | 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 | if (TEST_FCOMI) { | 770 | if (TEST_FCOMI) { |
| 734 | - long eflags; | ||
| 735 | /* test f(u)comi instruction */ | 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 | "pushf\n" | 775 | "pushf\n" |
| 738 | "pop %0\n" | 776 | "pop %0\n" |
| 739 | - : "=r" (eflags) | 777 | + : "=r" (eflags), "=a" (fpus) |
| 740 | : "t" (a), "u" (b)); | 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 | void test_fcvt(double a) | 794 | void test_fcvt(double a) |
| @@ -907,6 +956,8 @@ void test_floats(void) | @@ -907,6 +956,8 @@ void test_floats(void) | ||
| 907 | test_fcmp(2, -1); | 956 | test_fcmp(2, -1); |
| 908 | test_fcmp(2, 2); | 957 | test_fcmp(2, 2); |
| 909 | test_fcmp(2, 3); | 958 | test_fcmp(2, 3); |
| 959 | + test_fcmp(2, q_nan.d); | ||
| 960 | + test_fcmp(q_nan.d, -1); | ||
| 910 | test_fcvt(0.5); | 961 | test_fcvt(0.5); |
| 911 | test_fcvt(-0.5); | 962 | test_fcvt(-0.5); |
| 912 | test_fcvt(1.0/7.0); | 963 | test_fcvt(1.0/7.0); |
| @@ -2191,6 +2242,7 @@ void test_fxsave(void) | @@ -2191,6 +2242,7 @@ void test_fxsave(void) | ||
| 2191 | void test_sse(void) | 2242 | void test_sse(void) |
| 2192 | { | 2243 | { |
| 2193 | XMMReg r, a, b; | 2244 | XMMReg r, a, b; |
| 2245 | + int i; | ||
| 2194 | 2246 | ||
| 2195 | MMX_OP2(punpcklbw); | 2247 | MMX_OP2(punpcklbw); |
| 2196 | MMX_OP2(punpcklwd); | 2248 | MMX_OP2(punpcklwd); |
| @@ -2354,51 +2406,65 @@ void test_sse(void) | @@ -2354,51 +2406,65 @@ void test_sse(void) | ||
| 2354 | test_sse_comi(2, -1); | 2406 | test_sse_comi(2, -1); |
| 2355 | test_sse_comi(2, 2); | 2407 | test_sse_comi(2, 2); |
| 2356 | test_sse_comi(2, 3); | 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 | /* float to float/int */ | 2468 | /* float to float/int */ |
| 2403 | a.s[0] = 2.7; | 2469 | a.s[0] = 2.7; |
| 2404 | a.s[1] = 3.4; | 2470 | a.s[1] = 3.4; |