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