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