(root)/
glibc-2.38/
sysdeps/
m68k/
m680x0/
fpu/
mathimpl.h
       1  /* Definitions of libc internal inline math functions implemented
       2     by the m68881/2.
       3     Copyright (C) 1991-2023 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, see
      18     <https://www.gnu.org/licenses/>.  */
      19  
      20  #ifndef _MATHIMPL_H
      21  #define _MATHIMPL_H
      22  
      23  /* This file contains the definitions of the inline math functions that
      24     are only used internally inside libm, not visible to the user.  */
      25  
      26  #define __MATH_INLINE __extern_inline
      27  
      28  /* This is used when defining the functions themselves.  Define them with
      29     __ names, and with `static inline' instead of `extern inline' so the
      30     bodies will always be used, never an external function call.
      31     Note: GCC 6 objects to __attribute__ ((__leaf__)) on static functions.  */
      32  #define __m81_u(x)             __CONCAT(__,x)
      33  #define __m81_inline           static __inline
      34  #define __m81_nth(fn)          __NTH (fn)
      35  
      36  /* Define a math function.  */
      37  #define __m81_defun(rettype, func, args, attrs)	\
      38    __m81_inline rettype attrs			\
      39    __m81_nth (__m81_u(func) args)
      40  
      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).  */
      45  
      46  # define __inline_mathop(func, op, attrs)			\
      47    __inline_mathop1(double, func, op, attrs)			\
      48    __inline_mathop1(float, __CONCAT(func,f), op, attrs)		\
      49    __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
      50  
      51  #define __inline_mathop1(float_type,func, op, attrs)			      \
      52    __m81_defun (float_type, func, (float_type __mathop_x), attrs)	      \
      53    {									      \
      54      float_type __result;						      \
      55      __asm __volatile__ ("f" __STRING(op) "%.x %1, %0"			      \
      56  			: "=f" (__result) : "f" (__mathop_x));		      \
      57      return __result;							      \
      58    }
      59  
      60  __inline_mathop(__atan, atan,)
      61  __inline_mathop(__cos, cos,)
      62  __inline_mathop(__sin, sin,)
      63  __inline_mathop(__tan, tan,)
      64  __inline_mathop(__tanh, tanh,)
      65  __inline_mathop(__fabs, abs, __attribute__ ((__const__)))
      66  
      67  __inline_mathop(__rint, int,)
      68  __inline_mathop(__expm1, etoxm1,)
      69  __inline_mathop(__log1p, lognp1,)
      70  
      71  __inline_mathop(__significand, getman,)
      72  
      73  __inline_mathop(__trunc, intrz, __attribute__ ((__const__)))
      74  
      75  
      76  /* This macro contains the definition for the rest of the inline
      77     functions, using FLOAT_TYPE as the domain type and M as a macro
      78     that adds the suffix for the function names.  */
      79  
      80  #define __inline_functions(float_type, m)				  \
      81  __m81_defun (float_type, m(__floor), (float_type __x),			  \
      82  	     __attribute__ ((__const__)))				  \
      83  {									  \
      84    float_type __result;							  \
      85    unsigned long int __ctrl_reg;						  \
      86    __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
      87    /* Set rounding towards negative infinity.  */			  \
      88    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
      89  		      : "dmi" ((__ctrl_reg & ~0x10) | 0x20));		  \
      90    /* Convert X to an integer, using -Inf rounding.  */			  \
      91    __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
      92    /* Restore the previous rounding mode.  */				  \
      93    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
      94  		      : "dmi" (__ctrl_reg));				  \
      95    return __result;							  \
      96  }									  \
      97  									  \
      98  __m81_defun (float_type, m(__ceil), (float_type __x),			  \
      99  	     __attribute__ ((__const__)))				  \
     100  {									  \
     101    float_type __result;							  \
     102    unsigned long int __ctrl_reg;						  \
     103    __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
     104    /* Set rounding towards positive infinity.  */			  \
     105    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
     106  		      : "dmi" (__ctrl_reg | 0x30));			  \
     107    /* Convert X to an integer, using +Inf rounding.  */			  \
     108    __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
     109    /* Restore the previous rounding mode.  */				  \
     110    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
     111  		      : "dmi" (__ctrl_reg));				  \
     112    return __result;							  \
     113  }
     114  
     115  #define __CONCAT_d(arg) arg
     116  #define __CONCAT_f(arg) arg ## f
     117  #define __CONCAT_l(arg) arg ## l
     118  __inline_functions(double, __CONCAT_d)
     119  __inline_functions(float, __CONCAT_f)
     120  __inline_functions(long double, __CONCAT_l)
     121  #undef __inline_functions
     122  
     123  # define __inline_functions(float_type, m)				  \
     124  __m81_defun (int, m(__isinf), (float_type __value),			  \
     125  	     __attribute__ ((__const__)))				  \
     126  {									  \
     127    /* There is no branch-condition for infinity,				  \
     128       so we must extract and examine the condition codes manually.  */	  \
     129    unsigned long int __fpsr;						  \
     130    __asm ("ftst%.x %1\n"							  \
     131  	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
     132    return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0;	  \
     133  }									  \
     134  									  \
     135  __m81_defun (int, m(__finite), (float_type __value),			  \
     136  	     __attribute__ ((__const__)))				  \
     137  {									  \
     138    /* There is no branch-condition for infinity, so we must extract and	  \
     139       examine the condition codes manually.  */				  \
     140    unsigned long int __fpsr;						  \
     141    __asm ("ftst%.x %1\n"							  \
     142  	 "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value));	  \
     143    return (__fpsr & (3 << 24)) == 0;					  \
     144  }									  \
     145  									  \
     146  __m81_defun (float_type, m(__scalbn),					  \
     147  	     (float_type __x, int __n),)				  \
     148  {									  \
     149    float_type __result;							  \
     150    __asm __volatile__  ("fscale%.l %1, %0" : "=f" (__result)		  \
     151  		       : "dmi" (__n), "0" (__x));			  \
     152    return __result;							  \
     153  }
     154  
     155  __inline_functions(double, __CONCAT_d)
     156  __inline_functions(float, __CONCAT_f)
     157  __inline_functions(long double, __CONCAT_l)
     158  #undef __inline_functions
     159  
     160  # define __inline_functions(float_type, m)				  \
     161  __m81_defun (int, m(__isnan), (float_type __value),			  \
     162  	     __attribute__ ((__const__)))			  	  \
     163  {									  \
     164    char __result;							  \
     165    __asm ("ftst%.x %1\n"							  \
     166  	 "fsun %0" : "=dm" (__result) : "f" (__value));			  \
     167    return __result;							  \
     168  }
     169  
     170  __inline_functions(double, __CONCAT_d)
     171  __inline_functions(float, __CONCAT_f)
     172  __inline_functions(long double, __CONCAT_l)
     173  #undef __inline_functions
     174  
     175  # define __inline_functions(float_type, m)				  \
     176  __m81_defun (float_type, m(__scalbln),					  \
     177  	     (float_type __x, long int __n),)				  \
     178  {									  \
     179    return m(__scalbn) (__x, __n);					  \
     180  }									  \
     181  									  \
     182  __m81_defun (float_type, m(__nearbyint), (float_type __x),)		  \
     183  {									  \
     184    float_type __result;							  \
     185    unsigned long int __ctrl_reg;						  \
     186    __asm __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg));		  \
     187    /* Temporarily disable the inexact exception.  */			  \
     188    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
     189  		      : "dmi" (__ctrl_reg & ~0x200));			  \
     190    __asm __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x));	  \
     191    __asm __volatile__ ("fmove%.l %0, %!" : /* No outputs.  */		  \
     192  		      : "dmi" (__ctrl_reg));				  \
     193    return __result;							  \
     194  }									  \
     195  									  \
     196  __m81_defun (long int, m(__lrint), (float_type __x),)			  \
     197  {									  \
     198    long int __result;							  \
     199    __asm __volatile__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x));  \
     200    return __result;							  \
     201  }
     202  
     203  __inline_functions (double, __CONCAT_d)
     204  __inline_functions (float, __CONCAT_f)
     205  __inline_functions (long double, __CONCAT_l)
     206  #undef __inline_functions
     207  
     208  #define __inline_functions(float_type, m)				\
     209  __m81_inline void							\
     210  __m81_nth (__m81_u(m(__sincos))						\
     211  	   (float_type __x, float_type *__sinx, float_type *__cosx))	\
     212  {									\
     213    __asm __volatile__ ("fsincos%.x %2,%1:%0"				\
     214  		      : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x));	\
     215  }
     216  
     217  __inline_functions (double, __CONCAT_d)
     218  __inline_functions (float, __CONCAT_f)
     219  __inline_functions (long double, __CONCAT_l)
     220  #undef __inline_functions
     221  
     222  #undef __CONCAT_d
     223  #undef __CONCAT_f
     224  #undef __CONCAT_l
     225  
     226  /* Define the three variants of a math function that has a direct
     227     implementation in the m68k fpu.  FUNC is the name for C (which will be
     228     suffixed with f and l for the float and long double version, resp).  OP
     229     is the name of the fpu operation (without leading f).  */
     230  
     231  #define __inline_mathop(func, op, attrs)			\
     232    __inline_mathop1(double, func, op, attrs)			\
     233    __inline_mathop1(float, __CONCAT(func,f), op, attrs)		\
     234    __inline_mathop1(long double, __CONCAT(func,l), op, attrs)
     235  
     236  #define __inline_mathop1(float_type,func, op, attrs)			      \
     237    __m81_defun (float_type, func, (float_type __mathop_x), attrs)	      \
     238    {									      \
     239      float_type __result;						      \
     240      __asm __volatile__ ("f" __STRING(op) "%.x %1, %0"			      \
     241  			: "=f" (__result) : "f" (__mathop_x));		      \
     242      return __result;							      \
     243    }
     244  
     245  __inline_mathop	(__ieee754_acos, acos,)
     246  __inline_mathop	(__ieee754_asin, asin,)
     247  __inline_mathop	(__ieee754_cosh, cosh,)
     248  __inline_mathop	(__ieee754_sinh, sinh,)
     249  __inline_mathop	(__ieee754_exp, etox,)
     250  __inline_mathop	(__ieee754_exp2, twotox,)
     251  __inline_mathop	(__ieee754_exp10, tentox,)
     252  __inline_mathop	(__ieee754_log10, log10,)
     253  __inline_mathop	(__ieee754_log2, log2,)
     254  __inline_mathop	(__ieee754_log, logn,)
     255  __inline_mathop	(__ieee754_sqrt, sqrt,)
     256  __inline_mathop	(__ieee754_atanh, atanh,)
     257  
     258  __m81_defun (double, __ieee754_remainder, (double __x, double __y),)
     259  {
     260    double __result;
     261    __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     262    return __result;
     263  }
     264  
     265  __m81_defun (float, __ieee754_remainderf, (float __x, float __y),)
     266  {
     267    float __result;
     268    __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     269    return __result;
     270  }
     271  
     272  __m81_defun (long double,
     273  	     __ieee754_remainderl, (long double __x, long double __y),)
     274  {
     275    long double __result;
     276    __asm ("frem%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     277    return __result;
     278  }
     279  
     280  __m81_defun (double, __ieee754_fmod, (double __x, double __y),)
     281  {
     282    double __result;
     283    __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     284    return __result;
     285  }
     286  
     287  __m81_defun (float, __ieee754_fmodf, (float __x, float __y),)
     288  {
     289    float __result;
     290    __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     291    return __result;
     292  }
     293  
     294  __m81_defun (long double,
     295  	     __ieee754_fmodl, (long double __x, long double __y),)
     296  {
     297    long double __result;
     298    __asm ("fmod%.x %1, %0" : "=f" (__result) : "f" (__y), "0" (__x));
     299    return __result;
     300  }
     301  
     302  /* Get the m68881 condition codes, to quickly check multiple conditions.  */
     303  static __inline__ unsigned long
     304  __m81_test (long double __val)
     305  {
     306    unsigned long __fpsr;
     307    __asm ("ftst%.x %1; fmove%.l %/fpsr,%0" : "=dm" (__fpsr) : "f" (__val));
     308    return __fpsr;
     309  }
     310  
     311  /* Bit values returned by __m81_test.  */
     312  #define __M81_COND_NAN  (1 << 24)
     313  #define __M81_COND_INF  (2 << 24)
     314  #define __M81_COND_ZERO (4 << 24)
     315  #define __M81_COND_NEG  (8 << 24)
     316  
     317  #endif /* _MATHIMPL_H  */