1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * LoongArch float point emulation helpers for QEMU 4 * 5 * Copyright (c) 2021 Loongson Technology Corporation Limited 6 */ 7 8 #include "qemu/osdep.h" 9 #include "cpu.h" 10 #include "exec/helper-proto.h" 11 #include "accel/tcg/cpu-ldst.h" 12 #include "fpu/softfloat.h" 13 #include "internals.h" 14 15 static inline uint64_t nanbox_s(float32 fp) 16 { 17 return fp | MAKE_64BIT_MASK(32, 32); 18 } 19 20 /* Convert loongarch rounding mode in fcsr0 to IEEE library */ 21 static const FloatRoundMode ieee_rm[4] = { 22 float_round_nearest_even, 23 float_round_to_zero, 24 float_round_up, 25 float_round_down 26 }; 27 28 void restore_fp_status(CPULoongArchState *env) 29 { 30 set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], 31 &env->fp_status); 32 set_flush_to_zero(0, &env->fp_status); 33 set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status); 34 /* 35 * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan) 36 * case sets InvalidOp and returns the input value 'c' 37 */ 38 set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status); 39 set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status); 40 /* Default NaN: sign bit clear, msb frac bit set */ 41 set_float_default_nan_pattern(0b01000000, &env->fp_status); 42 } 43 44 int ieee_ex_to_loongarch(int xcpt) 45 { 46 int ret = 0; 47 if (xcpt & float_flag_invalid) { 48 ret |= FP_INVALID; 49 } 50 if (xcpt & float_flag_overflow) { 51 ret |= FP_OVERFLOW; 52 } 53 if (xcpt & float_flag_underflow) { 54 ret |= FP_UNDERFLOW; 55 } 56 if (xcpt & float_flag_divbyzero) { 57 ret |= FP_DIV0; 58 } 59 if (xcpt & float_flag_inexact) { 60 ret |= FP_INEXACT; 61 } 62 return ret; 63 } 64 65 static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask) 66 { 67 int flags = get_float_exception_flags(&env->fp_status); 68 69 set_float_exception_flags(0, &env->fp_status); 70 71 flags &= ~mask; 72 73 if (!flags) { 74 SET_FP_CAUSE(env->fcsr0, flags); 75 return; 76 } else { 77 flags = ieee_ex_to_loongarch(flags); 78 SET_FP_CAUSE(env->fcsr0, flags); 79 } 80 81 if (GET_FP_ENABLES(env->fcsr0) & flags) { 82 do_raise_exception(env, EXCCODE_FPE, pc); 83 } else { 84 UPDATE_FP_FLAGS(env->fcsr0, flags); 85 } 86 } 87 88 static void update_fcsr0(CPULoongArchState *env, uintptr_t pc) 89 { 90 update_fcsr0_mask(env, pc, 0); 91 } 92 93 uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 94 { 95 uint64_t fd; 96 97 fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 98 update_fcsr0(env, GETPC()); 99 return fd; 100 } 101 102 uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 103 { 104 uint64_t fd; 105 106 fd = float64_add(fj, fk, &env->fp_status); 107 update_fcsr0(env, GETPC()); 108 return fd; 109 } 110 111 uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 112 { 113 uint64_t fd; 114 115 fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 116 update_fcsr0(env, GETPC()); 117 return fd; 118 } 119 120 uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 121 { 122 uint64_t fd; 123 124 fd = float64_sub(fj, fk, &env->fp_status); 125 update_fcsr0(env, GETPC()); 126 return fd; 127 } 128 129 uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 130 { 131 uint64_t fd; 132 133 fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 134 update_fcsr0(env, GETPC()); 135 return fd; 136 } 137 138 uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 139 { 140 uint64_t fd; 141 142 fd = float64_mul(fj, fk, &env->fp_status); 143 update_fcsr0(env, GETPC()); 144 return fd; 145 } 146 147 uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 148 { 149 uint64_t fd; 150 151 fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 152 update_fcsr0(env, GETPC()); 153 return fd; 154 } 155 156 uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 157 { 158 uint64_t fd; 159 160 fd = float64_div(fj, fk, &env->fp_status); 161 update_fcsr0(env, GETPC()); 162 return fd; 163 } 164 165 uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 166 { 167 uint64_t fd; 168 169 fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 170 update_fcsr0(env, GETPC()); 171 return fd; 172 } 173 174 uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 175 { 176 uint64_t fd; 177 178 fd = float64_maxnum(fj, fk, &env->fp_status); 179 update_fcsr0(env, GETPC()); 180 return fd; 181 } 182 183 uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 184 { 185 uint64_t fd; 186 187 fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 188 update_fcsr0(env, GETPC()); 189 return fd; 190 } 191 192 uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 193 { 194 uint64_t fd; 195 196 fd = float64_minnum(fj, fk, &env->fp_status); 197 update_fcsr0(env, GETPC()); 198 return fd; 199 } 200 201 uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 202 { 203 uint64_t fd; 204 205 fd = nanbox_s(float32_maxnummag((uint32_t)fj, 206 (uint32_t)fk, &env->fp_status)); 207 update_fcsr0(env, GETPC()); 208 return fd; 209 } 210 211 uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 212 { 213 uint64_t fd; 214 215 fd = float64_maxnummag(fj, fk, &env->fp_status); 216 update_fcsr0(env, GETPC()); 217 return fd; 218 } 219 220 uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 221 { 222 uint64_t fd; 223 224 fd = nanbox_s(float32_minnummag((uint32_t)fj, 225 (uint32_t)fk, &env->fp_status)); 226 update_fcsr0(env, GETPC()); 227 return fd; 228 } 229 230 uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 231 { 232 uint64_t fd; 233 234 fd = float64_minnummag(fj, fk, &env->fp_status); 235 update_fcsr0(env, GETPC()); 236 return fd; 237 } 238 239 uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 240 { 241 uint64_t fd; 242 int32_t n = (int32_t)fk; 243 244 fd = nanbox_s(float32_scalbn((uint32_t)fj, 245 n > 0x200 ? 0x200 : 246 n < -0x200 ? -0x200 : n, 247 &env->fp_status)); 248 update_fcsr0(env, GETPC()); 249 return fd; 250 } 251 252 uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 253 { 254 uint64_t fd; 255 int64_t n = (int64_t)fk; 256 257 fd = float64_scalbn(fj, 258 n > 0x1000 ? 0x1000 : 259 n < -0x1000 ? -0x1000 : n, 260 &env->fp_status); 261 update_fcsr0(env, GETPC()); 262 return fd; 263 } 264 265 uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj) 266 { 267 uint64_t fd; 268 269 fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status)); 270 update_fcsr0(env, GETPC()); 271 return fd; 272 } 273 274 uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj) 275 { 276 uint64_t fd; 277 278 fd = float64_sqrt(fj, &env->fp_status); 279 update_fcsr0(env, GETPC()); 280 return fd; 281 } 282 283 uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj) 284 { 285 uint64_t fd; 286 287 fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status)); 288 update_fcsr0(env, GETPC()); 289 return fd; 290 } 291 292 uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj) 293 { 294 uint64_t fd; 295 296 fd = float64_div(float64_one, fj, &env->fp_status); 297 update_fcsr0(env, GETPC()); 298 return fd; 299 } 300 301 uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj) 302 { 303 uint64_t fd; 304 uint32_t fp; 305 306 fp = float32_sqrt((uint32_t)fj, &env->fp_status); 307 fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status)); 308 update_fcsr0(env, GETPC()); 309 return fd; 310 } 311 312 uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj) 313 { 314 uint64_t fp, fd; 315 316 fp = float64_sqrt(fj, &env->fp_status); 317 fd = float64_div(float64_one, fp, &env->fp_status); 318 update_fcsr0(env, GETPC()); 319 return fd; 320 } 321 322 uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj) 323 { 324 uint64_t fd; 325 uint32_t fp; 326 float_status *status = &env->fp_status; 327 FloatRoundMode old_mode = get_float_rounding_mode(status); 328 329 set_float_rounding_mode(float_round_down, status); 330 fp = float32_log2((uint32_t)fj, status); 331 fd = nanbox_s(float32_round_to_int(fp, status)); 332 set_float_rounding_mode(old_mode, status); 333 update_fcsr0_mask(env, GETPC(), float_flag_inexact); 334 return fd; 335 } 336 337 uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj) 338 { 339 uint64_t fd; 340 float_status *status = &env->fp_status; 341 FloatRoundMode old_mode = get_float_rounding_mode(status); 342 343 set_float_rounding_mode(float_round_down, status); 344 fd = float64_log2(fj, status); 345 fd = float64_round_to_int(fd, status); 346 set_float_rounding_mode(old_mode, status); 347 update_fcsr0_mask(env, GETPC(), float_flag_inexact); 348 return fd; 349 } 350 351 uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj) 352 { 353 float32 f = fj; 354 bool sign = float32_is_neg(f); 355 356 if (float32_is_infinity(f)) { 357 return sign ? 1 << 2 : 1 << 6; 358 } else if (float32_is_zero(f)) { 359 return sign ? 1 << 5 : 1 << 9; 360 } else if (float32_is_zero_or_denormal(f)) { 361 return sign ? 1 << 4 : 1 << 8; 362 } else if (float32_is_any_nan(f)) { 363 return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0; 364 } else { 365 return sign ? 1 << 3 : 1 << 7; 366 } 367 } 368 369 uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj) 370 { 371 float64 f = fj; 372 bool sign = float64_is_neg(f); 373 374 if (float64_is_infinity(f)) { 375 return sign ? 1 << 2 : 1 << 6; 376 } else if (float64_is_zero(f)) { 377 return sign ? 1 << 5 : 1 << 9; 378 } else if (float64_is_zero_or_denormal(f)) { 379 return sign ? 1 << 4 : 1 << 8; 380 } else if (float64_is_any_nan(f)) { 381 return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0; 382 } else { 383 return sign ? 1 << 3 : 1 << 7; 384 } 385 } 386 387 uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj, 388 uint64_t fk, uint64_t fa, uint32_t flag) 389 { 390 uint64_t fd; 391 392 fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk, 393 (uint32_t)fa, flag, &env->fp_status)); 394 update_fcsr0(env, GETPC()); 395 return fd; 396 } 397 398 uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, 399 uint64_t fk, uint64_t fa, uint32_t flag) 400 { 401 uint64_t fd; 402 403 fd = float64_muladd(fj, fk, fa, flag, &env->fp_status); 404 update_fcsr0(env, GETPC()); 405 return fd; 406 } 407 408 static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp, 409 uint32_t flags) 410 { 411 bool ret; 412 413 switch (cmp) { 414 case float_relation_less: 415 ret = (flags & FCMP_LT); 416 break; 417 case float_relation_equal: 418 ret = (flags & FCMP_EQ); 419 break; 420 case float_relation_greater: 421 ret = (flags & FCMP_GT); 422 break; 423 case float_relation_unordered: 424 ret = (flags & FCMP_UN); 425 break; 426 default: 427 g_assert_not_reached(); 428 } 429 update_fcsr0(env, GETPC()); 430 431 return ret; 432 } 433 434 /* fcmp_cXXX_s */ 435 uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj, 436 uint64_t fk, uint32_t flags) 437 { 438 FloatRelation cmp = float32_compare_quiet((uint32_t)fj, 439 (uint32_t)fk, &env->fp_status); 440 return fcmp_common(env, cmp, flags); 441 } 442 443 /* fcmp_sXXX_s */ 444 uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj, 445 uint64_t fk, uint32_t flags) 446 { 447 FloatRelation cmp = float32_compare((uint32_t)fj, 448 (uint32_t)fk, &env->fp_status); 449 return fcmp_common(env, cmp, flags); 450 } 451 452 /* fcmp_cXXX_d */ 453 uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj, 454 uint64_t fk, uint32_t flags) 455 { 456 FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status); 457 return fcmp_common(env, cmp, flags); 458 } 459 460 /* fcmp_sXXX_d */ 461 uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, 462 uint64_t fk, uint32_t flags) 463 { 464 FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); 465 return fcmp_common(env, cmp, flags); 466 } 467 468 /* floating point conversion */ 469 uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj) 470 { 471 uint64_t fd; 472 473 fd = nanbox_s(float64_to_float32(fj, &env->fp_status)); 474 update_fcsr0(env, GETPC()); 475 return fd; 476 } 477 478 uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj) 479 { 480 uint64_t fd; 481 482 fd = float32_to_float64((uint32_t)fj, &env->fp_status); 483 update_fcsr0(env, GETPC()); 484 return fd; 485 } 486 487 uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj) 488 { 489 uint64_t fd; 490 491 fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status)); 492 update_fcsr0(env, GETPC()); 493 return fd; 494 } 495 496 uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj) 497 { 498 uint64_t fd; 499 500 fd = nanbox_s(int64_to_float32(fj, &env->fp_status)); 501 update_fcsr0(env, GETPC()); 502 return fd; 503 } 504 505 uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj) 506 { 507 uint64_t fd; 508 509 fd = int32_to_float64((int32_t)fj, &env->fp_status); 510 update_fcsr0(env, GETPC()); 511 return fd; 512 } 513 514 uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj) 515 { 516 uint64_t fd; 517 518 fd = int64_to_float64(fj, &env->fp_status); 519 update_fcsr0(env, GETPC()); 520 return fd; 521 } 522 523 uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj) 524 { 525 uint64_t fd; 526 527 fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status)); 528 update_fcsr0(env, GETPC()); 529 return fd; 530 } 531 532 uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj) 533 { 534 uint64_t fd; 535 536 fd = float64_round_to_int(fj, &env->fp_status); 537 update_fcsr0(env, GETPC()); 538 return fd; 539 } 540 541 uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj) 542 { 543 uint64_t fd; 544 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 545 546 set_float_rounding_mode(float_round_down, &env->fp_status); 547 fd = float64_to_int64(fj, &env->fp_status); 548 set_float_rounding_mode(old_mode, &env->fp_status); 549 550 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 551 if (float64_is_any_nan(fj)) { 552 fd = 0; 553 } 554 } 555 update_fcsr0(env, GETPC()); 556 return fd; 557 } 558 559 uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj) 560 { 561 uint64_t fd; 562 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 563 564 set_float_rounding_mode(float_round_down, &env->fp_status); 565 fd = float32_to_int64((uint32_t)fj, &env->fp_status); 566 set_float_rounding_mode(old_mode, &env->fp_status); 567 568 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 569 if (float32_is_any_nan((uint32_t)fj)) { 570 fd = 0; 571 } 572 } 573 update_fcsr0(env, GETPC()); 574 return fd; 575 } 576 577 uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj) 578 { 579 uint64_t fd; 580 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 581 582 set_float_rounding_mode(float_round_down, &env->fp_status); 583 fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 584 set_float_rounding_mode(old_mode, &env->fp_status); 585 586 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 587 if (float64_is_any_nan(fj)) { 588 fd = 0; 589 } 590 } 591 update_fcsr0(env, GETPC()); 592 return fd; 593 } 594 595 uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj) 596 { 597 uint64_t fd; 598 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 599 600 set_float_rounding_mode(float_round_down, &env->fp_status); 601 fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 602 set_float_rounding_mode(old_mode, &env->fp_status); 603 604 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 605 if (float32_is_any_nan((uint32_t)fj)) { 606 fd = 0; 607 } 608 } 609 update_fcsr0(env, GETPC()); 610 return fd; 611 } 612 613 uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj) 614 { 615 uint64_t fd; 616 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 617 618 set_float_rounding_mode(float_round_up, &env->fp_status); 619 fd = float64_to_int64(fj, &env->fp_status); 620 set_float_rounding_mode(old_mode, &env->fp_status); 621 622 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 623 if (float64_is_any_nan(fj)) { 624 fd = 0; 625 } 626 } 627 update_fcsr0(env, GETPC()); 628 return fd; 629 } 630 631 uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj) 632 { 633 uint64_t fd; 634 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 635 636 set_float_rounding_mode(float_round_up, &env->fp_status); 637 fd = float32_to_int64((uint32_t)fj, &env->fp_status); 638 set_float_rounding_mode(old_mode, &env->fp_status); 639 640 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 641 if (float32_is_any_nan((uint32_t)fj)) { 642 fd = 0; 643 } 644 } 645 update_fcsr0(env, GETPC()); 646 return fd; 647 } 648 649 uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj) 650 { 651 uint64_t fd; 652 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 653 654 set_float_rounding_mode(float_round_up, &env->fp_status); 655 fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 656 set_float_rounding_mode(old_mode, &env->fp_status); 657 658 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 659 if (float64_is_any_nan(fj)) { 660 fd = 0; 661 } 662 } 663 update_fcsr0(env, GETPC()); 664 return fd; 665 } 666 667 uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj) 668 { 669 uint64_t fd; 670 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 671 672 set_float_rounding_mode(float_round_up, &env->fp_status); 673 fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 674 set_float_rounding_mode(old_mode, &env->fp_status); 675 676 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 677 if (float32_is_any_nan((uint32_t)fj)) { 678 fd = 0; 679 } 680 } 681 update_fcsr0(env, GETPC()); 682 return fd; 683 } 684 685 uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj) 686 { 687 uint64_t fd; 688 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 689 690 fd = float64_to_int64_round_to_zero(fj, &env->fp_status); 691 set_float_rounding_mode(old_mode, &env->fp_status); 692 693 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 694 if (float64_is_any_nan(fj)) { 695 fd = 0; 696 } 697 } 698 update_fcsr0(env, GETPC()); 699 return fd; 700 } 701 702 uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj) 703 { 704 uint64_t fd; 705 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 706 707 fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status); 708 set_float_rounding_mode(old_mode, &env->fp_status); 709 710 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 711 if (float32_is_any_nan((uint32_t)fj)) { 712 fd = 0; 713 } 714 } 715 update_fcsr0(env, GETPC()); 716 return fd; 717 } 718 719 uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj) 720 { 721 uint64_t fd; 722 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 723 724 fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status); 725 set_float_rounding_mode(old_mode, &env->fp_status); 726 727 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 728 if (float64_is_any_nan(fj)) { 729 fd = 0; 730 } 731 } 732 update_fcsr0(env, GETPC()); 733 return fd; 734 } 735 736 uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj) 737 { 738 uint32_t fd; 739 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 740 741 fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status); 742 set_float_rounding_mode(old_mode, &env->fp_status); 743 744 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 745 if (float32_is_any_nan((uint32_t)fj)) { 746 fd = 0; 747 } 748 } 749 update_fcsr0(env, GETPC()); 750 return (uint64_t)fd; 751 } 752 753 uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj) 754 { 755 uint64_t fd; 756 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 757 758 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 759 fd = float64_to_int64(fj, &env->fp_status); 760 set_float_rounding_mode(old_mode, &env->fp_status); 761 762 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 763 if (float64_is_any_nan(fj)) { 764 fd = 0; 765 } 766 } 767 update_fcsr0(env, GETPC()); 768 return fd; 769 } 770 771 uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj) 772 { 773 uint64_t fd; 774 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 775 776 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 777 fd = float32_to_int64((uint32_t)fj, &env->fp_status); 778 set_float_rounding_mode(old_mode, &env->fp_status); 779 780 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 781 if (float32_is_any_nan((uint32_t)fj)) { 782 fd = 0; 783 } 784 } 785 update_fcsr0(env, GETPC()); 786 return fd; 787 } 788 789 uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj) 790 { 791 uint64_t fd; 792 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 793 794 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 795 fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 796 set_float_rounding_mode(old_mode, &env->fp_status); 797 798 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 799 if (float64_is_any_nan(fj)) { 800 fd = 0; 801 } 802 } 803 update_fcsr0(env, GETPC()); 804 return fd; 805 } 806 807 uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj) 808 { 809 uint32_t fd; 810 FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 811 812 set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 813 fd = float32_to_int32((uint32_t)fj, &env->fp_status); 814 set_float_rounding_mode(old_mode, &env->fp_status); 815 816 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 817 if (float32_is_any_nan((uint32_t)fj)) { 818 fd = 0; 819 } 820 } 821 update_fcsr0(env, GETPC()); 822 return (uint64_t)fd; 823 } 824 825 uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj) 826 { 827 uint64_t fd; 828 829 fd = float64_to_int64(fj, &env->fp_status); 830 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 831 if (float64_is_any_nan(fj)) { 832 fd = 0; 833 } 834 } 835 update_fcsr0(env, GETPC()); 836 return fd; 837 } 838 839 uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj) 840 { 841 uint64_t fd; 842 843 fd = float32_to_int64((uint32_t)fj, &env->fp_status); 844 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 845 if (float32_is_any_nan((uint32_t)fj)) { 846 fd = 0; 847 } 848 } 849 update_fcsr0(env, GETPC()); 850 return fd; 851 } 852 853 uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj) 854 { 855 uint64_t fd; 856 857 fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 858 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 859 if (float32_is_any_nan((uint32_t)fj)) { 860 fd = 0; 861 } 862 } 863 update_fcsr0(env, GETPC()); 864 return fd; 865 } 866 867 uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) 868 { 869 uint64_t fd; 870 871 fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 872 if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 873 if (float64_is_any_nan(fj)) { 874 fd = 0; 875 } 876 } 877 update_fcsr0(env, GETPC()); 878 return fd; 879 } 880 881 void helper_set_rounding_mode(CPULoongArchState *env) 882 { 883 set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], 884 &env->fp_status); 885 } 886