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