(root)/
glibc-2.38/
sysdeps/
sparc/
sparc64/
sfp-machine.h
       1  /* Machine-dependent software floating-point definitions.
       2     Sparc64 userland (_Q_* and _Qp_*) version.
       3     Copyright (C) 1997-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  #include <fpu_control.h>
      21  #include <fenv.h>
      22  #include <stdlib.h>
      23  
      24  #define _FP_W_TYPE_SIZE		64
      25  #define _FP_W_TYPE		unsigned long
      26  #define _FP_WS_TYPE		signed long
      27  #define _FP_I_TYPE		long
      28  
      29  /* Helper macros for _FP_MUL_MEAT_2_120_240_double.  */
      30  #define _FP_MUL_MEAT_SET_FE_TZ		   			\
      31  do {								\
      32    static fpu_control_t _fetz = _FPU_RC_DOWN;			\
      33    _FPU_SETCW(_fetz);						\
      34  } while (0)
      35  #ifndef _FP_MUL_MEAT_RESET_FE
      36  #define _FP_MUL_MEAT_RESET_FE _FPU_SETCW(_fcw)
      37  #endif
      38  
      39  #define _FP_MUL_MEAT_S(R,X,Y)					\
      40    _FP_MUL_MEAT_1_imm(_FP_WFRACBITS_S,R,X,Y)
      41  #define _FP_MUL_MEAT_D(R,X,Y)					\
      42    _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
      43  #define _FP_MUL_MEAT_Q(R,X,Y)					\
      44    _FP_MUL_MEAT_2_120_240_double(_FP_WFRACBITS_Q,R,X,Y,		\
      45  				_FP_MUL_MEAT_SET_FE_TZ,		\
      46  				_FP_MUL_MEAT_RESET_FE)
      47  
      48  #define _FP_DIV_MEAT_S(R,X,Y)	_FP_DIV_MEAT_1_imm(S,R,X,Y,_FP_DIV_HELP_imm)
      49  #define _FP_DIV_MEAT_D(R,X,Y)	_FP_DIV_MEAT_1_udiv_norm(D,R,X,Y)
      50  #define _FP_DIV_MEAT_Q(R,X,Y)	_FP_DIV_MEAT_2_udiv(Q,R,X,Y)
      51  
      52  #define _FP_NANFRAC_S		((_FP_QNANBIT_S << 1) - 1)
      53  #define _FP_NANFRAC_D		((_FP_QNANBIT_D << 1) - 1)
      54  #define _FP_NANFRAC_Q		((_FP_QNANBIT_Q << 1) - 1), -1
      55  #define _FP_NANSIGN_S		0
      56  #define _FP_NANSIGN_D		0
      57  #define _FP_NANSIGN_Q		0
      58  
      59  #define _FP_KEEPNANFRACP 1
      60  #define _FP_QNANNEGATEDP 0
      61  
      62  /* If one NaN is signaling and the other is not,
      63   * we choose that one, otherwise we choose Y.
      64   */
      65  #define _FP_CHOOSENAN(fs, wc, R, X, Y, OP)			\
      66    do {								\
      67      if ((_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)		\
      68  	&& !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs))	\
      69        {								\
      70  	R##_s = X##_s;						\
      71  	_FP_FRAC_COPY_##wc(R,X);				\
      72        }								\
      73      else							\
      74        {								\
      75  	R##_s = Y##_s;						\
      76  	_FP_FRAC_COPY_##wc(R,Y);				\
      77        }								\
      78      R##_c = FP_CLS_NAN;						\
      79    } while (0)
      80  
      81  /* Obtain the current rounding mode. */
      82  #ifndef FP_ROUNDMODE
      83  #define FP_ROUNDMODE	((_fcw >> 30) & 0x3)
      84  #endif
      85  
      86  /* Exception flags. */
      87  #define FP_EX_INVALID		(1 << 4)
      88  #define FP_EX_OVERFLOW		(1 << 3)
      89  #define FP_EX_UNDERFLOW		(1 << 2)
      90  #define FP_EX_DIVZERO		(1 << 1)
      91  #define FP_EX_INEXACT		(1 << 0)
      92  
      93  #define _FP_TININESS_AFTER_ROUNDING 0
      94  
      95  #define _FP_DECL_EX \
      96    fpu_control_t _fcw __attribute__ ((unused)) = (FP_RND_NEAREST << 30)
      97  
      98  #define FP_INIT_ROUNDMODE					\
      99  do {								\
     100    _FPU_GETCW(_fcw);						\
     101  } while (0)
     102  
     103  #define FP_TRAPPING_EXCEPTIONS ((_fcw >> 23) & 0x1f)
     104  #define FP_INHIBIT_RESULTS ((_fcw >> 23) & _fex)
     105  
     106  /* Simulate exceptions using double arithmetics. */
     107  extern void __Qp_handle_exceptions(int exc);
     108  
     109  #define FP_HANDLE_EXCEPTIONS					\
     110  do {								\
     111    if (!_fex)							\
     112      {								\
     113        /* This is the common case, so we do it inline.		\
     114         * We need to clear cexc bits if any.			\
     115         */							\
     116        __asm__ __volatile__("fzero %%f62\n\t"			\
     117  			   "faddd %%f62, %%f62, %%f62"		\
     118  			   : : : "f62");			\
     119      }								\
     120    else								\
     121      {								\
     122        __Qp_handle_exceptions (_fex);				\
     123      }								\
     124  } while (0)
     125  
     126  #define QP_HANDLE_EXCEPTIONS(_a)				\
     127  do {								\
     128    if ((_fcw >> 23) & _fex)					\
     129      {								\
     130        _a;							\
     131      }								\
     132    else								\
     133      {								\
     134        _fcw = (_fcw & ~0x1fL) | (_fex << 5) | _fex;		\
     135        _FPU_SETCW(_fcw);						\
     136      }								\
     137  } while (0)
     138  
     139  #define QP_NO_EXCEPTIONS					\
     140    __asm ("fzero %%f62\n\t"					\
     141  	 "faddd %%f62, %%f62, %%f62" : : : "f62")
     142  
     143  #define QP_CLOBBER "memory", "f52", "f54", "f56", "f58", "f60", "f62"
     144  #define QP_CLOBBER_CC QP_CLOBBER , "cc"