OSDN Git Service

9dd784d12293b33df945a31be763114992ee47a9
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / sparc / bits / mathinline.h
1 /* Inline math functions for SPARC.
2    Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006
3    Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5    Contributed by Jakub Jelinek <jakub@redhat.com>.
6
7    The GNU C Library is free software; you can redistribute it and/or
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.
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
15    Lesser General Public License for more details.
16
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.  */
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
28 #ifdef __GNUC__
29
30 #if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0)
31 # undef isgreater
32 # undef isgreaterequal
33 # undef isless
34 # undef islessequal
35 # undef islessgreater
36 # undef isunordered
37
38 # if __WORDSIZE == 32
39
40 #  ifndef __NO_LONG_DOUBLE_MATH
41
42 #   define __unordered_cmp(x, y) \
43   (__extension__                                                              \
44    ({ unsigned __r;                                                           \
45       if (sizeof (x) == 4 && sizeof (y) == 4)                                 \
46         {                                                                     \
47           float __x = (x); float __y = (y);                                   \
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");                                         \
75         }                                                                     \
76       else                                                                    \
77         {                                                                     \
78           double __x = (x); double __y = (y);                                 \
79           __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x),   \
80                    "f" (__y) : "cc");                                         \
81         }                                                                     \
82       __r; }))
83
84 #  endif
85
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))
92
93 # else /* sparc64 */
94
95 #  define __unordered_v9cmp(x, y, op, qop) \
96   (__extension__                                                              \
97    ({ unsigned __r;                                                           \
98       if (sizeof (x) == 4 && sizeof (y) == 4)                                 \
99         {                                                                     \
100           float __x = (x); float __y = (y);                                   \
101           __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"            \
102                    : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
103         }                                                                     \
104       else if (sizeof (x) <= 8 && sizeof (y) <= 8)                            \
105         {                                                                     \
106           double __x = (x); double __y = (y);                                 \
107           __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0"            \
108                    : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc");      \
109         }                                                                     \
110       else                                                                    \
111         {                                                                     \
112           long double __x = (x); long double __y = (y);                       \
113           extern int _Qp_cmp (const long double *a, const long double *b);    \
114           __r = qop;                                                          \
115         }                                                                     \
116       __r; }))
117
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)
124
125 # endif /* sparc64 */
126
127 #endif /* __USE_ISOC99 */
128
129 #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__
130
131 # ifdef __cplusplus
132 #  define __MATH_INLINE __inline
133 # else
134 #  define __MATH_INLINE extern __inline
135 # endif  /* __cplusplus */
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.  */
139 # if __GNUC_PREREQ (2, 8)
140
141 #  ifdef __USE_ISOC99
142
143 /* Test for negative number.  Used in the signbit() macro.  */
144 __MATH_INLINE int
145 __NTH (__signbitf (float __x))
146 {
147   __extension__ union { float __f; int __i; } __u = { __f: __x };
148   return __u.__i < 0;
149 }
150
151 #   if __WORDSIZE == 32
152
153 __MATH_INLINE int
154 __NTH (__signbit (double __x))
155 {
156   __extension__ union { double __d; int __i[2]; } __u = { __d: __x };
157   return __u.__i[0] < 0;
158 }
159
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
168 __MATH_INLINE int
169 __NTH (__signbitl (long double __x))
170 {
171   return __signbit ((double)__x);
172 }
173 #    endif
174
175 #   else /* sparc64 */
176
177 __MATH_INLINE int
178 __NTH (__signbit (double __x))
179 {
180   __extension__ union { double __d; long int __i; } __u = { __d: __x };
181   return __u.__i < 0;
182 }
183
184 __MATH_INLINE int
185 __NTH (__signbitl (long double __x))
186 {
187   __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x };
188   return __u.__i[0] < 0;
189 }
190
191 #   endif /* sparc64 */
192
193 #  endif /* __USE_ISOC99 */
194
195 #  if !defined __NO_MATH_INLINES && !__GNUC_PREREQ (3, 2)
196
197 __MATH_INLINE double
198 __NTH (sqrt (double __x))
199 {
200   register double __r;
201   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
202   return __r;
203 }
204
205 __MATH_INLINE float
206 __NTH (sqrtf (float __x))
207 {
208   register float __r;
209   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
210   return __r;
211 }
212
213 #   if __WORDSIZE == 64
214 __MATH_INLINE long double
215 __NTH (sqrtl (long double __x))
216 {
217   long double __r;
218   extern void _Qp_sqrt (long double *, __const__ long double *);
219   _Qp_sqrt (&__r, &__x);
220   return __r;
221 }
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 }
229 #   endif /* sparc64 */
230
231 #  endif /* !__NO_MATH_INLINES && !GCC 3.2+ */
232
233 /* This code is used internally in the GNU libc.  */
234 #  ifdef __LIBC_INTERNAL_MATH_INLINES
235 __MATH_INLINE double
236 __ieee754_sqrt (double __x)
237 {
238   register double __r;
239   __asm ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x));
240   return __r;
241 }
242
243 __MATH_INLINE float
244 __ieee754_sqrtf (float __x)
245 {
246   register float __r;
247   __asm ("fsqrts %1,%0" : "=f" (__r) : "f" (__x));
248   return __r;
249 }
250
251 #   if __WORDSIZE == 64
252 __MATH_INLINE long double
253 __ieee754_sqrtl (long double __x)
254 {
255   long double __r;
256   extern void _Qp_sqrt (long double *, __const__ long double *);
257   _Qp_sqrt(&__r, &__x);
258   return __r;
259 }
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 }
267 #   endif /* sparc64 */
268 #  endif /* __LIBC_INTERNAL_MATH_INLINES */
269 # endif /* gcc 2.8+ */
270
271 # ifdef __USE_ISOC99
272
273 #  ifndef __NO_MATH_INLINES
274
275 __MATH_INLINE double __NTH (fdim (double __x, double __y));
276 __MATH_INLINE double
277 __NTH (fdim (double __x, double __y))
278 {
279   return __x <= __y ? 0 : __x - __y;
280 }
281
282 __MATH_INLINE float __NTH (fdimf (float __x, float __y));
283 __MATH_INLINE float
284 __NTH (fdimf (float __x, float __y))
285 {
286   return __x <= __y ? 0 : __x - __y;
287 }
288
289 #  endif /* !__NO_MATH_INLINES */
290 # endif /* __USE_ISOC99 */
291 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
292 #endif /* __GNUC__ */