1 /* $NetBSD: fenv.c,v 1.1 2016/08/23 10:00:15 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: src/lib/msun/alpha/fenv.c,v 1.2 2005/03/16 19:03:44 das Exp $ 29 */ 30 #include <sys/cdefs.h> 31 __RCSID("$NetBSD: fenv.c,v 1.1 2016/08/23 10:00:15 christos Exp $"); 32 33 #ifdef __weak_alias 34 #define feenableexcept _feenableexcept 35 #define fedisableexcept _fedisableexcept 36 #define fegetexcept _fegetexcept 37 #endif 38 #include <machine/sysarch.h> 39 #include <fenv.h> 40 41 const fenv_t __fe_dfl_env = 0x680e000000000000ULL; 42 43 /* 44 * The lower 49 bits of the FPCR are unused by the hardware, so we use 45 * the lower order bits to store the kernel's idea of the FP mask as 46 * described in the Alpha Architecture Manual. 47 */ 48 int 49 fegetenv(fenv_t *envp) 50 { 51 struct alpha_fp_except_args p; 52 union __fpcr r; 53 54 /* 55 * The syscall acts as an implicit exception barrier, so we 56 * only need to issue an excb after the mf_fpcr to ensure that 57 * the read is executed before any subsequent FP ops. 58 */ 59 sysarch(ALPHA_FPGETMASK, (char *)&p); 60 __mf_fpcr(&r.__d); 61 *envp = r.__bits | p.mask; 62 __excb(); 63 return 0; 64 } 65 66 int 67 feholdexcept(fenv_t *envp) 68 { 69 struct alpha_fp_except_args p; 70 union __fpcr r; 71 72 sysarch(ALPHA_FPGETMASK, (char *)&p); 73 __mf_fpcr(&r.__d); 74 *envp = r.__bits | p.mask; 75 r.__bits &= ~((fenv_t)FE_ALL_EXCEPT << _FPUSW_SHIFT); 76 __mt_fpcr(r.__d); 77 if (p.mask & FE_ALL_EXCEPT) { 78 p.mask = 0; 79 sysarch(ALPHA_FPSETMASK, &p); 80 } 81 __excb(); 82 return 0; 83 } 84 85 int 86 fesetenv(const fenv_t *envp) 87 { 88 struct alpha_fp_except_args p; 89 union __fpcr r; 90 91 p.mask = *envp & FE_ALL_EXCEPT; 92 sysarch(ALPHA_FPSETMASK, &p); 93 r.__bits = *envp & ~FE_ALL_EXCEPT; 94 __mt_fpcr(r.__d); 95 __excb(); 96 return 0; 97 } 98 99 int 100 feupdateenv(const fenv_t *envp) 101 { 102 struct alpha_fp_except_args p; 103 union __fpcr oldr, newr; 104 105 p.mask = *envp & FE_ALL_EXCEPT; 106 sysarch(ALPHA_FPSETMASK, &p); 107 __mf_fpcr(&oldr.__d); 108 newr.__bits = *envp & ~FE_ALL_EXCEPT; 109 __excb(); 110 __mt_fpcr(newr.__d); 111 feraiseexcept((oldr.__bits >> _FPUSW_SHIFT) & FE_ALL_EXCEPT); 112 return 0; 113 } 114 115 #ifdef __weak_alias 116 __weak_alias(feenableexcept, _feenableexcept); 117 __weak_alias(fedisableexcept, _fedisableexcept); 118 __weak_alias(fegetexcept, _fegetexcept); 119 #endif 120 121 int 122 feenableexcept(int mask) 123 { 124 struct alpha_fp_except_args p; 125 126 sysarch(ALPHA_FPGETMASK, &p); 127 p.mask |= (mask & FE_ALL_EXCEPT); 128 sysarch(ALPHA_FPSETMASK, &p); 129 return p.mask; 130 } 131 132 int 133 fedisableexcept(int mask) 134 { 135 struct alpha_fp_except_args p; 136 137 sysarch(ALPHA_FPGETMASK, &p); 138 p.mask &= ~(mask & FE_ALL_EXCEPT); 139 sysarch(ALPHA_FPSETMASK, &p); 140 return p.mask; 141 } 142 143 int 144 fegetexcept(void) 145 { 146 struct alpha_fp_except_args p; 147 148 sysarch(ALPHA_FPGETMASK, &p); 149 return p.mask; 150 } 151