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