]>
Commit | Line | Data |
---|---|---|
3e336a87 UD |
1 | #ifndef _MATH_PRIVATE_H |
2 | ||
3 | #define math_opt_barrier(x) \ | |
4 | ({ __typeof(x) __x; \ | |
5 | if (sizeof (x) <= sizeof (double)) \ | |
6 | __asm ("" : "=x" (__x) : "0" (x)); \ | |
7 | else \ | |
8 | __asm ("" : "=t" (__x) : "0" (x)); \ | |
9 | __x; }) | |
10 | #define math_force_eval(x) \ | |
11 | do \ | |
12 | { \ | |
13 | if (sizeof (x) <= sizeof (double)) \ | |
14 | __asm __volatile ("" : : "x" (x)); \ | |
15 | else \ | |
16 | __asm __volatile ("" : : "f" (x)); \ | |
17 | } \ | |
18 | while (0) | |
19 | ||
20 | #include <math/math_private.h> | |
9a1ea152 UD |
21 | |
22 | /* We can do a few things better on x86-64. */ | |
23 | ||
cf00cc00 UD |
24 | /* Direct movement of float into integer register. */ |
25 | #undef EXTRACT_WORDS64 | |
26 | #define EXTRACT_WORDS64(i,d) \ | |
27 | do { \ | |
28 | long int i_; \ | |
29 | asm ("movd %1, %0" : "=rm" (i_) : "x" (d)); \ | |
30 | (i) = i_; \ | |
31 | } while (0) | |
32 | ||
33 | /* And the reverse. */ | |
34 | #undef INSERT_WORDS64 | |
35 | #define INSERT_WORDS64(d,i) \ | |
36 | do { \ | |
37 | long int i_ = i; \ | |
38 | asm ("movd %1, %0" : "=x" (d) : "rm" (i_)); \ | |
39 | } while (0) | |
40 | ||
9a1ea152 UD |
41 | /* Direct movement of float into integer register. */ |
42 | #undef GET_FLOAT_WORD | |
43 | #define GET_FLOAT_WORD(i,d) \ | |
44 | do { \ | |
45 | int i_; \ | |
46 | asm ("movd %1, %0" : "=rm" (i_) : "x" (d)); \ | |
47 | (i) = i_; \ | |
48 | } while (0) | |
49 | ||
50 | /* And the reverse. */ | |
51 | #undef SET_FLOAT_WORD | |
52 | #define SET_FLOAT_WORD(d,i) \ | |
53 | do { \ | |
54 | int i_ = i; \ | |
55 | asm ("movd %1, %0" : "=x" (d) : "rm" (i_)); \ | |
56 | } while (0) | |
57 | ||
3e336a87 | 58 | #endif |
7edb55ce UD |
59 | |
60 | #define __isnan(d) \ | |
c8553a6a | 61 | ({ long int __di; EXTRACT_WORDS64 (__di, (double) (d)); \ |
7edb55ce UD |
62 | (__di & 0x7fffffffffffffffl) > 0x7ff0000000000000l; }) |
63 | #define __isnanf(d) \ | |
0ac5ae23 | 64 | ({ int __di; GET_FLOAT_WORD (__di, (float) d); \ |
7edb55ce UD |
65 | (__di & 0x7fffffff) > 0x7f800000; }) |
66 | ||
67 | #define __isinf_ns(d) \ | |
c8553a6a | 68 | ({ long int __di; EXTRACT_WORDS64 (__di, (double) (d)); \ |
7edb55ce UD |
69 | (__di & 0x7fffffffffffffffl) == 0x7ff0000000000000l; }) |
70 | #define __isinf_nsf(d) \ | |
0ac5ae23 | 71 | ({ int __di; GET_FLOAT_WORD (__di, (float) d); \ |
7edb55ce UD |
72 | (__di & 0x7fffffff) == 0x7f800000; }) |
73 | ||
74 | #define __finite(d) \ | |
c8553a6a | 75 | ({ long int __di; EXTRACT_WORDS64 (__di, (double) (d)); \ |
7edb55ce UD |
76 | (__di & 0x7fffffffffffffffl) < 0x7ff0000000000000l; }) |
77 | #define __finitef(d) \ | |
0ac5ae23 | 78 | ({ int __di; GET_FLOAT_WORD (__di, (float) d); \ |
7edb55ce | 79 | (__di & 0x7fffffff) < 0x7f800000; }) |
0ac5ae23 UD |
80 | |
81 | #define __ieee754_sqrt(d) \ | |
82 | ({ double __res; \ | |
c8553a6a | 83 | asm ("sqrtsd %1, %0" : "=x" (__res) : "xm" ((double) (d))); \ |
0ac5ae23 UD |
84 | __res; }) |
85 | #define __ieee754_sqrtf(d) \ | |
86 | ({ float __res; \ | |
c8553a6a | 87 | asm ("sqrtss %1, %0" : "=x" (__res) : "xm" ((float) (d))); \ |
0ac5ae23 UD |
88 | __res; }) |
89 | #define __ieee754_sqrtl(d) \ | |
90 | ({ long double __res; \ | |
c8553a6a | 91 | asm ("fsqrt" : "=t" (__res) : "0" ((long double) (d))); \ |
0ac5ae23 | 92 | __res; }) |
ed22dcf6 UD |
93 | |
94 | #ifdef __SSE4_1__ | |
95 | # ifndef __rint | |
96 | # define __rint(d) \ | |
97 | ({ double __res; \ | |
228a984d | 98 | asm ("roundsd $4, %1, %0" : "=x" (__res) : "xm" ((double) (d))); \ |
ed22dcf6 UD |
99 | __res; }) |
100 | # endif | |
101 | # ifndef __rintf | |
102 | # define __rintf(d) \ | |
103 | ({ float __res; \ | |
228a984d | 104 | asm ("roundss $4, %1, %0" : "=x" (__res) : "xm" ((float) (d))); \ |
ed22dcf6 UD |
105 | __res; }) |
106 | # endif | |
107 | ||
108 | # ifndef __floor | |
109 | # define __floor(d) \ | |
110 | ({ double __res; \ | |
228a984d | 111 | asm ("roundsd $1, %1, %0" : "=x" (__res) : "xm" ((double) (d))); \ |
ed22dcf6 UD |
112 | __res; }) |
113 | # endif | |
114 | # ifndef __floorf | |
115 | # define __floorf(d) \ | |
116 | ({ float __res; \ | |
228a984d | 117 | asm ("roundss $1, %1, %0" : "=x" (__res) : "xm" ((float) (d))); \ |
ed22dcf6 UD |
118 | __res; }) |
119 | # endif | |
120 | #endif | |
d38f1dba UD |
121 | |
122 | ||
123 | /* Specialized variants of the <fenv.h> interfaces which only handle | |
124 | either the FPU or the SSE unit. */ | |
125 | #undef libc_fegetround | |
126 | #define libc_fegetround() \ | |
127 | ({ \ | |
128 | unsigned int mxcsr; \ | |
129 | asm volatile ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
130 | (mxcsr & 0x6000) >> 3; \ | |
131 | }) | |
d9a8d0ab UD |
132 | #undef libc_fegetroundf |
133 | #define libc_fegetroundf() libc_fegetround () | |
d38f1dba UD |
134 | // #define libc_fegetroundl() fegetround () |
135 | ||
136 | #undef libc_fesetround | |
137 | #define libc_fesetround(r) \ | |
138 | do { \ | |
139 | unsigned int mxcsr; \ | |
140 | asm ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
141 | mxcsr = (mxcsr & ~0x6000) | ((r) << 3); \ | |
142 | asm volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); \ | |
143 | } while (0) | |
d9a8d0ab UD |
144 | #undef libc_fesetroundf |
145 | #define libc_fesetroundf(r) libc_fesetround (r) | |
d38f1dba UD |
146 | // #define libc_fesetroundl(r) (void) fesetround (r) |
147 | ||
148 | #undef libc_feholdexcept | |
149 | #define libc_feholdexcept(e) \ | |
4855e3dd | 150 | do { \ |
d38f1dba UD |
151 | unsigned int mxcsr; \ |
152 | asm ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
153 | (e)->__mxcsr = mxcsr; \ | |
154 | mxcsr = (mxcsr | 0x1f80) & ~0x3f; \ | |
155 | asm volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); \ | |
156 | } while (0) | |
d9a8d0ab UD |
157 | #undef libc_feholdexceptf |
158 | #define libc_feholdexceptf(e) libc_feholdexcept (e) | |
d38f1dba UD |
159 | // #define libc_feholdexceptl(e) (void) feholdexcept (e) |
160 | ||
4855e3dd UD |
161 | #undef libc_feholdexcept_setround |
162 | #define libc_feholdexcept_setround(e, r) \ | |
163 | do { \ | |
164 | unsigned int mxcsr; \ | |
165 | asm ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
166 | (e)->__mxcsr = mxcsr; \ | |
167 | mxcsr = ((mxcsr | 0x1f80) & ~0x603f) | ((r) << 3); \ | |
168 | asm volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); \ | |
169 | } while (0) | |
d9a8d0ab UD |
170 | #undef libc_feholdexcept_setroundf |
171 | #define libc_feholdexcept_setroundf(e, r) libc_feholdexcept_setround (e, r) | |
4855e3dd UD |
172 | // #define libc_feholdexcept_setroundl(e, r) ... |
173 | ||
d9a8d0ab UD |
174 | #undef libc_fetestexcept |
175 | #define libc_fetestexcept(e) \ | |
176 | ({ unsigned int mxcsr; asm volatile ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
177 | mxcsr & (e) & FE_ALL_EXCEPT; }) | |
178 | #undef libc_fetestexceptf | |
179 | #define libc_fetestexceptf(e) libc_fetestexcept (e) | |
180 | // #define libc_fetestexceptl(e) fetestexcept (e) | |
181 | ||
d38f1dba UD |
182 | #undef libc_fesetenv |
183 | #define libc_fesetenv(e) \ | |
184 | asm volatile ("ldmxcsr %0" : : "m" ((e)->__mxcsr)) | |
d9a8d0ab UD |
185 | #undef libc_fesetenvf |
186 | #define libc_fesetenvf(e) libc_fesetenv (e) | |
d38f1dba | 187 | // #define libc_fesetenvl(e) (void) fesetenv (e) |
d9a8d0ab UD |
188 | |
189 | #undef libc_feupdateenv | |
190 | #define libc_feupdateenv(e) \ | |
191 | do { \ | |
192 | unsigned int mxcsr; \ | |
193 | asm volatile ("stmxcsr %0" : "=m" (*&mxcsr)); \ | |
194 | asm volatile ("ldmxcsr %0" : : "m" ((e)->__mxcsr)); \ | |
8f3b1ffe | 195 | __feraiseexcept (mxcsr & FE_ALL_EXCEPT); \ |
d9a8d0ab UD |
196 | } while (0) |
197 | #undef libc_feupdateenvf | |
198 | #define libc_feupdateenvf(e) libc_feupdateenv (e) | |
199 | // #define libc_feupdateenvl(e) (void) feupdateenv (e) |