#include #include #include /* the test intends to test following insns. flds faddp fstps fstpl fldl fxch fabs fdivrp fmulp fsubrp fucomp fnstsw fsqrt fchs f2xm1 fyl2x fxtract fprem1 fld fdecstp fld1 fldl2t fldl2e FLDPI FLDLG2 FLDLN2 FLDZ fincstp ffree fptan fpatan fincstp fsincos frndint fscale fsin fcos fcmovb fcmovbe fcmove fcmovu fcmovnb fcmovnbe fsave frstor fstsw */ float no1,no2,no3,no4,no5,no6,no7; double x = 100.345, y = 25.7789; long double ldx = 88888888888888888888.88, ldy = 9999999999999999999.99; float result,resultd,resultld; float *float_memory; /* initialization of floats */ void init_floats() { no1 = 10.45; no2 = 20.77; no3 = 156.89874646; no4 = 14.56; no5 = 11.11; no6 = 66.77; no7 = 88.88; float_memory = malloc(sizeof(float) * 4); *float_memory = 256.256; *(float_memory + 1) = 356.356; *(float_memory + 2) = 456.456; *(float_memory + 3) = 556.556; } /* marks FPU stack as empty */ void empty_fpu_stack() { asm ("ffree %st(1) \n\t" "ffree %st(2) \n\t" "ffree %st(3) \n\t" "ffree %st(4) \n\t" "ffree %st(5) \n\t" "ffree %st(6) \n\t" "ffree %st(7)"); } /* tests floating point arithmatic */ void test_arith_floats() { result = no1 + no2 + no3 + no4 + no5 + no6 + no7; printf("result is %f\n",result); result = fmodf(no2,no1); printf("result is %f\n",result); resultd = fmod(x,y); printf("result is %f\n",resultd); resultld = fmodl(ldy,ldy); printf("result is %f\n",resultld); result = fabsf(no1); printf("result is %f\n",result); result = no3 / no4; printf("result is %f\n",result); result = no1 * no2 * no3 * no4; printf("result is %f\n",result); result = no1 - no2 - no3 - no4; printf("result is %f\n",result); asm ("fld %0" : :"m"(*float_memory)); asm ("fchs"); /* test for f2xm1 */ asm ("fld %0" : :"m"(*float_memory)); asm ("f2xm1"); asm ("fyl2x"); asm ("fld %0" : :"m"(*float_memory)); asm ("fxtract"); asm ("fld %0" : :"m"(*float_memory)); asm ("fprem1"); /* decrement fpu stack pointer only status register should get affected */ asm ("fld %0" : :"m"(*float_memory)); empty_fpu_stack(); asm ("fld1"); asm ("fldl2t"); asm ("fldl2e"); asm ("fldpi"); asm ("fldlg2"); asm ("fldln2"); asm ("fldz"); empty_fpu_stack(); /* finishing emptying the stack */ result = sqrt(no3); printf("result is %f\n",result); } void test_log_exp_floats() { result = log10(no3); printf("result is %f\n",result); result = log(no3); printf("result is %f\n",result); result = exp10(no3); printf("result is %f\n",result); result = exp(no3); printf("result is %f\n",result); } void test_trigo_floats() { result = sin(30); printf("result is %f\n",result); result = cos(30); printf("result is %f\n",result); result = tan(30); printf("result is %f\n",result); result = atan(30); printf("result is %f\n",result); asm ("fld %0" : :"m"(*float_memory)); asm ("fptan"); /* changes st1 and popping register stack */ asm ("fpatan"); asm("fincstp"); asm ("fld %0" : :"m"(float_memory)); asm ("fsincos"); asm ("fld %0" : :"m"(*float_memory)); asm ("frndint"); asm ("fld %0" : :"m"(*float_memory)); asm ("fld %0" : :"m"(*(float_memory+1))); asm ("fscale"); empty_fpu_stack(); asm ("fld %0" : :"m"(*float_memory)); asm ("fsin"); asm ("fcos"); /* currently we assume condition likely and always record the registers code could be optimized only if the flag is set then record */ asm ("fld %0" : :"m"(*float_memory)); asm ("fld %0" : :"m"(*(float_memory+1))); asm ("fcmovb %st(1), %st"); asm ("fcmovbe %st(1), %st"); asm ("fcmove %st(1), %st"); asm ("fcmovu %st(1), %st"); asm ("fcmovnb %st(1), %st"); asm ("fcmovnbe %st(1), %st"); empty_fpu_stack(); /* finished emtyping the stack */ } void test_compare_floats() { ldy = 88888888888888888888.88; if (ldx == ldy) ldy = 7777777777777777777777777777.777; else ldy = 666666666666666666666666666.666; } /* test loading and saving of FPU environment */ void test_fpu_env() { asm ("fsave %0" : "=m"(*float_memory) : ); asm ("frstor %0" : : "m"(*float_memory)); asm ("fstsw %ax"); } int main() { init_floats(); test_arith_floats(); test_log_exp_floats(); test_trigo_floats(); test_compare_floats(); test_fpu_env(); }