]>
Commit | Line | Data |
---|---|---|
abfbdde1 | 1 | /* Inline math functions for SPARC. |
0ecb606c JJ |
2 | Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 |
3 | Free Software Foundation, Inc. | |
abfbdde1 | 4 | This file is part of the GNU C Library. |
5e20fde1 | 5 | Contributed by Jakub Jelinek <jakub@redhat.com>. |
abfbdde1 UD |
6 | |
7 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
8 | modify it under the terms of the GNU Lesser General Public |
9 | License as published by the Free Software Foundation; either | |
10 | version 2.1 of the License, or (at your option) any later version. | |
abfbdde1 UD |
11 | |
12 | The GNU C Library is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
41bdb6e2 | 15 | Lesser General Public License for more details. |
abfbdde1 | 16 | |
41bdb6e2 AJ |
17 | You should have received a copy of the GNU Lesser General Public |
18 | License along with the GNU C Library; if not, write to the Free | |
19 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
20 | 02111-1307 USA. */ | |
abfbdde1 UD |
21 | |
22 | #ifndef _MATH_H | |
23 | # error "Never use <bits/mathinline.h> directly; include <math.h> instead." | |
24 | #endif | |
25 | ||
26 | #include <bits/wordsize.h> | |
27 | ||
6ac36398 UD |
28 | #ifdef __GNUC__ |
29 | ||
3dbfd811 | 30 | #if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0) |
f4c024d1 UD |
31 | # undef isgreater |
32 | # undef isgreaterequal | |
33 | # undef isless | |
34 | # undef islessequal | |
35 | # undef islessgreater | |
36 | # undef isunordered | |
abfbdde1 | 37 | |
4e735c9a | 38 | # if __WORDSIZE == 32 |
abfbdde1 | 39 | |
0ecb606c JJ |
40 | # ifndef __NO_LONG_DOUBLE_MATH |
41 | ||
42 | # define __unordered_cmp(x, y) \ | |
abfbdde1 UD |
43 | (__extension__ \ |
44 | ({ unsigned __r; \ | |
0ecb606c | 45 | if (sizeof (x) == 4 && sizeof (y) == 4) \ |
abfbdde1 UD |
46 | { \ |
47 | float __x = (x); float __y = (y); \ | |
0ecb606c JJ |
48 | __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ |
49 | "f" (__y) : "cc"); \ | |
50 | } \ | |
51 | else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ | |
52 | { \ | |
53 | double __x = (x); double __y = (y); \ | |
54 | __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ | |
55 | "f" (__y) : "cc"); \ | |
56 | } \ | |
57 | else \ | |
58 | { \ | |
59 | long double __x = (x); long double __y = (y); \ | |
60 | extern int _Q_cmp (const long double a, const long double b); \ | |
61 | __r = _Q_cmp (__x, __y) << 10; \ | |
62 | } \ | |
63 | __r; })) | |
64 | ||
65 | # else | |
66 | ||
67 | # define __unordered_cmp(x, y) \ | |
68 | (__extension__ \ | |
69 | ({ unsigned __r; \ | |
70 | if (sizeof (x) == 4 && sizeof (y) == 4) \ | |
71 | { \ | |
72 | float __x = (x); float __y = (y); \ | |
73 | __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ | |
74 | "f" (__y) : "cc"); \ | |
abfbdde1 UD |
75 | } \ |
76 | else \ | |
77 | { \ | |
78 | double __x = (x); double __y = (y); \ | |
0ecb606c JJ |
79 | __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ |
80 | "f" (__y) : "cc"); \ | |
abfbdde1 UD |
81 | } \ |
82 | __r; })) | |
83 | ||
0ecb606c JJ |
84 | # endif |
85 | ||
4e735c9a UD |
86 | # define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10)) |
87 | # define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0) | |
88 | # define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10)) | |
89 | # define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0) | |
90 | # define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0) | |
91 | # define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10)) | |
abfbdde1 | 92 | |
4e735c9a | 93 | # else /* sparc64 */ |
abfbdde1 | 94 | |
4e735c9a | 95 | # define __unordered_v9cmp(x, y, op, qop) \ |
abfbdde1 UD |
96 | (__extension__ \ |
97 | ({ unsigned __r; \ | |
0ecb606c | 98 | if (sizeof (x) == 4 && sizeof (y) == 4) \ |
abfbdde1 UD |
99 | { \ |
100 | float __x = (x); float __y = (y); \ | |
0ecb606c JJ |
101 | __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ |
102 | : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ | |
abfbdde1 | 103 | } \ |
0ecb606c | 104 | else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ |
abfbdde1 UD |
105 | { \ |
106 | double __x = (x); double __y = (y); \ | |
0ecb606c JJ |
107 | __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ |
108 | : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ | |
abfbdde1 UD |
109 | } \ |
110 | else \ | |
111 | { \ | |
112 | long double __x = (x); long double __y = (y); \ | |
0ecb606c | 113 | extern int _Qp_cmp (const long double *a, const long double *b); \ |
abfbdde1 UD |
114 | __r = qop; \ |
115 | } \ | |
116 | __r; })) | |
ec751a23 | 117 | |
4e735c9a UD |
118 | # define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2) |
119 | # define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0) | |
120 | # define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1) | |
121 | # define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0) | |
122 | # define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0) | |
123 | # define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3) | |
abfbdde1 | 124 | |
4e735c9a | 125 | # endif /* sparc64 */ |
abfbdde1 | 126 | |
ec751a23 | 127 | #endif /* __USE_ISOC99 */ |
abfbdde1 UD |
128 | |
129 | #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__ | |
130 | ||
4e735c9a UD |
131 | # ifdef __cplusplus |
132 | # define __MATH_INLINE __inline | |
133 | # else | |
134 | # define __MATH_INLINE extern __inline | |
135 | # endif /* __cplusplus */ | |
abfbdde1 UD |
136 | |
137 | /* The gcc, version 2.7 or below, has problems with all this inlining | |
138 | code. So disable it for this version of the compiler. */ | |
beaaf574 | 139 | # if __GNUC_PREREQ (2, 8) |
4e735c9a UD |
140 | |
141 | # ifdef __USE_ISOC99 | |
142 | ||
143 | /* Test for negative number. Used in the signbit() macro. */ | |
abfbdde1 | 144 | __MATH_INLINE int |
5ca3d19c | 145 | __NTH (__signbitf (float __x)) |
abfbdde1 UD |
146 | { |
147 | __extension__ union { float __f; int __i; } __u = { __f: __x }; | |
148 | return __u.__i < 0; | |
149 | } | |
150 | ||
4e735c9a | 151 | # if __WORDSIZE == 32 |
dbbbaf53 | 152 | |
abfbdde1 | 153 | __MATH_INLINE int |
5ca3d19c | 154 | __NTH (__signbit (double __x)) |
abfbdde1 UD |
155 | { |
156 | __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; | |
157 | return __u.__i[0] < 0; | |
158 | } | |
159 | ||
0ecb606c JJ |
160 | # ifndef __NO_LONG_DOUBLE_MATH |
161 | __MATH_INLINE int | |
162 | __NTH (__signbitl (long double __x)) | |
163 | { | |
164 | __extension__ union { long double __l; int __i[4]; } __u = { __l: __x }; | |
165 | return __u.__i[0] < 0; | |
166 | } | |
167 | # else | |
abfbdde1 | 168 | __MATH_INLINE int |
5ca3d19c | 169 | __NTH (__signbitl (long double __x)) |
abfbdde1 | 170 | { |
dbbbaf53 UD |
171 | return __signbit ((double)__x); |
172 | } | |
0ecb606c | 173 | # endif |
dbbbaf53 | 174 | |
4e735c9a | 175 | # else /* sparc64 */ |
dbbbaf53 UD |
176 | |
177 | __MATH_INLINE int | |
5ca3d19c | 178 | __NTH (__signbit (double __x)) |
dbbbaf53 | 179 | { |
4e735c9a | 180 | __extension__ union { double __d; long int __i; } __u = { __d: __x }; |
dbbbaf53 UD |
181 | return __u.__i < 0; |
182 | } | |
183 | ||
184 | __MATH_INLINE int | |
5ca3d19c | 185 | __NTH (__signbitl (long double __x)) |
dbbbaf53 | 186 | { |
4e735c9a | 187 | __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x }; |
dbbbaf53 | 188 | return __u.__i[0] < 0; |
abfbdde1 UD |
189 | } |
190 | ||
4e735c9a | 191 | # endif /* sparc64 */ |
dbbbaf53 | 192 | |
4e735c9a UD |
193 | # endif /* __USE_ISOC99 */ |
194 | ||
3dbfd811 | 195 | # if !defined __NO_MATH_INLINES && !__GNUC_PREREQ (3, 2) |
7c5bb945 | 196 | |
abfbdde1 | 197 | __MATH_INLINE double |
5ca3d19c | 198 | __NTH (sqrt (double __x)) |
abfbdde1 UD |
199 | { |
200 | register double __r; | |
201 | __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); | |
202 | return __r; | |
203 | } | |
204 | ||
205 | __MATH_INLINE float | |
5ca3d19c | 206 | __NTH (sqrtf (float __x)) |
abfbdde1 UD |
207 | { |
208 | register float __r; | |
209 | __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); | |
210 | return __r; | |
211 | } | |
212 | ||
4e735c9a | 213 | # if __WORDSIZE == 64 |
abfbdde1 | 214 | __MATH_INLINE long double |
5ca3d19c | 215 | __NTH (sqrtl (long double __x)) |
abfbdde1 UD |
216 | { |
217 | long double __r; | |
4e735c9a UD |
218 | extern void _Qp_sqrt (long double *, __const__ long double *); |
219 | _Qp_sqrt (&__r, &__x); | |
abfbdde1 UD |
220 | return __r; |
221 | } | |
0ecb606c JJ |
222 | # elif !defined __NO_LONG_DOUBLE_MATH |
223 | __MATH_INLINE long double | |
224 | sqrtl (long double __x) __THROW | |
225 | { | |
226 | extern long double _Q_sqrt (__const__ long double); | |
227 | return _Q_sqrt (__x); | |
228 | } | |
4e735c9a | 229 | # endif /* sparc64 */ |
abfbdde1 | 230 | |
3dbfd811 | 231 | # endif /* !__NO_MATH_INLINES && !GCC 3.2+ */ |
7c5bb945 | 232 | |
abfbdde1 | 233 | /* This code is used internally in the GNU libc. */ |
4e735c9a | 234 | # ifdef __LIBC_INTERNAL_MATH_INLINES |
abfbdde1 | 235 | __MATH_INLINE double |
4e735c9a | 236 | __ieee754_sqrt (double __x) |
abfbdde1 UD |
237 | { |
238 | register double __r; | |
239 | __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); | |
240 | return __r; | |
241 | } | |
242 | ||
243 | __MATH_INLINE float | |
4e735c9a | 244 | __ieee754_sqrtf (float __x) |
abfbdde1 UD |
245 | { |
246 | register float __r; | |
247 | __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); | |
248 | return __r; | |
249 | } | |
250 | ||
4e735c9a | 251 | # if __WORDSIZE == 64 |
abfbdde1 | 252 | __MATH_INLINE long double |
4e735c9a | 253 | __ieee754_sqrtl (long double __x) |
abfbdde1 UD |
254 | { |
255 | long double __r; | |
4e735c9a | 256 | extern void _Qp_sqrt (long double *, __const__ long double *); |
abfbdde1 UD |
257 | _Qp_sqrt(&__r, &__x); |
258 | return __r; | |
259 | } | |
0ecb606c JJ |
260 | # elif !defined __NO_LONG_DOUBLE_MATH |
261 | __MATH_INLINE long double | |
262 | __ieee754_sqrtl (long double __x) | |
263 | { | |
264 | extern long double _Q_sqrt (__const__ long double); | |
265 | return _Q_sqrt (__x); | |
266 | } | |
4e735c9a UD |
267 | # endif /* sparc64 */ |
268 | # endif /* __LIBC_INTERNAL_MATH_INLINES */ | |
269 | # endif /* gcc 2.8+ */ | |
abfbdde1 | 270 | |
4e735c9a | 271 | # ifdef __USE_ISOC99 |
abfbdde1 | 272 | |
4e735c9a | 273 | # ifndef __NO_MATH_INLINES |
7c5bb945 | 274 | |
5ca3d19c | 275 | __MATH_INLINE double __NTH (fdim (double __x, double __y)); |
abfbdde1 | 276 | __MATH_INLINE double |
5ca3d19c | 277 | __NTH (fdim (double __x, double __y)) |
abfbdde1 | 278 | { |
8930fcf9 | 279 | return __x <= __y ? 0 : __x - __y; |
abfbdde1 UD |
280 | } |
281 | ||
5ca3d19c | 282 | __MATH_INLINE float __NTH (fdimf (float __x, float __y)); |
abfbdde1 | 283 | __MATH_INLINE float |
5ca3d19c | 284 | __NTH (fdimf (float __x, float __y)) |
abfbdde1 | 285 | { |
8930fcf9 | 286 | return __x <= __y ? 0 : __x - __y; |
abfbdde1 UD |
287 | } |
288 | ||
4e735c9a UD |
289 | # endif /* !__NO_MATH_INLINES */ |
290 | # endif /* __USE_ISOC99 */ | |
abfbdde1 UD |
291 | #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ |
292 | #endif /* __GNUC__ */ |