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