qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

fpu_helper.c (23337B)


      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 static 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 }