Home | History | Annotate | Line # | Download | only in include
fenv.h revision 1.10
      1  1.10  riastrad /*	$NetBSD: fenv.h,v 1.10 2024/10/30 15:56:11 riastradh Exp $	*/
      2   1.1  christos 
      3   1.1  christos /*-
      4   1.1  christos  * Copyright (c) 2015 The NetBSD Foundation, Inc.
      5   1.1  christos  * All rights reserved.
      6   1.1  christos  *
      7   1.1  christos  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1  christos  * by Christos Zoulas.
      9   1.1  christos  *
     10   1.1  christos  * Redistribution and use in source and binary forms, with or without
     11   1.1  christos  * modification, are permitted provided that the following conditions
     12   1.1  christos  * are met:
     13   1.1  christos  * 1. Redistributions of source code must retain the above copyright
     14   1.1  christos  *    notice, this list of conditions and the following disclaimer.
     15   1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     17   1.1  christos  *    documentation and/or other materials provided with the distribution.
     18   1.1  christos  *
     19   1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20   1.1  christos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21   1.1  christos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22   1.1  christos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23   1.1  christos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24   1.1  christos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25   1.1  christos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26   1.1  christos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27   1.1  christos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28   1.1  christos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29   1.1  christos  * POSSIBILITY OF SUCH DAMAGE.
     30   1.1  christos  */
     31   1.1  christos 
     32   1.1  christos #ifndef _M68K_FENV_H_
     33   1.1  christos #define _M68K_FENV_H_
     34   1.1  christos 
     35  1.10  riastrad #include <sys/featuretest.h>
     36   1.1  christos #include <sys/stdint.h>
     37  1.10  riastrad 
     38   1.1  christos #include <m68k/float.h>
     39   1.1  christos #include <m68k/fpreg.h>
     40   1.1  christos 
     41   1.1  christos /* Exception bits, from FPSR */
     42   1.1  christos #define	FE_INEXACT	FPSR_AINEX
     43   1.1  christos #define	FE_DIVBYZERO	FPSR_ADZ
     44   1.1  christos #define	FE_UNDERFLOW	FPSR_AUNFL
     45   1.1  christos #define	FE_OVERFLOW	FPSR_AOVFL
     46   1.1  christos #define	FE_INVALID	FPSR_AIOP
     47   1.1  christos 
     48   1.1  christos #define FE_ALL_EXCEPT \
     49   1.1  christos     (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
     50   1.1  christos 
     51   1.5       chs /* Rounding modes, from FPCR */
     52   1.1  christos #define FE_TONEAREST	FPCR_NEAR
     53   1.1  christos #define	FE_TOWARDZERO	FPCR_ZERO
     54   1.1  christos #define	FE_DOWNWARD	FPCR_MINF
     55   1.1  christos #define	FE_UPWARD	FPCR_PINF
     56   1.1  christos 
     57   1.1  christos #define _ROUND_MASK	\
     58   1.1  christos     (FE_TONEAREST | FE_TOWARDZERO | FE_DOWNWARD | FE_UPWARD)
     59   1.1  christos 
     60   1.6       chs #if defined(__HAVE_68881__)
     61   1.6       chs 
     62   1.6       chs #ifndef __fenv_static
     63   1.6       chs #define __fenv_static   static
     64   1.6       chs #endif
     65   1.3  christos 
     66   1.1  christos typedef uint32_t fexcept_t;
     67   1.1  christos 
     68   1.1  christos /* same layout as fmovem */
     69   1.1  christos typedef struct {
     70   1.1  christos 	uint32_t fpcr;
     71   1.1  christos 	uint32_t fpsr;
     72   1.1  christos 	uint32_t fppc;
     73   1.1  christos } fenv_t;
     74   1.1  christos 
     75   1.1  christos #define FE_DFL_ENV	((fenv_t *) -1)
     76   1.1  christos 
     77   1.1  christos #define __get_fpcr(__fpcr) \
     78   1.1  christos     __asm__ __volatile__ ("fmove%.l %!,%0" : "=dm" (__fpcr))
     79   1.1  christos #define __set_fpcr(__fpcr) \
     80   1.1  christos     __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (__fpcr))
     81   1.1  christos 
     82   1.1  christos #define __get_fpsr(__fpsr) \
     83   1.1  christos     __asm__ __volatile__ ("fmove%.l %/fpsr,%0" : "=dm" (__fpsr))
     84   1.1  christos #define __set_fpsr(__fpsr) \
     85   1.1  christos     __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (__fpsr))
     86   1.1  christos 
     87   1.1  christos #define __fmul(__s, __t, __d) \
     88   1.1  christos     do { \
     89   1.1  christos 	    __t d = __d; \
     90   1.1  christos 	    __asm__ __volatile__ ("fmul" __s "; fnop" : "=f" (d) : "0" (d)); \
     91   1.9   tsutsui     } while (/*CONSTCOND*/0)
     92   1.1  christos 
     93   1.1  christos #define __fdiv(__s, __t, __d) \
     94   1.1  christos     do { \
     95   1.1  christos 	    __t d = __d; \
     96   1.1  christos 	    __asm__ __volatile__ ("fdiv" __s "; fnop" : "=f" (d) : "0" (d)); \
     97   1.9   tsutsui     } while (/*CONSTCOND*/0)
     98   1.1  christos 
     99   1.1  christos #define __fetox(__s, __t, __d) \
    100   1.1  christos     do { \
    101   1.1  christos 	    __t d = __d; \
    102   1.1  christos 	    __asm__ __volatile__ ("fetox" __s "; fnop" : "=f" (d) : "0" (d)); \
    103   1.9   tsutsui     } while (/*CONSTCOND*/0)
    104   1.1  christos 
    105   1.1  christos #define __fgetenv(__envp) \
    106   1.1  christos     __asm__ __volatile__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (__envp))
    107   1.1  christos 
    108   1.1  christos #define __fsetenv(__envp) \
    109   1.1  christos     __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (__envp))
    110   1.1  christos 
    111   1.2  christos __BEGIN_DECLS
    112   1.2  christos 
    113   1.8  christos #if __GNUC_PREREQ__(8, 0)
    114   1.8  christos #pragma GCC diagnostic push
    115   1.8  christos #pragma GCC diagnostic ignored "-Wshadow"
    116   1.8  christos #endif
    117   1.8  christos 
    118   1.1  christos __fenv_static inline int
    119   1.1  christos feclearexcept(int __excepts)
    120   1.1  christos {
    121   1.1  christos 	fexcept_t __fpsr;
    122   1.1  christos 
    123   1.1  christos 	__excepts &= FE_ALL_EXCEPT;
    124   1.1  christos 
    125   1.1  christos 	__get_fpsr(__fpsr);
    126   1.1  christos 	__fpsr &= ~__excepts;
    127   1.1  christos 	__set_fpsr(__fpsr);
    128   1.1  christos 
    129   1.1  christos 	return 0;
    130   1.1  christos }
    131   1.1  christos 
    132   1.1  christos __fenv_static inline int
    133   1.1  christos fegetexceptflag(fexcept_t *__flagp, int __excepts)
    134   1.1  christos {
    135   1.1  christos 	fexcept_t __fpsr;
    136   1.1  christos 
    137   1.1  christos 	__get_fpsr(__fpsr);
    138   1.1  christos 
    139   1.1  christos 	*__flagp = __fpsr & __excepts & FE_ALL_EXCEPT;
    140   1.1  christos 
    141   1.1  christos 	return 0;
    142   1.1  christos }
    143   1.1  christos 
    144   1.1  christos __fenv_static inline int
    145   1.1  christos fesetexceptflag(const fexcept_t *__flagp, int __excepts)
    146   1.1  christos {
    147   1.1  christos 	fexcept_t __fpsr;
    148   1.1  christos 
    149   1.1  christos 	__get_fpsr(__fpsr);
    150   1.1  christos 
    151   1.1  christos 	__fpsr &= ~(__excepts & FE_ALL_EXCEPT);
    152   1.1  christos 	__fpsr |= *__flagp & __excepts & FE_ALL_EXCEPT;
    153   1.1  christos 
    154   1.1  christos 	__set_fpsr(__fpsr);
    155   1.1  christos 
    156   1.1  christos 	return 0;
    157   1.1  christos }
    158   1.1  christos 
    159   1.1  christos __fenv_static inline int
    160   1.1  christos feraiseexcept(int __excepts)
    161   1.1  christos {
    162   1.1  christos 	if (__excepts & FE_INVALID)	/* Inf * 0 */
    163   1.1  christos 		__fmul("%.s %#0r0,%0", double, __builtin_huge_val());
    164   1.1  christos 
    165   1.1  christos 	if (__excepts & FE_DIVBYZERO)	/* 1.0 / 0 */
    166   1.1  christos 		__fdiv("%.s %#0r0,%0", double, 1.0);
    167   1.1  christos 
    168   1.1  christos 	if (__excepts & FE_OVERFLOW)	/* MAX * MAX */
    169   1.1  christos 		__fmul("%.x %0,%0", long double, LDBL_MAX);
    170   1.1  christos 
    171   1.1  christos 	if (__excepts & FE_UNDERFLOW)	/* e ^ -MAX */
    172   1.1  christos 		__fetox("%.x %0", long double, -LDBL_MAX);
    173   1.1  christos 
    174   1.1  christos 	if (__excepts & FE_INEXACT)	/* 1 / 3 */
    175   1.1  christos 		__fdiv("%.s %#0r3,%0", long double, 1.0);
    176   1.1  christos 
    177   1.1  christos 	return 0;
    178   1.1  christos }
    179   1.1  christos 
    180   1.1  christos __fenv_static inline int
    181   1.1  christos fetestexcept(int __excepts)
    182   1.1  christos {
    183   1.1  christos 	fexcept_t __fpsr;
    184   1.1  christos 
    185   1.1  christos 	__get_fpsr(__fpsr);
    186   1.1  christos 
    187   1.1  christos 	return __fpsr & __excepts & FE_ALL_EXCEPT;
    188   1.1  christos }
    189   1.1  christos 
    190   1.1  christos __fenv_static inline int
    191   1.1  christos fegetround(void)
    192   1.1  christos {
    193   1.1  christos 	fexcept_t __fpcr;
    194   1.1  christos 
    195   1.1  christos 	__get_fpcr(__fpcr);
    196   1.1  christos 	return __fpcr & _ROUND_MASK;
    197   1.1  christos }
    198   1.1  christos 
    199   1.1  christos __fenv_static inline int
    200   1.1  christos fesetround(int __round)
    201   1.1  christos {
    202   1.1  christos 	fexcept_t __fpcr;
    203   1.1  christos 
    204   1.1  christos 	if (__round & ~_ROUND_MASK)
    205   1.1  christos 		return -1;
    206   1.1  christos 
    207   1.1  christos 	__get_fpcr(__fpcr);
    208   1.1  christos 
    209   1.1  christos 	__fpcr &= ~_ROUND_MASK;
    210   1.1  christos 	__fpcr |= __round;
    211   1.1  christos 
    212   1.1  christos 	__set_fpcr(__fpcr);
    213   1.1  christos 
    214   1.1  christos 	return 0;
    215   1.1  christos }
    216   1.1  christos 
    217   1.1  christos __fenv_static inline int
    218   1.1  christos fegetenv(fenv_t *__envp)
    219   1.1  christos {
    220   1.7       phx 	__fgetenv(*__envp);
    221   1.1  christos 
    222   1.1  christos 	return 0;
    223   1.1  christos }
    224   1.1  christos 
    225   1.1  christos __fenv_static inline int
    226   1.1  christos feholdexcept(fenv_t *__envp)
    227   1.1  christos {
    228   1.1  christos 	fexcept_t __fpcr, __fpsr;
    229   1.1  christos 
    230   1.7       phx 	__fgetenv(*__envp);
    231   1.1  christos 	__fpsr = __envp->fpsr & ~FE_ALL_EXCEPT;
    232   1.2  christos 	__set_fpsr(__fpsr);	/* clear all */
    233   1.1  christos 	__fpcr = __envp->fpcr & ~(FE_ALL_EXCEPT << 6);
    234   1.2  christos 	__set_fpcr(__fpcr);	/* set non/stop */
    235   1.1  christos 
    236   1.1  christos 	return 0;
    237   1.1  christos }
    238   1.1  christos 
    239   1.1  christos __fenv_static inline int
    240   1.1  christos fesetenv(const fenv_t *__envp)
    241   1.1  christos {
    242   1.1  christos 	fenv_t __tenv;
    243   1.1  christos 
    244   1.1  christos 	__fgetenv(__tenv);
    245   1.1  christos 
    246   1.1  christos 	if (__envp == FE_DFL_ENV) {
    247   1.1  christos 		__tenv.fpcr |=
    248   1.1  christos 		    __envp->fpcr & ((FE_ALL_EXCEPT << 6) | FE_UPWARD);
    249   1.1  christos 		__tenv.fpsr |= __envp->fpsr & FE_ALL_EXCEPT;
    250   1.1  christos 	}
    251   1.1  christos 
    252   1.1  christos 	__fsetenv(__tenv);
    253   1.1  christos 
    254   1.1  christos 	return 0;
    255   1.1  christos }
    256   1.1  christos 
    257   1.1  christos __fenv_static inline int
    258   1.1  christos feupdateenv(const fenv_t *__envp)
    259   1.1  christos {
    260   1.1  christos 	fexcept_t __fpsr;
    261   1.1  christos 
    262   1.1  christos 	__get_fpsr(__fpsr);
    263   1.1  christos 	__fpsr &= FE_ALL_EXCEPT;
    264   1.1  christos 	fesetenv(__envp);
    265   1.1  christos 	feraiseexcept((int)__fpsr);
    266   1.1  christos 	return 0;
    267   1.1  christos }
    268   1.1  christos 
    269   1.8  christos #if __GNUC_PREREQ__(8, 0)
    270   1.8  christos #pragma GCC diagnostic pop
    271   1.8  christos #endif
    272   1.8  christos 
    273   1.1  christos #if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
    274   1.1  christos 
    275   1.6       chs __fenv_static inline int
    276   1.1  christos feenableexcept(int __mask)
    277   1.1  christos {
    278   1.5       chs 	fexcept_t __fpcr, __oldmask;
    279   1.1  christos 
    280   1.5       chs 	__get_fpcr(__fpcr);
    281   1.5       chs 	__oldmask = (__fpcr >> 6) & FE_ALL_EXCEPT;
    282   1.5       chs 	__fpcr |= (__mask & FE_ALL_EXCEPT) << 6;
    283   1.5       chs 	__set_fpcr(__fpcr);
    284   1.1  christos 
    285   1.1  christos 	return __oldmask;
    286   1.1  christos }
    287   1.1  christos 
    288   1.6       chs __fenv_static inline int
    289   1.1  christos fedisableexcept(int __mask)
    290   1.1  christos {
    291   1.5       chs 	fexcept_t __fpcr, __oldmask;
    292   1.1  christos 
    293   1.5       chs 	__get_fpcr(__fpcr);
    294   1.5       chs 	__oldmask = (__fpcr >> 6) & FE_ALL_EXCEPT;
    295   1.5       chs 	__fpcr &= ~((__mask & FE_ALL_EXCEPT) << 6);
    296   1.5       chs 	__set_fpcr(__fpcr);
    297   1.1  christos 
    298   1.1  christos 	return __oldmask;
    299   1.1  christos }
    300   1.1  christos 
    301   1.6       chs __fenv_static inline int
    302   1.1  christos fegetexcept(void)
    303   1.1  christos {
    304   1.5       chs 	fexcept_t __fpcr;
    305   1.1  christos 
    306   1.5       chs 	__get_fpcr(__fpcr);
    307   1.1  christos 
    308   1.5       chs 	return (__fpcr >> 6) & FE_ALL_EXCEPT;
    309   1.1  christos }
    310   1.1  christos 
    311   1.1  christos #endif /* _NETBSD_SOURCE || _GNU_SOURCE */
    312   1.1  christos 
    313   1.4     ozaki __END_DECLS
    314   1.4     ozaki 
    315   1.6       chs #endif /* __HAVE_68881__ */
    316   1.3  christos 
    317   1.1  christos #endif /* _M68K_FENV_H_ */
    318