]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i386/include/ieeefp.h
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i386 / include / ieeefp.h
1 /*-
2  * Copyright (c) 1990 Andrew Moore, Talke Studio
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  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *      from: @(#) ieeefp.h     1.0 (Berkeley) 9/23/93
34  * $FreeBSD$
35  */
36
37 /*
38  *      IEEE floating point type and constant definitions.
39  */
40
41 #ifndef _MACHINE_IEEEFP_H_
42 #define _MACHINE_IEEEFP_H_
43
44 #ifndef _SYS_CDEFS_H_
45 #error this file needs sys/cdefs.h as a prerequisite
46 #endif
47
48 /*
49  * FP rounding modes
50  */
51 typedef enum {
52         FP_RN=0,        /* round to nearest */
53         FP_RM,          /* round down to minus infinity */
54         FP_RP,          /* round up to plus infinity */
55         FP_RZ           /* truncate */
56 } fp_rnd_t;
57
58 /*
59  * FP precision modes
60  */
61 typedef enum {
62         FP_PS=0,        /* 24 bit (single-precision) */
63         FP_PRS,         /* reserved */
64         FP_PD,          /* 53 bit (double-precision) */
65         FP_PE           /* 64 bit (extended-precision) */
66 } fp_prec_t;
67
68 #define fp_except_t     int
69
70 /*
71  * FP exception masks
72  */
73 #define FP_X_INV        0x01    /* invalid operation */
74 #define FP_X_DNML       0x02    /* denormal */
75 #define FP_X_DZ         0x04    /* zero divide */
76 #define FP_X_OFL        0x08    /* overflow */
77 #define FP_X_UFL        0x10    /* underflow */
78 #define FP_X_IMP        0x20    /* (im)precision */
79 #define FP_X_STK        0x40    /* stack fault */
80
81 /*
82  * FP registers
83  */
84 #define FP_MSKS_REG     0       /* exception masks */
85 #define FP_PRC_REG      0       /* precision */
86 #define FP_RND_REG      0       /* direction */
87 #define FP_STKY_REG     1       /* sticky flags */
88
89 /*
90  * FP register bit field masks
91  */
92 #define FP_MSKS_FLD     0x3f    /* exception masks field */
93 #define FP_PRC_FLD      0x300   /* precision control field */
94 #define FP_RND_FLD      0xc00   /* round control field */
95 #define FP_STKY_FLD     0x3f    /* sticky flags field */
96
97 /*
98  * FP register bit field offsets
99  */
100 #define FP_MSKS_OFF     0       /* exception masks offset */
101 #define FP_PRC_OFF      8       /* precision control offset */
102 #define FP_RND_OFF      10      /* round control offset */
103 #define FP_STKY_OFF     0       /* sticky flags offset */
104
105 #ifdef __GNUCLIKE_ASM
106
107 #define __fldenv(addr)  __asm __volatile("fldenv %0" : : "m" (*(addr)))
108 #define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
109 #define __fnstcw(addr)  __asm __volatile("fnstcw %0" : "=m" (*(addr)))
110 #define __fnstsw(addr)  __asm __volatile("fnstsw %0" : "=m" (*(addr)))
111
112 /*
113  * return the contents of a FP register
114  */
115 static __inline__ int
116 __fpgetreg(int _reg)
117 {
118         unsigned short _mem;
119
120         /*-
121          * This is more efficient than it looks.  The switch gets optimized
122          * away if _reg is constant.
123          *
124          * The default case only supports _reg == 0.  We could handle more
125          * registers (e.g., tags) using fnstenv, but the interface doesn't
126          * support more.
127          */
128         switch(_reg) {
129         default:
130                 __fnstcw(&_mem);
131                 break;
132         case FP_STKY_REG:
133                 __fnstsw(&_mem);
134                 break;
135         }
136         return _mem;
137 }
138
139 /*
140  * set a FP mode; return previous mode
141  */
142 static __inline__ int
143 __fpsetreg(int _m, int _reg, int _fld, int _off)
144 {
145         unsigned _env[7];
146         unsigned _p;
147
148         /*
149          * _reg == 0 could be handled better using fnstcw/fldcw.
150          */
151         __fnstenv(_env);
152         _p =  (_env[_reg] & _fld) >> _off;
153         _env[_reg] = (_env[_reg] & ~_fld) | (_m << _off & _fld);
154         __fldenv(_env);
155         return _p;
156 }
157
158 #endif /* __GNUCLIKE_ASM */
159
160 /*
161  * SysV/386 FP control interface
162  */
163 #define fpgetround()    ((fp_rnd_t)                                     \
164         ((__fpgetreg(FP_RND_REG) & FP_RND_FLD) >> FP_RND_OFF))
165 #define fpsetround(m)   ((fp_rnd_t)                                     \
166         __fpsetreg((m), FP_RND_REG, FP_RND_FLD, FP_RND_OFF))
167 #define fpgetprec()     ((fp_prec_t)                                    \
168         ((__fpgetreg(FP_PRC_REG) & FP_PRC_FLD) >> FP_PRC_OFF))
169 #define fpsetprec(m)    ((fp_prec_t)                                    \
170         __fpsetreg((m), FP_PRC_REG, FP_PRC_FLD, FP_PRC_OFF))
171 #define fpgetmask()     ((fp_except_t)                                  \
172         ((~__fpgetreg(FP_MSKS_REG) & FP_MSKS_FLD) >> FP_MSKS_OFF))
173 #define fpsetmask(m)    ((fp_except_t)                                  \
174         (~__fpsetreg(~(m), FP_MSKS_REG, FP_MSKS_FLD, FP_MSKS_OFF)) &    \
175             (FP_MSKS_FLD >> FP_MSKS_OFF))
176 #define fpgetsticky()   ((fp_except_t)                                  \
177         ((__fpgetreg(FP_STKY_REG) & FP_STKY_FLD) >> FP_STKY_OFF))
178 #define fpresetsticky(m) ((fp_except_t)                                 \
179         __fpsetreg(0, FP_STKY_REG, (m), FP_STKY_OFF))
180
181 /* Suppress prototypes in the MI header. */
182 #define _IEEEFP_INLINED_        1
183
184 #endif /* !_MACHINE_IEEEFP_H_ */