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