]> sourceware.org Git - glibc.git/blame - sysdeps/m68k/fpu/bits/mathinline.h
Update.
[glibc.git] / sysdeps / m68k / fpu / bits / mathinline.h
CommitLineData
377a515b
UD
1/* Definitions of inline math functions implemented by the m68881/2.
2 Copyright (C) 1991, 92, 93, 94, 96, 97 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
28f540f4 4
377a515b
UD
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
28f540f4 9
377a515b
UD
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
13 Library General Public License for more details.
28f540f4 14
377a515b
UD
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
28f540f4
RM
19
20#ifdef __GNUC__
21
22#include <sys/cdefs.h>
23
377a515b 24#ifdef __LIBC_M81_MATH_INLINES
28f540f4
RM
25/* This is used when defining the functions themselves. Define them with
26 __ names, and with `static inline' instead of `extern inline' so the
27 bodies will always be used, never an external function call. */
28#define __m81_u(x) __CONCAT(__,x)
29#define __m81_inline static __inline
30#else
31#define __m81_u(x) x
7176f4e4 32#define __m81_inline extern __inline
569c558c 33#define __M81_MATH_INLINES 1
28f540f4
RM
34#endif
35
6025c399
RM
36/* Define a const math function. */
37#define __m81_defun(rettype, func, args) \
377a515b 38 __m81_inline rettype __attribute__((__const__)) \
6025c399
RM
39 __m81_u(func) args
40
ec4b0518
UD
41/* Define the three variants of a math function that has a direct
42 implementation in the m68k fpu. FUNC is the name for C (which will be
43 suffixed with f and l for the float and long double version, resp). OP
44 is the name of the fpu operation (without leading f). */
377a515b 45
4cca6b86 46#if defined __USE_MISC || defined __USE_ISOC9X
377a515b
UD
47#define __inline_mathop(func, op) \
48 __inline_mathop1(double, func, op) \
49 __inline_mathop1(float, __CONCAT(func,f), op) \
50 __inline_mathop1(long double, __CONCAT(func,l), op)
51#else
52#define __inline_mathop(func, op) \
53 __inline_mathop1(double, func, op)
54#endif
55
56#define __inline_mathop1(float_type,func, op) \
57 __m81_defun (float_type, func, (float_type __mathop_x)) \
8f30ca23 58 { \
377a515b 59 float_type __result; \
8f30ca23
RM
60 __asm("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\
61 return __result; \
62 }
ec4b0518 63
377a515b 64#ifdef __LIBC_M81_MATH_INLINES
6025c399 65/* ieee style elementary functions */
377a515b 66/* These are internal to the implementation of libm. */
6025c399
RM
67__inline_mathop(__ieee754_acos, acos)
68__inline_mathop(__ieee754_asin, asin)
69__inline_mathop(__ieee754_cosh, cosh)
70__inline_mathop(__ieee754_sinh, sinh)
71__inline_mathop(__ieee754_exp, etox)
72__inline_mathop(__ieee754_log10, log10)
73__inline_mathop(__ieee754_log, logn)
74__inline_mathop(__ieee754_sqrt, sqrt)
75__inline_mathop(__ieee754_atanh, atanh)
377a515b 76#endif
6025c399 77
6025c399
RM
78__inline_mathop(__atan, atan)
79__inline_mathop(__cos, cos)
80__inline_mathop(__sin, sin)
81__inline_mathop(__tan, tan)
82__inline_mathop(__tanh, tanh)
83__inline_mathop(__fabs, abs)
6025c399
RM
84
85__inline_mathop(__rint, int)
86__inline_mathop(__expm1, etoxm1)
87__inline_mathop(__log1p, lognp1)
6025c399
RM
88__inline_mathop(__significand, getman)
89
4cca6b86
UD
90__inline_mathop(__log2, log2)
91__inline_mathop(__exp2, twotox)
22d57dd3 92__inline_mathop(__trunc, intrz)
4cca6b86 93
377a515b
UD
94#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
95
96__inline_mathop(atan, atan)
97__inline_mathop(cos, cos)
98__inline_mathop(sin, sin)
99__inline_mathop(tan, tan)
100__inline_mathop(tanh, tanh)
377a515b 101
4cca6b86 102#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC9X
377a515b
UD
103__inline_mathop(rint, int)
104__inline_mathop(expm1, etoxm1)
105__inline_mathop(log1p, lognp1)
377a515b
UD
106#endif
107
108#ifdef __USE_MISC
109__inline_mathop(significand, getman)
110#endif
111
4cca6b86
UD
112#ifdef __USE_ISOC9X
113__inline_mathop(log2, log2)
114__inline_mathop(exp2, twotox)
22d57dd3 115__inline_mathop(trunc, intrz)
4cca6b86
UD
116#endif
117
377a515b
UD
118#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
119
ec4b0518
UD
120/* This macro contains the definition for the rest of the inline
121 functions, using __FLOAT_TYPE as the domain type and __S as the suffix
122 for the function names. */
123
377a515b
UD
124#ifdef __LIBC_M81_MATH_INLINES
125/* Internally used functions. */
126#define __internal_inline_functions(float_type, s) \
127__m81_defun (float_type, __CONCAT(__ieee754_remainder,s), \
128 (float_type __x, float_type __y)) \
ec4b0518 129{ \
377a515b 130 float_type __result; \
ec4b0518
UD
131 __asm("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x)); \
132 return __result; \
133} \
134 \
377a515b
UD
135__m81_defun (float_type, __CONCAT(__ieee754_fmod,s), \
136 (float_type __x, float_type __y)) \
ec4b0518 137{ \
377a515b 138 float_type __result; \
ec4b0518
UD
139 __asm("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x)); \
140 return __result; \
377a515b
UD
141}
142
143__internal_inline_functions (double,)
144__internal_inline_functions (float,f)
145__internal_inline_functions (long double,l)
146#undef __internal_inline_functions
147
51702635
UD
148/* Get the m68881 condition codes, to quickly check multiple conditions. */
149static __inline__ unsigned long
150__m81_test (long double __val)
151{
152 unsigned long __fpsr;
153 __asm ("ftst%.x %1; fmove%.l %/fpsr,%0" : "=dm" (__fpsr) : "f" (__val));
154 return __fpsr;
155}
156
157/* Bit values returned by __m81_test. */
158#define __M81_COND_NAN (1 << 24)
159#define __M81_COND_INF (2 << 24)
160#define __M81_COND_ZERO (4 << 24)
161#define __M81_COND_NEG (8 << 24)
162
377a515b
UD
163#endif /* __LIBC_M81_MATH_INLINES */
164
165/* The rest of the functions are available to the user. */
166
22d57dd3
UD
167#define __inline_functions(float_type, s) \
168__m81_inline float_type \
169__m81_u(__CONCAT(__frexp,s))(float_type __value, int *__expptr) \
170{ \
171 float_type __mantissa, __exponent; \
172 int __iexponent; \
51702635
UD
173 unsigned long __fpsr; \
174 __asm("ftst%.x %1\n" \
175 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
176 if (__fpsr & (7 << 24)) \
22d57dd3 177 { \
51702635 178 /* Not finite or zero. */ \
22d57dd3
UD
179 *__expptr = 0; \
180 return __value; \
181 } \
182 __asm("fgetexp%.x %1, %0" : "=f" (__exponent) : "f" (__value)); \
183 __iexponent = (int) __exponent + 1; \
184 *__expptr = __iexponent; \
185 __asm("fscale%.l %2, %0" : "=f" (__mantissa) \
186 : "0" (__value), "dmi" (-__iexponent)); \
187 return __mantissa; \
188} \
189 \
190__m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \
191{ \
192 float_type __result; \
193 unsigned long int __ctrl_reg; \
194 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
195 /* Set rounding towards negative infinity. */ \
196 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
197 : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \
198 /* Convert X to an integer, using -Inf rounding. */ \
199 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
200 /* Restore the previous rounding mode. */ \
201 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
202 : "dmi" (__ctrl_reg)); \
203 return __result; \
204} \
205 \
206__m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \
207{ \
208 float_type __result; \
209 unsigned long int __ctrl_reg; \
210 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
211 /* Set rounding towards positive infinity. */ \
212 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
213 : "dmi" (__ctrl_reg | 0x30)); \
214 /* Convert X to an integer, using +Inf rounding. */ \
215 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
216 /* Restore the previous rounding mode. */ \
217 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
218 : "dmi" (__ctrl_reg)); \
219 return __result; \
220} \
221 \
222__m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \
223{ \
224 /* There is no branch-condition for infinity, \
225 so we must extract and examine the condition codes manually. */ \
226 unsigned long int __fpsr; \
227 __asm("ftst%.x %1\n" \
228 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
229 return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \
230} \
231 \
232__m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) \
233{ \
234 char __result; \
235 __asm("ftst%.x %1\n" \
236 "fsun %0" : "=dm" (__result) : "f" (__value)); \
237 return __result; \
238} \
239 \
240__m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \
241{ \
242 /* There is no branch-condition for infinity, so we must extract and \
243 examine the condition codes manually. */ \
244 unsigned long int __fpsr; \
245 __asm ("ftst%.x %1\n" \
246 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
247 return (__fpsr & (3 << 24)) == 0; \
248} \
249 \
250__m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) \
251{ \
252 /* There is no branch-condition for the sign bit, so we must extract \
253 and examine the condition codes manually. */ \
254 unsigned long int __fpsr; \
255 __asm ("ftst%.x %1\n" \
256 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \
257 return (__fpsr >> 27) & 1; \
258} \
259 \
260__m81_defun (int, __CONCAT(__ilogb,s), (float_type __x)) \
261{ \
262 float_type __result; \
478b92f0
UD
263 if (__m81_u(__CONCAT(__isnan,s)) (__x)) \
264 /* The stupid standard requires us to return a specific value where \
265 it would depend on the bitpattern of the NaN. */ \
266 return 0x7fffffff; \
22d57dd3
UD
267 __asm("fgetexp%.x %1, %0" : "=f" (__result) : "f" (__x)); \
268 return (int) __result; \
269} \
270 \
478b92f0
UD
271__m81_defun (float_type, __CONCAT(__scalbn,s), \
272 (float_type __x, long int __n)) \
22d57dd3
UD
273{ \
274 float_type __result; \
275 __asm ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x)); \
276 return __result; \
277} \
278 \
279__m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \
280{ \
281 float_type __result; \
282 unsigned long int __ctrl_reg; \
283 __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \
284 /* Temporarily disable the inexact exception. */ \
285 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
286 : "dmi" (__ctrl_reg & ~0x200)); \
287 __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \
288 __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \
289 : "dmi" (__ctrl_reg)); \
290 return __result; \
b4012b75
UD
291} \
292 \
293__m81_inline void \
294__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \
295 float_type *__cosx) \
296{ \
297 __asm ("fsincos%.x %2,%1:%0" \
298 : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \
ec4b0518
UD
299}
300
301/* This defines the three variants of the inline functions. */
377a515b
UD
302__inline_functions (double,)
303__inline_functions (float,f)
304__inline_functions (long double,l)
ec4b0518 305#undef __inline_functions
8f30ca23 306
d705269e 307__m81_defun (long int, __lrint, (long double __x))
63551311
UD
308{
309 long int __result;
310 __asm ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));
311 return __result;
312}
313
377a515b
UD
314#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__
315
316/* Define inline versions of the user visible functions. */
317
318#define __inline_forward_c(rettype, name, args1, args2) \
319extern __inline rettype __attribute__((__const__)) \
320name args1 \
321{ \
322 return __CONCAT(__,name) args2; \
323}
324
325#define __inline_forward(rettype, name, args1, args2) \
326extern __inline rettype name args1 \
327{ \
328 return __CONCAT(__,name) args2; \
329}
330
331__inline_forward(double,frexp, (double __value, int *__expptr),
332 (__value, __expptr))
333__inline_forward_c(double,floor, (double __x), (__x))
334__inline_forward_c(double,ceil, (double __x), (__x))
377a515b
UD
335#ifdef __USE_MISC
336__inline_forward_c(int,isinf, (double __value), (__value))
337__inline_forward_c(int,finite, (double __value), (__value))
478b92f0 338__inline_forward_c(double,scalbn, (double __x, long int __n), (__x, __n))
377a515b
UD
339#endif
340#if defined __USE_MISC || defined __USE_XOPEN
4cca6b86 341#ifndef __USE_ISOC9X /* Conflict with macro of same name. */
377a515b 342__inline_forward_c(int,isnan, (double __value), (__value))
4cca6b86 343#endif
377a515b
UD
344__inline_forward_c(int,ilogb, (double __value), (__value))
345#endif
22d57dd3
UD
346#ifdef __USE_ISOC9X
347__inline_forward_c(double,nearbyint, (double __value), (__value))
348#endif
b4012b75
UD
349#ifdef __USE_GNU
350__inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx),
351 (__x, __sinx, __cosx))
352#endif
377a515b 353
4cca6b86 354#if defined __USE_MISC || defined __USE_ISOC9X
377a515b
UD
355
356__inline_forward(float,frexpf, (float __value, int *__expptr),
357 (__value, __expptr))
358__inline_forward_c(float,floorf, (float __x), (__x))
359__inline_forward_c(float,ceilf, (float __x), (__x))
4cca6b86 360#ifdef __USE_MISC
377a515b
UD
361__inline_forward_c(int,isinff, (float __value), (__value))
362__inline_forward_c(int,finitef, (float __value), (__value))
478b92f0 363__inline_forward_c(float,scalbnf, (float __x, long int __n), (__x, __n))
377a515b
UD
364__inline_forward_c(int,isnanf, (float __value), (__value))
365__inline_forward_c(int,ilogbf, (float __value), (__value))
4cca6b86 366#endif
22d57dd3
UD
367#ifdef __USE_ISOC9X
368__inline_forward_c(float,nearbyintf, (float __value), (__value))
369#endif
b4012b75
UD
370#ifdef __USE_GNU
371__inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx),
372 (__x, __sinx, __cosx))
373#endif
377a515b
UD
374
375__inline_forward(long double,frexpl, (long double __value, int *__expptr),
376 (__value, __expptr))
377__inline_forward_c(long double,floorl, (long double __x), (__x))
378__inline_forward_c(long double,ceill, (long double __x), (__x))
4cca6b86 379#ifdef __USE_MISC
377a515b
UD
380__inline_forward_c(int,isinfl, (long double __value), (__value))
381__inline_forward_c(int,finitel, (long double __value), (__value))
478b92f0 382__inline_forward_c(long double,scalbnl, (long double __x, long int __n),
377a515b
UD
383 (__x, __n))
384__inline_forward_c(int,isnanl, (long double __value), (__value))
385__inline_forward_c(int,ilogbl, (long double __value), (__value))
4cca6b86 386#endif
22d57dd3
UD
387#ifdef __USE_ISOC9X
388__inline_forward_c(long double,nearbyintl, (long double __value), (__value))
d705269e 389__inline_forward_c(long int,lrint, (long double __value), (__value))
22d57dd3 390#endif
b4012b75
UD
391#ifdef __USE_GNU
392__inline_forward(void,sincosl,
393 (long double __x, long double *__sinx, long double *__cosx),
394 (__x, __sinx, __cosx))
395#endif
377a515b 396
4cca6b86 397#endif /* Use misc or ISO C9X */
377a515b
UD
398
399#undef __inline_forward
400#undef __inline_forward_c
401
b4012b75
UD
402#ifdef __USE_ISOC9X
403
404/* ISO C 9X defines some macros to perform unordered comparisons. The
405 m68k FPU supports this with special opcodes and we should use them.
406 These must not be inline functions since we have to be able to handle
407 all floating-point types. */
408#undef isgreater
409#define isgreater(x, y) \
410 __extension__ \
411 ({ char __result; \
5649a1d6 412 __asm__ ("fcmp%.x %2,%1; fsogt %0" \
b4012b75
UD
413 : "=dm" (__result) : "f" (x), "f" (y)); \
414 (int) __result; })
415
416#undef isgreaterequal
417#define isgreaterequal(x, y) \
418 __extension__ \
419 ({ char __result; \
5649a1d6 420 __asm__ ("fcmp%.x %2,%1; fsoge %0" \
b4012b75
UD
421 : "=dm" (__result) : "f" (x), "f" (y)); \
422 (int) __result; })
423
424#undef isless
425#define isless(x, y) \
426 __extension__ \
427 ({ char __result; \
5649a1d6 428 __asm__ ("fcmp%.x %2,%1; fsolt %0" \
b4012b75
UD
429 : "=dm" (__result) : "f" (x), "f" (y)); \
430 (int) __result; })
431
432#undef islessequal
433#define islessequal(x, y) \
434 __extension__ \
435 ({ char __result; \
5649a1d6 436 __asm__ ("fcmp%.x %2,%1; fsole %0" \
b4012b75
UD
437 : "=dm" (__result) : "f" (x), "f" (y)); \
438 (int) __result; })
439
440#undef islessgreater
441#define islessgreater(x, y) \
442 __extension__ \
443 ({ char __result; \
5649a1d6 444 __asm__ ("fcmp%.x %2,%1; fsogl %0" \
b4012b75
UD
445 : "=dm" (__result) : "f" (x), "f" (y)); \
446 (int) __result; })
447
448#undef isunordered
449#define isunordered(x, y) \
450 __extension__ \
451 ({ char __result; \
5649a1d6 452 __asm__ ("fcmp%.x %2,%1; fsun %0" \
b4012b75
UD
453 : "=dm" (__result) : "f" (x), "f" (y)); \
454 (int) __result; })
455#endif
456
377a515b
UD
457#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */
458
28f540f4 459#endif /* GCC. */
This page took 0.125377 seconds and 5 git commands to generate.