1fc27daefSDavid Schultz /*- 210b01832SDavid Schultz * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 3fc27daefSDavid Schultz * All rights reserved. 4fc27daefSDavid Schultz * 5fc27daefSDavid Schultz * Redistribution and use in source and binary forms, with or without 6fc27daefSDavid Schultz * modification, are permitted provided that the following conditions 7fc27daefSDavid Schultz * are met: 8fc27daefSDavid Schultz * 1. Redistributions of source code must retain the above copyright 9fc27daefSDavid Schultz * notice, this list of conditions and the following disclaimer. 10fc27daefSDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 11fc27daefSDavid Schultz * notice, this list of conditions and the following disclaimer in the 12fc27daefSDavid Schultz * documentation and/or other materials provided with the distribution. 13fc27daefSDavid Schultz * 14fc27daefSDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15fc27daefSDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16fc27daefSDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17fc27daefSDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18fc27daefSDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19fc27daefSDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20fc27daefSDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21fc27daefSDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22fc27daefSDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23fc27daefSDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24fc27daefSDavid Schultz * SUCH DAMAGE. 25fc27daefSDavid Schultz * 26fc27daefSDavid Schultz * $FreeBSD$ 27fc27daefSDavid Schultz */ 28fc27daefSDavid Schultz 29fc27daefSDavid Schultz #include <sys/cdefs.h> 30fc27daefSDavid Schultz #include <sys/types.h> 31fc27daefSDavid Schultz #include <machine/fpu.h> 32d78e594bSDavid Schultz 33d78e594bSDavid Schultz #define __fenv_static 345d9fefacSDavid Schultz #include "fenv.h" 35fc27daefSDavid Schultz 36d78e594bSDavid Schultz #ifdef __GNUC_GNU_INLINE__ 37d78e594bSDavid Schultz #error "This file must be compiled with C99 'inline' semantics" 38d78e594bSDavid Schultz #endif 39d78e594bSDavid Schultz 40fc27daefSDavid Schultz const fenv_t __fe_dfl_env = { 41fc27daefSDavid Schultz { 0xffff0000 | __INITIAL_FPUCW__, 42fc27daefSDavid Schultz 0xffff0000, 43fc27daefSDavid Schultz 0xffffffff, 44fc27daefSDavid Schultz { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45fc27daefSDavid Schultz 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } 46fc27daefSDavid Schultz }, 47fc27daefSDavid Schultz __INITIAL_MXCSR__ 48fc27daefSDavid Schultz }; 49fc27daefSDavid Schultz 50d78e594bSDavid Schultz extern inline int feclearexcept(int __excepts); 51d78e594bSDavid Schultz extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts); 52d78e594bSDavid Schultz 53fc27daefSDavid Schultz int 54fc27daefSDavid Schultz fesetexceptflag(const fexcept_t *flagp, int excepts) 55fc27daefSDavid Schultz { 56fc27daefSDavid Schultz fenv_t env; 57fc27daefSDavid Schultz 58fc27daefSDavid Schultz __fnstenv(&env.__x87); 59fc27daefSDavid Schultz env.__x87.__status &= ~excepts; 60fc27daefSDavid Schultz env.__x87.__status |= *flagp & excepts; 61fc27daefSDavid Schultz __fldenv(env.__x87); 62fc27daefSDavid Schultz 63fc27daefSDavid Schultz __stmxcsr(&env.__mxcsr); 64fc27daefSDavid Schultz env.__mxcsr &= ~excepts; 65fc27daefSDavid Schultz env.__mxcsr |= *flagp & excepts; 66fc27daefSDavid Schultz __ldmxcsr(env.__mxcsr); 67fc27daefSDavid Schultz 68fc27daefSDavid Schultz return (0); 69fc27daefSDavid Schultz } 70fc27daefSDavid Schultz 71fc27daefSDavid Schultz int 72fc27daefSDavid Schultz feraiseexcept(int excepts) 73fc27daefSDavid Schultz { 74fc27daefSDavid Schultz fexcept_t ex = excepts; 75fc27daefSDavid Schultz 76fc27daefSDavid Schultz fesetexceptflag(&ex, excepts); 77fc27daefSDavid Schultz __fwait(); 78fc27daefSDavid Schultz return (0); 79fc27daefSDavid Schultz } 80fc27daefSDavid Schultz 81d78e594bSDavid Schultz extern inline int fetestexcept(int __excepts); 82d78e594bSDavid Schultz extern inline int fegetround(void); 83d78e594bSDavid Schultz extern inline int fesetround(int __round); 84d78e594bSDavid Schultz 85fc27daefSDavid Schultz int 86fc27daefSDavid Schultz fegetenv(fenv_t *envp) 87fc27daefSDavid Schultz { 88fc27daefSDavid Schultz 89fc27daefSDavid Schultz __fnstenv(&envp->__x87); 90fc27daefSDavid Schultz __stmxcsr(&envp->__mxcsr); 913cb636ceSDavid Schultz /* 923cb636ceSDavid Schultz * fnstenv masks all exceptions, so we need to restore the 933cb636ceSDavid Schultz * control word to avoid this side effect. 943cb636ceSDavid Schultz */ 953cb636ceSDavid Schultz __fldcw(envp->__x87.__control); 96fc27daefSDavid Schultz return (0); 97fc27daefSDavid Schultz } 98fc27daefSDavid Schultz 99fc27daefSDavid Schultz int 100fc27daefSDavid Schultz feholdexcept(fenv_t *envp) 101fc27daefSDavid Schultz { 10260d818efSKonstantin Belousov __uint32_t mxcsr; 103fc27daefSDavid Schultz 104fc27daefSDavid Schultz __stmxcsr(&mxcsr); 105fc27daefSDavid Schultz __fnstenv(&envp->__x87); 106fc27daefSDavid Schultz __fnclex(); 107fc27daefSDavid Schultz envp->__mxcsr = mxcsr; 1080d2354c6SDavid Schultz mxcsr &= ~FE_ALL_EXCEPT; 109fc27daefSDavid Schultz mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; 110fc27daefSDavid Schultz __ldmxcsr(mxcsr); 111fc27daefSDavid Schultz return (0); 112fc27daefSDavid Schultz } 113fc27daefSDavid Schultz 114d78e594bSDavid Schultz extern inline int fesetenv(const fenv_t *__envp); 115d78e594bSDavid Schultz 116fc27daefSDavid Schultz int 117fc27daefSDavid Schultz feupdateenv(const fenv_t *envp) 118fc27daefSDavid Schultz { 11960d818efSKonstantin Belousov __uint32_t mxcsr; 12060d818efSKonstantin Belousov __uint16_t status; 121fc27daefSDavid Schultz 122fc27daefSDavid Schultz __fnstsw(&status); 123fc27daefSDavid Schultz __stmxcsr(&mxcsr); 124fc27daefSDavid Schultz fesetenv(envp); 125fc27daefSDavid Schultz feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); 126fc27daefSDavid Schultz return (0); 127fc27daefSDavid Schultz } 128fc27daefSDavid Schultz 129fc27daefSDavid Schultz int 13010b01832SDavid Schultz __feenableexcept(int mask) 131fc27daefSDavid Schultz { 13260d818efSKonstantin Belousov __uint32_t mxcsr, omask; 13360d818efSKonstantin Belousov __uint16_t control; 134fc27daefSDavid Schultz 13510b01832SDavid Schultz mask &= FE_ALL_EXCEPT; 136fc27daefSDavid Schultz __fnstcw(&control); 137fc27daefSDavid Schultz __stmxcsr(&mxcsr); 138*741ae1d0SDavid Schultz omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 13910b01832SDavid Schultz control &= ~mask; 140fc27daefSDavid Schultz __fldcw(control); 141fc27daefSDavid Schultz mxcsr &= ~(mask << _SSE_EMASK_SHIFT); 142fc27daefSDavid Schultz __ldmxcsr(mxcsr); 143*741ae1d0SDavid Schultz return (omask); 144fc27daefSDavid Schultz } 145fc27daefSDavid Schultz 14610b01832SDavid Schultz int 14710b01832SDavid Schultz __fedisableexcept(int mask) 14810b01832SDavid Schultz { 14960d818efSKonstantin Belousov __uint32_t mxcsr, omask; 15060d818efSKonstantin Belousov __uint16_t control; 15110b01832SDavid Schultz 15210b01832SDavid Schultz mask &= FE_ALL_EXCEPT; 15310b01832SDavid Schultz __fnstcw(&control); 15410b01832SDavid Schultz __stmxcsr(&mxcsr); 155*741ae1d0SDavid Schultz omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 15610b01832SDavid Schultz control |= mask; 15710b01832SDavid Schultz __fldcw(control); 15810b01832SDavid Schultz mxcsr |= mask << _SSE_EMASK_SHIFT; 15910b01832SDavid Schultz __ldmxcsr(mxcsr); 160*741ae1d0SDavid Schultz return (omask); 16110b01832SDavid Schultz } 16210b01832SDavid Schultz 16310b01832SDavid Schultz __weak_reference(__feenableexcept, feenableexcept); 16410b01832SDavid Schultz __weak_reference(__fedisableexcept, fedisableexcept); 165