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