about summary refs log tree commit diff
path: root/sysdeps/m68k/m680x0/fpu/mathimpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/m68k/m680x0/fpu/mathimpl.h')
-rw-r--r--sysdeps/m68k/m680x0/fpu/mathimpl.h224
1 files changed, 224 insertions, 0 deletions
diff --git a/sysdeps/m68k/m680x0/fpu/mathimpl.h b/sysdeps/m68k/m680x0/fpu/mathimpl.h
index 245fe7b2e3..b4df24043c 100644
--- a/sysdeps/m68k/m680x0/fpu/mathimpl.h
+++ b/sysdeps/m68k/m680x0/fpu/mathimpl.h
@@ -17,9 +17,231 @@
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
+#ifndef _MATHIMPL_H
+#define _MATHIMPL_H
+
 /* This file contains the definitions of the inline math functions that
    are only used internally inside libm, not visible to the user.  */
 
+#define __MATH_INLINE __extern_inline
+
+/* This is used when defining the functions themselves.  Define them with
+   __ names, and with `static inline' instead of `extern inline' so the
+   bodies will always be used, never an external function call.
+   Note: GCC 6 objects to __attribute__ ((__leaf__)) on static functions.  */
+#define __m81_u(x)             __CONCAT(__,x)
+#define __m81_inline           static __inline
+#define __m81_nth(fn)          __NTH (fn)
+
+/* Define a math function.  */
+#define __m81_defun(rettype, func, args, attrs)	\
+  __m81_inline rettype attrs			\
+  __m81_nth (__m81_u(func) args)
+
+/* Define the three variants of a math function that has a direct
+   implementation in the m68k fpu.  FUNC is the name for C (which will be
+   suffixed with f and l for the float and long double version, resp).  OP
+   is the name of the fpu operation (without leading f).  */
+
+# define __inline_mathop(func, op, attrs)			\
+  __inline_mathop1(double, func, op, attrs)			\
+  __inline_mathop1(float, __CONCAT(func,f), op, attrs)		\
+  __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
+
+#define __inline_mathop1(float_type,func, op, attrs)			      \
+  __m81_defun (float_type, func, (float_type __mathop_x), attrs)	      \
+  {									      \
+    float_type __result;						      \
+    __asm __volatile__ ("f" __STRING(op) "%.x %1, %0"			      \
+			: "=f" (__result) : "f" (__mathop_x));		      \
+    return __result;							      \
+  }
+
+__inline_mathop(__atan, atan,)
+__inline_mathop(__cos, cos,)
+__inline_mathop(__sin, sin,)
+__inline_mathop(__tan, tan,)
+__inline_mathop(__tanh, tanh,)
+__inline_mathop(__fabs, abs, __attribute__ ((__const__)))
+
+__inline_mathop(__rint, int,)
+__inline_mathop(__expm1, etoxm1,)
+__inline_mathop(__log1p, lognp1,)
+
+__inline_mathop(__significand, getman,)
+
+__inline_mathop(__trunc, intrz, __attribute__ ((__const__)))
+
+
+/* This macro contains the definition for the rest of the inline
+   functions, using FLOAT_TYPE as the domain type and M as a macro
+   that adds the suffix for the function names.  */
+
+#define __inline_functions(float_type, m)				  \
+__m81_defun (float_type, m(__floor), (float_type __x),			  \
+	     __attribute__ ((__const__)))				  \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Set rounding towards negative infinity.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" ((__ctrl_reg & ~0x10) | 0x20));		  \
+  /* Convert X to an integer, using -Inf rounding.  */			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  /* Restore the previous rounding mode.  */				  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}									  \
+									  \
+__m81_defun (float_type, m(__ceil), (float_type __x),			  \
+	     __attribute__ ((__const__)))				  \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Set rounding towards positive infinity.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg | 0x30));			  \
+  /* Convert X to an integer, using +Inf rounding.  */			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  /* Restore the previous rounding mode.  */				  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}
+
+#define __CONCAT_d(arg) arg
+#define __CONCAT_f(arg) arg ## f
+#define __CONCAT_l(arg) arg ## l
+__inline_functions(double, __CONCAT_d)
+__inline_functions(float, __CONCAT_f)
+__inline_functions(long double, __CONCAT_l)
+#undef __inline_functions
+
+# define __inline_functions(float_type, m)				  \
+__m81_defun (int, m(__isinf), (float_type __value),			  \
+	     __attribute__ ((__const__)))				  \
+{									  \
+  /* There is no branch-condition for infinity,				  \
+     so we must extract and examine the condition codes manually.  */	  \
+  unsigned long int __fpsr;						  \
+  __asm ("ftst%.x %1\n"							  \
+	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;	  \
+}									  \
+									  \
+__m81_defun (int, m(__finite), (float_type __value),			  \
+	     __attribute__ ((__const__)))				  \
+{									  \
+  /* There is no branch-condition for infinity, so we must extract and	  \
+     examine the condition codes manually.  */				  \
+  unsigned long int __fpsr;						  \
+  __asm ("ftst%.x %1\n"							  \
+	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
+  return (__fpsr & (3 << 24)) == 0;					  \
+}									  \
+									  \
+__m81_defun (float_type, m(__scalbn),					  \
+	     (float_type __x, int __n),)				  \
+{									  \
+  float_type __result;							  \
+  __asm __volatile__  ("fscale%.l %1, %0" : "=f" (__result)		  \
+		       : "dmi" (__n), "0" (__x));			  \
+  return __result;							  \
+}
+
+__inline_functions(double, __CONCAT_d)
+__inline_functions(float, __CONCAT_f)
+__inline_functions(long double, __CONCAT_l)
+#undef __inline_functions
+
+# define __inline_functions(float_type, m)				  \
+__m81_defun (int, m(__isnan), (float_type __value),			  \
+	     __attribute__ ((__const__)))			  	  \
+{									  \
+  char __result;							  \
+  __asm ("ftst%.x %1\n"							  \
+	 "fsun %0" : "=dm" (__result) : "f" (__value));			  \
+  return __result;							  \
+}
+
+__inline_functions(double, __CONCAT_d)
+__inline_functions(float, __CONCAT_f)
+__inline_functions(long double, __CONCAT_l)
+#undef __inline_functions
+
+# define __inline_functions(float_type, m)				  \
+__m81_defun (float_type, m(__scalbln),					  \
+	     (float_type __x, long int __n),)				  \
+{									  \
+  return m(__scalbn) (__x, __n);					  \
+}									  \
+									  \
+__m81_defun (float_type, m(__nearbyint), (float_type __x),)		  \
+{									  \
+  float_type __result;							  \
+  unsigned long int __ctrl_reg;						  \
+  __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
+  /* Temporarily disable the inexact exception.  */			  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg & ~0x200));			  \
+  __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
+  __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
+		      : "dmi" (__ctrl_reg));				  \
+  return __result;							  \
+}									  \
+									  \
+__m81_defun (long int, m(__lrint), (float_type __x),)			  \
+{									  \
+  long int __result;							  \
+  __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));  \
+  return __result;							  \
+}
+
+__inline_functions (double, __CONCAT_d)
+__inline_functions (float, __CONCAT_f)
+__inline_functions (long double, __CONCAT_l)
+#undef __inline_functions
+
+#define __inline_functions(float_type, m)				\
+__m81_inline void							\
+__m81_nth (__m81_u(m(__sincos))						\
+	   (float_type __x, float_type *__sinx, float_type *__cosx))	\
+{									\
+  __asm __volatile__ ("fsincos%.x %2,%1:%0"				\
+		      : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));	\
+}
+
+__inline_functions (double, __CONCAT_d)
+__inline_functions (float, __CONCAT_f)
+__inline_functions (long double, __CONCAT_l)
+#undef __inline_functions
+
+#undef __CONCAT_d
+#undef __CONCAT_f
+#undef __CONCAT_l
+
+/* Define the three variants of a math function that has a direct
+   implementation in the m68k fpu.  FUNC is the name for C (which will be
+   suffixed with f and l for the float and long double version, resp).  OP
+   is the name of the fpu operation (without leading f).  */
+
+#define __inline_mathop(func, op, attrs)			\
+  __inline_mathop1(double, func, op, attrs)			\
+  __inline_mathop1(float, __CONCAT(func,f), op, attrs)		\
+  __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
+
+#define __inline_mathop1(float_type,func, op, attrs)			      \
+  __m81_defun (float_type, func, (float_type __mathop_x), attrs)	      \
+  {									      \
+    float_type __result;						      \
+    __asm __volatile__ ("f" __STRING(op) "%.x %1, %0"			      \
+			: "=f" (__result) : "f" (__mathop_x));		      \
+    return __result;							      \
+  }
+
 __inline_mathop	(__ieee754_acos, acos,)
 __inline_mathop	(__ieee754_asin, asin,)
 __inline_mathop	(__ieee754_cosh, cosh,)
@@ -91,3 +313,5 @@ __m81_test (long double __val)
 #define __M81_COND_INF  (2 << 24)
 #define __M81_COND_ZERO (4 << 24)
 #define __M81_COND_NEG  (8 << 24)
+
+#endif /* _MATHIMPL_H  */