1 2 /* Tests out of range handling for FSIN, FCOS, FSINCOS and FPTAN. Be 3 careful with the inline assembly -- this program is compiled as 4 both a 32-bit and 64-bit test. */ 5 6 #include <stdio.h> 7 #include <string.h> 8 #include <assert.h> 9 10 typedef unsigned short int UShort; 11 typedef unsigned int UInt; 12 typedef double Double; 13 typedef unsigned long long int ULong; 14 15 typedef struct { Double arg; Double st0; Double st1; UShort fpusw; } Res; 16 17 #define SHIFT_C3 14 18 #define SHIFT_C2 10 19 #define SHIFT_C1 9 20 #define SHIFT_C0 8 21 22 23 #define my_offsetof(type,memb) ((int)(unsigned long int)&((type*)0)->memb) 24 25 void do_fsin ( /*OUT*/Res* r, double d ) 26 { 27 assert(my_offsetof(Res,arg) == 0); 28 assert(my_offsetof(Res,st0) == 8); 29 assert(my_offsetof(Res,st1) == 16); 30 assert(my_offsetof(Res,fpusw) == 24); 31 memset(r, 0, sizeof(*r)); 32 r->arg = d; 33 __asm__ __volatile__( 34 "finit" "\n\t" 35 "fldpi" "\n\t" 36 "fldl 0(%0)" "\n\t" // .arg 37 "fsin" "\n\t" 38 "fstsw %%ax" "\n\t" 39 "fstpl 8(%0)" "\n\t" // .st0 40 "fstpl 16(%0)" "\n\t" // .st1 41 "movw %%ax, 24(%0)" "\n\t" // .fpusw 42 "finit" "\n" 43 : : "r"(r) : "eax","cc","memory" 44 ); 45 } 46 47 void do_fcos ( /*OUT*/Res* r, double d ) 48 { 49 assert(my_offsetof(Res,arg) == 0); 50 assert(my_offsetof(Res,st0) == 8); 51 assert(my_offsetof(Res,st1) == 16); 52 assert(my_offsetof(Res,fpusw) == 24); 53 memset(r, 0, sizeof(*r)); 54 r->arg = d; 55 __asm__ __volatile__( 56 "finit" "\n\t" 57 "fldpi" "\n\t" 58 "fldl 0(%0)" "\n\t" // .arg 59 "fcos" "\n\t" 60 "fstsw %%ax" "\n\t" 61 "fstpl 8(%0)" "\n\t" // .st0 62 "fstpl 16(%0)" "\n\t" // .st1 63 "movw %%ax, 24(%0)" "\n\t" // .fpusw 64 "finit" "\n" 65 : : "r"(r) : "eax","cc","memory" 66 ); 67 } 68 69 void do_fsincos ( /*OUT*/Res* r, double d ) 70 { 71 assert(my_offsetof(Res,arg) == 0); 72 assert(my_offsetof(Res,st0) == 8); 73 assert(my_offsetof(Res,st1) == 16); 74 assert(my_offsetof(Res,fpusw) == 24); 75 memset(r, 0, sizeof(*r)); 76 r->arg = d; 77 __asm__ __volatile__( 78 "finit" "\n\t" 79 "fldpi" "\n\t" 80 "fldl 0(%0)" "\n\t" // .arg 81 "fsincos" "\n\t" 82 "fstsw %%ax" "\n\t" 83 "fstpl 8(%0)" "\n\t" // .st0 84 "fstpl 16(%0)" "\n\t" // .st1 85 "movw %%ax, 24(%0)" "\n\t" // .fpusw 86 "finit" "\n" 87 : : "r"(r) : "eax","cc","memory" 88 ); 89 } 90 91 void do_fptan ( /*OUT*/Res* r, double d ) 92 { 93 assert(my_offsetof(Res,arg) == 0); 94 assert(my_offsetof(Res,st0) == 8); 95 assert(my_offsetof(Res,st1) == 16); 96 assert(my_offsetof(Res,fpusw) == 24); 97 memset(r, 0, sizeof(*r)); 98 r->arg = d; 99 __asm__ __volatile__( 100 "finit" "\n\t" 101 "fldpi" "\n\t" 102 "fldl 0(%0)" "\n\t" // .arg 103 "fptan" "\n\t" 104 "fstsw %%ax" "\n\t" 105 "fstpl 8(%0)" "\n\t" // .st0 106 "fstpl 16(%0)" "\n\t" // .st1 107 "movw %%ax, 24(%0)" "\n\t" // .fpusw 108 "finit" "\n" 109 : : "r"(r) : "eax","cc","memory" 110 ); 111 } 112 113 114 void try ( char* name, void(*fn)(Res*,double), double d ) 115 { 116 Res r; 117 fn(&r, d); 118 // Mask out all except C2 (range) 119 r.fpusw &= (1 << SHIFT_C2); 120 printf("%s %16e --> %16e %16e %04x\n", 121 name, r.arg, r.st0, r.st1, (UInt)r.fpusw); 122 } 123 124 int main ( void ) 125 { 126 Double limit = 9223372036854775808.0; // 2^63 127 128 char* names[4] = { "fsin ", "fcos ", "fsincos", "fptan " }; 129 void(*fns[4])(Res*,double) = { do_fsin, do_fcos, do_fsincos, do_fptan }; 130 131 int i; 132 for (i = 0; i < 4; i++) { 133 char* name = names[i]; 134 void (*fn)(Res*,double) = fns[i]; 135 136 try( name, fn, 0.0 ); 137 try( name, fn, 0.123 ); 138 try( name, fn, -0.456 ); 139 try( name, fn, 37.0 ); 140 try( name, fn, -53.0 ); 141 printf("\n"); 142 143 try( name, fn, limit * 0.900000 ); 144 try( name, fn, limit * 0.999999 ); 145 try( name, fn, limit * 1.000000 ); 146 try( name, fn, limit * 1.000001 ); 147 try( name, fn, limit * 1.100000 ); 148 printf("\n"); 149 150 try( name, fn, -limit * 0.900000 ); 151 try( name, fn, -limit * 0.999999 ); 152 try( name, fn, -limit * 1.000000 ); 153 try( name, fn, -limit * 1.000001 ); 154 try( name, fn, -limit * 1.100000 ); 155 printf("\n"); 156 } 157 158 return 0; 159 } 160