1156888Srwatson/*	$NetBSD: fenv.h,v 1.3 2019/10/27 21:27:10 christos Exp $	*/
2156888Srwatson
3156888Srwatson/*-
4156888Srwatson * Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
5156888Srwatson * All rights reserved.
6156888Srwatson *
7156888Srwatson * Redistribution and use in source and binary forms, with or without
8156888Srwatson * modification, are permitted provided that the following conditions
9156888Srwatson * are met:
10156888Srwatson * 1. Redistributions of source code must retain the above copyright
11156888Srwatson *    notice, this list of conditions and the following disclaimer.
12156888Srwatson * 2. Redistributions in binary form must reproduce the above copyright
13156888Srwatson *    notice, this list of conditions and the following disclaimer in the
14156888Srwatson *    documentation and/or other materials provided with the distribution.
15156888Srwatson *
16156888Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17156888Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18156888Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19156888Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20156888Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21156888Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22156888Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23156888Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24156888Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25156888Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26156888Srwatson * SUCH DAMAGE.
27156888Srwatson *
28156888Srwatson * $FreeBSD: src/lib/msun/alpha/fenv.h,v 1.3 2005/03/16 19:03:44 das Exp $
29156888Srwatson */
30156888Srwatson
31156888Srwatson#ifndef	_ALPHA_FENV_H_
32156888Srwatson#define	_ALPHA_FENV_H_
33156888Srwatson
34156888Srwatson#include <sys/stdint.h>
35156888Srwatson
36156888Srwatsontypedef	__uint64_t	fenv_t;
37156888Srwatsontypedef	__uint16_t	fexcept_t;
38156888Srwatson
39156888Srwatson/* Exception flags */
40156888Srwatson#define	FE_INVALID	0x01
41156888Srwatson#define	FE_DIVBYZERO	0x02
42156888Srwatson#define	FE_OVERFLOW	0x04
43156888Srwatson#define	FE_UNDERFLOW	0x08
44156888Srwatson#define	FE_INEXACT	0x10
45156888Srwatson#define	FE_INTOVF	0x20	/* not maskable */
46156888Srwatson#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | FE_INTOVF | \
47156888Srwatson			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
48156888Srwatson
49156888Srwatson/* Rounding modes */
50156888Srwatson#define	FE_TOWARDZERO	0x00
51156888Srwatson#define	FE_DOWNWARD	0x01
52156888Srwatson#define	FE_TONEAREST	0x02
53156888Srwatson#define	FE_UPWARD	0x03
54156888Srwatson#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
55156888Srwatson			 FE_UPWARD | FE_TOWARDZERO)
56156888Srwatson#define	_ROUND_SHIFT	58
57156888Srwatson
58156888Srwatson#define	_FPUSW_SHIFT	52
59156888Srwatson
60156888Srwatson#define	__excb()	__asm __volatile("excb")
61156888Srwatson#define	__mf_fpcr(__cw)	__asm __volatile("mf_fpcr %0" : "=f" (*(__cw)))
62156888Srwatson#define	__mt_fpcr(__cw)	__asm __volatile("mt_fpcr %0" : : "f" (__cw))
63156888Srwatson
64156888Srwatsonunion __fpcr {
65156888Srwatson	double __d;
66156888Srwatson	fenv_t __bits;
67156888Srwatson};
68156888Srwatson
69156888Srwatson__BEGIN_DECLS
70156888Srwatson
71156888Srwatson/* Default floating-point environment */
72156888Srwatsonextern const fenv_t	__fe_dfl_env;
73156888Srwatson#define	FE_DFL_ENV	(&__fe_dfl_env)
74156889Srwatson
75156888Srwatson#if __GNUC_PREREQ__(8, 0)
76156888Srwatson#pragma GCC diagnostic push
77156888Srwatson#pragma GCC diagnostic ignored "-Wshadow"
78156889Srwatson#endif
79156889Srwatson
80156889Srwatsonstatic __inline int
81156889Srwatsonfeclearexcept(int __excepts)
82156889Srwatson{
83156889Srwatson	union __fpcr __r;
84156889Srwatson
85156889Srwatson	__excb();
86156889Srwatson	__mf_fpcr(&__r.__d);
87156889Srwatson	__r.__bits &= ~((fenv_t)__excepts << _FPUSW_SHIFT);
88156889Srwatson	__mt_fpcr(__r.__d);
89156889Srwatson	__excb();
90156888Srwatson	return 0;
91156888Srwatson}
92156888Srwatson
93156888Srwatsonstatic __inline int
94156888Srwatsonfegetexceptflag(fexcept_t *__flagp, int __excepts)
95156888Srwatson{
96156888Srwatson	union __fpcr __r;
97156888Srwatson
98156888Srwatson	__excb();
99156888Srwatson	__mf_fpcr(&__r.__d);
100156888Srwatson	__excb();
101156888Srwatson	*__flagp = (__r.__bits >> _FPUSW_SHIFT) & __excepts;
102156888Srwatson	return 0;
103156888Srwatson}
104156888Srwatson
105156888Srwatsonstatic __inline int
106156889Srwatsonfesetexceptflag(const fexcept_t *__flagp, int __excepts)
107156889Srwatson{
108156889Srwatson	union __fpcr __r;
109156889Srwatson	fenv_t __xflag, __xexcepts;
110156888Srwatson
111156888Srwatson	__xflag = (fenv_t)*__flagp << _FPUSW_SHIFT;
112156889Srwatson	__xexcepts = (fenv_t)__excepts << _FPUSW_SHIFT;
113156888Srwatson	__excb();
114156888Srwatson	__mf_fpcr(&__r.__d);
115156888Srwatson	__r.__bits &= ~__xexcepts;
116156888Srwatson	__r.__bits |= __xflag & __xexcepts;
117156888Srwatson	__mt_fpcr(__r.__d);
118156888Srwatson	__excb();
119156888Srwatson	return 0;
120156888Srwatson}
121156888Srwatson
122156888Srwatsonstatic __inline int
123156888Srwatsonferaiseexcept(int __excepts)
124156888Srwatson{
125156889Srwatson
126156889Srwatson	/*
127156889Srwatson	 * XXX Generating exceptions this way does not actually invoke
128156889Srwatson	 * a userland trap handler when enabled, but neither do
129156888Srwatson	 * arithmetic operations as far as I can tell.  Perhaps there
130156888Srwatson	 * are more bugs in the kernel trap handler.
131156888Srwatson	 */
132156888Srwatson	fexcept_t __ex = __excepts;
133156888Srwatson	fesetexceptflag(&__ex, __excepts);
134156888Srwatson	return 0;
135156888Srwatson}
136156888Srwatson
137156888Srwatsonstatic __inline int
138156888Srwatsonfetestexcept(int __excepts)
139156888Srwatson{
140156888Srwatson	union __fpcr __r;
141156888Srwatson
142156889Srwatson	__excb();
143156888Srwatson	__mf_fpcr(&__r.__d);
144156888Srwatson	__excb();
145156888Srwatson	return (__r.__bits >> _FPUSW_SHIFT) & __excepts;
146156888Srwatson}
147156888Srwatson
148156888Srwatsonstatic __inline int
149156889Srwatsonfegetround(void)
150156888Srwatson{
151156888Srwatson	union __fpcr __r;
152156889Srwatson
153156889Srwatson	/*
154156889Srwatson	 * No exception barriers should be required here if we assume
155156888Srwatson	 * that only fesetround() can change the rounding mode.
156156888Srwatson	 */
157156888Srwatson	__mf_fpcr(&__r.__d);
158156889Srwatson	return (int)(__r.__bits >> _ROUND_SHIFT) & _ROUND_MASK;
159156889Srwatson}
160156888Srwatson
161156888Srwatsonstatic __inline int
162156888Srwatsonfesetround(int __round)
163156888Srwatson{
164156888Srwatson	union __fpcr __r;
165156888Srwatson
166156888Srwatson	if (__round & ~_ROUND_MASK)
167156888Srwatson		return (-1);
168156888Srwatson	__excb();
169156888Srwatson	__mf_fpcr(&__r.__d);
170156888Srwatson	__r.__bits &= ~((fenv_t)_ROUND_MASK << _ROUND_SHIFT);
171156889Srwatson	__r.__bits |= (fenv_t)__round << _ROUND_SHIFT;
172156889Srwatson	__mt_fpcr(__r.__d);
173156889Srwatson	__excb();
174156888Srwatson	return 0;
175156888Srwatson}
176156888Srwatson
177156888Srwatson#if __GNUC_PREREQ__(8, 0)
178156889Srwatson#pragma GCC diagnostic pop
179156888Srwatson#endif
180156888Srwatson
181156888Srwatsonint	fegetenv(fenv_t *);
182156888Srwatsonint	feholdexcept(fenv_t *);
183156888Srwatsonint	fesetenv(const fenv_t *);
184156889Srwatsonint	feupdateenv(const fenv_t *);
185156889Srwatson
186156889Srwatson#if defined(_NETBSD_SOURCE) || defined(_GNU_SOURCE)
187156889Srwatsonint	feenableexcept(int);
188156889Srwatsonint	fedisableexcept(int);
189156888Srwatsonint	fegetexcept(void);
190156888Srwatson#endif /* _NETBSD_SOURCE || _GNU_SOURCE */
191156889Srwatson
192156888Srwatson
193156888Srwatson__END_DECLS
194156888Srwatson
195156888Srwatson#endif	/* !_ALPHA_FENV_H_ */
196156888Srwatson