qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

wrap.c.inc (28376B)


      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 
      9 static 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 
     21 static 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 
     41 static 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  */
     67 static 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 
     76 static 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 
     85 static 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 
     95 static 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 
    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)
    118 
    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
    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 
    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
    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 
    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
    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 
    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
    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 
    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)
    177 
    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)
    180 
    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)
    183 
    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)
    186 
    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)
    189 
    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
    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 
    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)
    207 
    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)
    212 
    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)
    217 
    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)
    222 
    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)
    227 
    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
    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 
    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
    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 
    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
    263 
    264 static 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 
    274 static 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 
    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)
    296 
    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)
    300 
    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)
    304 
    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
    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 
    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
    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 
    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
    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 
    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
    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 
    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)
    369 
    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
    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 
    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)
    388 
    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
    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 
    404 WRAP_INT_TO_128(qemu_ui64_to_f128M, uint64_to_float128, uint64_t)
    405 
    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
    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 
    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
    426 
    427 static 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 
    439 static 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 
    480 WRAP_COMMON_OPS(16)
    481 WRAP_COMMON_OPS(32)
    482 WRAP_COMMON_OPS(64)
    483 #undef WRAP_COMMON
    484 
    485 WRAP2(qemu_f32_rem, float32_rem, float32)
    486 WRAP2(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 
    501 WRAP1_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 
    515 WRAP1_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 
    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
    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 
    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
    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 
    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
    576 
    577 static 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 
    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
    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 
    625 GEN_WRAP_CMP(32)
    626 GEN_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 
    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
    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 
    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