1230192Sdas/*- 2230192Sdas * Copyright (c) 2004-2011 David Schultz <das@FreeBSD.ORG> 3230192Sdas * All rights reserved. 4230192Sdas * 5230192Sdas * Redistribution and use in source and binary forms, with or without 6230192Sdas * modification, are permitted provided that the following conditions 7230192Sdas * are met: 8230192Sdas * 1. Redistributions of source code must retain the above copyright 9230192Sdas * notice, this list of conditions and the following disclaimer. 10230192Sdas * 2. Redistributions in binary form must reproduce the above copyright 11230192Sdas * notice, this list of conditions and the following disclaimer in the 12230192Sdas * documentation and/or other materials provided with the distribution. 13230192Sdas * 14230192Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15230192Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16230192Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17230192Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18230192Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19230192Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20230192Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21230192Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22230192Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23230192Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24230192Sdas * SUCH DAMAGE. 25230192Sdas * 26230192Sdas * $FreeBSD$ 27230192Sdas */ 28230192Sdas 29230192Sdas#ifndef _FENV_H_ 30230192Sdas#error "This file is meant to be included only by <fenv.h>." 31230192Sdas#endif 32230192Sdas 33230192Sdas/* 34230192Sdas * This file implements the functionality of <fenv.h> on platforms that 35230192Sdas * lack an FPU and use softfloat in libc for floating point. To use it, 36230192Sdas * you must write an <fenv.h> that provides the following: 37230192Sdas * 38230192Sdas * - a typedef for fenv_t, which may be an integer or struct type 39230192Sdas * - a typedef for fexcept_t (XXX This file assumes fexcept_t is a 40230192Sdas * simple integer type containing the exception mask.) 41230192Sdas * - definitions of FE_* constants for the five exceptions and four 42230192Sdas * rounding modes in IEEE 754, as described in fenv(3) 43230192Sdas * - a definition, and the corresponding external symbol, for FE_DFL_ENV 44230192Sdas * - a macro __set_env(env, flags, mask, rnd), which sets the given fenv_t 45230192Sdas * from the exception flags, mask, and rounding mode 46230192Sdas * - macros __env_flags(env), __env_mask(env), and __env_round(env), which 47230192Sdas * extract fields from an fenv_t 48230192Sdas * - a definition of __fenv_static 49230192Sdas * 50230192Sdas * If the architecture supports an optional FPU, it's recommended that you 51230192Sdas * define fenv_t and fexcept_t to match the hardware ABI. Otherwise, it 52230192Sdas * doesn't matter how you define them. 53230192Sdas */ 54230192Sdas 55230192Sdasextern int __softfloat_float_exception_flags; 56230192Sdasextern int __softfloat_float_exception_mask; 57230192Sdasextern int __softfloat_float_rounding_mode; 58230192Sdasvoid __softfloat_float_raise(int); 59230192Sdas 60230192Sdas__fenv_static inline int 61230192Sdasfeclearexcept(int __excepts) 62230192Sdas{ 63230192Sdas 64230192Sdas __softfloat_float_exception_flags &= ~__excepts; 65230192Sdas return (0); 66230192Sdas} 67230192Sdas 68230192Sdas__fenv_static inline int 69230192Sdasfegetexceptflag(fexcept_t *__flagp, int __excepts) 70230192Sdas{ 71230192Sdas 72230192Sdas *__flagp = __softfloat_float_exception_flags & __excepts; 73230192Sdas return (0); 74230192Sdas} 75230192Sdas 76230192Sdas__fenv_static inline int 77230192Sdasfesetexceptflag(const fexcept_t *__flagp, int __excepts) 78230192Sdas{ 79230192Sdas 80230192Sdas __softfloat_float_exception_flags &= ~__excepts; 81230192Sdas __softfloat_float_exception_flags |= *__flagp & __excepts; 82230192Sdas return (0); 83230192Sdas} 84230192Sdas 85230192Sdas__fenv_static inline int 86230192Sdasferaiseexcept(int __excepts) 87230192Sdas{ 88230192Sdas 89230192Sdas __softfloat_float_raise(__excepts); 90230192Sdas return (0); 91230192Sdas} 92230192Sdas 93230192Sdas__fenv_static inline int 94230192Sdasfetestexcept(int __excepts) 95230192Sdas{ 96230192Sdas 97230192Sdas return (__softfloat_float_exception_flags & __excepts); 98230192Sdas} 99230192Sdas 100230192Sdas__fenv_static inline int 101230192Sdasfegetround(void) 102230192Sdas{ 103230192Sdas 104230192Sdas return (__softfloat_float_rounding_mode); 105230192Sdas} 106230192Sdas 107230192Sdas__fenv_static inline int 108230192Sdasfesetround(int __round) 109230192Sdas{ 110230192Sdas 111230192Sdas __softfloat_float_rounding_mode = __round; 112230192Sdas return (0); 113230192Sdas} 114230192Sdas 115230192Sdas__fenv_static inline int 116230192Sdasfegetenv(fenv_t *__envp) 117230192Sdas{ 118230192Sdas 119230192Sdas __set_env(*__envp, __softfloat_float_exception_flags, 120230192Sdas __softfloat_float_exception_mask, __softfloat_float_rounding_mode); 121230192Sdas return (0); 122230192Sdas} 123230192Sdas 124230192Sdas__fenv_static inline int 125230192Sdasfeholdexcept(fenv_t *__envp) 126230192Sdas{ 127230192Sdas fenv_t __env; 128230192Sdas 129230192Sdas fegetenv(__envp); 130230192Sdas __softfloat_float_exception_flags = 0; 131230192Sdas __softfloat_float_exception_mask = 0; 132230192Sdas return (0); 133230192Sdas} 134230192Sdas 135230192Sdas__fenv_static inline int 136230192Sdasfesetenv(const fenv_t *__envp) 137230192Sdas{ 138230192Sdas 139230192Sdas __softfloat_float_exception_flags = __env_flags(*__envp); 140230192Sdas __softfloat_float_exception_mask = __env_mask(*__envp); 141230192Sdas __softfloat_float_rounding_mode = __env_round(*__envp); 142230192Sdas return (0); 143230192Sdas} 144230192Sdas 145230192Sdas__fenv_static inline int 146230192Sdasfeupdateenv(const fenv_t *__envp) 147230192Sdas{ 148230192Sdas int __oflags = __softfloat_float_exception_flags; 149230192Sdas 150230192Sdas fesetenv(__envp); 151230192Sdas feraiseexcept(__oflags); 152230192Sdas return (0); 153230192Sdas} 154230192Sdas 155230192Sdas#if __BSD_VISIBLE 156230192Sdas 157230192Sdas/* We currently provide no external definitions of the functions below. */ 158230192Sdas 159266133Sian__fenv_static inline int 160230192Sdasfeenableexcept(int __mask) 161230192Sdas{ 162230192Sdas int __omask = __softfloat_float_exception_mask; 163230192Sdas 164230192Sdas __softfloat_float_exception_mask |= __mask; 165230192Sdas return (__omask); 166230192Sdas} 167230192Sdas 168266133Sian__fenv_static inline int 169230192Sdasfedisableexcept(int __mask) 170230192Sdas{ 171230192Sdas int __omask = __softfloat_float_exception_mask; 172230192Sdas 173230192Sdas __softfloat_float_exception_mask &= ~__mask; 174230192Sdas return (__omask); 175230192Sdas} 176230192Sdas 177266133Sian__fenv_static inline int 178230192Sdasfegetexcept(void) 179230192Sdas{ 180230192Sdas 181230192Sdas return (__softfloat_float_exception_mask); 182230192Sdas} 183230192Sdas 184230192Sdas#endif /* __BSD_VISIBLE */ 185