OSDN Git Service

f3166000dad0fce7f57a9e709dfd54b6caf2a7a2
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / m68k / bits / mathinline.h
1 /* Definitions of inline math functions implemented by the m68881/2.
2    Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002, 2003, 2004
3      Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 #ifdef  __GNUC__
22
23 #ifdef __USE_ISOC99
24 /* GCC 3.1 and up have builtins that actually can be used.  */
25 # if !__GNUC_PREREQ (3,1)
26 /* ISO C99 defines some macros to perform unordered comparisons.  The
27    m68k FPU supports this with special opcodes and we should use them.
28    These must not be inline functions since we have to be able to handle
29    all floating-point types.  */
30 #  undef isgreater
31 #  undef isgreaterequal
32 #  undef isless
33 #  undef islessequal
34 #  undef islessgreater
35 #  undef isunordered
36 #  define isgreater(x, y)                                       \
37    __extension__                                        \
38    ({ char __result;                                    \
39       __asm__ ("fcmp%.x %2,%1; fsogt %0"                \
40                : "=dm" (__result) : "f" (x), "f" (y));  \
41       __result != 0; })
42
43 #  define isgreaterequal(x, y)                          \
44    __extension__                                        \
45    ({ char __result;                                    \
46       __asm__ ("fcmp%.x %2,%1; fsoge %0"                \
47                : "=dm" (__result) : "f" (x), "f" (y));  \
48       __result != 0; })
49
50 #  define isless(x, y)                                  \
51    __extension__                                        \
52    ({ char __result;                                    \
53       __asm__ ("fcmp%.x %2,%1; fsolt %0"                \
54                : "=dm" (__result) : "f" (x), "f" (y));  \
55       __result != 0; })
56
57 #  define islessequal(x, y)                             \
58    __extension__                                        \
59    ({ char __result;                                    \
60       __asm__ ("fcmp%.x %2,%1; fsole %0"                \
61                : "=dm" (__result) : "f" (x), "f" (y));  \
62       __result != 0; })
63
64 #  define islessgreater(x, y)                           \
65    __extension__                                        \
66    ({ char __result;                                    \
67       __asm__ ("fcmp%.x %2,%1; fsogl %0"                \
68                : "=dm" (__result) : "f" (x), "f" (y));  \
69       __result != 0; })
70
71 #  define isunordered(x, y)                             \
72    __extension__                                        \
73    ({ char __result;                                    \
74       __asm__ ("fcmp%.x %2,%1; fsun %0"                 \
75                : "=dm" (__result) : "f" (x), "f" (y));  \
76       __result != 0; })
77 # endif /* GCC 3.1 */
78 #endif
79
80
81 #if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \
82     || defined __LIBC_INTERNAL_MATH_INLINES
83
84 #ifdef  __LIBC_INTERNAL_MATH_INLINES
85 /* This is used when defining the functions themselves.  Define them with
86    __ names, and with `static inline' instead of `extern inline' so the
87    bodies will always be used, never an external function call.  */
88 # define __m81_u(x)             __CONCAT(__,x)
89 # define __m81_inline           static __inline
90 #else
91 # define __m81_u(x)             x
92 # ifdef __cplusplus
93 #  define __m81_inline          __inline
94 # else
95 #  define __m81_inline          extern __inline
96 # endif
97 # define __M81_MATH_INLINES     1
98 #endif
99
100 /* Define a const math function.  */
101 #define __m81_defun(rettype, func, args)                                      \
102   __m81_inline rettype __attribute__((__const__))                             \
103   __m81_u(func) args
104
105 /* Define the three variants of a math function that has a direct
106    implementation in the m68k fpu.  FUNC is the name for C (which will be
107    suffixed with f and l for the float and long double version, resp).  OP
108    is the name of the fpu operation (without leading f).  */
109
110 #if defined __USE_MISC || defined __USE_ISOC99
111 # define __inline_mathop(func, op)                      \
112   __inline_mathop1(double, func, op)                    \
113   __inline_mathop1(float, __CONCAT(func,f), op) \
114   __inline_mathop1(long double, __CONCAT(func,l), op)
115 #else
116 # define __inline_mathop(func, op)                      \
117   __inline_mathop1(double, func, op)
118 #endif
119
120 #define __inline_mathop1(float_type,func, op)                                 \
121   __m81_defun (float_type, func, (float_type __mathop_x))                     \
122   {                                                                           \
123     float_type __result;                                                      \
124     __asm__("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
125     return __result;                                                          \
126   }
127
128 __inline_mathop(__atan, atan)
129 __inline_mathop(__cos, cos)
130 __inline_mathop(__sin, sin)
131 __inline_mathop(__tan, tan)
132 __inline_mathop(__tanh, tanh)
133 __inline_mathop(__fabs, abs)
134
135 #if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
136 __inline_mathop(__rint, int)
137 __inline_mathop(__expm1, etoxm1)
138 __inline_mathop(__log1p, lognp1)
139 #endif
140
141 #ifdef __USE_MISC
142 __inline_mathop(__significand, getman)
143 #endif
144
145 #ifdef __USE_ISOC99
146 __inline_mathop(__trunc, intrz)
147 #endif
148
149 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
150
151 __inline_mathop(atan, atan)
152 __inline_mathop(cos, cos)
153 __inline_mathop(sin, sin)
154 __inline_mathop(tan, tan)
155 __inline_mathop(tanh, tanh)
156
157 # if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99
158 __inline_mathop(rint, int)
159 __inline_mathop(expm1, etoxm1)
160 __inline_mathop(log1p, lognp1)
161 # endif
162
163 # ifdef __USE_MISC
164 __inline_mathop(significand, getman)
165 # endif
166
167 # ifdef __USE_ISOC99
168 __inline_mathop(trunc, intrz)
169 # endif
170
171 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
172
173 /* This macro contains the definition for the rest of the inline
174    functions, using FLOAT_TYPE as the domain type and S as the suffix
175    for the function names.  */
176
177 #define __inline_functions(float_type, s)                                 \
178 __m81_defun (float_type, __CONCAT(__floor,s), (float_type __x))   \
179 {                                                                         \
180   float_type __result;                                                    \
181   unsigned long int __ctrl_reg;                                           \
182   __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));                  \
183   /* Set rounding towards negative infinity.  */                          \
184   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
185                       : "dmi" ((__ctrl_reg & ~0x10) | 0x20));             \
186   /* Convert X to an integer, using -Inf rounding.  */                    \
187   __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));          \
188   /* Restore the previous rounding mode.  */                              \
189   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
190                       : "dmi" (__ctrl_reg));                              \
191   return __result;                                                        \
192 }                                                                         \
193                                                                           \
194 __m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x))            \
195 {                                                                         \
196   float_type __result;                                                    \
197   unsigned long int __ctrl_reg;                                           \
198   __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));                  \
199   /* Set rounding towards positive infinity.  */                          \
200   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
201                       : "dmi" (__ctrl_reg | 0x30));                       \
202   /* Convert X to an integer, using +Inf rounding.  */                    \
203   __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));          \
204   /* Restore the previous rounding mode.  */                              \
205   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
206                       : "dmi" (__ctrl_reg));                              \
207   return __result;                                                        \
208 }
209
210 __inline_functions(double,)
211 #if defined __USE_MISC || defined __USE_ISOC99
212 __inline_functions(float,f)
213 __inline_functions(long double,l)
214 #endif
215 #undef __inline_functions
216
217 #ifdef __USE_MISC
218
219 # define __inline_functions(float_type, s)                                \
220 __m81_defun (int, __CONCAT(__isinf,s), (float_type __value))              \
221 {                                                                         \
222   /* There is no branch-condition for infinity,                           \
223      so we must extract and examine the condition codes manually.  */     \
224   unsigned long int __fpsr;                                               \
225   __asm__("ftst%.x %1\n"                                                          \
226         "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));          \
227   return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;        \
228 }                                                                         \
229                                                                           \
230 __m81_defun (int, __CONCAT(__finite,s), (float_type __value))             \
231 {                                                                         \
232   /* There is no branch-condition for infinity, so we must extract and    \
233      examine the condition codes manually.  */                            \
234   unsigned long int __fpsr;                                               \
235   __asm__ ("ftst%.x %1\n"                                                         \
236          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
237   return (__fpsr & (3 << 24)) == 0;                                       \
238 }                                                                         \
239                                                                           \
240 __m81_defun (float_type, __CONCAT(__scalbn,s),                            \
241              (float_type __x, int __n))                                   \
242 {                                                                         \
243   float_type __result;                                                    \
244   __asm__ ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x));  \
245   return __result;                                                        \
246 }
247
248 __inline_functions(double,)
249 __inline_functions(float,f)
250 __inline_functions(long double,l)
251 # undef __inline_functions
252
253 #endif /* Use misc.  */
254
255 #if defined __USE_MISC || defined __USE_XOPEN
256
257 # define __inline_functions(float_type, s)                                \
258 __m81_defun (int, __CONCAT(__isnan,s), (float_type __value))              \
259 {                                                                         \
260   char __result;                                                          \
261   __asm__("ftst%.x %1\n"                                                          \
262         "fsun %0" : "=dm" (__result) : "f" (__value));                    \
263   return __result;                                                        \
264 }
265
266 __inline_functions(double,)
267 # ifdef __USE_MISC
268 __inline_functions(float,f)
269 __inline_functions(long double,l)
270 # endif
271 # undef __inline_functions
272
273 #endif
274
275 #ifdef __USE_ISOC99
276
277 # define __inline_functions(float_type, s)                                \
278 __m81_defun (int, __CONCAT(__signbit,s), (float_type __value))            \
279 {                                                                         \
280   /* There is no branch-condition for the sign bit, so we must extract    \
281      and examine the condition codes manually.  */                        \
282   unsigned long int __fpsr;                                               \
283   __asm__ ("ftst%.x %1\n"                                                         \
284          "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));         \
285   return (__fpsr >> 27) & 1;                                              \
286 }                                                                         \
287                                                                           \
288   __m81_defun (float_type, __CONCAT(__scalbln,s),                         \
289              (float_type __x, long int __n))                              \
290 {                                                                         \
291   return __CONCAT(__scalbn,s) (__x, __n);                                 \
292 }                                                                         \
293                                                                           \
294 __m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x))       \
295 {                                                                         \
296   float_type __result;                                                    \
297   unsigned long int __ctrl_reg;                                           \
298   __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));                  \
299   /* Temporarily disable the inexact exception.  */                       \
300   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
301                       : "dmi" (__ctrl_reg & ~0x200));                     \
302   __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));          \
303   __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */            \
304                       : "dmi" (__ctrl_reg));                              \
305   return __result;                                                        \
306 }                                                                         \
307                                                                           \
308 __m81_defun (long int, __CONCAT(__lrint,s), (float_type __x))             \
309 {                                                                         \
310   long int __result;                                                      \
311   __asm__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));             \
312   return __result;                                                        \
313 }                                                                         \
314                                                                           \
315 __m81_inline float_type                                                   \
316 __m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y,                \
317                            float_type __z)                                \
318 {                                                                         \
319   return (__x * __y) + __z;                                               \
320 }
321
322 __inline_functions (double,)
323 __inline_functions (float,f)
324 __inline_functions (long double,l)
325 # undef __inline_functions
326
327 #endif /* Use ISO C9x */
328
329 #ifdef __USE_GNU
330
331 # define __inline_functions(float_type, s)                              \
332 __m81_inline void                                                       \
333 __m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx,       \
334                               float_type *__cosx)                       \
335 {                                                                       \
336   __asm__ ("fsincos%.x %2,%1:%0"                                                \
337          : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));                 \
338 }
339
340 __inline_functions (double,)
341 __inline_functions (float,f)
342 __inline_functions (long double,l)
343 # undef __inline_functions
344
345 #endif
346
347 #if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
348
349 /* Define inline versions of the user visible functions.  */
350
351 /* Note that there must be no whitespace before the argument passed for
352    NAME, to make token pasting work correctly with -traditional.  */
353 # define __inline_forward_c(rettype, name, args1, args2)        \
354 extern __inline rettype __attribute__((__const__))              \
355   name args1                                                    \
356 {                                                               \
357   return __CONCAT(__,name) args2;                               \
358 }
359
360 # define __inline_forward(rettype, name, args1, args2)  \
361 extern __inline rettype name args1                      \
362 {                                                       \
363   return __CONCAT(__,name) args2;                       \
364 }
365
366 __inline_forward_c(double,floor, (double __x), (__x))
367 __inline_forward_c(double,ceil, (double __x), (__x))
368 # ifdef __USE_MISC
369 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
370 __inline_forward_c(int,isinf, (double __value), (__value))
371 #  endif
372 __inline_forward_c(int,finite, (double __value), (__value))
373 __inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n))
374 # endif
375 # if defined __USE_MISC || defined __USE_XOPEN
376 #  ifndef __USE_ISOC99 /* Conflict with macro of same name.  */
377 __inline_forward_c(int,isnan, (double __value), (__value))
378 #  endif
379 # endif
380 # ifdef __USE_ISOC99
381 __inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n))
382 __inline_forward_c(double,nearbyint, (double __value), (__value))
383 __inline_forward_c(long int,lrint, (double __value), (__value))
384 __inline_forward_c(double,fma, (double __x, double __y, double __z),
385                    (__x, __y, __z))
386 # endif
387 # ifdef __USE_GNU
388 __inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
389                  (__x, __sinx, __cosx))
390 # endif
391
392 # if defined __USE_MISC || defined __USE_ISOC99
393
394 __inline_forward_c(float,floorf, (float __x), (__x))
395 __inline_forward_c(float,ceilf, (float __x), (__x))
396 #  ifdef __USE_MISC
397 __inline_forward_c(int,isinff, (float __value), (__value))
398 __inline_forward_c(int,finitef, (float __value), (__value))
399 __inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n))
400 __inline_forward_c(int,isnanf, (float __value), (__value))
401 #  endif
402 # ifdef __USE_ISOC99
403 __inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n))
404 __inline_forward_c(float,nearbyintf, (float __value), (__value))
405 __inline_forward_c(long int,lrintf, (float __value), (__value))
406 __inline_forward_c(float,fmaf, (float __x, float __y, float __z),
407                    (__x, __y, __z))
408 # endif
409 # ifdef __USE_GNU
410 __inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
411                  (__x, __sinx, __cosx))
412 # endif
413
414 __inline_forward_c(long double,floorl, (long double __x), (__x))
415 __inline_forward_c(long double,ceill, (long double __x), (__x))
416 # ifdef __USE_MISC
417 __inline_forward_c(int,isinfl, (long double __value), (__value))
418 __inline_forward_c(int,finitel, (long double __value), (__value))
419 __inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n))
420 __inline_forward_c(int,isnanl, (long double __value), (__value))
421 # endif
422 # ifdef __USE_ISOC99
423 __inline_forward_c(long double,scalblnl, (long double __x, long int __n),
424                    (__x, __n))
425 __inline_forward_c(long double,nearbyintl, (long double __value), (__value))
426 __inline_forward_c(long int,lrintl, (long double __value), (__value))
427 __inline_forward_c(long double,fmal,
428                    (long double __x, long double __y, long double __z),
429                    (__x, __y, __z))
430 # endif
431 # ifdef __USE_GNU
432 __inline_forward(void,sincosl,
433                  (long double __x, long double *__sinx, long double *__cosx),
434                  (__x, __sinx, __cosx))
435 # endif
436
437 #endif /* Use misc or ISO C99 */
438
439 #undef __inline_forward
440 #undef __inline_forward_c
441
442 #endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
443
444 #endif
445 #endif  /* GCC.  */