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