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