xref: /relibc/openlibm/include/openlibm_fenv_s390.h (revision 4e3d70965d2987f2836921494781f83cbc22d109)
1 /*-
2  * Copyright (c) 2016 Dan Horák <dan[at]danny.cz>
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$
27  */
28 
29 #ifndef	_FENV_H_
30 #define	_FENV_H_
31 
32 #include <sys/types.h>
33 
34 #ifndef	__fenv_static
35 #define	__fenv_static	static
36 #endif
37 
38 typedef	__uint32_t	fenv_t;
39 typedef	__uint32_t	fexcept_t;
40 
41 /* Exception flags */
42 #define	FE_INEXACT	0x080000
43 #define	FE_UNDERFLOW	0x100000
44 #define	FE_OVERFLOW	0x200000
45 #define	FE_DIVBYZERO	0x400000
46 #define	FE_INVALID	0x800000	/* all types of invalid FP ops */
47 
48 #define	FE_ALL_EXCEPT	(FE_INVALID | FE_DIVBYZERO | FE_INEXACT | FE_OVERFLOW | FE_UNDERFLOW)
49 
50 /* Rounding modes */
51 #define	FE_TONEAREST	0x0000
52 #define	FE_TOWARDZERO	0x0001
53 #define	FE_UPWARD	0x0002
54 #define	FE_DOWNWARD	0x0003
55 #define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
56 			 FE_UPWARD | FE_TOWARDZERO)
57 
58 __BEGIN_DECLS
59 
60 /* Default floating-point environment */
61 extern const fenv_t	__fe_dfl_env;
62 #define	FE_DFL_ENV	(&__fe_dfl_env)
63 
64 /* We need to be able to map status flag positions to mask flag positions */
65 #define	_FPC_EXC_MASK_SHIFT	8
66 #define	_ENABLE_MASK	((FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \
67 			 FE_OVERFLOW | FE_UNDERFLOW) << _FPC_EXC_MASK_SHIFT)
68 
69 /* Macros for accessing the hardware control word.  */
70 #define _FPU_GETCW(cw)  __asm__ __volatile__ ("efpc %0,0" : "=d" (cw))
71 #define _FPU_SETCW(cw)  __asm__ __volatile__ ("sfpc  %0,0" : : "d" (cw))
72 
73 __fenv_static inline int
74 feclearexcept(int __excepts)
75 {
76 	fexcept_t __r;
77 
78 	if (__excepts & FE_INVALID)
79 		__excepts |= FE_ALL_EXCEPT;
80 	_FPU_GETCW(__r);
81 	__r &= ~__excepts;
82 	_FPU_SETCW(__r);
83 	return (0);
84 }
85 
86 __fenv_static inline int
87 fegetexceptflag(fexcept_t *__flagp, int __excepts)
88 {
89 	fexcept_t __r;
90 
91 	_FPU_GETCW(__r);
92 	*__flagp = __r & __excepts;
93 	return (0);
94 }
95 
96 __fenv_static inline int
97 fesetexceptflag(const fexcept_t *__flagp, int __excepts)
98 {
99 	fexcept_t __r;
100 
101 	if (__excepts & FE_INVALID)
102 		__excepts |= FE_ALL_EXCEPT;
103 	_FPU_GETCW(__r);
104 	__r &= ~__excepts;
105 	__r |= *__flagp & __excepts;
106 	_FPU_SETCW(__r);
107 	return (0);
108 }
109 
110 __fenv_static inline int
111 feraiseexcept(int __excepts)
112 {
113 	fexcept_t __r;
114 
115 	_FPU_GETCW(__r);
116 	__r |= __excepts;
117 	_FPU_SETCW(__r);
118 	return (0);
119 }
120 
121 __fenv_static inline int
122 fetestexcept(int __excepts)
123 {
124 	fexcept_t __r;
125 
126 	_FPU_GETCW(__r);
127 	return (__r & __excepts);
128 }
129 
130 __fenv_static inline int
131 fegetround(void)
132 {
133 	fexcept_t __r;
134 
135 	_FPU_GETCW(__r);
136 	return (__r & _ROUND_MASK);
137 }
138 
139 __fenv_static inline int
140 fesetround(int __round)
141 {
142 	fexcept_t __r;
143 
144 	if (__round & ~_ROUND_MASK)
145 		return (-1);
146 
147 	_FPU_GETCW(__r);
148 	__r &= ~_ROUND_MASK;
149 	__r |= __round;
150 	_FPU_SETCW(__r);
151 	return (0);
152 }
153 
154 __fenv_static inline int
155 fegetenv(fenv_t *__envp)
156 {
157 	_FPU_GETCW(*__envp);
158 	return (0);
159 }
160 
161 __fenv_static inline int
162 feholdexcept(fenv_t *__envp)
163 {
164 	fexcept_t __r;
165 
166 	_FPU_GETCW(__r);
167 	*__envp = __r;
168 	__r &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
169 	_FPU_SETCW(__r);
170 	return (0);
171 }
172 
173 __fenv_static inline int
174 fesetenv(const fenv_t *__envp)
175 {
176 	_FPU_SETCW(*__envp);
177 	return (0);
178 }
179 
180 __fenv_static inline int
181 feupdateenv(const fenv_t *__envp)
182 {
183 	fexcept_t __r;
184 
185 	_FPU_GETCW(__r);
186 	__r &= FE_ALL_EXCEPT;
187 	__r |= *__envp;
188 	_FPU_SETCW(__r);
189 	return (0);
190 }
191 
192 #if __BSD_VISIBLE
193 
194 /* We currently provide no external definitions of the functions below. */
195 
196 static inline int
197 feenableexcept(int __mask)
198 {
199 	fenv_t __r;
200 	fenv_t __oldmask;
201 
202 	_FPU_GETCW(__r);
203 	__oldmask = __r;
204 	__r |= (__mask & FE_ALL_EXCEPT) << _FPC_EXC_MASK_SHIFT;
205 	_FPU_SETCW(__r);
206 	return ((__oldmask & _ENABLE_MASK) >> _FPC_EXC_MASK_SHIFT);
207 }
208 
209 static inline int
210 fedisableexcept(int __mask)
211 {
212 	fenv_t __r;
213 	fenv_t __oldmask;
214 
215 	_FPU_GETCW(__r);
216 	__oldmask = __r;
217 	__r &= ~((__mask & FE_ALL_EXCEPT) << _FPC_EXC_MASK_SHIFT);
218 	_FPU_SETCW(__r);
219 	return ((__oldmask & _ENABLE_MASK) >> _FPC_EXC_MASK_SHIFT);
220 }
221 
222 static inline int
223 fegetexcept(void)
224 {
225 	fexcept_t __r;
226 
227 	_FPU_GETCW(__r);
228 	return (__r & (_ENABLE_MASK >> _FPC_EXC_MASK_SHIFT));
229 }
230 
231 #endif /* __BSD_VISIBLE */
232 
233 __END_DECLS
234 
235 #endif	/* !_FENV_H_ */
236