qemu/tests/fp/wrap.inc.c
<<
>>
Prefs
   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
 577#define WRAP_CMP16(name, func, retcond)         \
 578    static bool name(float16_t a, float16_t b)  \
 579    {                                           \
 580        float16 *ap = (float16 *)&a;            \
 581        float16 *bp = (float16 *)&b;            \
 582        int ret;                                \
 583                                                \
 584        ret = func(*ap, *bp, &qsf);             \
 585        return retcond;                         \
 586    }
 587
 588WRAP_CMP16(qemu_f16_eq_signaling, float16_compare, ret == 0)
 589WRAP_CMP16(qemu_f16_eq, float16_compare_quiet, ret == 0)
 590WRAP_CMP16(qemu_f16_le, float16_compare, ret <= 0)
 591WRAP_CMP16(qemu_f16_lt, float16_compare, ret < 0)
 592WRAP_CMP16(qemu_f16_le_quiet, float16_compare_quiet, ret <= 0)
 593WRAP_CMP16(qemu_f16_lt_quiet, float16_compare_quiet, ret < 0)
 594#undef WRAP_CMP16
 595
 596#define WRAP_CMP(name, func, type)              \
 597    static bool name(type##_t a, type##_t b)    \
 598    {                                           \
 599        type *ap = (type *)&a;                  \
 600        type *bp = (type *)&b;                  \
 601                                                \
 602        return !!func(*ap, *bp, &qsf);          \
 603    }
 604
 605#define GEN_WRAP_CMP(b)                                                 \
 606    WRAP_CMP(qemu_f##b##_eq_signaling, float##b##_eq, float##b)         \
 607    WRAP_CMP(qemu_f##b##_eq, float##b##_eq_quiet, float##b)             \
 608    WRAP_CMP(qemu_f##b##_le, float##b##_le, float##b)                   \
 609    WRAP_CMP(qemu_f##b##_lt, float##b##_lt, float##b)                   \
 610    WRAP_CMP(qemu_f##b##_le_quiet, float##b##_le_quiet, float##b)       \
 611    WRAP_CMP(qemu_f##b##_lt_quiet, float##b##_lt_quiet, float##b)
 612
 613GEN_WRAP_CMP(32)
 614GEN_WRAP_CMP(64)
 615#undef GEN_WRAP_CMP
 616#undef WRAP_CMP
 617
 618#define WRAP_CMP80(name, func)                                          \
 619    static bool name(const extFloat80_t *ap, const extFloat80_t *bp)    \
 620    {                                                                   \
 621        floatx80 a;                                                     \
 622        floatx80 b;                                                     \
 623                                                                        \
 624        a = soft_to_qemu80(*ap);                                        \
 625        b = soft_to_qemu80(*bp);                                        \
 626        return !!func(a, b, &qsf);                                      \
 627    }
 628
 629WRAP_CMP80(qemu_extF80M_eq_signaling, floatx80_eq)
 630WRAP_CMP80(qemu_extF80M_eq, floatx80_eq_quiet)
 631WRAP_CMP80(qemu_extF80M_le, floatx80_le)
 632WRAP_CMP80(qemu_extF80M_lt, floatx80_lt)
 633WRAP_CMP80(qemu_extF80M_le_quiet, floatx80_le_quiet)
 634WRAP_CMP80(qemu_extF80M_lt_quiet, floatx80_le_quiet)
 635#undef WRAP_CMP80
 636
 637#define WRAP_CMP128(name, func)                                         \
 638    static bool name(const float128_t *ap, const float128_t *bp)        \
 639    {                                                                   \
 640        float128 a;                                                     \
 641        float128 b;                                                     \
 642                                                                        \
 643        a = soft_to_qemu128(*ap);                                       \
 644        b = soft_to_qemu128(*bp);                                       \
 645        return !!func(a, b, &qsf);                                      \
 646    }
 647
 648WRAP_CMP128(qemu_f128M_eq_signaling, float128_eq)
 649WRAP_CMP128(qemu_f128M_eq, float128_eq_quiet)
 650WRAP_CMP128(qemu_f128M_le, float128_le)
 651WRAP_CMP128(qemu_f128M_lt, float128_lt)
 652WRAP_CMP128(qemu_f128M_le_quiet, float128_le_quiet)
 653WRAP_CMP128(qemu_f128M_lt_quiet, float128_lt_quiet)
 654#undef WRAP_CMP128
 655