40 |
#define TEST_CMOV 1 |
#define TEST_CMOV 1 |
41 |
#define TEST_FCOMI 1 |
#define TEST_FCOMI 1 |
42 |
#else |
#else |
43 |
|
//#define TEST_SSE |
44 |
#define TEST_CMOV 0 |
#define TEST_CMOV 0 |
45 |
#define TEST_FCOMI 0 |
#define TEST_FCOMI 0 |
46 |
#endif |
#endif |
698 |
|
|
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 |
|
|
709 |
void test_fops(double a, double b) |
void test_fops(double a, double b) |
710 |
{ |
{ |
711 |
printf("a=%f b=%f a+b=%f\n", a, b, a + b); |
printf("a=%f b=%f a+b=%f\n", a, b, a + b); |
727 |
|
|
728 |
} |
} |
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 |
|
|
752 |
void test_fcmp(double a, double b) |
void test_fcmp(double a, double b) |
753 |
{ |
{ |
754 |
printf("(%f<%f)=%d\n", |
long eflags, fpus; |
755 |
a, b, a < b); |
|
756 |
printf("(%f<=%f)=%d\n", |
fpu_clear_exceptions(); |
757 |
a, b, a <= b); |
asm("fcom %2\n" |
758 |
printf("(%f==%f)=%d\n", |
"fstsw %%ax\n" |
759 |
a, b, a == b); |
: "=a" (fpus) |
760 |
printf("(%f>%f)=%d\n", |
: "t" (a), "u" (b)); |
761 |
a, b, a > b); |
printf("fcom(%f %f)=%04lx \n", |
762 |
printf("(%f<=%f)=%d\n", |
a, b, fpus & (0x4500 | FPUS_EMASK)); |
763 |
a, b, a >= b); |
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)); |
770 |
if (TEST_FCOMI) { |
if (TEST_FCOMI) { |
|
long eflags; |
|
771 |
/* test f(u)comi instruction */ |
/* test f(u)comi instruction */ |
772 |
asm("fcomi %2, %1\n" |
fpu_clear_exceptions(); |
773 |
|
asm("fcomi %3, %2\n" |
774 |
|
"fstsw %%ax\n" |
775 |
"pushf\n" |
"pushf\n" |
776 |
"pop %0\n" |
"pop %0\n" |
777 |
: "=r" (eflags) |
: "=r" (eflags), "=a" (fpus) |
778 |
: "t" (a), "u" (b)); |
: "t" (a), "u" (b)); |
779 |
printf("fcomi(%f %f)=%08lx\n", a, b, eflags & (CC_Z | CC_P | CC_C)); |
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)); |
790 |
} |
} |
791 |
|
fpu_clear_exceptions(); |
792 |
} |
} |
793 |
|
|
794 |
void test_fcvt(double a) |
void test_fcvt(double a) |
956 |
test_fcmp(2, -1); |
test_fcmp(2, -1); |
957 |
test_fcmp(2, 2); |
test_fcmp(2, 2); |
958 |
test_fcmp(2, 3); |
test_fcmp(2, 3); |
959 |
|
test_fcmp(2, q_nan.d); |
960 |
|
test_fcmp(q_nan.d, -1); |
961 |
test_fcvt(0.5); |
test_fcvt(0.5); |
962 |
test_fcvt(-0.5); |
test_fcvt(-0.5); |
963 |
test_fcvt(1.0/7.0); |
test_fcvt(1.0/7.0); |
2242 |
void test_sse(void) |
void test_sse(void) |
2243 |
{ |
{ |
2244 |
XMMReg r, a, b; |
XMMReg r, a, b; |
2245 |
|
int i; |
2246 |
|
|
2247 |
MMX_OP2(punpcklbw); |
MMX_OP2(punpcklbw); |
2248 |
MMX_OP2(punpcklwd); |
MMX_OP2(punpcklwd); |
2406 |
test_sse_comi(2, -1); |
test_sse_comi(2, -1); |
2407 |
test_sse_comi(2, 2); |
test_sse_comi(2, 2); |
2408 |
test_sse_comi(2, 3); |
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 |
|
} |
2467 |
|
|
|
a.s[0] = 2.7; |
|
|
a.s[1] = 3.4; |
|
|
a.s[2] = 4; |
|
|
a.s[3] = -6.3; |
|
|
b.s[0] = 45.7; |
|
|
b.s[1] = 353.4; |
|
|
b.s[2] = 4; |
|
|
b.s[3] = 56.3; |
|
|
SSE_OPS(add); |
|
|
SSE_OPS(mul); |
|
|
SSE_OPS(sub); |
|
|
SSE_OPS(min); |
|
|
SSE_OPS(div); |
|
|
SSE_OPS(max); |
|
|
SSE_OPS(sqrt); |
|
|
SSE_OPS(cmpeq); |
|
|
SSE_OPS(cmplt); |
|
|
SSE_OPS(cmple); |
|
|
SSE_OPS(cmpunord); |
|
|
SSE_OPS(cmpneq); |
|
|
SSE_OPS(cmpnlt); |
|
|
SSE_OPS(cmpnle); |
|
|
SSE_OPS(cmpord); |
|
|
|
|
|
a.d[0] = 2.7; |
|
|
a.d[1] = -3.4; |
|
|
b.d[0] = 45.7; |
|
|
b.d[1] = -53.4; |
|
|
SSE_OPD(add); |
|
|
SSE_OPD(mul); |
|
|
SSE_OPD(sub); |
|
|
SSE_OPD(min); |
|
|
SSE_OPD(div); |
|
|
SSE_OPD(max); |
|
|
SSE_OPD(sqrt); |
|
|
SSE_OPD(cmpeq); |
|
|
SSE_OPD(cmplt); |
|
|
SSE_OPD(cmple); |
|
|
SSE_OPD(cmpunord); |
|
|
SSE_OPD(cmpneq); |
|
|
SSE_OPD(cmpnlt); |
|
|
SSE_OPD(cmpnle); |
|
|
SSE_OPD(cmpord); |
|
|
|
|
2468 |
/* float to float/int */ |
/* float to float/int */ |
2469 |
a.s[0] = 2.7; |
a.s[0] = 2.7; |
2470 |
a.s[1] = 3.4; |
a.s[1] = 3.4; |