xref: /netbsd-src/lib/libm/arch/alpha/fenv.c (revision 5e52dad13cab2a62a0ba1e9f060133ccf8db6f76)
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