fenv.c revision 226218
11206Ssundar/*- 21206Ssundar * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 31206Ssundar * All rights reserved. 41206Ssundar * 51206Ssundar * Redistribution and use in source and binary forms, with or without 61206Ssundar * modification, are permitted provided that the following conditions 71206Ssundar * are met: 81206Ssundar * 1. Redistributions of source code must retain the above copyright 91206Ssundar * notice, this list of conditions and the following disclaimer. 101206Ssundar * 2. Redistributions in binary form must reproduce the above copyright 111206Ssundar * notice, this list of conditions and the following disclaimer in the 121206Ssundar * documentation and/or other materials provided with the distribution. 131206Ssundar * 141206Ssundar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151206Ssundar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161206Ssundar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171206Ssundar * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181206Ssundar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191206Ssundar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201206Ssundar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211206Ssundar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221206Ssundar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231206Ssundar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241206Ssundar * SUCH DAMAGE. 251206Ssundar * 261206Ssundar * $FreeBSD: head/lib/msun/amd64/fenv.c 226218 2011-10-10 15:43:09Z das $ 271206Ssundar */ 281206Ssundar 291206Ssundar#include <sys/cdefs.h> 301206Ssundar#include <sys/types.h> 311206Ssundar#include <machine/fpu.h> 321206Ssundar 331206Ssundar#define __fenv_static 341206Ssundar#include <fenv.h> 351206Ssundar 361206Ssundar#ifdef __GNUC_GNU_INLINE__ 371206Ssundar#error "This file must be compiled with C99 'inline' semantics" 381206Ssundar#endif 391206Ssundar 401206Ssundarconst fenv_t __fe_dfl_env = { 411206Ssundar { 0xffff0000 | __INITIAL_FPUCW__, 421206Ssundar 0xffff0000, 431206Ssundar 0xffffffff, 441206Ssundar { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 451206Ssundar 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } 461206Ssundar }, 471206Ssundar __INITIAL_MXCSR__ 481206Ssundar}; 491206Ssundar 501206Ssundarextern inline int feclearexcept(int __excepts); 511206Ssundarextern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); 521206Ssundar 531206Ssundarint 541206Ssundarfesetexceptflag(const fexcept_t *flagp, int excepts) 551206Ssundar{ 561206Ssundar fenv_t env; 571206Ssundar 581206Ssundar __fnstenv(&env.__x87); 591206Ssundar env.__x87.__status &= ~excepts; 601206Ssundar env.__x87.__status |= *flagp & excepts; 611206Ssundar __fldenv(env.__x87); 621206Ssundar 631206Ssundar __stmxcsr(&env.__mxcsr); 641206Ssundar env.__mxcsr &= ~excepts; 651206Ssundar env.__mxcsr |= *flagp & excepts; 661206Ssundar __ldmxcsr(env.__mxcsr); 671206Ssundar 681206Ssundar return (0); 691206Ssundar} 701206Ssundar 711206Ssundarint 721206Ssundarferaiseexcept(int excepts) 731206Ssundar{ 741206Ssundar fexcept_t ex = excepts; 751206Ssundar 761206Ssundar fesetexceptflag(&ex, excepts); 771206Ssundar __fwait(); 781206Ssundar return (0); 791206Ssundar} 801206Ssundar 811206Ssundarextern inline int fetestexcept(int __excepts); 821206Ssundarextern inline int fegetround(void); 831206Ssundarextern inline int fesetround(int __round); 841206Ssundar 851206Ssundarint 861206Ssundarfegetenv(fenv_t *envp) 871206Ssundar{ 881206Ssundar 891206Ssundar __fnstenv(&envp->__x87); 901206Ssundar __stmxcsr(&envp->__mxcsr); 911206Ssundar /* 921206Ssundar * fnstenv masks all exceptions, so we need to restore the 931206Ssundar * control word to avoid this side effect. 941206Ssundar */ 951206Ssundar __fldcw(envp->__x87.__control); 961206Ssundar return (0); 971206Ssundar} 981206Ssundar 991206Ssundarint 1001206Ssundarfeholdexcept(fenv_t *envp) 1011206Ssundar{ 1021206Ssundar __uint32_t mxcsr; 1031206Ssundar 1041206Ssundar __stmxcsr(&mxcsr); 1051206Ssundar __fnstenv(&envp->__x87); 1061206Ssundar __fnclex(); 1071206Ssundar envp->__mxcsr = mxcsr; 1081206Ssundar mxcsr &= ~FE_ALL_EXCEPT; 1091206Ssundar mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; 1101206Ssundar __ldmxcsr(mxcsr); 1111206Ssundar return (0); 1121206Ssundar} 1131206Ssundar 114extern inline int fesetenv(const fenv_t *__envp); 115 116int 117feupdateenv(const fenv_t *envp) 118{ 119 __uint32_t mxcsr; 120 __uint16_t status; 121 122 __fnstsw(&status); 123 __stmxcsr(&mxcsr); 124 fesetenv(envp); 125 feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); 126 return (0); 127} 128 129int 130__feenableexcept(int mask) 131{ 132 __uint32_t mxcsr, omask; 133 __uint16_t control; 134 135 mask &= FE_ALL_EXCEPT; 136 __fnstcw(&control); 137 __stmxcsr(&mxcsr); 138 omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 139 control &= ~mask; 140 __fldcw(control); 141 mxcsr &= ~(mask << _SSE_EMASK_SHIFT); 142 __ldmxcsr(mxcsr); 143 return (~omask); 144} 145 146int 147__fedisableexcept(int mask) 148{ 149 __uint32_t mxcsr, omask; 150 __uint16_t control; 151 152 mask &= FE_ALL_EXCEPT; 153 __fnstcw(&control); 154 __stmxcsr(&mxcsr); 155 omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 156 control |= mask; 157 __fldcw(control); 158 mxcsr |= mask << _SSE_EMASK_SHIFT; 159 __ldmxcsr(mxcsr); 160 return (~omask); 161} 162 163__weak_reference(__feenableexcept, feenableexcept); 164__weak_reference(__fedisableexcept, fedisableexcept); 165