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> 32fc27daefSDavid Schultz #include <fenv.h> 33fc27daefSDavid Schultz 34fc27daefSDavid Schultz const fenv_t __fe_dfl_env = { 35fc27daefSDavid Schultz { 0xffff0000 | __INITIAL_FPUCW__, 36fc27daefSDavid Schultz 0xffff0000, 37fc27daefSDavid Schultz 0xffffffff, 38fc27daefSDavid Schultz { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39fc27daefSDavid Schultz 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff } 40fc27daefSDavid Schultz }, 41fc27daefSDavid Schultz __INITIAL_MXCSR__ 42fc27daefSDavid Schultz }; 43fc27daefSDavid Schultz 44fc27daefSDavid Schultz int 45fc27daefSDavid Schultz fesetexceptflag(const fexcept_t *flagp, int excepts) 46fc27daefSDavid Schultz { 47fc27daefSDavid Schultz fenv_t env; 48fc27daefSDavid Schultz 49fc27daefSDavid Schultz __fnstenv(&env.__x87); 50fc27daefSDavid Schultz env.__x87.__status &= ~excepts; 51fc27daefSDavid Schultz env.__x87.__status |= *flagp & excepts; 52fc27daefSDavid Schultz __fldenv(env.__x87); 53fc27daefSDavid Schultz 54fc27daefSDavid Schultz __stmxcsr(&env.__mxcsr); 55fc27daefSDavid Schultz env.__mxcsr &= ~excepts; 56fc27daefSDavid Schultz env.__mxcsr |= *flagp & excepts; 57fc27daefSDavid Schultz __ldmxcsr(env.__mxcsr); 58fc27daefSDavid Schultz 59fc27daefSDavid Schultz return (0); 60fc27daefSDavid Schultz } 61fc27daefSDavid Schultz 62fc27daefSDavid Schultz int 63fc27daefSDavid Schultz feraiseexcept(int excepts) 64fc27daefSDavid Schultz { 65fc27daefSDavid Schultz fexcept_t ex = excepts; 66fc27daefSDavid Schultz 67fc27daefSDavid Schultz fesetexceptflag(&ex, excepts); 68fc27daefSDavid Schultz __fwait(); 69fc27daefSDavid Schultz return (0); 70fc27daefSDavid Schultz } 71fc27daefSDavid Schultz 72fc27daefSDavid Schultz int 73fc27daefSDavid Schultz fegetenv(fenv_t *envp) 74fc27daefSDavid Schultz { 75fc27daefSDavid Schultz int control; 76fc27daefSDavid Schultz 77fc27daefSDavid Schultz /* 78fc27daefSDavid Schultz * fnstenv masks all exceptions, so we need to save and 79fc27daefSDavid Schultz * restore the control word to avoid this side effect. 80fc27daefSDavid Schultz */ 81fc27daefSDavid Schultz __fnstcw(&control); 82fc27daefSDavid Schultz __fnstenv(&envp->__x87); 83fc27daefSDavid Schultz __stmxcsr(&envp->__mxcsr); 84fc27daefSDavid Schultz __fldcw(control); 85fc27daefSDavid Schultz return (0); 86fc27daefSDavid Schultz } 87fc27daefSDavid Schultz 88fc27daefSDavid Schultz int 89fc27daefSDavid Schultz feholdexcept(fenv_t *envp) 90fc27daefSDavid Schultz { 91fc27daefSDavid Schultz int mxcsr; 92fc27daefSDavid Schultz 93fc27daefSDavid Schultz __stmxcsr(&mxcsr); 94fc27daefSDavid Schultz __fnstenv(&envp->__x87); 95fc27daefSDavid Schultz __fnclex(); 96fc27daefSDavid Schultz envp->__mxcsr = mxcsr; 970d2354c6SDavid Schultz mxcsr &= ~FE_ALL_EXCEPT; 98fc27daefSDavid Schultz mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT; 99fc27daefSDavid Schultz __ldmxcsr(mxcsr); 100fc27daefSDavid Schultz return (0); 101fc27daefSDavid Schultz } 102fc27daefSDavid Schultz 103fc27daefSDavid Schultz int 104fc27daefSDavid Schultz feupdateenv(const fenv_t *envp) 105fc27daefSDavid Schultz { 106fc27daefSDavid Schultz int mxcsr, status; 107fc27daefSDavid Schultz 108fc27daefSDavid Schultz __fnstsw(&status); 109fc27daefSDavid Schultz __stmxcsr(&mxcsr); 110fc27daefSDavid Schultz fesetenv(envp); 111fc27daefSDavid Schultz feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT); 112fc27daefSDavid Schultz return (0); 113fc27daefSDavid Schultz } 114fc27daefSDavid Schultz 115fc27daefSDavid Schultz int 11610b01832SDavid Schultz __feenableexcept(int mask) 117fc27daefSDavid Schultz { 118fc27daefSDavid Schultz int mxcsr, control, omask; 119fc27daefSDavid Schultz 12010b01832SDavid Schultz mask &= FE_ALL_EXCEPT; 121fc27daefSDavid Schultz __fnstcw(&control); 122fc27daefSDavid Schultz __stmxcsr(&mxcsr); 123fc27daefSDavid Schultz omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 12410b01832SDavid Schultz control &= ~mask; 125fc27daefSDavid Schultz __fldcw(control); 126fc27daefSDavid Schultz mxcsr &= ~(mask << _SSE_EMASK_SHIFT); 127fc27daefSDavid Schultz __ldmxcsr(mxcsr); 128fc27daefSDavid Schultz return (~omask); 129fc27daefSDavid Schultz } 130fc27daefSDavid Schultz 13110b01832SDavid Schultz int 13210b01832SDavid Schultz __fedisableexcept(int mask) 13310b01832SDavid Schultz { 13410b01832SDavid Schultz int mxcsr, control, omask; 13510b01832SDavid Schultz 13610b01832SDavid Schultz mask &= FE_ALL_EXCEPT; 13710b01832SDavid Schultz __fnstcw(&control); 13810b01832SDavid Schultz __stmxcsr(&mxcsr); 13910b01832SDavid Schultz omask = (control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT; 14010b01832SDavid Schultz control |= mask; 14110b01832SDavid Schultz __fldcw(control); 14210b01832SDavid Schultz mxcsr |= mask << _SSE_EMASK_SHIFT; 14310b01832SDavid Schultz __ldmxcsr(mxcsr); 14410b01832SDavid Schultz return (~omask); 14510b01832SDavid Schultz } 14610b01832SDavid Schultz 14710b01832SDavid Schultz __weak_reference(__feenableexcept, feenableexcept); 14810b01832SDavid Schultz __weak_reference(__fedisableexcept, fedisableexcept); 149