Add missing softfloat helpers.
[qemu] / fpu / softfloat-native.h
1 /* Native implementation of soft float functions */
2 #include <math.h>
3
4 #if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
5 #include <ieeefp.h>
6 #define fabsf(f) ((float)fabs(f))
7 #else
8 #include <fenv.h>
9 #endif
10
11 /*
12  * Define some C99-7.12.3 classification macros and
13  *        some C99-.12.4 for Solaris systems OS less than 10,
14  *        or Solaris 10 systems running GCC 3.x or less.
15  *   Solaris 10 with GCC4 does not need these macros as they
16  *   are defined in <iso/math_c99.h> with a compiler directive
17  */
18 #if defined(HOST_SOLARIS) && (( HOST_SOLARIS <= 9 ) || ( ( HOST_SOLARIS >= 10 ) && ( __GNUC__ <= 4) ))
19 /*
20  * C99 7.12.3 classification macros
21  * and
22  * C99 7.12.14 comparison macros
23  *
24  * ... do not work on Solaris 10 using GNU CC 3.4.x.
25  * Try to workaround the missing / broken C99 math macros.
26  */
27
28 #define isnormal(x)             (fpclass(x) >= FP_NZERO)
29 #define isgreater(x, y)         ((!unordered(x, y)) && ((x) > (y)))
30 #define isgreaterequal(x, y)    ((!unordered(x, y)) && ((x) >= (y)))
31 #define isless(x, y)            ((!unordered(x, y)) && ((x) < (y)))
32 #define islessequal(x, y)       ((!unordered(x, y)) && ((x) <= (y)))
33 #define isunordered(x,y)        unordered(x, y)
34 #endif
35
36 typedef float float32;
37 typedef double float64;
38 #ifdef FLOATX80
39 typedef long double floatx80;
40 #endif
41
42 typedef union {
43     float32 f;
44     uint32_t i;
45 } float32u;
46 typedef union {
47     float64 f;
48     uint64_t i;
49 } float64u;
50 #ifdef FLOATX80
51 typedef union {
52     floatx80 f;
53     struct {
54         uint64_t low;
55         uint16_t high;
56     } i;
57 } floatx80u;
58 #endif
59
60 /*----------------------------------------------------------------------------
61 | Software IEC/IEEE floating-point rounding mode.
62 *----------------------------------------------------------------------------*/
63 #if (defined(_BSD) && !defined(__APPLE__)) || defined(HOST_SOLARIS)
64 enum {
65     float_round_nearest_even = FP_RN,
66     float_round_down         = FP_RM,
67     float_round_up           = FP_RP,
68     float_round_to_zero      = FP_RZ
69 };
70 #elif defined(__arm__)
71 enum {
72     float_round_nearest_even = 0,
73     float_round_down         = 1,
74     float_round_up           = 2,
75     float_round_to_zero      = 3
76 };
77 #else
78 enum {
79     float_round_nearest_even = FE_TONEAREST,
80     float_round_down         = FE_DOWNWARD,
81     float_round_up           = FE_UPWARD,
82     float_round_to_zero      = FE_TOWARDZERO
83 };
84 #endif
85
86 typedef struct float_status {
87     signed char float_rounding_mode;
88 #ifdef FLOATX80
89     signed char floatx80_rounding_precision;
90 #endif
91 } float_status;
92
93 void set_float_rounding_mode(int val STATUS_PARAM);
94 #ifdef FLOATX80
95 void set_floatx80_rounding_precision(int val STATUS_PARAM);
96 #endif
97
98 /*----------------------------------------------------------------------------
99 | Software IEC/IEEE integer-to-floating-point conversion routines.
100 *----------------------------------------------------------------------------*/
101 float32 int32_to_float32( int STATUS_PARAM);
102 float32 uint32_to_float32( unsigned int STATUS_PARAM);
103 float64 int32_to_float64( int STATUS_PARAM);
104 float64 uint32_to_float64( unsigned int STATUS_PARAM);
105 #ifdef FLOATX80
106 floatx80 int32_to_floatx80( int STATUS_PARAM);
107 #endif
108 #ifdef FLOAT128
109 float128 int32_to_float128( int STATUS_PARAM);
110 #endif
111 float32 int64_to_float32( int64_t STATUS_PARAM);
112 float32 uint64_to_float32( uint64_t STATUS_PARAM);
113 float64 int64_to_float64( int64_t STATUS_PARAM);
114 float64 uint64_to_float64( uint64_t v STATUS_PARAM);
115 #ifdef FLOATX80
116 floatx80 int64_to_floatx80( int64_t STATUS_PARAM);
117 #endif
118 #ifdef FLOAT128
119 float128 int64_to_float128( int64_t STATUS_PARAM);
120 #endif
121
122 /*----------------------------------------------------------------------------
123 | Software IEC/IEEE single-precision conversion routines.
124 *----------------------------------------------------------------------------*/
125 int float32_to_int32( float32  STATUS_PARAM);
126 int float32_to_int32_round_to_zero( float32  STATUS_PARAM);
127 unsigned int float32_to_uint32( float32 a STATUS_PARAM);
128 unsigned int float32_to_uint32_round_to_zero( float32 a STATUS_PARAM);
129 int64_t float32_to_int64( float32  STATUS_PARAM);
130 int64_t float32_to_int64_round_to_zero( float32  STATUS_PARAM);
131 float64 float32_to_float64( float32  STATUS_PARAM);
132 #ifdef FLOATX80
133 floatx80 float32_to_floatx80( float32  STATUS_PARAM);
134 #endif
135 #ifdef FLOAT128
136 float128 float32_to_float128( float32  STATUS_PARAM);
137 #endif
138
139 /*----------------------------------------------------------------------------
140 | Software IEC/IEEE single-precision operations.
141 *----------------------------------------------------------------------------*/
142 float32 float32_round_to_int( float32  STATUS_PARAM);
143 INLINE float32 float32_add( float32 a, float32 b STATUS_PARAM)
144 {
145     return a + b;
146 }
147 INLINE float32 float32_sub( float32 a, float32 b STATUS_PARAM)
148 {
149     return a - b;
150 }
151 INLINE float32 float32_mul( float32 a, float32 b STATUS_PARAM)
152 {
153     return a * b;
154 }
155 INLINE float32 float32_div( float32 a, float32 b STATUS_PARAM)
156 {
157     return a / b;
158 }
159 float32 float32_rem( float32, float32  STATUS_PARAM);
160 float32 float32_sqrt( float32  STATUS_PARAM);
161 INLINE int float32_eq( float32 a, float32 b STATUS_PARAM)
162 {
163     return a == b;
164 }
165 INLINE int float32_le( float32 a, float32 b STATUS_PARAM)
166 {
167     return a <= b;
168 }
169 INLINE int float32_lt( float32 a, float32 b STATUS_PARAM)
170 {
171     return a < b;
172 }
173 INLINE int float32_eq_signaling( float32 a, float32 b STATUS_PARAM)
174 {
175     return a <= b && a >= b;
176 }
177 INLINE int float32_le_quiet( float32 a, float32 b STATUS_PARAM)
178 {
179     return islessequal(a, b);
180 }
181 INLINE int float32_lt_quiet( float32 a, float32 b STATUS_PARAM)
182 {
183     return isless(a, b);
184 }
185 INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
186 {
187     return isunordered(a, b);
188
189 }
190 int float32_compare( float32, float32 STATUS_PARAM );
191 int float32_compare_quiet( float32, float32 STATUS_PARAM );
192 int float32_is_signaling_nan( float32 );
193
194 INLINE float32 float32_abs(float32 a)
195 {
196     return fabsf(a);
197 }
198
199 INLINE float32 float32_chs(float32 a)
200 {
201     return -a;
202 }
203
204 /*----------------------------------------------------------------------------
205 | Software IEC/IEEE double-precision conversion routines.
206 *----------------------------------------------------------------------------*/
207 int float64_to_int32( float64 STATUS_PARAM );
208 int float64_to_int32_round_to_zero( float64 STATUS_PARAM );
209 unsigned int float64_to_uint32( float64 STATUS_PARAM );
210 unsigned int float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
211 int64_t float64_to_int64( float64 STATUS_PARAM );
212 int64_t float64_to_int64_round_to_zero( float64 STATUS_PARAM );
213 uint64_t float64_to_uint64( float64 STATUS_PARAM );
214 uint64_t float64_to_uint64_round_to_zero( float64 STATUS_PARAM );
215 float32 float64_to_float32( float64 STATUS_PARAM );
216 #ifdef FLOATX80
217 floatx80 float64_to_floatx80( float64 STATUS_PARAM );
218 #endif
219 #ifdef FLOAT128
220 float128 float64_to_float128( float64 STATUS_PARAM );
221 #endif
222
223 /*----------------------------------------------------------------------------
224 | Software IEC/IEEE double-precision operations.
225 *----------------------------------------------------------------------------*/
226 float64 float64_round_to_int( float64 STATUS_PARAM );
227 float64 float64_trunc_to_int( float64 STATUS_PARAM );
228 INLINE float64 float64_add( float64 a, float64 b STATUS_PARAM)
229 {
230     return a + b;
231 }
232 INLINE float64 float64_sub( float64 a, float64 b STATUS_PARAM)
233 {
234     return a - b;
235 }
236 INLINE float64 float64_mul( float64 a, float64 b STATUS_PARAM)
237 {
238     return a * b;
239 }
240 INLINE float64 float64_div( float64 a, float64 b STATUS_PARAM)
241 {
242     return a / b;
243 }
244 float64 float64_rem( float64, float64 STATUS_PARAM );
245 float64 float64_sqrt( float64 STATUS_PARAM );
246 INLINE int float64_eq( float64 a, float64 b STATUS_PARAM)
247 {
248     return a == b;
249 }
250 INLINE int float64_le( float64 a, float64 b STATUS_PARAM)
251 {
252     return a <= b;
253 }
254 INLINE int float64_lt( float64 a, float64 b STATUS_PARAM)
255 {
256     return a < b;
257 }
258 INLINE int float64_eq_signaling( float64 a, float64 b STATUS_PARAM)
259 {
260     return a <= b && a >= b;
261 }
262 INLINE int float64_le_quiet( float64 a, float64 b STATUS_PARAM)
263 {
264     return islessequal(a, b);
265 }
266 INLINE int float64_lt_quiet( float64 a, float64 b STATUS_PARAM)
267 {
268     return isless(a, b);
269
270 }
271 INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
272 {
273     return isunordered(a, b);
274
275 }
276 int float64_compare( float64, float64 STATUS_PARAM );
277 int float64_compare_quiet( float64, float64 STATUS_PARAM );
278 int float64_is_signaling_nan( float64 );
279 int float64_is_nan( float64 );
280
281 INLINE float64 float64_abs(float64 a)
282 {
283     return fabs(a);
284 }
285
286 INLINE float64 float64_chs(float64 a)
287 {
288     return -a;
289 }
290
291 #ifdef FLOATX80
292
293 /*----------------------------------------------------------------------------
294 | Software IEC/IEEE extended double-precision conversion routines.
295 *----------------------------------------------------------------------------*/
296 int floatx80_to_int32( floatx80 STATUS_PARAM );
297 int floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
298 int64_t floatx80_to_int64( floatx80 STATUS_PARAM);
299 int64_t floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM);
300 float32 floatx80_to_float32( floatx80 STATUS_PARAM );
301 float64 floatx80_to_float64( floatx80 STATUS_PARAM );
302 #ifdef FLOAT128
303 float128 floatx80_to_float128( floatx80 STATUS_PARAM );
304 #endif
305
306 /*----------------------------------------------------------------------------
307 | Software IEC/IEEE extended double-precision operations.
308 *----------------------------------------------------------------------------*/
309 floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
310 INLINE floatx80 floatx80_add( floatx80 a, floatx80 b STATUS_PARAM)
311 {
312     return a + b;
313 }
314 INLINE floatx80 floatx80_sub( floatx80 a, floatx80 b STATUS_PARAM)
315 {
316     return a - b;
317 }
318 INLINE floatx80 floatx80_mul( floatx80 a, floatx80 b STATUS_PARAM)
319 {
320     return a * b;
321 }
322 INLINE floatx80 floatx80_div( floatx80 a, floatx80 b STATUS_PARAM)
323 {
324     return a / b;
325 }
326 floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
327 floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
328 INLINE int floatx80_eq( floatx80 a, floatx80 b STATUS_PARAM)
329 {
330     return a == b;
331 }
332 INLINE int floatx80_le( floatx80 a, floatx80 b STATUS_PARAM)
333 {
334     return a <= b;
335 }
336 INLINE int floatx80_lt( floatx80 a, floatx80 b STATUS_PARAM)
337 {
338     return a < b;
339 }
340 INLINE int floatx80_eq_signaling( floatx80 a, floatx80 b STATUS_PARAM)
341 {
342     return a <= b && a >= b;
343 }
344 INLINE int floatx80_le_quiet( floatx80 a, floatx80 b STATUS_PARAM)
345 {
346     return islessequal(a, b);
347 }
348 INLINE int floatx80_lt_quiet( floatx80 a, floatx80 b STATUS_PARAM)
349 {
350     return isless(a, b);
351
352 }
353 INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
354 {
355     return isunordered(a, b);
356
357 }
358 int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
359 int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
360 int floatx80_is_signaling_nan( floatx80 );
361
362 INLINE floatx80 floatx80_abs(floatx80 a)
363 {
364     return fabsl(a);
365 }
366
367 INLINE floatx80 floatx80_chs(floatx80 a)
368 {
369     return -a;
370 }
371 #endif