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_le_quiet) 647#undef WRAP_CMP80 648 649#define WRAP_CMP128(name, func) \ 650 static bool name(const float128_t *ap, const float128_t *bp) \ 651 { \ 652 float128 a; \ 653 float128 b; \ 654 \ 655 a = soft_to_qemu128(*ap); \ 656 b = soft_to_qemu128(*bp); \ 657 return !!func(a, b, &qsf); \ 658 } 659 660WRAP_CMP128(qemu_f128M_eq_signaling, float128_eq) 661WRAP_CMP128(qemu_f128M_eq, float128_eq_quiet) 662WRAP_CMP128(qemu_f128M_le, float128_le) 663WRAP_CMP128(qemu_f128M_lt, float128_lt) 664WRAP_CMP128(qemu_f128M_le_quiet, float128_le_quiet) 665WRAP_CMP128(qemu_f128M_lt_quiet, float128_lt_quiet) 666#undef WRAP_CMP128 667