cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
      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