fenv.h revision 1.3
1181624Skmacy/* $NetBSD: fenv.h,v 1.3 2015/12/29 16:02:37 christos Exp $ */ 2181624Skmacy 3181624Skmacy/*- 4183375Skmacy * Copyright (c) 2015 The NetBSD Foundation, Inc. 5183375Skmacy * All rights reserved. 6183375Skmacy * 7183375Skmacy * This code is derived from software contributed to The NetBSD Foundation 8183375Skmacy * by Christos Zoulas. 9183375Skmacy * 10183375Skmacy * Redistribution and use in source and binary forms, with or without 11183375Skmacy * modification, are permitted provided that the following conditions 12183375Skmacy * are met: 13183375Skmacy * 1. Redistributions of source code must retain the above copyright 14183375Skmacy * notice, this list of conditions and the following disclaimer. 15183375Skmacy * 2. Redistributions in binary form must reproduce the above copyright 16183375Skmacy * notice, this list of conditions and the following disclaimer in the 17183375Skmacy * documentation and/or other materials provided with the distribution. 18183375Skmacy * 19183375Skmacy * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20183375Skmacy * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21183375Skmacy * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22181624Skmacy * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23181624Skmacy * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24181624Skmacy * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25181624Skmacy * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26181624Skmacy * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27181624Skmacy * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28181624Skmacy * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29181624Skmacy * POSSIBILITY OF SUCH DAMAGE. 30181624Skmacy */ 31181624Skmacy 32181624Skmacy#ifndef _M68K_FENV_H_ 33181624Skmacy#define _M68K_FENV_H_ 34181624Skmacy 35181624Skmacy#include <sys/stdint.h> 36181624Skmacy#include <m68k/float.h> 37181624Skmacy#include <m68k/fpreg.h> 38181624Skmacy 39181624Skmacy#ifndef __fenv_static 40181624Skmacy#define __fenv_static static 41181624Skmacy#endif 42181624Skmacy 43181624Skmacy/* Exception bits, from FPSR */ 44181624Skmacy#define FE_INEXACT FPSR_AINEX 45181624Skmacy#define FE_DIVBYZERO FPSR_ADZ 46181624Skmacy#define FE_UNDERFLOW FPSR_AUNFL 47181624Skmacy#define FE_OVERFLOW FPSR_AOVFL 48181624Skmacy#define FE_INVALID FPSR_AIOP 49181624Skmacy 50181624Skmacy#define FE_ALL_EXCEPT \ 51181624Skmacy (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) 52181624Skmacy 53181624Skmacy/* Rounding modes, from FPSR */ 54181624Skmacy#define FE_TONEAREST FPCR_NEAR 55181624Skmacy#define FE_TOWARDZERO FPCR_ZERO 56181624Skmacy#define FE_DOWNWARD FPCR_MINF 57181624Skmacy#define FE_UPWARD FPCR_PINF 58181624Skmacy 59181624Skmacy#define _ROUND_MASK \ 60181624Skmacy (FE_TONEAREST | FE_TOWARDZERO | FE_DOWNWARD | FE_UPWARD) 61181624Skmacy 62181624Skmacy#if !defined(__mc68010__) && !defined(__mcoldfire__) 63181624Skmacy 64181624Skmacytypedef uint32_t fexcept_t; 65181624Skmacy 66181624Skmacy/* same layout as fmovem */ 67181624Skmacytypedef struct { 68181624Skmacy uint32_t fpcr; 69181624Skmacy uint32_t fpsr; 70181624Skmacy uint32_t fppc; 71181624Skmacy} fenv_t; 72181624Skmacy 73181624Skmacy#define FE_DFL_ENV ((fenv_t *) -1) 74181624Skmacy 75181624Skmacy#define __get_fpcr(__fpcr) \ 76181624Skmacy __asm__ __volatile__ ("fmove%.l %!,%0" : "=dm" (__fpcr)) 77181624Skmacy#define __set_fpcr(__fpcr) \ 78181624Skmacy __asm__ __volatile__ ("fmove%.l %0,%!" : : "dm" (__fpcr)) 79181624Skmacy 80181624Skmacy#define __get_fpsr(__fpsr) \ 81181624Skmacy __asm__ __volatile__ ("fmove%.l %/fpsr,%0" : "=dm" (__fpsr)) 82181624Skmacy#define __set_fpsr(__fpsr) \ 83181624Skmacy __asm__ __volatile__ ("fmove%.l %0,%/fpsr" : : "dm" (__fpsr)) 84181624Skmacy 85181624Skmacy#define __fmul(__s, __t, __d) \ 86181624Skmacy do { \ 87181624Skmacy __t d = __d; \ 88181624Skmacy __asm__ __volatile__ ("fmul" __s "; fnop" : "=f" (d) : "0" (d)); \ 89181624Skmacy } while (/*CONSTCOND*/0) 90181624Skmacy 91181624Skmacy#define __fdiv(__s, __t, __d) \ 92181624Skmacy do { \ 93181624Skmacy __t d = __d; \ 94181624Skmacy __asm__ __volatile__ ("fdiv" __s "; fnop" : "=f" (d) : "0" (d)); \ 95181624Skmacy } while (/*CONSTCOND*/0) 96181624Skmacy 97181624Skmacy#define __fetox(__s, __t, __d) \ 98181624Skmacy do { \ 99181624Skmacy __t d = __d; \ 100183375Skmacy __asm__ __volatile__ ("fetox" __s "; fnop" : "=f" (d) : "0" (d)); \ 101183375Skmacy } while (/*CONSTCOND*/0) 102183375Skmacy 103181624Skmacy#define __fgetenv(__envp) \ 104181624Skmacy __asm__ __volatile__ ("fmovem%.l %/fpcr/%/fpsr/%/fpiar,%0" : "=m" (__envp)) 105181624Skmacy 106181624Skmacy#define __fsetenv(__envp) \ 107181624Skmacy __asm__ __volatile__ ("fmovem%.l %0,%/fpcr/%/fpsr/%/fpiar" : : "m" (__envp)) 108181624Skmacy 109181624Skmacy__BEGIN_DECLS 110181624Skmacy 111181624Skmacy__fenv_static inline int 112181624Skmacyfeclearexcept(int __excepts) 113181624Skmacy{ 114181624Skmacy fexcept_t __fpsr; 115181624Skmacy 116181624Skmacy __excepts &= FE_ALL_EXCEPT; 117181624Skmacy 118181624Skmacy __get_fpsr(__fpsr); 119181624Skmacy __fpsr &= ~__excepts; 120181624Skmacy __set_fpsr(__fpsr); 121181624Skmacy 122181624Skmacy return 0; 123181624Skmacy} 124181624Skmacy 125181624Skmacy__fenv_static inline int 126181624Skmacyfegetexceptflag(fexcept_t *__flagp, int __excepts) 127181624Skmacy{ 128181624Skmacy fexcept_t __fpsr; 129183375Skmacy 130183375Skmacy __get_fpsr(__fpsr); 131183375Skmacy 132183375Skmacy *__flagp = __fpsr & __excepts & FE_ALL_EXCEPT; 133183375Skmacy 134183375Skmacy return 0; 135183375Skmacy} 136183375Skmacy 137183375Skmacy__fenv_static inline int 138183375Skmacyfesetexceptflag(const fexcept_t *__flagp, int __excepts) 139183375Skmacy{ 140183375Skmacy fexcept_t __fpsr; 141183375Skmacy 142181624Skmacy __get_fpsr(__fpsr); 143181624Skmacy 144181624Skmacy __fpsr &= ~(__excepts & FE_ALL_EXCEPT); 145181624Skmacy __fpsr |= *__flagp & __excepts & FE_ALL_EXCEPT; 146181624Skmacy 147181624Skmacy __set_fpsr(__fpsr); 148181624Skmacy 149181624Skmacy return 0; 150181624Skmacy} 151181624Skmacy 152181624Skmacy__fenv_static inline int 153181624Skmacyferaiseexcept(int __excepts) 154181624Skmacy{ 155181624Skmacy if (__excepts & FE_INVALID) /* Inf * 0 */ 156181624Skmacy __fmul("%.s %#0r0,%0", double, __builtin_huge_val()); 157181624Skmacy 158181624Skmacy if (__excepts & FE_DIVBYZERO) /* 1.0 / 0 */ 159181624Skmacy __fdiv("%.s %#0r0,%0", double, 1.0); 160181624Skmacy 161181624Skmacy if (__excepts & FE_OVERFLOW) /* MAX * MAX */ 162181624Skmacy __fmul("%.x %0,%0", long double, LDBL_MAX); 163181624Skmacy 164181624Skmacy if (__excepts & FE_UNDERFLOW) /* e ^ -MAX */ 165181624Skmacy __fetox("%.x %0", long double, -LDBL_MAX); 166181624Skmacy 167181624Skmacy if (__excepts & FE_INEXACT) /* 1 / 3 */ 168181624Skmacy __fdiv("%.s %#0r3,%0", long double, 1.0); 169 170 return 0; 171} 172 173__fenv_static inline int 174fetestexcept(int __excepts) 175{ 176 fexcept_t __fpsr; 177 178 __get_fpsr(__fpsr); 179 180 return __fpsr & __excepts & FE_ALL_EXCEPT; 181} 182 183__fenv_static inline int 184fegetround(void) 185{ 186 fexcept_t __fpcr; 187 188 __get_fpcr(__fpcr); 189 return __fpcr & _ROUND_MASK; 190} 191 192__fenv_static inline int 193fesetround(int __round) 194{ 195 fexcept_t __fpcr; 196 197 if (__round & ~_ROUND_MASK) 198 return -1; 199 200 __get_fpcr(__fpcr); 201 202 __fpcr &= ~_ROUND_MASK; 203 __fpcr |= __round; 204 205 __set_fpcr(__fpcr); 206 207 return 0; 208} 209 210__fenv_static inline int 211fegetenv(fenv_t *__envp) 212{ 213 __fgetenv(__envp); 214 215 return 0; 216} 217 218__fenv_static inline int 219feholdexcept(fenv_t *__envp) 220{ 221 fexcept_t __fpcr, __fpsr; 222 223 __fgetenv(__envp); 224 __fpsr = __envp->fpsr & ~FE_ALL_EXCEPT; 225 __set_fpsr(__fpsr); /* clear all */ 226 __fpcr = __envp->fpcr & ~(FE_ALL_EXCEPT << 6); 227 __set_fpcr(__fpcr); /* set non/stop */ 228 229 return 0; 230} 231 232__fenv_static inline int 233fesetenv(const fenv_t *__envp) 234{ 235 fenv_t __tenv; 236 237 __fgetenv(__tenv); 238 239 if (__envp == FE_DFL_ENV) { 240 __tenv.fpcr |= 241 __envp->fpcr & ((FE_ALL_EXCEPT << 6) | FE_UPWARD); 242 __tenv.fpsr |= __envp->fpsr & FE_ALL_EXCEPT; 243 } 244 245 __fsetenv(__tenv); 246 247 return 0; 248} 249 250__fenv_static inline int 251feupdateenv(const fenv_t *__envp) 252{ 253 fexcept_t __fpsr; 254 255 __get_fpsr(__fpsr); 256 __fpsr &= FE_ALL_EXCEPT; 257 fesetenv(__envp); 258 feraiseexcept((int)__fpsr); 259 return 0; 260} 261 262#if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE) 263 264/* We currently provide no external definitions of the functions below. */ 265 266static inline int 267feenableexcept(int __mask) 268{ 269 fexcept_t __fpsr, __oldmask; 270 271 __get_fpsr(__fpsr); 272 __oldmask = __fpsr & FE_ALL_EXCEPT; 273 __fpsr |= __mask & FE_ALL_EXCEPT; 274 __set_fpsr(__fpsr); 275 276 return __oldmask; 277} 278 279static inline int 280fedisableexcept(int __mask) 281{ 282 fexcept_t __fpsr, __oldmask; 283 284 __get_fpsr(__fpsr); 285 __oldmask = __fpsr & FE_ALL_EXCEPT; 286 __fpsr &= ~(__mask & FE_ALL_EXCEPT); 287 __set_fpsr(__fpsr); 288 289 return __oldmask; 290} 291 292static inline int 293fegetexcept(void) 294{ 295 fexcept_t __fpsr; 296 297 __get_fpsr(__fpsr); 298 299 return __fpsr & FE_ALL_EXCEPT; 300} 301 302#endif /* _NETBSD_SOURCE || _GNU_SOURCE */ 303 304#endif /* !__m68010__ && !__mcoldfire__ */ 305 306__END_DECLS 307 308#endif /* _M68K_FENV_H_ */ 309