soft float support
[qemu] / fpu / softfloat-native.h
1 /* Native implementation of soft float functions */
2 #include <math.h>
3 #if defined(_BSD) && !defined(__APPLE__)
4 #include <ieeefp.h>
5 #else
6 #include <fenv.h>
7 #endif
8
9 typedef float float32;
10 typedef double float64;
11 #ifdef FLOATX80
12 typedef long double floatx80;
13 #endif
14
15 typedef union {
16     float32 f;
17     uint32_t i;
18 } float32u;
19 typedef union {
20     float64 f;
21     uint64_t i;
22 } float64u;
23 #ifdef FLOATX80
24 typedef union {
25     floatx80 f;
26     struct {
27         uint64_t low;
28         uint16_t high;
29     } i;
30 } floatx80u;
31 #endif
32
33 /*----------------------------------------------------------------------------
34 | Software IEC/IEEE floating-point rounding mode.
35 *----------------------------------------------------------------------------*/
36 #if defined(_BSD) && !defined(__APPLE__)
37 enum {
38     float_round_nearest_even = FP_RN,
39     float_round_down         = FE_RM,
40     float_round_up           = FE_RP,
41     float_round_to_zero      = FE_RZ
42 };
43 #elif defined(__arm__)
44 enum {
45     float_round_nearest_even = 0,
46     float_round_down         = 1,
47     float_round_up           = 2,
48     float_round_to_zero      = 3
49 };
50 #else
51 enum {
52     float_round_nearest_even = FE_TONEAREST,
53     float_round_down         = FE_DOWNWARD,
54     float_round_up           = FE_UPWARD,
55     float_round_to_zero      = FE_TOWARDZERO
56 };
57 #endif
58
59 typedef struct float_status {
60     signed char float_rounding_mode;
61 #ifdef FLOATX80
62     signed char floatx80_rounding_precision;
63 #endif
64 } float_status;
65
66 void set_float_rounding_mode(int val STATUS_PARAM);
67 #ifdef FLOATX80
68 void set_floatx80_rounding_precision(int val STATUS_PARAM);
69 #endif
70
71 /*----------------------------------------------------------------------------
72 | Software IEC/IEEE integer-to-floating-point conversion routines.
73 *----------------------------------------------------------------------------*/
74 float32 int32_to_float32( int STATUS_PARAM);
75 float64 int32_to_float64( int STATUS_PARAM);
76 #ifdef FLOATX80
77 floatx80 int32_to_floatx80( int STATUS_PARAM);
78 #endif
79 #ifdef FLOAT128
80 float128 int32_to_float128( int STATUS_PARAM);
81 #endif
82 float32 int64_to_float32( int64_t STATUS_PARAM);
83 float64 int64_to_float64( int64_t STATUS_PARAM);
84 #ifdef FLOATX80
85 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
86 #endif
87 #ifdef FLOAT128
88 float128 int64_to_float128( int64_t STATUS_PARAM);
89 #endif
90
91 /*----------------------------------------------------------------------------
92 | Software IEC/IEEE single-precision conversion routines.
93 *----------------------------------------------------------------------------*/
94 int float32_to_int32( float32  STATUS_PARAM);
95 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
96 int64_t float32_to_int64( float32  STATUS_PARAM);
97 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
98 float64 float32_to_float64( float32  STATUS_PARAM);
99 #ifdef FLOATX80
100 floatx80 float32_to_floatx80( float32  STATUS_PARAM);
101 #endif
102 #ifdef FLOAT128
103 float128 float32_to_float128( float32  STATUS_PARAM);
104 #endif
105
106 /*----------------------------------------------------------------------------
107 | Software IEC/IEEE single-precision operations.
108 *----------------------------------------------------------------------------*/
109 float32 float32_round_to_int( float32  STATUS_PARAM);
110 INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
111 {
112     return a + b;
113 }
114 INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
115 {
116     return a - b;
117 }
118 INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
119 {
120     return a * b;
121 }
122 INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
123 {
124     return a / b;
125 }
126 float32 float32_rem( float32, float32  STATUS_PARAM);
127 float32 float32_sqrt( float32  STATUS_PARAM);
128 INLINE char float32_eq( float32 a, float32 b STATUS_PARAM)
129 {
130     /* XXX: incorrect because it can raise an exception */
131     return a == b;
132 }
133 INLINE char float32_le( float32 a, float32 b STATUS_PARAM)
134 {
135     return a <= b;
136 }
137 INLINE char float32_lt( float32 a, float32 b STATUS_PARAM)
138 {
139     return a < b;
140 }
141 INLINE char float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
142 {
143     return a == b;
144 }
145 INLINE char float32_le_quiet( float32 a, float32 b STATUS_PARAM)
146 {
147     return islessequal(a, b);
148 }
149 INLINE char float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
150 {
151     return isless(a, b);
152 }
153 char float32_is_signaling_nan( float32 );
154
155 INLINE float32 float32_abs(float32 a)
156 {
157     return fabsf(a);
158 }
159
160 INLINE float32 float32_chs(float32 a)
161 {
162     return -a;
163 }
164
165 /*----------------------------------------------------------------------------
166 | Software IEC/IEEE double-precision conversion routines.
167 *----------------------------------------------------------------------------*/
168 int float64_to_int32( float64 STATUS_PARAM );
169 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
170 int64_t float64_to_int64( float64 STATUS_PARAM );
171 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
172 float32 float64_to_float32( float64 STATUS_PARAM );
173 #ifdef FLOATX80
174 floatx80 float64_to_floatx80( float64 STATUS_PARAM );
175 #endif
176 #ifdef FLOAT128
177 float128 float64_to_float128( float64 STATUS_PARAM );
178 #endif
179
180 /*----------------------------------------------------------------------------
181 | Software IEC/IEEE double-precision operations.
182 *----------------------------------------------------------------------------*/
183 float64 float64_round_to_int( float64 STATUS_PARAM );
184 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
185 {
186     return a + b;
187 }
188 INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
189 {
190     return a - b;
191 }
192 INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
193 {
194     return a * b;
195 }
196 INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
197 {
198     return a / b;
199 }
200 float64 float64_rem( float64, float64 STATUS_PARAM );
201 float64 float64_sqrt( float64 STATUS_PARAM );
202 INLINE char float64_eq( float64 a, float64 b STATUS_PARAM)
203 {
204     return a == b;
205 }
206 INLINE char float64_le( float64 a, float64 b STATUS_PARAM)
207 {
208     return a <= b;
209 }
210 INLINE char float64_lt( float64 a, float64 b STATUS_PARAM)
211 {
212     return a < b;
213 }
214 INLINE char float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
215 {
216     return a == b;
217 }
218 INLINE char float64_le_quiet( float64 a, float64 b STATUS_PARAM)
219 {
220     return islessequal(a, b);
221 }
222 INLINE char float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
223 {
224     return isless(a, b);
225
226 }
227 char float64_is_signaling_nan( float64 );
228
229 INLINE float64 float64_abs(float64 a)
230 {
231     return fabs(a);
232 }
233
234 INLINE float64 float64_chs(float64 a)
235 {
236     return -a;
237 }
238
239 #ifdef FLOATX80
240
241 /*----------------------------------------------------------------------------
242 | Software IEC/IEEE extended double-precision conversion routines.
243 *----------------------------------------------------------------------------*/
244 int floatx80_to_int32( floatx80 STATUS_PARAM );
245 int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
246 int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
247 int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
248 float32 floatx80_to_float32( floatx80 STATUS_PARAM );
249 float64 floatx80_to_float64( floatx80 STATUS_PARAM );
250 #ifdef FLOAT128
251 float128 floatx80_to_float128( floatx80 STATUS_PARAM );
252 #endif
253
254 /*----------------------------------------------------------------------------
255 | Software IEC/IEEE extended double-precision operations.
256 *----------------------------------------------------------------------------*/
257 floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
258 INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
259 {
260     return a + b;
261 }
262 INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
263 {
264     return a - b;
265 }
266 INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
267 {
268     return a * b;
269 }
270 INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
271 {
272     return a / b;
273 }
274 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
275 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
276 INLINE char floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
277 {
278     return a == b;
279 }
280 INLINE char floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
281 {
282     return a <= b;
283 }
284 INLINE char floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
285 {
286     return a < b;
287 }
288 INLINE char floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
289 {
290     return a == b;
291 }
292 INLINE char floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
293 {
294     return islessequal(a, b);
295 }
296 INLINE char floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
297 {
298     return isless(a, b);
299
300 }
301 char floatx80_is_signaling_nan( floatx80 );
302
303 INLINE floatx80 floatx80_abs(floatx80 a)
304 {
305     return fabsl(a);
306 }
307
308 INLINE floatx80 floatx80_chs(floatx80 a)
309 {
310     return -a;
311 }
312 #endif