diff options
Diffstat (limited to 'gcc/config/m68k/math-68881.h')
-rw-r--r-- | gcc/config/m68k/math-68881.h | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/gcc/config/m68k/math-68881.h b/gcc/config/m68k/math-68881.h new file mode 100644 index 000000000..6d9f8b2d4 --- /dev/null +++ b/gcc/config/m68k/math-68881.h @@ -0,0 +1,529 @@ +/******************************************************************\ +* * +* <math-68881.h> last modified: 23 May 1992. * +* * +* Copyright (C) 1989 by Matthew Self. * +* You may freely distribute verbatim copies of this software * +* provided that this copyright notice is retained in all copies. * +* You may distribute modifications to this software under the * +* conditions above if you also clearly note such modifications * +* with their author and date. * +* * +* Note: errno is not set to EDOM when domain errors occur for * +* most of these functions. Rather, it is assumed that the * +* 68881's OPERR exception will be enabled and handled * +* appropriately by the operating system. Similarly, overflow * +* and underflow do not set errno to ERANGE. * +* * +* Send bugs to Matthew Self (self@bayes.arc.nasa.gov). * +* * +\******************************************************************/ + +/* This file is NOT a part of GCC, just distributed with it. */ + +/* If you find this in GCC, + please send bug reports to bug-gcc@prep.ai.mit.edu. */ + +/* Changed by Richard Stallman: + May 1993, add conditional to prevent multiple inclusion. + % inserted before a #. + New function `hypot' added. + Nans written in hex to avoid 0rnan. + May 1992, use %! for fpcr register. Break lines before function names. + December 1989, add parens around `&' in pow. + November 1990, added alternate definition of HUGE_VAL for Sun. */ + +/* Changed by Jim Wilson: + September 1993, Use #undef before HUGE_VAL instead of #ifdef/#endif. */ + +/* Changed by Ian Lance Taylor: + September 1994, use extern inline instead of static inline. */ + +#ifndef __math_68881 +#define __math_68881 + +#include <errno.h> + +#undef HUGE_VAL +#ifdef __sun__ +/* The Sun assembler fails to handle the hex constant in the usual defn. */ +#define HUGE_VAL \ +({ \ + static union { int i[2]; double d; } u = { {0x7ff00000, 0} }; \ + u.d; \ +}) +#else +#define HUGE_VAL \ +({ \ + double huge_val; \ + \ + __asm ("fmove%.d #0x7ff0000000000000,%0" /* Infinity */ \ + : "=f" (huge_val) \ + : /* no inputs */); \ + huge_val; \ +}) +#endif + +__inline extern double +sin (double x) +{ + double value; + + __asm ("fsin%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +cos (double x) +{ + double value; + + __asm ("fcos%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +tan (double x) +{ + double value; + + __asm ("ftan%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +asin (double x) +{ + double value; + + __asm ("fasin%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +acos (double x) +{ + double value; + + __asm ("facos%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +atan (double x) +{ + double value; + + __asm ("fatan%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +atan2 (double y, double x) +{ + double pi, pi_over_2; + + __asm ("fmovecr%.x #0,%0" /* extended precision pi */ + : "=f" (pi) + : /* no inputs */ ); + __asm ("fscale%.b #-1,%0" /* no loss of accuracy */ + : "=f" (pi_over_2) + : "0" (pi)); + if (x > 0) + { + if (y > 0) + { + if (x > y) + return atan (y / x); + else + return pi_over_2 - atan (x / y); + } + else + { + if (x > -y) + return atan (y / x); + else + return - pi_over_2 - atan (x / y); + } + } + else + { + if (y < 0) + { + if (-x > -y) + return - pi + atan (y / x); + else + return - pi_over_2 - atan (x / y); + } + else + { + if (-x > y) + return pi + atan (y / x); + else if (y > 0) + return pi_over_2 - atan (x / y); + else + { + double value; + + errno = EDOM; + __asm ("fmove%.d #0x7fffffffffffffff,%0" /* quiet NaN */ + : "=f" (value) + : /* no inputs */); + return value; + } + } + } +} + +__inline extern double +sinh (double x) +{ + double value; + + __asm ("fsinh%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +cosh (double x) +{ + double value; + + __asm ("fcosh%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +tanh (double x) +{ + double value; + + __asm ("ftanh%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +atanh (double x) +{ + double value; + + __asm ("fatanh%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +exp (double x) +{ + double value; + + __asm ("fetox%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +expm1 (double x) +{ + double value; + + __asm ("fetoxm1%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +log (double x) +{ + double value; + + __asm ("flogn%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +log1p (double x) +{ + double value; + + __asm ("flognp1%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +log10 (double x) +{ + double value; + + __asm ("flog10%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +sqrt (double x) +{ + double value; + + __asm ("fsqrt%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +hypot (double x, double y) +{ + return sqrt (x*x + y*y); +} + +__inline extern double +pow (double x, double y) +{ + if (x > 0) + return exp (y * log (x)); + else if (x == 0) + { + if (y > 0) + return 0.0; + else + { + double value; + + errno = EDOM; + __asm ("fmove%.d #0x7fffffffffffffff,%0" /* quiet NaN */ + : "=f" (value) + : /* no inputs */); + return value; + } + } + else + { + double temp; + + __asm ("fintrz%.x %1,%0" + : "=f" (temp) /* integer-valued float */ + : "f" (y)); + if (y == temp) + { + int i = (int) y; + + if ((i & 1) == 0) /* even */ + return exp (y * log (-x)); + else + return - exp (y * log (-x)); + } + else + { + double value; + + errno = EDOM; + __asm ("fmove%.d #0x7fffffffffffffff,%0" /* quiet NaN */ + : "=f" (value) + : /* no inputs */); + return value; + } + } +} + +__inline extern double +fabs (double x) +{ + double value; + + __asm ("fabs%.x %1,%0" + : "=f" (value) + : "f" (x)); + return value; +} + +__inline extern double +ceil (double x) +{ + int rounding_mode, round_up; + double value; + + __asm volatile ("fmove%.l %!,%0" + : "=dm" (rounding_mode) + : /* no inputs */ ); + round_up = rounding_mode | 0x30; + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (round_up)); + __asm volatile ("fint%.x %1,%0" + : "=f" (value) + : "f" (x)); + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (rounding_mode)); + return value; +} + +__inline extern double +floor (double x) +{ + int rounding_mode, round_down; + double value; + + __asm volatile ("fmove%.l %!,%0" + : "=dm" (rounding_mode) + : /* no inputs */ ); + round_down = (rounding_mode & ~0x10) + | 0x20; + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (round_down)); + __asm volatile ("fint%.x %1,%0" + : "=f" (value) + : "f" (x)); + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (rounding_mode)); + return value; +} + +__inline extern double +rint (double x) +{ + int rounding_mode, round_nearest; + double value; + + __asm volatile ("fmove%.l %!,%0" + : "=dm" (rounding_mode) + : /* no inputs */ ); + round_nearest = rounding_mode & ~0x30; + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (round_nearest)); + __asm volatile ("fint%.x %1,%0" + : "=f" (value) + : "f" (x)); + __asm volatile ("fmove%.l %0,%!" + : /* no outputs */ + : "dmi" (rounding_mode)); + return value; +} + +__inline extern double +fmod (double x, double y) +{ + double value; + + __asm ("fmod%.x %2,%0" + : "=f" (value) + : "0" (x), + "f" (y)); + return value; +} + +__inline extern double +drem (double x, double y) +{ + double value; + + __asm ("frem%.x %2,%0" + : "=f" (value) + : "0" (x), + "f" (y)); + return value; +} + +__inline extern double +scalb (double x, int n) +{ + double value; + + __asm ("fscale%.l %2,%0" + : "=f" (value) + : "0" (x), + "dmi" (n)); + return value; +} + +__inline extern double +logb (double x) +{ + double exponent; + + __asm ("fgetexp%.x %1,%0" + : "=f" (exponent) + : "f" (x)); + return exponent; +} + +__inline extern double +ldexp (double x, int n) +{ + double value; + + __asm ("fscale%.l %2,%0" + : "=f" (value) + : "0" (x), + "dmi" (n)); + return value; +} + +__inline extern double +frexp (double x, int *exp) +{ + double float_exponent; + int int_exponent; + double mantissa; + + __asm ("fgetexp%.x %1,%0" + : "=f" (float_exponent) /* integer-valued float */ + : "f" (x)); + int_exponent = (int) float_exponent; + __asm ("fgetman%.x %1,%0" + : "=f" (mantissa) /* 1.0 <= mantissa < 2.0 */ + : "f" (x)); + if (mantissa != 0) + { + __asm ("fscale%.b #-1,%0" + : "=f" (mantissa) /* mantissa /= 2.0 */ + : "0" (mantissa)); + int_exponent += 1; + } + *exp = int_exponent; + return mantissa; +} + +__inline extern double +modf (double x, double *ip) +{ + double temp; + + __asm ("fintrz%.x %1,%0" + : "=f" (temp) /* integer-valued float */ + : "f" (x)); + *ip = temp; + return x - temp; +} + +#endif /* not __math_68881 */ |