linux-user: Add LoongArch syscall support
[qemu/rayw.git] / tests / fp / wrap.c.inc
blob9ff884c140be82487f4d63e585b6cfc092c6f230
1 /*
2  * In this file we wrap QEMU FP functions to look like softfloat/testfloat's,
3  * so that we can use the testfloat infrastructure as-is.
4  *
5  * This file must be included directly from fp-test.c. We could compile it
6  * separately, but it would be tedious to add declarations for all the wrappers.
7  */
9 static signed char sf_tininess_to_qemu(uint_fast8_t mode)
11     switch (mode) {
12     case softfloat_tininess_beforeRounding:
13         return float_tininess_before_rounding;
14     case softfloat_tininess_afterRounding:
15         return float_tininess_after_rounding;
16     default:
17         g_assert_not_reached();
18     }
21 static signed char sf_rounding_to_qemu(uint_fast8_t mode)
23     switch (mode) {
24     case softfloat_round_near_even:
25         return float_round_nearest_even;
26     case softfloat_round_minMag:
27         return float_round_to_zero;
28     case softfloat_round_min:
29         return float_round_down;
30     case softfloat_round_max:
31         return float_round_up;
32     case softfloat_round_near_maxMag:
33         return float_round_ties_away;
34     case softfloat_round_odd:
35         return float_round_to_odd;
36     default:
37         g_assert_not_reached();
38     }
41 static uint_fast8_t qemu_flags_to_sf(uint8_t qflags)
43     uint_fast8_t ret = 0;
45     if (qflags & float_flag_invalid) {
46         ret |= softfloat_flag_invalid;
47     }
48     if (qflags & float_flag_divbyzero) {
49         ret |= softfloat_flag_infinite;
50     }
51     if (qflags & float_flag_overflow) {
52         ret |= softfloat_flag_overflow;
53     }
54     if (qflags & float_flag_underflow) {
55         ret |= softfloat_flag_underflow;
56     }
57     if (qflags & float_flag_inexact) {
58         ret |= softfloat_flag_inexact;
59     }
60     return ret;
64  * floatx80 and float128 cannot be cast between qemu and softfloat, because
65  * in softfloat the order of the fields depends on the host's endianness.
66  */
67 static extFloat80_t qemu_to_soft80(floatx80 a)
69     extFloat80_t ret;
71     ret.signif = a.low;
72     ret.signExp = a.high;
73     return ret;
76 static floatx80 soft_to_qemu80(extFloat80_t a)
78     floatx80 ret;
80     ret.low = a.signif;
81     ret.high = a.signExp;
82     return ret;
85 static float128_t qemu_to_soft128(float128 a)
87     float128_t ret;
88     struct uint128 *to = (struct uint128 *)&ret;
90     to->v0 = a.low;
91     to->v64 = a.high;
92     return ret;
95 static float128 soft_to_qemu128(float128_t a)
97     struct uint128 *from = (struct uint128 *)&a;
98     float128 ret;
100     ret.low = from->v0;
101     ret.high = from->v64;
102     return ret;
105 /* conversions */
106 #define WRAP_SF_TO_SF_IEEE(name, func, a_type, b_type)  \
107     static b_type##_t name(a_type##_t a)                \
108     {                                                   \
109         a_type *ap = (a_type *)&a;                      \
110         b_type ret;                                     \
111                                                         \
112         ret = func(*ap, true, &qsf);                    \
113         return *(b_type##_t *)&ret;                     \
114     }
116 WRAP_SF_TO_SF_IEEE(qemu_f16_to_f32, float16_to_float32, float16, float32)
117 WRAP_SF_TO_SF_IEEE(qemu_f16_to_f64, float16_to_float64, float16, float64)
119 WRAP_SF_TO_SF_IEEE(qemu_f32_to_f16, float32_to_float16, float32, float16)
120 WRAP_SF_TO_SF_IEEE(qemu_f64_to_f16, float64_to_float16, float64, float16)
121 #undef WRAP_SF_TO_SF_IEEE
123 #define WRAP_SF_TO_SF(name, func, a_type, b_type)       \
124     static b_type##_t name(a_type##_t a)                \
125     {                                                   \
126         a_type *ap = (a_type *)&a;                      \
127         b_type ret;                                     \
128                                                         \
129         ret = func(*ap, &qsf);                          \
130         return *(b_type##_t *)&ret;                     \
131     }
133 WRAP_SF_TO_SF(qemu_f32_to_f64, float32_to_float64, float32, float64)
134 WRAP_SF_TO_SF(qemu_f64_to_f32, float64_to_float32, float64, float32)
135 #undef WRAP_SF_TO_SF
137 #define WRAP_SF_TO_80(name, func, type)                 \
138     static void name(type##_t a, extFloat80_t *res)     \
139     {                                                   \
140         floatx80 ret;                                   \
141         type *ap = (type *)&a;                          \
142                                                         \
143         ret = func(*ap, &qsf);                          \
144         *res = qemu_to_soft80(ret);                     \
145     }
147 WRAP_SF_TO_80(qemu_f32_to_extF80M, float32_to_floatx80, float32)
148 WRAP_SF_TO_80(qemu_f64_to_extF80M, float64_to_floatx80, float64)
149 #undef WRAP_SF_TO_80
151 #define WRAP_SF_TO_128(name, func, type)                \
152     static void name(type##_t a, float128_t *res)       \
153     {                                                   \
154         float128 ret;                                   \
155         type *ap = (type *)&a;                          \
156                                                         \
157         ret = func(*ap, &qsf);                          \
158         *res = qemu_to_soft128(ret);                    \
159     }
161 WRAP_SF_TO_128(qemu_f32_to_f128M, float32_to_float128, float32)
162 WRAP_SF_TO_128(qemu_f64_to_f128M, float64_to_float128, float64)
163 #undef WRAP_SF_TO_128
165 /* Note: exact is ignored since qemu's softfloat assumes it is set */
166 #define WRAP_SF_TO_INT(name, func, type, fast_type)                     \
167     static fast_type name(type##_t a, uint_fast8_t round, bool exact)   \
168     {                                                                   \
169         type *ap = (type *)&a;                                          \
170                                                                         \
171         qsf.float_rounding_mode = sf_rounding_to_qemu(round);           \
172         return func(*ap, &qsf);                                         \
173     }
175 WRAP_SF_TO_INT(qemu_f16_to_ui32, float16_to_uint32, float16, uint_fast32_t)
176 WRAP_SF_TO_INT(qemu_f16_to_ui64, float16_to_uint64, float16, uint_fast64_t)
178 WRAP_SF_TO_INT(qemu_f32_to_ui32, float32_to_uint32, float32, uint_fast32_t)
179 WRAP_SF_TO_INT(qemu_f32_to_ui64, float32_to_uint64, float32, uint_fast64_t)
181 WRAP_SF_TO_INT(qemu_f64_to_ui32, float64_to_uint32, float64, uint_fast32_t)
182 WRAP_SF_TO_INT(qemu_f64_to_ui64, float64_to_uint64, float64, uint_fast64_t)
184 WRAP_SF_TO_INT(qemu_f16_to_i32, float16_to_int32, float16, int_fast32_t)
185 WRAP_SF_TO_INT(qemu_f16_to_i64, float16_to_int64, float16, int_fast64_t)
187 WRAP_SF_TO_INT(qemu_f32_to_i32, float32_to_int32, float32, int_fast32_t)
188 WRAP_SF_TO_INT(qemu_f32_to_i64, float32_to_int64, float32, int_fast64_t)
190 WRAP_SF_TO_INT(qemu_f64_to_i32, float64_to_int32, float64, int_fast32_t)
191 WRAP_SF_TO_INT(qemu_f64_to_i64, float64_to_int64, float64, int_fast64_t)
192 #undef WRAP_SF_TO_INT
194 /* Note: exact is ignored since qemu's softfloat assumes it is set */
195 #define WRAP_SF_TO_INT_MINMAG(name, func, type, fast_type)      \
196     static fast_type name(type##_t a, bool exact)               \
197     {                                                           \
198         type *ap = (type *)&a;                                  \
199                                                                 \
200         return func(*ap, &qsf);                                 \
201     }
203 WRAP_SF_TO_INT_MINMAG(qemu_f16_to_ui32_r_minMag,
204                       float16_to_uint32_round_to_zero, float16, uint_fast32_t)
205 WRAP_SF_TO_INT_MINMAG(qemu_f16_to_ui64_r_minMag,
206                       float16_to_uint64_round_to_zero, float16, uint_fast64_t)
208 WRAP_SF_TO_INT_MINMAG(qemu_f16_to_i32_r_minMag,
209                       float16_to_int32_round_to_zero, float16, int_fast32_t)
210 WRAP_SF_TO_INT_MINMAG(qemu_f16_to_i64_r_minMag,
211                       float16_to_int64_round_to_zero, float16, int_fast64_t)
213 WRAP_SF_TO_INT_MINMAG(qemu_f32_to_ui32_r_minMag,
214                       float32_to_uint32_round_to_zero, float32, uint_fast32_t)
215 WRAP_SF_TO_INT_MINMAG(qemu_f32_to_ui64_r_minMag,
216                       float32_to_uint64_round_to_zero, float32, uint_fast64_t)
218 WRAP_SF_TO_INT_MINMAG(qemu_f32_to_i32_r_minMag,
219                       float32_to_int32_round_to_zero, float32, int_fast32_t)
220 WRAP_SF_TO_INT_MINMAG(qemu_f32_to_i64_r_minMag,
221                       float32_to_int64_round_to_zero, float32, int_fast64_t)
223 WRAP_SF_TO_INT_MINMAG(qemu_f64_to_ui32_r_minMag,
224                       float64_to_uint32_round_to_zero, float64, uint_fast32_t)
225 WRAP_SF_TO_INT_MINMAG(qemu_f64_to_ui64_r_minMag,
226                       float64_to_uint64_round_to_zero, float64, uint_fast64_t)
228 WRAP_SF_TO_INT_MINMAG(qemu_f64_to_i32_r_minMag,
229                       float64_to_int32_round_to_zero, float64, int_fast32_t)
230 WRAP_SF_TO_INT_MINMAG(qemu_f64_to_i64_r_minMag,
231                       float64_to_int64_round_to_zero, float64, int_fast64_t)
232 #undef WRAP_SF_TO_INT_MINMAG
234 #define WRAP_80_TO_SF(name, func, type)                 \
235     static type##_t name(const extFloat80_t *ap)        \
236     {                                                   \
237         floatx80 a;                                     \
238         type ret;                                       \
239                                                         \
240         a = soft_to_qemu80(*ap);                        \
241         ret = func(a, &qsf);                            \
242         return *(type##_t *)&ret;                       \
243     }
245 WRAP_80_TO_SF(qemu_extF80M_to_f32, floatx80_to_float32, float32)
246 WRAP_80_TO_SF(qemu_extF80M_to_f64, floatx80_to_float64, float64)
247 #undef WRAP_80_TO_SF
249 #define WRAP_128_TO_SF(name, func, type)        \
250     static type##_t name(const float128_t *ap)  \
251     {                                           \
252         float128 a;                             \
253         type ret;                               \
254                                                 \
255         a = soft_to_qemu128(*ap);               \
256         ret = func(a, &qsf);                    \
257         return *(type##_t *)&ret;               \
258     }
260 WRAP_128_TO_SF(qemu_f128M_to_f32, float128_to_float32, float32)
261 WRAP_128_TO_SF(qemu_f128M_to_f64, float128_to_float64, float64)
262 #undef WRAP_128_TO_SF
264 static void qemu_extF80M_to_f128M(const extFloat80_t *from, float128_t *to)
266     floatx80 qfrom;
267     float128 qto;
269     qfrom = soft_to_qemu80(*from);
270     qto = floatx80_to_float128(qfrom, &qsf);
271     *to = qemu_to_soft128(qto);
274 static void qemu_f128M_to_extF80M(const float128_t *from, extFloat80_t *to)
276     float128 qfrom;
277     floatx80 qto;
279     qfrom = soft_to_qemu128(*from);
280     qto = float128_to_floatx80(qfrom, &qsf);
281     *to = qemu_to_soft80(qto);
284 #define WRAP_INT_TO_SF(name, func, int_type, type)      \
285     static type##_t name(int_type a)                    \
286     {                                                   \
287         type ret;                                       \
288                                                         \
289         ret = func(a, &qsf);                            \
290         return *(type##_t *)&ret;                       \
291     }
293 WRAP_INT_TO_SF(qemu_ui32_to_f16, uint32_to_float16, uint32_t, float16)
294 WRAP_INT_TO_SF(qemu_ui32_to_f32, uint32_to_float32, uint32_t, float32)
295 WRAP_INT_TO_SF(qemu_ui32_to_f64, uint32_to_float64, uint32_t, float64)
297 WRAP_INT_TO_SF(qemu_ui64_to_f16, uint64_to_float16, uint64_t, float16)
298 WRAP_INT_TO_SF(qemu_ui64_to_f32, uint64_to_float32, uint64_t, float32)
299 WRAP_INT_TO_SF(qemu_ui64_to_f64, uint64_to_float64, uint64_t, float64)
301 WRAP_INT_TO_SF(qemu_i32_to_f16, int32_to_float16, int32_t, float16)
302 WRAP_INT_TO_SF(qemu_i32_to_f32, int32_to_float32, int32_t, float32)
303 WRAP_INT_TO_SF(qemu_i32_to_f64, int32_to_float64, int32_t, float64)
305 WRAP_INT_TO_SF(qemu_i64_to_f16, int64_to_float16, int64_t, float16)
306 WRAP_INT_TO_SF(qemu_i64_to_f32, int64_to_float32, int64_t, float32)
307 WRAP_INT_TO_SF(qemu_i64_to_f64, int64_to_float64, int64_t, float64)
308 #undef WRAP_INT_TO_SF
310 #define WRAP_INT_TO_80(name, func, int_type)            \
311     static void name(int_type a, extFloat80_t *res)     \
312     {                                                   \
313         floatx80 ret;                                   \
314                                                         \
315         ret = func(a, &qsf);                            \
316         *res = qemu_to_soft80(ret);                     \
317     }
319 WRAP_INT_TO_80(qemu_i32_to_extF80M, int32_to_floatx80, int32_t)
320 WRAP_INT_TO_80(qemu_i64_to_extF80M, int64_to_floatx80, int64_t)
321 #undef WRAP_INT_TO_80
323 /* Note: exact is ignored since qemu's softfloat assumes it is set */
324 #define WRAP_80_TO_INT(name, func, fast_type)                           \
325     static fast_type name(const extFloat80_t *ap, uint_fast8_t round,   \
326                           bool exact)                                   \
327     {                                                                   \
328         floatx80 a;                                                     \
329                                                                         \
330         a = soft_to_qemu80(*ap);                                        \
331         qsf.float_rounding_mode = sf_rounding_to_qemu(round);           \
332         return func(a, &qsf);                                           \
333     }
335 WRAP_80_TO_INT(qemu_extF80M_to_i32, floatx80_to_int32, int_fast32_t)
336 WRAP_80_TO_INT(qemu_extF80M_to_i64, floatx80_to_int64, int_fast64_t)
337 #undef WRAP_80_TO_INT
339 /* Note: exact is ignored since qemu's softfloat assumes it is set */
340 #define WRAP_80_TO_INT_MINMAG(name, func, fast_type)            \
341     static fast_type name(const extFloat80_t *ap, bool exact)   \
342     {                                                           \
343         floatx80 a;                                             \
344                                                                 \
345         a = soft_to_qemu80(*ap);                                \
346         return func(a, &qsf);                                   \
347     }
349 WRAP_80_TO_INT_MINMAG(qemu_extF80M_to_i32_r_minMag,
350                       floatx80_to_int32_round_to_zero, int_fast32_t)
351 WRAP_80_TO_INT_MINMAG(qemu_extF80M_to_i64_r_minMag,
352                       floatx80_to_int64_round_to_zero, int_fast64_t)
353 #undef WRAP_80_TO_INT_MINMAG
355 /* Note: exact is ignored since qemu's softfloat assumes it is set */
356 #define WRAP_128_TO_INT(name, func, fast_type)                          \
357     static fast_type name(const float128_t *ap, uint_fast8_t round,     \
358                           bool exact)                                   \
359     {                                                                   \
360         float128 a;                                                     \
361                                                                         \
362         a = soft_to_qemu128(*ap);                                       \
363         qsf.float_rounding_mode = sf_rounding_to_qemu(round);           \
364         return func(a, &qsf);                                           \
365     }
367 WRAP_128_TO_INT(qemu_f128M_to_i32, float128_to_int32, int_fast32_t)
368 WRAP_128_TO_INT(qemu_f128M_to_i64, float128_to_int64, int_fast64_t)
370 WRAP_128_TO_INT(qemu_f128M_to_ui32, float128_to_uint32, uint_fast32_t)
371 WRAP_128_TO_INT(qemu_f128M_to_ui64, float128_to_uint64, uint_fast64_t)
372 #undef WRAP_128_TO_INT
374 /* Note: exact is ignored since qemu's softfloat assumes it is set */
375 #define WRAP_128_TO_INT_MINMAG(name, func, fast_type)           \
376     static fast_type name(const float128_t *ap, bool exact)     \
377     {                                                           \
378         float128 a;                                             \
379                                                                 \
380         a = soft_to_qemu128(*ap);                               \
381         return func(a, &qsf);                                   \
382     }
384 WRAP_128_TO_INT_MINMAG(qemu_f128M_to_i32_r_minMag,
385                        float128_to_int32_round_to_zero, int_fast32_t)
386 WRAP_128_TO_INT_MINMAG(qemu_f128M_to_i64_r_minMag,
387                        float128_to_int64_round_to_zero, int_fast64_t)
389 WRAP_128_TO_INT_MINMAG(qemu_f128M_to_ui32_r_minMag,
390                        float128_to_uint32_round_to_zero, uint_fast32_t)
391 WRAP_128_TO_INT_MINMAG(qemu_f128M_to_ui64_r_minMag,
392                        float128_to_uint64_round_to_zero, uint_fast64_t)
393 #undef WRAP_128_TO_INT_MINMAG
395 #define WRAP_INT_TO_128(name, func, int_type)           \
396     static void name(int_type a, float128_t *res)       \
397     {                                                   \
398         float128 ret;                                   \
399                                                         \
400         ret = func(a, &qsf);                            \
401         *res = qemu_to_soft128(ret);                    \
402     }
404 WRAP_INT_TO_128(qemu_ui64_to_f128M, uint64_to_float128, uint64_t)
406 WRAP_INT_TO_128(qemu_i32_to_f128M, int32_to_float128, int32_t)
407 WRAP_INT_TO_128(qemu_i64_to_f128M, int64_to_float128, int64_t)
408 #undef WRAP_INT_TO_128
410 /* Note: exact is ignored since qemu's softfloat assumes it is set */
411 #define WRAP_ROUND_TO_INT(name, func, type)                             \
412     static type##_t name(type##_t a, uint_fast8_t round, bool exact)    \
413     {                                                                   \
414         type *ap = (type *)&a;                                          \
415         type ret;                                                       \
416                                                                         \
417         qsf.float_rounding_mode = sf_rounding_to_qemu(round);           \
418         ret = func(*ap, &qsf);                                          \
419         return *(type##_t *)&ret;                                       \
420     }
422 WRAP_ROUND_TO_INT(qemu_f16_roundToInt, float16_round_to_int, float16)
423 WRAP_ROUND_TO_INT(qemu_f32_roundToInt, float32_round_to_int, float32)
424 WRAP_ROUND_TO_INT(qemu_f64_roundToInt, float64_round_to_int, float64)
425 #undef WRAP_ROUND_TO_INT
427 static void qemu_extF80M_roundToInt(const extFloat80_t *ap, uint_fast8_t round,
428                                     bool exact, extFloat80_t *res)
430     floatx80 a;
431     floatx80 ret;
433     a = soft_to_qemu80(*ap);
434     qsf.float_rounding_mode = sf_rounding_to_qemu(round);
435     ret = floatx80_round_to_int(a, &qsf);
436     *res = qemu_to_soft80(ret);
439 static void qemu_f128M_roundToInt(const float128_t *ap, uint_fast8_t round,
440                                   bool exact, float128_t *res)
442     float128 a;
443     float128 ret;
445     a = soft_to_qemu128(*ap);
446     qsf.float_rounding_mode = sf_rounding_to_qemu(round);
447     ret = float128_round_to_int(a, &qsf);
448     *res = qemu_to_soft128(ret);
451 /* operations */
452 #define WRAP1(name, func, type)                 \
453     static type##_t name(type##_t a)            \
454     {                                           \
455         type *ap = (type *)&a;                  \
456         type ret;                               \
457                                                 \
458         ret = func(*ap, &qsf);                  \
459         return *(type##_t *)&ret;               \
460     }
462 #define WRAP2(name, func, type)                         \
463     static type##_t name(type##_t a, type##_t b)        \
464     {                                                   \
465         type *ap = (type *)&a;                          \
466         type *bp = (type *)&b;                          \
467         type ret;                                       \
468                                                         \
469         ret = func(*ap, *bp, &qsf);                     \
470         return *(type##_t *)&ret;                       \
471     }
473 #define WRAP_COMMON_OPS(b)                              \
474     WRAP1(qemu_f##b##_sqrt, float##b##_sqrt, float##b)  \
475     WRAP2(qemu_f##b##_add, float##b##_add, float##b)    \
476     WRAP2(qemu_f##b##_sub, float##b##_sub, float##b)    \
477     WRAP2(qemu_f##b##_mul, float##b##_mul, float##b)    \
478     WRAP2(qemu_f##b##_div, float##b##_div, float##b)
480 WRAP_COMMON_OPS(16)
481 WRAP_COMMON_OPS(32)
482 WRAP_COMMON_OPS(64)
483 #undef WRAP_COMMON
485 WRAP2(qemu_f32_rem, float32_rem, float32)
486 WRAP2(qemu_f64_rem, float64_rem, float64)
487 #undef WRAP2
488 #undef WRAP1
490 #define WRAP1_80(name, func)                                    \
491     static void name(const extFloat80_t *ap, extFloat80_t *res) \
492     {                                                           \
493         floatx80 a;                                             \
494         floatx80 ret;                                           \
495                                                                 \
496         a = soft_to_qemu80(*ap);                                \
497         ret = func(a, &qsf);                                    \
498         *res = qemu_to_soft80(ret);                             \
499     }
501 WRAP1_80(qemu_extF80M_sqrt, floatx80_sqrt)
502 #undef WRAP1_80
504 #define WRAP1_128(name, func)                                   \
505     static void name(const float128_t *ap, float128_t *res)     \
506     {                                                           \
507         float128 a;                                             \
508         float128 ret;                                           \
509                                                                 \
510         a = soft_to_qemu128(*ap);                               \
511         ret = func(a, &qsf);                                    \
512         *res = qemu_to_soft128(ret);                            \
513     }
515 WRAP1_128(qemu_f128M_sqrt, float128_sqrt)
516 #undef WRAP1_128
518 #define WRAP2_80(name, func)                                            \
519     static void name(const extFloat80_t *ap, const extFloat80_t *bp,    \
520                      extFloat80_t *res)                                 \
521     {                                                                   \
522         floatx80 a;                                                     \
523         floatx80 b;                                                     \
524         floatx80 ret;                                                   \
525                                                                         \
526         a = soft_to_qemu80(*ap);                                        \
527         b = soft_to_qemu80(*bp);                                        \
528         ret = func(a, b, &qsf);                                         \
529         *res = qemu_to_soft80(ret);                                     \
530     }
532 WRAP2_80(qemu_extF80M_add, floatx80_add)
533 WRAP2_80(qemu_extF80M_sub, floatx80_sub)
534 WRAP2_80(qemu_extF80M_mul, floatx80_mul)
535 WRAP2_80(qemu_extF80M_div, floatx80_div)
536 WRAP2_80(qemu_extF80M_rem, floatx80_rem)
537 #undef WRAP2_80
539 #define WRAP2_128(name, func)                                           \
540     static void name(const float128_t *ap, const float128_t *bp,        \
541                      float128_t *res)                                   \
542     {                                                                   \
543         float128 a;                                                     \
544         float128 b;                                                     \
545         float128 ret;                                                   \
546                                                                         \
547         a = soft_to_qemu128(*ap);                                       \
548         b = soft_to_qemu128(*bp);                                       \
549         ret = func(a, b, &qsf);                                         \
550         *res = qemu_to_soft128(ret);                                    \
551     }
553 WRAP2_128(qemu_f128M_add, float128_add)
554 WRAP2_128(qemu_f128M_sub, float128_sub)
555 WRAP2_128(qemu_f128M_mul, float128_mul)
556 WRAP2_128(qemu_f128M_div, float128_div)
557 WRAP2_128(qemu_f128M_rem, float128_rem)
558 #undef WRAP2_128
560 #define WRAP_MULADD(name, func, type)                           \
561     static type##_t name(type##_t a, type##_t b, type##_t c)    \
562     {                                                           \
563         type *ap = (type *)&a;                                  \
564         type *bp = (type *)&b;                                  \
565         type *cp = (type *)&c;                                  \
566         type ret;                                               \
567                                                                 \
568         ret = func(*ap, *bp, *cp, 0, &qsf);                     \
569         return *(type##_t *)&ret;                               \
570     }
572 WRAP_MULADD(qemu_f16_mulAdd, float16_muladd, float16)
573 WRAP_MULADD(qemu_f32_mulAdd, float32_muladd, float32)
574 WRAP_MULADD(qemu_f64_mulAdd, float64_muladd, float64)
575 #undef WRAP_MULADD
577 static void qemu_f128M_mulAdd(const float128_t *ap, const float128_t *bp,
578                               const float128_t *cp, float128_t *res)
580     float128 a, b, c, ret;
582     a = soft_to_qemu128(*ap);
583     b = soft_to_qemu128(*bp);
584     c = soft_to_qemu128(*cp);
585     ret = float128_muladd(a, b, c, 0, &qsf);
586     *res = qemu_to_soft128(ret);
589 #define WRAP_CMP16(name, func, retcond)         \
590     static bool name(float16_t a, float16_t b)  \
591     {                                           \
592         float16 *ap = (float16 *)&a;            \
593         float16 *bp = (float16 *)&b;            \
594         int ret;                                \
595                                                 \
596         ret = func(*ap, *bp, &qsf);             \
597         return retcond;                         \
598     }
600 WRAP_CMP16(qemu_f16_eq_signaling, float16_compare, ret == 0)
601 WRAP_CMP16(qemu_f16_eq, float16_compare_quiet, ret == 0)
602 WRAP_CMP16(qemu_f16_le, float16_compare, ret <= 0)
603 WRAP_CMP16(qemu_f16_lt, float16_compare, ret < 0)
604 WRAP_CMP16(qemu_f16_le_quiet, float16_compare_quiet, ret <= 0)
605 WRAP_CMP16(qemu_f16_lt_quiet, float16_compare_quiet, ret < 0)
606 #undef WRAP_CMP16
608 #define WRAP_CMP(name, func, type)              \
609     static bool name(type##_t a, type##_t b)    \
610     {                                           \
611         type *ap = (type *)&a;                  \
612         type *bp = (type *)&b;                  \
613                                                 \
614         return !!func(*ap, *bp, &qsf);          \
615     }
617 #define GEN_WRAP_CMP(b)                                                 \
618     WRAP_CMP(qemu_f##b##_eq_signaling, float##b##_eq, float##b)         \
619     WRAP_CMP(qemu_f##b##_eq, float##b##_eq_quiet, float##b)             \
620     WRAP_CMP(qemu_f##b##_le, float##b##_le, float##b)                   \
621     WRAP_CMP(qemu_f##b##_lt, float##b##_lt, float##b)                   \
622     WRAP_CMP(qemu_f##b##_le_quiet, float##b##_le_quiet, float##b)       \
623     WRAP_CMP(qemu_f##b##_lt_quiet, float##b##_lt_quiet, float##b)
625 GEN_WRAP_CMP(32)
626 GEN_WRAP_CMP(64)
627 #undef GEN_WRAP_CMP
628 #undef WRAP_CMP
630 #define WRAP_CMP80(name, func)                                          \
631     static bool name(const extFloat80_t *ap, const extFloat80_t *bp)    \
632     {                                                                   \
633         floatx80 a;                                                     \
634         floatx80 b;                                                     \
635                                                                         \
636         a = soft_to_qemu80(*ap);                                        \
637         b = soft_to_qemu80(*bp);                                        \
638         return !!func(a, b, &qsf);                                      \
639     }
641 WRAP_CMP80(qemu_extF80M_eq_signaling, floatx80_eq)
642 WRAP_CMP80(qemu_extF80M_eq, floatx80_eq_quiet)
643 WRAP_CMP80(qemu_extF80M_le, floatx80_le)
644 WRAP_CMP80(qemu_extF80M_lt, floatx80_lt)
645 WRAP_CMP80(qemu_extF80M_le_quiet, floatx80_le_quiet)
646 WRAP_CMP80(qemu_extF80M_lt_quiet, floatx80_lt_quiet)
647 #undef WRAP_CMP80
649 #define WRAP_CMP128(name, func)                                         \
650     static bool name(const float128_t *ap, const float128_t *bp)        \
651     {                                                                   \
652         float128 a;                                                     \
653         float128 b;                                                     \
654                                                                         \
655         a = soft_to_qemu128(*ap);                                       \
656         b = soft_to_qemu128(*bp);                                       \
657         return !!func(a, b, &qsf);                                      \
658     }
660 WRAP_CMP128(qemu_f128M_eq_signaling, float128_eq)
661 WRAP_CMP128(qemu_f128M_eq, float128_eq_quiet)
662 WRAP_CMP128(qemu_f128M_le, float128_le)
663 WRAP_CMP128(qemu_f128M_lt, float128_lt)
664 WRAP_CMP128(qemu_f128M_le_quiet, float128_le_quiet)
665 WRAP_CMP128(qemu_f128M_lt_quiet, float128_lt_quiet)
666 #undef WRAP_CMP128