File: x87trigOOR.c

package info (click to toggle)
valgrind 1%3A3.12.0~svn20160714-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 120,428 kB
  • ctags: 70,855
  • sloc: ansic: 674,645; exp: 26,134; xml: 21,574; asm: 7,570; cpp: 7,567; makefile: 7,380; sh: 6,188; perl: 5,855; haskell: 195
file content (159 lines) | stat: -rw-r--r-- 4,453 bytes parent folder | download | duplicates (16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

/* Tests out of range handling for FSIN, FCOS, FSINCOS and FPTAN.  Be
   careful with the inline assembly -- this program is compiled as
   both a 32-bit and 64-bit test. */

#include <stdio.h>
#include <string.h>
#include <assert.h>

typedef  unsigned short int      UShort;
typedef  unsigned int            UInt;
typedef  double                  Double;
typedef  unsigned long long int  ULong;

typedef  struct { Double arg; Double st0; Double st1; UShort fpusw; }  Res;

#define SHIFT_C3   14
#define SHIFT_C2   10
#define SHIFT_C1   9
#define SHIFT_C0   8


#define my_offsetof(type,memb) ((int)(unsigned long int)&((type*)0)->memb)

void do_fsin ( /*OUT*/Res* r, double d )
{
   assert(my_offsetof(Res,arg) == 0);
   assert(my_offsetof(Res,st0) == 8);
   assert(my_offsetof(Res,st1) == 16);
   assert(my_offsetof(Res,fpusw) == 24);
   memset(r, 0, sizeof(*r));
   r->arg = d;
   __asm__ __volatile__(
     "finit"              "\n\t"
     "fldpi"              "\n\t"
     "fldl 0(%0)"         "\n\t" // .arg
     "fsin"               "\n\t"
     "fstsw %%ax"         "\n\t"
     "fstpl 8(%0)"        "\n\t" // .st0
     "fstpl 16(%0)"       "\n\t" // .st1
     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
     "finit"              "\n"
     : : "r"(r) : "eax","cc","memory"
   );
}

void do_fcos ( /*OUT*/Res* r, double d )
{
   assert(my_offsetof(Res,arg) == 0);
   assert(my_offsetof(Res,st0) == 8);
   assert(my_offsetof(Res,st1) == 16);
   assert(my_offsetof(Res,fpusw) == 24);
   memset(r, 0, sizeof(*r));
   r->arg = d;
   __asm__ __volatile__(
     "finit"              "\n\t"
     "fldpi"              "\n\t"
     "fldl 0(%0)"         "\n\t" // .arg
     "fcos"               "\n\t"
     "fstsw %%ax"         "\n\t"
     "fstpl 8(%0)"        "\n\t" // .st0
     "fstpl 16(%0)"       "\n\t" // .st1
     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
     "finit"              "\n"
     : : "r"(r) : "eax","cc","memory"
   );
}

void do_fsincos ( /*OUT*/Res* r, double d )
{
   assert(my_offsetof(Res,arg) == 0);
   assert(my_offsetof(Res,st0) == 8);
   assert(my_offsetof(Res,st1) == 16);
   assert(my_offsetof(Res,fpusw) == 24);
   memset(r, 0, sizeof(*r));
   r->arg = d;
   __asm__ __volatile__(
     "finit"              "\n\t"
     "fldpi"              "\n\t"
     "fldl 0(%0)"         "\n\t" // .arg
     "fsincos"            "\n\t"
     "fstsw %%ax"         "\n\t"
     "fstpl 8(%0)"        "\n\t" // .st0
     "fstpl 16(%0)"       "\n\t" // .st1
     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
     "finit"              "\n"
     : : "r"(r) : "eax","cc","memory"
   );
}

void do_fptan ( /*OUT*/Res* r, double d )
{
   assert(my_offsetof(Res,arg) == 0);
   assert(my_offsetof(Res,st0) == 8);
   assert(my_offsetof(Res,st1) == 16);
   assert(my_offsetof(Res,fpusw) == 24);
   memset(r, 0, sizeof(*r));
   r->arg = d;
   __asm__ __volatile__(
     "finit"              "\n\t"
     "fldpi"              "\n\t"
     "fldl 0(%0)"         "\n\t" // .arg
     "fptan"              "\n\t"
     "fstsw %%ax"         "\n\t"
     "fstpl 8(%0)"        "\n\t" // .st0
     "fstpl 16(%0)"       "\n\t" // .st1
     "movw %%ax, 24(%0)"  "\n\t" // .fpusw
     "finit"              "\n"
     : : "r"(r) : "eax","cc","memory"
   );
}


void try ( char* name, void(*fn)(Res*,double), double d )
{
   Res r;
   fn(&r, d);
   // Mask out all except C2 (range)
   r.fpusw &= (1 << SHIFT_C2);
   printf("%s  %16e --> %16e %16e %04x\n",
          name, r.arg, r.st0, r.st1, (UInt)r.fpusw);
}

int main ( void )
{
   Double limit = 9223372036854775808.0; // 2^63

   char* names[4] = { "fsin   ", "fcos   ", "fsincos", "fptan  " };
   void(*fns[4])(Res*,double) = { do_fsin, do_fcos, do_fsincos, do_fptan };

   int i;
   for (i = 0; i < 4; i++) {
      char* name = names[i];
      void (*fn)(Res*,double) = fns[i];

      try( name, fn,   0.0   );
      try( name, fn,   0.123 );
      try( name, fn,  -0.456 );
      try( name, fn,  37.0   );
      try( name, fn, -53.0   );
      printf("\n");

      try( name, fn, limit * 0.900000 );
      try( name, fn, limit * 0.999999 );
      try( name, fn, limit * 1.000000 );
      try( name, fn, limit * 1.000001 );
      try( name, fn, limit * 1.100000 );
      printf("\n");

      try( name, fn, -limit * 0.900000 );
      try( name, fn, -limit * 0.999999 );
      try( name, fn, -limit * 1.000000 );
      try( name, fn, -limit * 1.000001 );
      try( name, fn, -limit * 1.100000 );
      printf("\n");
   }

   return 0;
}