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. */
10 typedef unsigned short int UShort
;
11 typedef unsigned int UInt
;
12 typedef double Double
;
13 typedef unsigned long long int ULong
;
15 typedef struct { Double arg
; Double st0
; Double st1
; UShort fpusw
; } Res
;
23 #define my_offsetof(type,memb) ((int)(unsigned long int)&((type*)0)->memb)
25 void do_fsin ( /*OUT*/Res
* r
, double d
)
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
));
36 "fldl 0(%0)" "\n\t" // .arg
39 "fstpl 8(%0)" "\n\t" // .st0
40 "fstpl 16(%0)" "\n\t" // .st1
41 "movw %%ax, 24(%0)" "\n\t" // .fpusw
43 : : "r"(r
) : "eax","cc","memory"
47 void do_fcos ( /*OUT*/Res
* r
, double d
)
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
));
58 "fldl 0(%0)" "\n\t" // .arg
61 "fstpl 8(%0)" "\n\t" // .st0
62 "fstpl 16(%0)" "\n\t" // .st1
63 "movw %%ax, 24(%0)" "\n\t" // .fpusw
65 : : "r"(r
) : "eax","cc","memory"
69 void do_fsincos ( /*OUT*/Res
* r
, double d
)
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
));
80 "fldl 0(%0)" "\n\t" // .arg
83 "fstpl 8(%0)" "\n\t" // .st0
84 "fstpl 16(%0)" "\n\t" // .st1
85 "movw %%ax, 24(%0)" "\n\t" // .fpusw
87 : : "r"(r
) : "eax","cc","memory"
91 void do_fptan ( /*OUT*/Res
* r
, double d
)
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
));
102 "fldl 0(%0)" "\n\t" // .arg
105 "fstpl 8(%0)" "\n\t" // .st0
106 "fstpl 16(%0)" "\n\t" // .st1
107 "movw %%ax, 24(%0)" "\n\t" // .fpusw
109 : : "r"(r
) : "eax","cc","memory"
114 void try ( char* name
, void(*fn
)(Res
*,double), double 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
);
126 Double limit
= 9223372036854775808.0; // 2^63
128 char* names
[4] = { "fsin ", "fcos ", "fsincos", "fptan " };
129 void(*fns
[4])(Res
*,double) = { do_fsin
, do_fcos
, do_fsincos
, do_fptan
};
132 for (i
= 0; i
< 4; i
++) {
133 char* name
= names
[i
];
134 void (*fn
)(Res
*,double) = fns
[i
];
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 );
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 );
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 );