qemu/target/loongarch/fpu_helper.c
<<
>>
Prefs
   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
  16static 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 */
  22static 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
  29void 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
  36static 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
  57static 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
  80static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
  81{
  82    update_fcsr0_mask(env, pc, 0);
  83}
  84
  85uint64_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
  94uint64_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
 103uint64_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
 112uint64_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
 121uint64_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
 130uint64_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
 139uint64_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
 148uint64_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
 157uint64_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
 166uint64_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
 175uint64_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
 184uint64_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
 193uint64_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
 203uint64_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
 212uint64_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
 222uint64_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
 231uint64_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
 244uint64_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
 257uint64_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
 266uint64_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
 275uint64_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
 284uint64_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
 293uint64_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
 304uint64_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
 314uint64_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
 329uint64_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
 343uint64_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
 362uint64_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
 381uint64_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
 392uint64_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
 402static 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 */
 429uint64_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 */
 438uint64_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 */
 447uint64_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 */
 455uint64_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 */
 463uint64_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
 472uint64_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
 481uint64_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
 490uint64_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
 499uint64_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
 508uint64_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
 517uint64_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
 526uint64_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
 535uint64_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
 553uint64_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
 571uint64_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
 589uint64_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
 607uint64_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
 625uint64_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
 643uint64_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
 661uint64_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
 679uint64_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
 696uint64_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
 713uint64_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
 730uint64_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
 747uint64_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
 765uint64_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
 783uint64_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
 801uint64_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
 819uint64_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
 833uint64_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
 847uint64_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
 861uint64_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
 875void 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