<cpu/ieeefp.h>: Use single-underscore instead of double.
[dragonfly.git] / sys / cpu / i386 / include / ieeefp.h
CommitLineData
984263bc 1/*-
410233b2 2 * Copyright (c) 2003 Peter Wemm.
984263bc
MD
3 * Copyright (c) 1990 Andrew Moore, Talke Studio
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93
410233b2 35 * $FreeBSD: src/sys/i386/include/ieeefp.h,v 1.14 2008/01/11 18:59:35 bde Exp $
984263bc
MD
36 */
37
88181b08
MD
38#ifndef _CPU_IEEEFP_H_
39#define _CPU_IEEEFP_H_
984263bc
MD
40
41/*
410233b2
PA
42 * IEEE floating point type, constant and function definitions.
43 * XXX: FP*FLD and FP*OFF are undocumented pollution.
44 */
45
46/*
47 * Rounding modes.
984263bc
MD
48 */
49typedef enum {
50 FP_RN=0, /* round to nearest */
410233b2
PA
51 FP_RM, /* round down towards minus infinity */
52 FP_RP, /* round up towards plus infinity */
984263bc
MD
53 FP_RZ /* truncate */
54} fp_rnd_t;
55
56/*
410233b2 57 * Precision (i.e., rounding precision) modes.
984263bc
MD
58 */
59typedef enum {
60 FP_PS=0, /* 24 bit (single-precision) */
61 FP_PRS, /* reserved */
62 FP_PD, /* 53 bit (double-precision) */
63 FP_PE /* 64 bit (extended-precision) */
64} fp_prec_t;
65
66#define fp_except_t int
67
68/*
410233b2 69 * Exception bit masks.
984263bc
MD
70 */
71#define FP_X_INV 0x01 /* invalid operation */
72#define FP_X_DNML 0x02 /* denormal */
73#define FP_X_DZ 0x04 /* zero divide */
74#define FP_X_OFL 0x08 /* overflow */
75#define FP_X_UFL 0x10 /* underflow */
76#define FP_X_IMP 0x20 /* (im)precision */
77#define FP_X_STK 0x40 /* stack fault */
78
79/*
410233b2 80 * FPU control word bit-field masks.
984263bc 81 */
410233b2
PA
82#define FP_MSKS_FLD 0x3f /* exception masks field */
83#define FP_PRC_FLD 0x300 /* precision control field */
84#define FP_RND_FLD 0xc00 /* rounding control field */
984263bc
MD
85
86/*
410233b2 87 * FPU status word bit-field masks.
984263bc 88 */
984263bc
MD
89#define FP_STKY_FLD 0x3f /* sticky flags field */
90
91/*
410233b2 92 * FPU control word bit-field offsets (shift counts).
984263bc
MD
93 */
94#define FP_MSKS_OFF 0 /* exception masks offset */
95#define FP_PRC_OFF 8 /* precision control offset */
410233b2
PA
96#define FP_RND_OFF 10 /* rounding control offset */
97
98/*
99 * FPU status word bit-field offsets (shift counts).
100 */
984263bc
MD
101#define FP_STKY_OFF 0 /* sticky flags offset */
102
fe667cd2
PA
103#ifdef __GNUC__
104
5a8d63ad
PA
105#define _fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr)))
106#define _fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr)))
107#define _fnclex() __asm __volatile("fnclex")
108#define _fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
109#define _fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
110#define _fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
fe667cd2
PA
111
112/*
410233b2
PA
113 * Load the control word. Be careful not to trap if there is a currently
114 * unmasked exception (ones that will become freshly unmasked are not a
115 * problem). This case must be handled by a save/restore of the
116 * environment or even of the full x87 state. Accessing the environment
117 * is very inefficient, so only do it when necessary.
fe667cd2 118 */
410233b2 119static __inline void
5a8d63ad 120_fnldcw(unsigned short _cw, unsigned short _newcw)
fe667cd2 121{
410233b2
PA
122 struct {
123 unsigned _cw;
124 unsigned _other[6];
125 } _env;
126 unsigned short _sw;
127
128 if ((_cw & FP_MSKS_FLD) != FP_MSKS_FLD) {
5a8d63ad 129 _fnstsw(&_sw);
410233b2 130 if (((_sw & ~_cw) & FP_STKY_FLD) != 0) {
5a8d63ad 131 _fnstenv(&_env);
410233b2 132 _env._cw = _newcw;
5a8d63ad 133 _fldenv(&_env);
410233b2
PA
134 return;
135 }
fe667cd2 136 }
5a8d63ad 137 _fldcw(&_newcw);
fe667cd2
PA
138}
139
410233b2
PA
140static __inline fp_rnd_t
141fpgetround(void)
fe667cd2 142{
410233b2
PA
143 unsigned short _cw;
144
5a8d63ad 145 _fnstcw(&_cw);
410233b2 146 return ((fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF));
fe667cd2
PA
147}
148
410233b2
PA
149static __inline fp_rnd_t
150fpsetround(fp_rnd_t _m)
151{
152 fp_rnd_t _p;
153 unsigned short _cw, _newcw;
154
5a8d63ad 155 _fnstcw(&_cw);
410233b2
PA
156 _p = (fp_rnd_t)((_cw & FP_RND_FLD) >> FP_RND_OFF);
157 _newcw = _cw & ~FP_RND_FLD;
158 _newcw |= (_m << FP_RND_OFF) & FP_RND_FLD;
5a8d63ad 159 _fnldcw(_cw, _newcw);
410233b2
PA
160 return (_p);
161}
162
163static __inline fp_prec_t
164fpgetprec(void)
165{
166 unsigned short _cw;
167
5a8d63ad 168 _fnstcw(&_cw);
410233b2
PA
169 return ((fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF));
170}
171
172static __inline fp_prec_t
173fpsetprec(fp_prec_t _m)
174{
175 fp_prec_t _p;
176 unsigned short _cw, _newcw;
177
5a8d63ad 178 _fnstcw(&_cw);
410233b2
PA
179 _p = (fp_prec_t)((_cw & FP_PRC_FLD) >> FP_PRC_OFF);
180 _newcw = _cw & ~FP_PRC_FLD;
181 _newcw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;
5a8d63ad 182 _fnldcw(_cw, _newcw);
410233b2
PA
183 return (_p);
184}
fe667cd2
PA
185
186/*
410233b2
PA
187 * Get or set the exception mask.
188 * Note that the x87 mask bits are inverted by the API -- a mask bit of 1
189 * means disable for x87 and SSE, but for fp*mask() it means enable.
fe667cd2 190 */
410233b2
PA
191
192static __inline fp_except_t
193fpgetmask(void)
194{
195 unsigned short _cw;
196
5a8d63ad 197 _fnstcw(&_cw);
410233b2
PA
198 return ((~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF);
199}
200
201static __inline fp_except_t
202fpsetmask(fp_except_t _m)
203{
204 fp_except_t _p;
205 unsigned short _cw, _newcw;
206
5a8d63ad 207 _fnstcw(&_cw);
410233b2
PA
208 _p = (~_cw & FP_MSKS_FLD) >> FP_MSKS_OFF;
209 _newcw = _cw & ~FP_MSKS_FLD;
210 _newcw |= (~_m << FP_MSKS_OFF) & FP_MSKS_FLD;
5a8d63ad 211 _fnldcw(_cw, _newcw);
410233b2
PA
212 return (_p);
213}
214
215static __inline fp_except_t
216fpgetsticky(void)
217{
218 unsigned _ex;
219 unsigned short _sw;
220
5a8d63ad 221 _fnstsw(&_sw);
410233b2
PA
222 _ex = (_sw & FP_STKY_FLD) >> FP_STKY_OFF;
223 return ((fp_except_t)_ex);
224}
225
226static __inline fp_except_t
227fpresetsticky(fp_except_t _m)
228{
229 struct {
230 unsigned _cw;
231 unsigned _sw;
232 unsigned _other[5];
233 } _env;
234 fp_except_t _p;
235
236 _m &= FP_STKY_FLD >> FP_STKY_OFF;
237 _p = fpgetsticky();
238 if ((_p & ~_m) == _p)
239 return (_p);
240 if ((_p & ~_m) == 0) {
5a8d63ad 241 _fnclex();
410233b2
PA
242 return (_p);
243 }
5a8d63ad 244 _fnstenv(&_env);
410233b2 245 _env._sw &= ~_m;
5a8d63ad 246 _fldenv(&_env);
410233b2
PA
247 return (_p);
248}
249
250#endif /* __GNUC__ */
fe667cd2
PA
251
252/* Suppress prototypes in the MI header. */
253#define _IEEEFP_INLINED_ 1
254
88181b08 255#endif /* !_CPU_IEEEFP_H_ */