blob: e8ab204c43992e8c6110c199d86f7b6e7108cf2d [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/*-
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
33const fenv_t __fe_dfl_env = 0x680e000000000000ULL;
34
35struct 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 */
44int
45fegetenv(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
62int
63feholdexcept(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
81int
82fesetenv(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
95int
96feupdateenv(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
111int
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
122int
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
133int
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);