ieeefp.h revision 175232
1/*-
2 * Copyright (c) 2003 Peter Wemm.
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
35 * $FreeBSD: head/sys/i386/include/ieeefp.h 175232 2008-01-11 17:54:20Z bde $
36 */
37
38#ifndef _MACHINE_IEEEFP_H_
39#define _MACHINE_IEEEFP_H_
40
41/*
42 * IEEE floating point type, constant and function definitions.
43 * XXX: FP*FLD, FP*REG and FP*OFF are undocumented pollution.
44 */
45
46#ifndef _SYS_CDEFS_H_
47#error this file needs sys/cdefs.h as a prerequisite
48#endif
49
50/*
51 * Rounding modes.
52 */
53typedef enum {
54	FP_RN=0,	/* round to nearest */
55	FP_RM,		/* round down towards minus infinity */
56	FP_RP,		/* round up towards plus infinity */
57	FP_RZ		/* truncate */
58} fp_rnd_t;
59
60/*
61 * Precision (i.e., rounding precision) modes.
62 */
63typedef enum {
64	FP_PS=0,	/* 24 bit (single-precision) */
65	FP_PRS,		/* reserved */
66	FP_PD,		/* 53 bit (double-precision) */
67	FP_PE		/* 64 bit (extended-precision) */
68} fp_prec_t;
69
70#define fp_except_t	int
71
72/*
73 * Exception bit masks.
74 */
75#define FP_X_INV	0x01	/* invalid operation */
76#define FP_X_DNML	0x02	/* denormal */
77#define FP_X_DZ		0x04	/* zero divide */
78#define FP_X_OFL	0x08	/* overflow */
79#define FP_X_UFL	0x10	/* underflow */
80#define FP_X_IMP	0x20	/* (im)precision */
81#define FP_X_STK	0x40	/* stack fault */
82
83/*
84 * FPU control and status register numbers (indexes into the env array).
85 */
86#define FP_MSKS_REG	0	/* exception masks */
87#define FP_PRC_REG	0	/* precision */
88#define FP_RND_REG	0	/* direction */
89#define FP_STKY_REG	1	/* sticky flags */
90
91/*
92 * FPU control word bit-field masks.
93 */
94#define FP_MSKS_FLD	0x3f	/* exception masks field */
95#define FP_PRC_FLD	0x300	/* precision control field */
96#define	FP_RND_FLD	0xc00	/* rounding control field */
97
98/*
99 * FPU status word bit-field masks.
100 */
101#define FP_STKY_FLD	0x3f	/* sticky flags field */
102
103/*
104 * FPU control word bit-field offsets (shift counts).
105 */
106#define FP_MSKS_OFF	0	/* exception masks offset */
107#define FP_PRC_OFF	8	/* precision control offset */
108#define	FP_RND_OFF	10	/* rounding control offset */
109
110/*
111 * FPU status word bit-field offsets (shift counts).
112 */
113#define FP_STKY_OFF	0	/* sticky flags offset */
114
115#ifdef __GNUCLIKE_ASM
116
117#define	__fldenv(addr)	__asm __volatile("fldenv %0" : : "m" (*(addr)))
118#define	__fnstcw(addr)	__asm __volatile("fnstcw %0" : "=m" (*(addr)))
119#define	__fnstenv(addr)	__asm __volatile("fnstenv %0" : "=m" (*(addr)))
120#define	__fnstsw(addr)	__asm __volatile("fnstsw %0" : "=m" (*(addr)))
121
122/*
123 * return the contents of a FP register
124 */
125static __inline__ int
126__fpgetreg(int _reg)
127{
128	unsigned short _mem;
129
130	/*-
131	 * This is more efficient than it looks.  The switch gets optimized
132	 * away if _reg is constant.
133	 *
134	 * The default case only supports _reg == 0.  We could handle more
135	 * registers (e.g., tags) using fnstenv, but the interface doesn't
136	 * support more.
137	 */
138	switch(_reg) {
139	default:
140		__fnstcw(&_mem);
141		break;
142	case FP_STKY_REG:
143		__fnstsw(&_mem);
144		break;
145	}
146	return _mem;
147}
148
149/*
150 * set a FP mode; return previous mode
151 */
152static __inline__ int
153__fpsetreg(int _m, int _reg, int _fld, int _off)
154{
155	unsigned _env[7];
156	unsigned _p;
157
158	/*
159	 * _reg == 0 could be handled better using fnstcw/fldcw.
160	 */
161	__fnstenv(_env);
162	_p =  (_env[_reg] & _fld) >> _off;
163	_env[_reg] = (_env[_reg] & ~_fld) | (_m << _off & _fld);
164	__fldenv(_env);
165	return _p;
166}
167
168#endif /* __GNUCLIKE_ASM */
169
170/*
171 * SysV/386 FP control interface
172 */
173#define	fpgetround()	((fp_rnd_t)					\
174	((__fpgetreg(FP_RND_REG) & FP_RND_FLD) >> FP_RND_OFF))
175#define	fpsetround(m)	((fp_rnd_t)					\
176	__fpsetreg((m), FP_RND_REG, FP_RND_FLD, FP_RND_OFF))
177#define	fpgetprec()	((fp_prec_t)					\
178	((__fpgetreg(FP_PRC_REG) & FP_PRC_FLD) >> FP_PRC_OFF))
179#define	fpsetprec(m)	((fp_prec_t)					\
180	__fpsetreg((m), FP_PRC_REG, FP_PRC_FLD, FP_PRC_OFF))
181#define	fpgetmask()	((fp_except_t)					\
182	((~__fpgetreg(FP_MSKS_REG) & FP_MSKS_FLD) >> FP_MSKS_OFF))
183#define	fpsetmask(m)	((fp_except_t)					\
184	(~__fpsetreg(~(m), FP_MSKS_REG, FP_MSKS_FLD, FP_MSKS_OFF)) &	\
185	    (FP_MSKS_FLD >> FP_MSKS_OFF))
186#define	fpgetsticky()	((fp_except_t)					\
187	((__fpgetreg(FP_STKY_REG) & FP_STKY_FLD) >> FP_STKY_OFF))
188#define	fpresetsticky(m) ((fp_except_t)					\
189	__fpsetreg(0, FP_STKY_REG, (m), FP_STKY_OFF))
190
191/* Suppress prototypes in the MI header. */
192#define	_IEEEFP_INLINED_	1
193
194#endif /* !_MACHINE_IEEEFP_H_ */
195