xref: /openbmc/qemu/tests/fp/wrap.c.inc (revision f101c9fe)
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 */
8
9static signed char sf_tininess_to_qemu(uint_fast8_t mode)
10{
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    }
19}
20
21static signed char sf_rounding_to_qemu(uint_fast8_t mode)
22{
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    }
39}
40
41static uint_fast8_t qemu_flags_to_sf(uint8_t qflags)
42{
43    uint_fast8_t ret = 0;
44
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;
61}
62
63/*
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 */
67static extFloat80_t qemu_to_soft80(floatx80 a)
68{
69    extFloat80_t ret;
70
71    ret.signif = a.low;
72    ret.signExp = a.high;
73    return ret;
74}
75
76static floatx80 soft_to_qemu80(extFloat80_t a)
77{
78    floatx80 ret;
79
80    ret.low = a.signif;
81    ret.high = a.signExp;
82    return ret;
83}
84
85static float128_t qemu_to_soft128(float128 a)
86{
87    float128_t ret;
88    struct uint128 *to = (struct uint128 *)&ret;
89
90    to->v0 = a.low;
91    to->v64 = a.high;
92    return ret;
93}
94
95static float128 soft_to_qemu128(float128_t a)
96{
97    struct uint128 *from = (struct uint128 *)&a;
98    float128 ret;
99
100    ret.low = from->v0;
101    ret.high = from->v64;
102    return ret;
103}
104
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    }
115
116WRAP_SF_TO_SF_IEEE(qemu_f16_to_f32, float16_to_float32, float16, float32)
117WRAP_SF_TO_SF_IEEE(qemu_f16_to_f64, float16_to_float64, float16, float64)
118
119WRAP_SF_TO_SF_IEEE(qemu_f32_to_f16, float32_to_float16, float32, float16)
120WRAP_SF_TO_SF_IEEE(qemu_f64_to_f16, float64_to_float16, float64, float16)
121#undef WRAP_SF_TO_SF_IEEE
122
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    }
132
133WRAP_SF_TO_SF(qemu_f32_to_f64, float32_to_float64, float32, float64)
134WRAP_SF_TO_SF(qemu_f64_to_f32, float64_to_float32, float64, float32)
135#undef WRAP_SF_TO_SF
136
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    }
146
147WRAP_SF_TO_80(qemu_f32_to_extF80M, float32_to_floatx80, float32)
148WRAP_SF_TO_80(qemu_f64_to_extF80M, float64_to_floatx80, float64)
149#undef WRAP_SF_TO_80
150
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    }
160
161WRAP_SF_TO_128(qemu_f32_to_f128M, float32_to_float128, float32)
162WRAP_SF_TO_128(qemu_f64_to_f128M, float64_to_float128, float64)
163#undef WRAP_SF_TO_128
164
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    }
174
175WRAP_SF_TO_INT(qemu_f16_to_ui32, float16_to_uint32, float16, uint_fast32_t)
176WRAP_SF_TO_INT(qemu_f16_to_ui64, float16_to_uint64, float16, uint_fast64_t)
177
178WRAP_SF_TO_INT(qemu_f32_to_ui32, float32_to_uint32, float32, uint_fast32_t)
179WRAP_SF_TO_INT(qemu_f32_to_ui64, float32_to_uint64, float32, uint_fast64_t)
180
181WRAP_SF_TO_INT(qemu_f64_to_ui32, float64_to_uint32, float64, uint_fast32_t)
182WRAP_SF_TO_INT(qemu_f64_to_ui64, float64_to_uint64, float64, uint_fast64_t)
183
184WRAP_SF_TO_INT(qemu_f16_to_i32, float16_to_int32, float16, int_fast32_t)
185WRAP_SF_TO_INT(qemu_f16_to_i64, float16_to_int64, float16, int_fast64_t)
186
187WRAP_SF_TO_INT(qemu_f32_to_i32, float32_to_int32, float32, int_fast32_t)
188WRAP_SF_TO_INT(qemu_f32_to_i64, float32_to_int64, float32, int_fast64_t)
189
190WRAP_SF_TO_INT(qemu_f64_to_i32, float64_to_int32, float64, int_fast32_t)
191WRAP_SF_TO_INT(qemu_f64_to_i64, float64_to_int64, float64, int_fast64_t)
192#undef WRAP_SF_TO_INT
193
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    }
202
203WRAP_SF_TO_INT_MINMAG(qemu_f16_to_ui32_r_minMag,
204                      float16_to_uint32_round_to_zero, float16, uint_fast32_t)
205WRAP_SF_TO_INT_MINMAG(qemu_f16_to_ui64_r_minMag,
206                      float16_to_uint64_round_to_zero, float16, uint_fast64_t)
207
208WRAP_SF_TO_INT_MINMAG(qemu_f16_to_i32_r_minMag,
209                      float16_to_int32_round_to_zero, float16, int_fast32_t)
210WRAP_SF_TO_INT_MINMAG(qemu_f16_to_i64_r_minMag,
211                      float16_to_int64_round_to_zero, float16, int_fast64_t)
212
213WRAP_SF_TO_INT_MINMAG(qemu_f32_to_ui32_r_minMag,
214                      float32_to_uint32_round_to_zero, float32, uint_fast32_t)
215WRAP_SF_TO_INT_MINMAG(qemu_f32_to_ui64_r_minMag,
216                      float32_to_uint64_round_to_zero, float32, uint_fast64_t)
217
218WRAP_SF_TO_INT_MINMAG(qemu_f32_to_i32_r_minMag,
219                      float32_to_int32_round_to_zero, float32, int_fast32_t)
220WRAP_SF_TO_INT_MINMAG(qemu_f32_to_i64_r_minMag,
221                      float32_to_int64_round_to_zero, float32, int_fast64_t)
222
223WRAP_SF_TO_INT_MINMAG(qemu_f64_to_ui32_r_minMag,
224                      float64_to_uint32_round_to_zero, float64, uint_fast32_t)
225WRAP_SF_TO_INT_MINMAG(qemu_f64_to_ui64_r_minMag,
226                      float64_to_uint64_round_to_zero, float64, uint_fast64_t)
227
228WRAP_SF_TO_INT_MINMAG(qemu_f64_to_i32_r_minMag,
229                      float64_to_int32_round_to_zero, float64, int_fast32_t)
230WRAP_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
233
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    }
244
245WRAP_80_TO_SF(qemu_extF80M_to_f32, floatx80_to_float32, float32)
246WRAP_80_TO_SF(qemu_extF80M_to_f64, floatx80_to_float64, float64)
247#undef WRAP_80_TO_SF
248
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    }
259
260WRAP_128_TO_SF(qemu_f128M_to_f32, float128_to_float32, float32)
261WRAP_128_TO_SF(qemu_f128M_to_f64, float128_to_float64, float64)
262#undef WRAP_128_TO_SF
263
264static void qemu_extF80M_to_f128M(const extFloat80_t *from, float128_t *to)
265{
266    floatx80 qfrom;
267    float128 qto;
268
269    qfrom = soft_to_qemu80(*from);
270    qto = floatx80_to_float128(qfrom, &qsf);
271    *to = qemu_to_soft128(qto);
272}
273
274static void qemu_f128M_to_extF80M(const float128_t *from, extFloat80_t *to)
275{
276    float128 qfrom;
277    floatx80 qto;
278
279    qfrom = soft_to_qemu128(*from);
280    qto = float128_to_floatx80(qfrom, &qsf);
281    *to = qemu_to_soft80(qto);
282}
283
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    }
292
293WRAP_INT_TO_SF(qemu_ui32_to_f16, uint32_to_float16, uint32_t, float16)
294WRAP_INT_TO_SF(qemu_ui32_to_f32, uint32_to_float32, uint32_t, float32)
295WRAP_INT_TO_SF(qemu_ui32_to_f64, uint32_to_float64, uint32_t, float64)
296
297WRAP_INT_TO_SF(qemu_ui64_to_f16, uint64_to_float16, uint64_t, float16)
298WRAP_INT_TO_SF(qemu_ui64_to_f32, uint64_to_float32, uint64_t, float32)
299WRAP_INT_TO_SF(qemu_ui64_to_f64, uint64_to_float64, uint64_t, float64)
300
301WRAP_INT_TO_SF(qemu_i32_to_f16, int32_to_float16, int32_t, float16)
302WRAP_INT_TO_SF(qemu_i32_to_f32, int32_to_float32, int32_t, float32)
303WRAP_INT_TO_SF(qemu_i32_to_f64, int32_to_float64, int32_t, float64)
304
305WRAP_INT_TO_SF(qemu_i64_to_f16, int64_to_float16, int64_t, float16)
306WRAP_INT_TO_SF(qemu_i64_to_f32, int64_to_float32, int64_t, float32)
307WRAP_INT_TO_SF(qemu_i64_to_f64, int64_to_float64, int64_t, float64)
308#undef WRAP_INT_TO_SF
309
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    }
318
319WRAP_INT_TO_80(qemu_i32_to_extF80M, int32_to_floatx80, int32_t)
320WRAP_INT_TO_80(qemu_i64_to_extF80M, int64_to_floatx80, int64_t)
321#undef WRAP_INT_TO_80
322
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    }
334
335WRAP_80_TO_INT(qemu_extF80M_to_i32, floatx80_to_int32, int_fast32_t)
336WRAP_80_TO_INT(qemu_extF80M_to_i64, floatx80_to_int64, int_fast64_t)
337#undef WRAP_80_TO_INT
338
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    }
348
349WRAP_80_TO_INT_MINMAG(qemu_extF80M_to_i32_r_minMag,
350                      floatx80_to_int32_round_to_zero, int_fast32_t)
351WRAP_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
354
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    }
366
367WRAP_128_TO_INT(qemu_f128M_to_i32, float128_to_int32, int_fast32_t)
368WRAP_128_TO_INT(qemu_f128M_to_i64, float128_to_int64, int_fast64_t)
369
370WRAP_128_TO_INT(qemu_f128M_to_ui32, float128_to_uint32, uint_fast32_t)
371WRAP_128_TO_INT(qemu_f128M_to_ui64, float128_to_uint64, uint_fast64_t)
372#undef WRAP_128_TO_INT
373
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    }
383
384WRAP_128_TO_INT_MINMAG(qemu_f128M_to_i32_r_minMag,
385                       float128_to_int32_round_to_zero, int_fast32_t)
386WRAP_128_TO_INT_MINMAG(qemu_f128M_to_i64_r_minMag,
387                       float128_to_int64_round_to_zero, int_fast64_t)
388
389WRAP_128_TO_INT_MINMAG(qemu_f128M_to_ui32_r_minMag,
390                       float128_to_uint32_round_to_zero, uint_fast32_t)
391WRAP_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
394
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    }
403
404WRAP_INT_TO_128(qemu_ui64_to_f128M, uint64_to_float128, uint64_t)
405
406WRAP_INT_TO_128(qemu_i32_to_f128M, int32_to_float128, int32_t)
407WRAP_INT_TO_128(qemu_i64_to_f128M, int64_to_float128, int64_t)
408#undef WRAP_INT_TO_128
409
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    }
421
422WRAP_ROUND_TO_INT(qemu_f16_roundToInt, float16_round_to_int, float16)
423WRAP_ROUND_TO_INT(qemu_f32_roundToInt, float32_round_to_int, float32)
424WRAP_ROUND_TO_INT(qemu_f64_roundToInt, float64_round_to_int, float64)
425#undef WRAP_ROUND_TO_INT
426
427static void qemu_extF80M_roundToInt(const extFloat80_t *ap, uint_fast8_t round,
428                                    bool exact, extFloat80_t *res)
429{
430    floatx80 a;
431    floatx80 ret;
432
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);
437}
438
439static void qemu_f128M_roundToInt(const float128_t *ap, uint_fast8_t round,
440                                  bool exact, float128_t *res)
441{
442    float128 a;
443    float128 ret;
444
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);
449}
450
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    }
461
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    }
472
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)
479
480WRAP_COMMON_OPS(16)
481WRAP_COMMON_OPS(32)
482WRAP_COMMON_OPS(64)
483#undef WRAP_COMMON
484
485WRAP2(qemu_f32_rem, float32_rem, float32)
486WRAP2(qemu_f64_rem, float64_rem, float64)
487#undef WRAP2
488#undef WRAP1
489
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    }
500
501WRAP1_80(qemu_extF80M_sqrt, floatx80_sqrt)
502#undef WRAP1_80
503
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    }
514
515WRAP1_128(qemu_f128M_sqrt, float128_sqrt)
516#undef WRAP1_128
517
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    }
531
532WRAP2_80(qemu_extF80M_add, floatx80_add)
533WRAP2_80(qemu_extF80M_sub, floatx80_sub)
534WRAP2_80(qemu_extF80M_mul, floatx80_mul)
535WRAP2_80(qemu_extF80M_div, floatx80_div)
536WRAP2_80(qemu_extF80M_rem, floatx80_rem)
537#undef WRAP2_80
538
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    }
552
553WRAP2_128(qemu_f128M_add, float128_add)
554WRAP2_128(qemu_f128M_sub, float128_sub)
555WRAP2_128(qemu_f128M_mul, float128_mul)
556WRAP2_128(qemu_f128M_div, float128_div)
557WRAP2_128(qemu_f128M_rem, float128_rem)
558#undef WRAP2_128
559
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    }
571
572WRAP_MULADD(qemu_f16_mulAdd, float16_muladd, float16)
573WRAP_MULADD(qemu_f32_mulAdd, float32_muladd, float32)
574WRAP_MULADD(qemu_f64_mulAdd, float64_muladd, float64)
575#undef WRAP_MULADD
576
577static void qemu_f128M_mulAdd(const float128_t *ap, const float128_t *bp,
578                              const float128_t *cp, float128_t *res)
579{
580    float128 a, b, c, ret;
581
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);
587}
588
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    }
599
600WRAP_CMP16(qemu_f16_eq_signaling, float16_compare, ret == 0)
601WRAP_CMP16(qemu_f16_eq, float16_compare_quiet, ret == 0)
602WRAP_CMP16(qemu_f16_le, float16_compare, ret <= 0)
603WRAP_CMP16(qemu_f16_lt, float16_compare, ret < 0)
604WRAP_CMP16(qemu_f16_le_quiet, float16_compare_quiet, ret <= 0)
605WRAP_CMP16(qemu_f16_lt_quiet, float16_compare_quiet, ret < 0)
606#undef WRAP_CMP16
607
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    }
616
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)
624
625GEN_WRAP_CMP(32)
626GEN_WRAP_CMP(64)
627#undef GEN_WRAP_CMP
628#undef WRAP_CMP
629
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    }
640
641WRAP_CMP80(qemu_extF80M_eq_signaling, floatx80_eq)
642WRAP_CMP80(qemu_extF80M_eq, floatx80_eq_quiet)
643WRAP_CMP80(qemu_extF80M_le, floatx80_le)
644WRAP_CMP80(qemu_extF80M_lt, floatx80_lt)
645WRAP_CMP80(qemu_extF80M_le_quiet, floatx80_le_quiet)
646WRAP_CMP80(qemu_extF80M_lt_quiet, floatx80_lt_quiet)
647#undef WRAP_CMP80
648
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    }
659
660WRAP_CMP128(qemu_f128M_eq_signaling, float128_eq)
661WRAP_CMP128(qemu_f128M_eq, float128_eq_quiet)
662WRAP_CMP128(qemu_f128M_le, float128_le)
663WRAP_CMP128(qemu_f128M_lt, float128_lt)
664WRAP_CMP128(qemu_f128M_le_quiet, float128_le_quiet)
665WRAP_CMP128(qemu_f128M_lt_quiet, float128_lt_quiet)
666#undef WRAP_CMP128
667