xref: /openbmc/qemu/target/loongarch/tcg/fpu_helper.c (revision f15f7273ea55472d5904c53566c82369d81214c1)
15c23704eSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
25c23704eSSong Gao /*
35c23704eSSong Gao  * LoongArch float point emulation helpers for QEMU
45c23704eSSong Gao  *
55c23704eSSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
65c23704eSSong Gao  */
75c23704eSSong Gao 
85c23704eSSong Gao #include "qemu/osdep.h"
95c23704eSSong Gao #include "cpu.h"
105c23704eSSong Gao #include "exec/helper-proto.h"
115c23704eSSong Gao #include "exec/exec-all.h"
125c23704eSSong Gao #include "exec/cpu_ldst.h"
135c23704eSSong Gao #include "fpu/softfloat.h"
145c23704eSSong Gao #include "internals.h"
155c23704eSSong Gao 
nanbox_s(float32 fp)165c23704eSSong Gao static inline uint64_t nanbox_s(float32 fp)
175c23704eSSong Gao {
185c23704eSSong Gao     return fp | MAKE_64BIT_MASK(32, 32);
195c23704eSSong Gao }
205c23704eSSong Gao 
215c23704eSSong Gao /* Convert loongarch rounding mode in fcsr0 to IEEE library */
225c23704eSSong Gao static const FloatRoundMode ieee_rm[4] = {
235c23704eSSong Gao     float_round_nearest_even,
245c23704eSSong Gao     float_round_to_zero,
255c23704eSSong Gao     float_round_up,
265c23704eSSong Gao     float_round_down
275c23704eSSong Gao };
285c23704eSSong Gao 
restore_fp_status(CPULoongArchState * env)295c23704eSSong Gao void restore_fp_status(CPULoongArchState *env)
305c23704eSSong Gao {
315c23704eSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
325c23704eSSong Gao                             &env->fp_status);
335c23704eSSong Gao     set_flush_to_zero(0, &env->fp_status);
34*1bb5257dSPeter Maydell     set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
355c23704eSSong Gao }
365c23704eSSong Gao 
ieee_ex_to_loongarch(int xcpt)375c23704eSSong Gao int ieee_ex_to_loongarch(int xcpt)
385c23704eSSong Gao {
395c23704eSSong Gao     int ret = 0;
405c23704eSSong Gao     if (xcpt & float_flag_invalid) {
415c23704eSSong Gao         ret |= FP_INVALID;
425c23704eSSong Gao     }
435c23704eSSong Gao     if (xcpt & float_flag_overflow) {
445c23704eSSong Gao         ret |= FP_OVERFLOW;
455c23704eSSong Gao     }
465c23704eSSong Gao     if (xcpt & float_flag_underflow) {
475c23704eSSong Gao         ret |= FP_UNDERFLOW;
485c23704eSSong Gao     }
495c23704eSSong Gao     if (xcpt & float_flag_divbyzero) {
505c23704eSSong Gao         ret |= FP_DIV0;
515c23704eSSong Gao     }
525c23704eSSong Gao     if (xcpt & float_flag_inexact) {
535c23704eSSong Gao         ret |= FP_INEXACT;
545c23704eSSong Gao     }
555c23704eSSong Gao     return ret;
565c23704eSSong Gao }
575c23704eSSong Gao 
update_fcsr0_mask(CPULoongArchState * env,uintptr_t pc,int mask)585c23704eSSong Gao static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
595c23704eSSong Gao {
605c23704eSSong Gao     int flags = get_float_exception_flags(&env->fp_status);
615c23704eSSong Gao 
625c23704eSSong Gao     set_float_exception_flags(0, &env->fp_status);
635c23704eSSong Gao 
645c23704eSSong Gao     flags &= ~mask;
655c23704eSSong Gao 
665c23704eSSong Gao     if (!flags) {
675c23704eSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
685c23704eSSong Gao         return;
695c23704eSSong Gao     } else {
705c23704eSSong Gao         flags = ieee_ex_to_loongarch(flags);
715c23704eSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
725c23704eSSong Gao     }
735c23704eSSong Gao 
745c23704eSSong Gao     if (GET_FP_ENABLES(env->fcsr0) & flags) {
755c23704eSSong Gao         do_raise_exception(env, EXCCODE_FPE, pc);
765c23704eSSong Gao     } else {
775c23704eSSong Gao         UPDATE_FP_FLAGS(env->fcsr0, flags);
785c23704eSSong Gao     }
795c23704eSSong Gao }
805c23704eSSong Gao 
update_fcsr0(CPULoongArchState * env,uintptr_t pc)815c23704eSSong Gao static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
825c23704eSSong Gao {
835c23704eSSong Gao     update_fcsr0_mask(env, pc, 0);
845c23704eSSong Gao }
855c23704eSSong Gao 
helper_fadd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)865c23704eSSong Gao uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
875c23704eSSong Gao {
885c23704eSSong Gao     uint64_t fd;
895c23704eSSong Gao 
905c23704eSSong Gao     fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status));
915c23704eSSong Gao     update_fcsr0(env, GETPC());
925c23704eSSong Gao     return fd;
935c23704eSSong Gao }
945c23704eSSong Gao 
helper_fadd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)955c23704eSSong Gao uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
965c23704eSSong Gao {
975c23704eSSong Gao     uint64_t fd;
985c23704eSSong Gao 
995c23704eSSong Gao     fd = float64_add(fj, fk, &env->fp_status);
1005c23704eSSong Gao     update_fcsr0(env, GETPC());
1015c23704eSSong Gao     return fd;
1025c23704eSSong Gao }
1035c23704eSSong Gao 
helper_fsub_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1045c23704eSSong Gao uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1055c23704eSSong Gao {
1065c23704eSSong Gao     uint64_t fd;
1075c23704eSSong Gao 
1085c23704eSSong Gao     fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status));
1095c23704eSSong Gao     update_fcsr0(env, GETPC());
1105c23704eSSong Gao     return fd;
1115c23704eSSong Gao }
1125c23704eSSong Gao 
helper_fsub_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)1135c23704eSSong Gao uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1145c23704eSSong Gao {
1155c23704eSSong Gao     uint64_t fd;
1165c23704eSSong Gao 
1175c23704eSSong Gao     fd = float64_sub(fj, fk, &env->fp_status);
1185c23704eSSong Gao     update_fcsr0(env, GETPC());
1195c23704eSSong Gao     return fd;
1205c23704eSSong Gao }
1215c23704eSSong Gao 
helper_fmul_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1225c23704eSSong Gao uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1235c23704eSSong Gao {
1245c23704eSSong Gao     uint64_t fd;
1255c23704eSSong Gao 
1265c23704eSSong Gao     fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status));
1275c23704eSSong Gao     update_fcsr0(env, GETPC());
1285c23704eSSong Gao     return fd;
1295c23704eSSong Gao }
1305c23704eSSong Gao 
helper_fmul_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)1315c23704eSSong Gao uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1325c23704eSSong Gao {
1335c23704eSSong Gao     uint64_t fd;
1345c23704eSSong Gao 
1355c23704eSSong Gao     fd = float64_mul(fj, fk, &env->fp_status);
1365c23704eSSong Gao     update_fcsr0(env, GETPC());
1375c23704eSSong Gao     return fd;
1385c23704eSSong Gao }
1395c23704eSSong Gao 
helper_fdiv_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1405c23704eSSong Gao uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1415c23704eSSong Gao {
1425c23704eSSong Gao     uint64_t fd;
1435c23704eSSong Gao 
1445c23704eSSong Gao     fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status));
1455c23704eSSong Gao     update_fcsr0(env, GETPC());
1465c23704eSSong Gao     return fd;
1475c23704eSSong Gao }
1485c23704eSSong Gao 
helper_fdiv_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)1495c23704eSSong Gao uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1505c23704eSSong Gao {
1515c23704eSSong Gao     uint64_t fd;
1525c23704eSSong Gao 
1535c23704eSSong Gao     fd = float64_div(fj, fk, &env->fp_status);
1545c23704eSSong Gao     update_fcsr0(env, GETPC());
1555c23704eSSong Gao     return fd;
1565c23704eSSong Gao }
1575c23704eSSong Gao 
helper_fmax_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1585c23704eSSong Gao uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1595c23704eSSong Gao {
1605c23704eSSong Gao     uint64_t fd;
1615c23704eSSong Gao 
1625c23704eSSong Gao     fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
1635c23704eSSong Gao     update_fcsr0(env, GETPC());
1645c23704eSSong Gao     return fd;
1655c23704eSSong Gao }
1665c23704eSSong Gao 
helper_fmax_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)1675c23704eSSong Gao uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1685c23704eSSong Gao {
1695c23704eSSong Gao     uint64_t fd;
1705c23704eSSong Gao 
1715c23704eSSong Gao     fd = float64_maxnum(fj, fk, &env->fp_status);
1725c23704eSSong Gao     update_fcsr0(env, GETPC());
1735c23704eSSong Gao     return fd;
1745c23704eSSong Gao }
1755c23704eSSong Gao 
helper_fmin_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1765c23704eSSong Gao uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1775c23704eSSong Gao {
1785c23704eSSong Gao     uint64_t fd;
1795c23704eSSong Gao 
1805c23704eSSong Gao     fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
1815c23704eSSong Gao     update_fcsr0(env, GETPC());
1825c23704eSSong Gao     return fd;
1835c23704eSSong Gao }
1845c23704eSSong Gao 
helper_fmin_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)1855c23704eSSong Gao uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1865c23704eSSong Gao {
1875c23704eSSong Gao     uint64_t fd;
1885c23704eSSong Gao 
1895c23704eSSong Gao     fd = float64_minnum(fj, fk, &env->fp_status);
1905c23704eSSong Gao     update_fcsr0(env, GETPC());
1915c23704eSSong Gao     return fd;
1925c23704eSSong Gao }
1935c23704eSSong Gao 
helper_fmaxa_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)1945c23704eSSong Gao uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
1955c23704eSSong Gao {
1965c23704eSSong Gao     uint64_t fd;
1975c23704eSSong Gao 
1985c23704eSSong Gao     fd = nanbox_s(float32_maxnummag((uint32_t)fj,
1995c23704eSSong Gao                                     (uint32_t)fk, &env->fp_status));
2005c23704eSSong Gao     update_fcsr0(env, GETPC());
2015c23704eSSong Gao     return fd;
2025c23704eSSong Gao }
2035c23704eSSong Gao 
helper_fmaxa_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)2045c23704eSSong Gao uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
2055c23704eSSong Gao {
2065c23704eSSong Gao     uint64_t fd;
2075c23704eSSong Gao 
2085c23704eSSong Gao     fd = float64_maxnummag(fj, fk, &env->fp_status);
2095c23704eSSong Gao     update_fcsr0(env, GETPC());
2105c23704eSSong Gao     return fd;
2115c23704eSSong Gao }
2125c23704eSSong Gao 
helper_fmina_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)2135c23704eSSong Gao uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
2145c23704eSSong Gao {
2155c23704eSSong Gao     uint64_t fd;
2165c23704eSSong Gao 
2175c23704eSSong Gao     fd = nanbox_s(float32_minnummag((uint32_t)fj,
2185c23704eSSong Gao                                     (uint32_t)fk, &env->fp_status));
2195c23704eSSong Gao     update_fcsr0(env, GETPC());
2205c23704eSSong Gao     return fd;
2215c23704eSSong Gao }
2225c23704eSSong Gao 
helper_fmina_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)2235c23704eSSong Gao uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
2245c23704eSSong Gao {
2255c23704eSSong Gao     uint64_t fd;
2265c23704eSSong Gao 
2275c23704eSSong Gao     fd = float64_minnummag(fj, fk, &env->fp_status);
2285c23704eSSong Gao     update_fcsr0(env, GETPC());
2295c23704eSSong Gao     return fd;
2305c23704eSSong Gao }
2315c23704eSSong Gao 
helper_fscaleb_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)2325c23704eSSong Gao uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
2335c23704eSSong Gao {
2345c23704eSSong Gao     uint64_t fd;
2355c23704eSSong Gao     int32_t n = (int32_t)fk;
2365c23704eSSong Gao 
2375c23704eSSong Gao     fd = nanbox_s(float32_scalbn((uint32_t)fj,
2385c23704eSSong Gao                                  n >  0x200 ?  0x200 :
2395c23704eSSong Gao                                  n < -0x200 ? -0x200 : n,
2405c23704eSSong Gao                                  &env->fp_status));
2415c23704eSSong Gao     update_fcsr0(env, GETPC());
2425c23704eSSong Gao     return fd;
2435c23704eSSong Gao }
2445c23704eSSong Gao 
helper_fscaleb_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)2455c23704eSSong Gao uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
2465c23704eSSong Gao {
2475c23704eSSong Gao     uint64_t fd;
2485c23704eSSong Gao     int64_t n = (int64_t)fk;
2495c23704eSSong Gao 
2505c23704eSSong Gao     fd = float64_scalbn(fj,
2515c23704eSSong Gao                         n >  0x1000 ?  0x1000 :
2525c23704eSSong Gao                         n < -0x1000 ? -0x1000 : n,
2535c23704eSSong Gao                         &env->fp_status);
2545c23704eSSong Gao     update_fcsr0(env, GETPC());
2555c23704eSSong Gao     return fd;
2565c23704eSSong Gao }
2575c23704eSSong Gao 
helper_fsqrt_s(CPULoongArchState * env,uint64_t fj)2585c23704eSSong Gao uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj)
2595c23704eSSong Gao {
2605c23704eSSong Gao     uint64_t fd;
2615c23704eSSong Gao 
2625c23704eSSong Gao     fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status));
2635c23704eSSong Gao     update_fcsr0(env, GETPC());
2645c23704eSSong Gao     return fd;
2655c23704eSSong Gao }
2665c23704eSSong Gao 
helper_fsqrt_d(CPULoongArchState * env,uint64_t fj)2675c23704eSSong Gao uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj)
2685c23704eSSong Gao {
2695c23704eSSong Gao     uint64_t fd;
2705c23704eSSong Gao 
2715c23704eSSong Gao     fd = float64_sqrt(fj, &env->fp_status);
2725c23704eSSong Gao     update_fcsr0(env, GETPC());
2735c23704eSSong Gao     return fd;
2745c23704eSSong Gao }
2755c23704eSSong Gao 
helper_frecip_s(CPULoongArchState * env,uint64_t fj)2765c23704eSSong Gao uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj)
2775c23704eSSong Gao {
2785c23704eSSong Gao     uint64_t fd;
2795c23704eSSong Gao 
2805c23704eSSong Gao     fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status));
2815c23704eSSong Gao     update_fcsr0(env, GETPC());
2825c23704eSSong Gao     return fd;
2835c23704eSSong Gao }
2845c23704eSSong Gao 
helper_frecip_d(CPULoongArchState * env,uint64_t fj)2855c23704eSSong Gao uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj)
2865c23704eSSong Gao {
2875c23704eSSong Gao     uint64_t fd;
2885c23704eSSong Gao 
2895c23704eSSong Gao     fd = float64_div(float64_one, fj, &env->fp_status);
2905c23704eSSong Gao     update_fcsr0(env, GETPC());
2915c23704eSSong Gao     return fd;
2925c23704eSSong Gao }
2935c23704eSSong Gao 
helper_frsqrt_s(CPULoongArchState * env,uint64_t fj)2945c23704eSSong Gao uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj)
2955c23704eSSong Gao {
2965c23704eSSong Gao     uint64_t fd;
2975c23704eSSong Gao     uint32_t fp;
2985c23704eSSong Gao 
2995c23704eSSong Gao     fp = float32_sqrt((uint32_t)fj, &env->fp_status);
3005c23704eSSong Gao     fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status));
3015c23704eSSong Gao     update_fcsr0(env, GETPC());
3025c23704eSSong Gao     return fd;
3035c23704eSSong Gao }
3045c23704eSSong Gao 
helper_frsqrt_d(CPULoongArchState * env,uint64_t fj)3055c23704eSSong Gao uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj)
3065c23704eSSong Gao {
3075c23704eSSong Gao     uint64_t fp, fd;
3085c23704eSSong Gao 
3095c23704eSSong Gao     fp = float64_sqrt(fj, &env->fp_status);
3105c23704eSSong Gao     fd = float64_div(float64_one, fp, &env->fp_status);
3115c23704eSSong Gao     update_fcsr0(env, GETPC());
3125c23704eSSong Gao     return fd;
3135c23704eSSong Gao }
3145c23704eSSong Gao 
helper_flogb_s(CPULoongArchState * env,uint64_t fj)3155c23704eSSong Gao uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj)
3165c23704eSSong Gao {
3175c23704eSSong Gao     uint64_t fd;
3185c23704eSSong Gao     uint32_t fp;
3195c23704eSSong Gao     float_status *status = &env->fp_status;
3205c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
3215c23704eSSong Gao 
3225c23704eSSong Gao     set_float_rounding_mode(float_round_down, status);
3235c23704eSSong Gao     fp = float32_log2((uint32_t)fj, status);
3245c23704eSSong Gao     fd = nanbox_s(float32_round_to_int(fp, status));
3255c23704eSSong Gao     set_float_rounding_mode(old_mode, status);
3265c23704eSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
3275c23704eSSong Gao     return fd;
3285c23704eSSong Gao }
3295c23704eSSong Gao 
helper_flogb_d(CPULoongArchState * env,uint64_t fj)3305c23704eSSong Gao uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj)
3315c23704eSSong Gao {
3325c23704eSSong Gao     uint64_t fd;
3335c23704eSSong Gao     float_status *status = &env->fp_status;
3345c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
3355c23704eSSong Gao 
3365c23704eSSong Gao     set_float_rounding_mode(float_round_down, status);
3375c23704eSSong Gao     fd = float64_log2(fj, status);
3385c23704eSSong Gao     fd = float64_round_to_int(fd, status);
3395c23704eSSong Gao     set_float_rounding_mode(old_mode, status);
3405c23704eSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
3415c23704eSSong Gao     return fd;
3425c23704eSSong Gao }
3435c23704eSSong Gao 
helper_fclass_s(CPULoongArchState * env,uint64_t fj)3445c23704eSSong Gao uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
3455c23704eSSong Gao {
3465c23704eSSong Gao     float32 f = fj;
3475c23704eSSong Gao     bool sign = float32_is_neg(f);
3485c23704eSSong Gao 
3495c23704eSSong Gao     if (float32_is_infinity(f)) {
3505c23704eSSong Gao         return sign ? 1 << 2 : 1 << 6;
3515c23704eSSong Gao     } else if (float32_is_zero(f)) {
3525c23704eSSong Gao         return sign ? 1 << 5 : 1 << 9;
3535c23704eSSong Gao     } else if (float32_is_zero_or_denormal(f)) {
3545c23704eSSong Gao         return sign ? 1 << 4 : 1 << 8;
3555c23704eSSong Gao     } else if (float32_is_any_nan(f)) {
3565c23704eSSong Gao         float_status s = { }; /* for snan_bit_is_one */
3575c23704eSSong Gao         return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
3585c23704eSSong Gao     } else {
3595c23704eSSong Gao         return sign ? 1 << 3 : 1 << 7;
3605c23704eSSong Gao     }
3615c23704eSSong Gao }
3625c23704eSSong Gao 
helper_fclass_d(CPULoongArchState * env,uint64_t fj)3635c23704eSSong Gao uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
3645c23704eSSong Gao {
3655c23704eSSong Gao     float64 f = fj;
3665c23704eSSong Gao     bool sign = float64_is_neg(f);
3675c23704eSSong Gao 
3685c23704eSSong Gao     if (float64_is_infinity(f)) {
3695c23704eSSong Gao         return sign ? 1 << 2 : 1 << 6;
3705c23704eSSong Gao     } else if (float64_is_zero(f)) {
3715c23704eSSong Gao         return sign ? 1 << 5 : 1 << 9;
3725c23704eSSong Gao     } else if (float64_is_zero_or_denormal(f)) {
3735c23704eSSong Gao         return sign ? 1 << 4 : 1 << 8;
3745c23704eSSong Gao     } else if (float64_is_any_nan(f)) {
3755c23704eSSong Gao         float_status s = { }; /* for snan_bit_is_one */
3765c23704eSSong Gao         return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
3775c23704eSSong Gao     } else {
3785c23704eSSong Gao         return sign ? 1 << 3 : 1 << 7;
3795c23704eSSong Gao     }
3805c23704eSSong Gao }
3815c23704eSSong Gao 
helper_fmuladd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)3825c23704eSSong Gao uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj,
3835c23704eSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
3845c23704eSSong Gao {
3855c23704eSSong Gao     uint64_t fd;
3865c23704eSSong Gao 
3875c23704eSSong Gao     fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk,
3885c23704eSSong Gao                                  (uint32_t)fa, flag, &env->fp_status));
3895c23704eSSong Gao     update_fcsr0(env, GETPC());
3905c23704eSSong Gao     return fd;
3915c23704eSSong Gao }
3925c23704eSSong Gao 
helper_fmuladd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)3935c23704eSSong Gao uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
3945c23704eSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
3955c23704eSSong Gao {
3965c23704eSSong Gao     uint64_t fd;
3975c23704eSSong Gao 
3985c23704eSSong Gao     fd = float64_muladd(fj, fk, fa, flag, &env->fp_status);
3995c23704eSSong Gao     update_fcsr0(env, GETPC());
4005c23704eSSong Gao     return fd;
4015c23704eSSong Gao }
4025c23704eSSong Gao 
fcmp_common(CPULoongArchState * env,FloatRelation cmp,uint32_t flags)4035c23704eSSong Gao static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
4045c23704eSSong Gao                             uint32_t flags)
4055c23704eSSong Gao {
4065c23704eSSong Gao     bool ret;
4075c23704eSSong Gao 
4085c23704eSSong Gao     switch (cmp) {
4095c23704eSSong Gao     case float_relation_less:
4105c23704eSSong Gao         ret = (flags & FCMP_LT);
4115c23704eSSong Gao         break;
4125c23704eSSong Gao     case float_relation_equal:
4135c23704eSSong Gao         ret = (flags & FCMP_EQ);
4145c23704eSSong Gao         break;
4155c23704eSSong Gao     case float_relation_greater:
4165c23704eSSong Gao         ret = (flags & FCMP_GT);
4175c23704eSSong Gao         break;
4185c23704eSSong Gao     case float_relation_unordered:
4195c23704eSSong Gao         ret = (flags & FCMP_UN);
4205c23704eSSong Gao         break;
4215c23704eSSong Gao     default:
4225c23704eSSong Gao         g_assert_not_reached();
4235c23704eSSong Gao     }
4245c23704eSSong Gao     update_fcsr0(env, GETPC());
4255c23704eSSong Gao 
4265c23704eSSong Gao     return ret;
4275c23704eSSong Gao }
4285c23704eSSong Gao 
4295c23704eSSong Gao /* fcmp_cXXX_s */
helper_fcmp_c_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)4305c23704eSSong Gao uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
4315c23704eSSong Gao                          uint64_t fk, uint32_t flags)
4325c23704eSSong Gao {
4335c23704eSSong Gao     FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
4345c23704eSSong Gao                                               (uint32_t)fk, &env->fp_status);
4355c23704eSSong Gao     return fcmp_common(env, cmp, flags);
4365c23704eSSong Gao }
4375c23704eSSong Gao 
4385c23704eSSong Gao /* fcmp_sXXX_s */
helper_fcmp_s_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)4395c23704eSSong Gao uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
4405c23704eSSong Gao                          uint64_t fk, uint32_t flags)
4415c23704eSSong Gao {
4425c23704eSSong Gao     FloatRelation cmp = float32_compare((uint32_t)fj,
4435c23704eSSong Gao                                         (uint32_t)fk, &env->fp_status);
4445c23704eSSong Gao     return fcmp_common(env, cmp, flags);
4455c23704eSSong Gao }
4465c23704eSSong Gao 
4475c23704eSSong Gao /* fcmp_cXXX_d */
helper_fcmp_c_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)4485c23704eSSong Gao uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
4495c23704eSSong Gao                          uint64_t fk, uint32_t flags)
4505c23704eSSong Gao {
4515c23704eSSong Gao     FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status);
4525c23704eSSong Gao     return fcmp_common(env, cmp, flags);
4535c23704eSSong Gao }
4545c23704eSSong Gao 
4555c23704eSSong Gao /* fcmp_sXXX_d */
helper_fcmp_s_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)4565c23704eSSong Gao uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
4575c23704eSSong Gao                          uint64_t fk, uint32_t flags)
4585c23704eSSong Gao {
4595c23704eSSong Gao     FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
4605c23704eSSong Gao     return fcmp_common(env, cmp, flags);
4615c23704eSSong Gao }
4625c23704eSSong Gao 
4635c23704eSSong Gao /* floating point conversion */
helper_fcvt_s_d(CPULoongArchState * env,uint64_t fj)4645c23704eSSong Gao uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
4655c23704eSSong Gao {
4665c23704eSSong Gao     uint64_t fd;
4675c23704eSSong Gao 
4685c23704eSSong Gao     fd = nanbox_s(float64_to_float32(fj, &env->fp_status));
4695c23704eSSong Gao     update_fcsr0(env, GETPC());
4705c23704eSSong Gao     return fd;
4715c23704eSSong Gao }
4725c23704eSSong Gao 
helper_fcvt_d_s(CPULoongArchState * env,uint64_t fj)4735c23704eSSong Gao uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
4745c23704eSSong Gao {
4755c23704eSSong Gao     uint64_t fd;
4765c23704eSSong Gao 
4775c23704eSSong Gao     fd = float32_to_float64((uint32_t)fj, &env->fp_status);
4785c23704eSSong Gao     update_fcsr0(env, GETPC());
4795c23704eSSong Gao     return fd;
4805c23704eSSong Gao }
4815c23704eSSong Gao 
helper_ffint_s_w(CPULoongArchState * env,uint64_t fj)4825c23704eSSong Gao uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
4835c23704eSSong Gao {
4845c23704eSSong Gao     uint64_t fd;
4855c23704eSSong Gao 
4865c23704eSSong Gao     fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status));
4875c23704eSSong Gao     update_fcsr0(env, GETPC());
4885c23704eSSong Gao     return fd;
4895c23704eSSong Gao }
4905c23704eSSong Gao 
helper_ffint_s_l(CPULoongArchState * env,uint64_t fj)4915c23704eSSong Gao uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
4925c23704eSSong Gao {
4935c23704eSSong Gao     uint64_t fd;
4945c23704eSSong Gao 
4955c23704eSSong Gao     fd = nanbox_s(int64_to_float32(fj, &env->fp_status));
4965c23704eSSong Gao     update_fcsr0(env, GETPC());
4975c23704eSSong Gao     return fd;
4985c23704eSSong Gao }
4995c23704eSSong Gao 
helper_ffint_d_w(CPULoongArchState * env,uint64_t fj)5005c23704eSSong Gao uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
5015c23704eSSong Gao {
5025c23704eSSong Gao     uint64_t fd;
5035c23704eSSong Gao 
5045c23704eSSong Gao     fd = int32_to_float64((int32_t)fj, &env->fp_status);
5055c23704eSSong Gao     update_fcsr0(env, GETPC());
5065c23704eSSong Gao     return fd;
5075c23704eSSong Gao }
5085c23704eSSong Gao 
helper_ffint_d_l(CPULoongArchState * env,uint64_t fj)5095c23704eSSong Gao uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
5105c23704eSSong Gao {
5115c23704eSSong Gao     uint64_t fd;
5125c23704eSSong Gao 
5135c23704eSSong Gao     fd = int64_to_float64(fj, &env->fp_status);
5145c23704eSSong Gao     update_fcsr0(env, GETPC());
5155c23704eSSong Gao     return fd;
5165c23704eSSong Gao }
5175c23704eSSong Gao 
helper_frint_s(CPULoongArchState * env,uint64_t fj)5185c23704eSSong Gao uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
5195c23704eSSong Gao {
5205c23704eSSong Gao     uint64_t fd;
5215c23704eSSong Gao 
5225c23704eSSong Gao     fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status));
5235c23704eSSong Gao     update_fcsr0(env, GETPC());
5245c23704eSSong Gao     return fd;
5255c23704eSSong Gao }
5265c23704eSSong Gao 
helper_frint_d(CPULoongArchState * env,uint64_t fj)5275c23704eSSong Gao uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
5285c23704eSSong Gao {
5295c23704eSSong Gao     uint64_t fd;
5305c23704eSSong Gao 
5315c23704eSSong Gao     fd = float64_round_to_int(fj, &env->fp_status);
5325c23704eSSong Gao     update_fcsr0(env, GETPC());
5335c23704eSSong Gao     return fd;
5345c23704eSSong Gao }
5355c23704eSSong Gao 
helper_ftintrm_l_d(CPULoongArchState * env,uint64_t fj)5365c23704eSSong Gao uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
5375c23704eSSong Gao {
5385c23704eSSong Gao     uint64_t fd;
5395c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5405c23704eSSong Gao 
5415c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5425c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
5435c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5445c23704eSSong Gao 
5455c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5465c23704eSSong Gao         if (float64_is_any_nan(fj)) {
5475c23704eSSong Gao             fd = 0;
5485c23704eSSong Gao         }
5495c23704eSSong Gao     }
5505c23704eSSong Gao     update_fcsr0(env, GETPC());
5515c23704eSSong Gao     return fd;
5525c23704eSSong Gao }
5535c23704eSSong Gao 
helper_ftintrm_l_s(CPULoongArchState * env,uint64_t fj)5545c23704eSSong Gao uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
5555c23704eSSong Gao {
5565c23704eSSong Gao     uint64_t fd;
5575c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5585c23704eSSong Gao 
5595c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5605c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
5615c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5625c23704eSSong Gao 
5635c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5645c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
5655c23704eSSong Gao             fd = 0;
5665c23704eSSong Gao         }
5675c23704eSSong Gao     }
5685c23704eSSong Gao     update_fcsr0(env, GETPC());
5695c23704eSSong Gao     return fd;
5705c23704eSSong Gao }
5715c23704eSSong Gao 
helper_ftintrm_w_d(CPULoongArchState * env,uint64_t fj)5725c23704eSSong Gao uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
5735c23704eSSong Gao {
5745c23704eSSong Gao     uint64_t fd;
5755c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5765c23704eSSong Gao 
5775c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5785c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
5795c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5805c23704eSSong Gao 
5815c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5825c23704eSSong Gao         if (float64_is_any_nan(fj)) {
5835c23704eSSong Gao             fd = 0;
5845c23704eSSong Gao         }
5855c23704eSSong Gao     }
5865c23704eSSong Gao     update_fcsr0(env, GETPC());
5875c23704eSSong Gao     return fd;
5885c23704eSSong Gao }
5895c23704eSSong Gao 
helper_ftintrm_w_s(CPULoongArchState * env,uint64_t fj)5905c23704eSSong Gao uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
5915c23704eSSong Gao {
5925c23704eSSong Gao     uint64_t fd;
5935c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5945c23704eSSong Gao 
5955c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5965c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
5975c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5985c23704eSSong Gao 
5995c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6005c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6015c23704eSSong Gao             fd = 0;
6025c23704eSSong Gao         }
6035c23704eSSong Gao     }
6045c23704eSSong Gao     update_fcsr0(env, GETPC());
6055c23704eSSong Gao     return fd;
6065c23704eSSong Gao }
6075c23704eSSong Gao 
helper_ftintrp_l_d(CPULoongArchState * env,uint64_t fj)6085c23704eSSong Gao uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
6095c23704eSSong Gao {
6105c23704eSSong Gao     uint64_t fd;
6115c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6125c23704eSSong Gao 
6135c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6145c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
6155c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6165c23704eSSong Gao 
6175c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6185c23704eSSong Gao         if (float64_is_any_nan(fj)) {
6195c23704eSSong Gao             fd = 0;
6205c23704eSSong Gao         }
6215c23704eSSong Gao     }
6225c23704eSSong Gao     update_fcsr0(env, GETPC());
6235c23704eSSong Gao     return fd;
6245c23704eSSong Gao }
6255c23704eSSong Gao 
helper_ftintrp_l_s(CPULoongArchState * env,uint64_t fj)6265c23704eSSong Gao uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj)
6275c23704eSSong Gao {
6285c23704eSSong Gao     uint64_t fd;
6295c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6305c23704eSSong Gao 
6315c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6325c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
6335c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6345c23704eSSong Gao 
6355c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6365c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6375c23704eSSong Gao             fd = 0;
6385c23704eSSong Gao         }
6395c23704eSSong Gao     }
6405c23704eSSong Gao     update_fcsr0(env, GETPC());
6415c23704eSSong Gao     return fd;
6425c23704eSSong Gao }
6435c23704eSSong Gao 
helper_ftintrp_w_d(CPULoongArchState * env,uint64_t fj)6445c23704eSSong Gao uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj)
6455c23704eSSong Gao {
6465c23704eSSong Gao     uint64_t fd;
6475c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6485c23704eSSong Gao 
6495c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6505c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
6515c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6525c23704eSSong Gao 
6535c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6545c23704eSSong Gao         if (float64_is_any_nan(fj)) {
6555c23704eSSong Gao             fd = 0;
6565c23704eSSong Gao         }
6575c23704eSSong Gao     }
6585c23704eSSong Gao     update_fcsr0(env, GETPC());
6595c23704eSSong Gao     return fd;
6605c23704eSSong Gao }
6615c23704eSSong Gao 
helper_ftintrp_w_s(CPULoongArchState * env,uint64_t fj)6625c23704eSSong Gao uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj)
6635c23704eSSong Gao {
6645c23704eSSong Gao     uint64_t fd;
6655c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6665c23704eSSong Gao 
6675c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6685c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
6695c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6705c23704eSSong Gao 
6715c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6725c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6735c23704eSSong Gao             fd = 0;
6745c23704eSSong Gao         }
6755c23704eSSong Gao     }
6765c23704eSSong Gao     update_fcsr0(env, GETPC());
6775c23704eSSong Gao     return fd;
6785c23704eSSong Gao }
6795c23704eSSong Gao 
helper_ftintrz_l_d(CPULoongArchState * env,uint64_t fj)6805c23704eSSong Gao uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj)
6815c23704eSSong Gao {
6825c23704eSSong Gao     uint64_t fd;
6835c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6845c23704eSSong Gao 
6855c23704eSSong Gao     fd = float64_to_int64_round_to_zero(fj, &env->fp_status);
6865c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6875c23704eSSong Gao 
6885c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6895c23704eSSong Gao         if (float64_is_any_nan(fj)) {
6905c23704eSSong Gao             fd = 0;
6915c23704eSSong Gao         }
6925c23704eSSong Gao     }
6935c23704eSSong Gao     update_fcsr0(env, GETPC());
6945c23704eSSong Gao     return fd;
6955c23704eSSong Gao }
6965c23704eSSong Gao 
helper_ftintrz_l_s(CPULoongArchState * env,uint64_t fj)6975c23704eSSong Gao uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj)
6985c23704eSSong Gao {
6995c23704eSSong Gao     uint64_t fd;
7005c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7015c23704eSSong Gao 
7025c23704eSSong Gao     fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status);
7035c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7045c23704eSSong Gao 
7055c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7065c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7075c23704eSSong Gao             fd = 0;
7085c23704eSSong Gao         }
7095c23704eSSong Gao     }
7105c23704eSSong Gao     update_fcsr0(env, GETPC());
7115c23704eSSong Gao     return fd;
7125c23704eSSong Gao }
7135c23704eSSong Gao 
helper_ftintrz_w_d(CPULoongArchState * env,uint64_t fj)7145c23704eSSong Gao uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj)
7155c23704eSSong Gao {
7165c23704eSSong Gao     uint64_t fd;
7175c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7185c23704eSSong Gao 
7195c23704eSSong Gao     fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status);
7205c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7215c23704eSSong Gao 
7225c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7235c23704eSSong Gao         if (float64_is_any_nan(fj)) {
7245c23704eSSong Gao             fd = 0;
7255c23704eSSong Gao         }
7265c23704eSSong Gao     }
7275c23704eSSong Gao     update_fcsr0(env, GETPC());
7285c23704eSSong Gao     return fd;
7295c23704eSSong Gao }
7305c23704eSSong Gao 
helper_ftintrz_w_s(CPULoongArchState * env,uint64_t fj)7315c23704eSSong Gao uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj)
7325c23704eSSong Gao {
7335c23704eSSong Gao     uint32_t fd;
7345c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7355c23704eSSong Gao 
7365c23704eSSong Gao     fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status);
7375c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7385c23704eSSong Gao 
7395c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7405c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7415c23704eSSong Gao             fd = 0;
7425c23704eSSong Gao         }
7435c23704eSSong Gao     }
7445c23704eSSong Gao     update_fcsr0(env, GETPC());
7455c23704eSSong Gao     return (uint64_t)fd;
7465c23704eSSong Gao }
7475c23704eSSong Gao 
helper_ftintrne_l_d(CPULoongArchState * env,uint64_t fj)7485c23704eSSong Gao uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj)
7495c23704eSSong Gao {
7505c23704eSSong Gao     uint64_t fd;
7515c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7525c23704eSSong Gao 
7535c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7545c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
7555c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7565c23704eSSong Gao 
7575c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7585c23704eSSong Gao         if (float64_is_any_nan(fj)) {
7595c23704eSSong Gao             fd = 0;
7605c23704eSSong Gao         }
7615c23704eSSong Gao     }
7625c23704eSSong Gao     update_fcsr0(env, GETPC());
7635c23704eSSong Gao     return fd;
7645c23704eSSong Gao }
7655c23704eSSong Gao 
helper_ftintrne_l_s(CPULoongArchState * env,uint64_t fj)7665c23704eSSong Gao uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj)
7675c23704eSSong Gao {
7685c23704eSSong Gao     uint64_t fd;
7695c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7705c23704eSSong Gao 
7715c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7725c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
7735c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7745c23704eSSong Gao 
7755c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7765c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7775c23704eSSong Gao             fd = 0;
7785c23704eSSong Gao         }
7795c23704eSSong Gao     }
7805c23704eSSong Gao     update_fcsr0(env, GETPC());
7815c23704eSSong Gao     return fd;
7825c23704eSSong Gao }
7835c23704eSSong Gao 
helper_ftintrne_w_d(CPULoongArchState * env,uint64_t fj)7845c23704eSSong Gao uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj)
7855c23704eSSong Gao {
7865c23704eSSong Gao     uint64_t fd;
7875c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7885c23704eSSong Gao 
7895c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7905c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
7915c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7925c23704eSSong Gao 
7935c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7945c23704eSSong Gao         if (float64_is_any_nan(fj)) {
7955c23704eSSong Gao             fd = 0;
7965c23704eSSong Gao         }
7975c23704eSSong Gao     }
7985c23704eSSong Gao     update_fcsr0(env, GETPC());
7995c23704eSSong Gao     return fd;
8005c23704eSSong Gao }
8015c23704eSSong Gao 
helper_ftintrne_w_s(CPULoongArchState * env,uint64_t fj)8025c23704eSSong Gao uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj)
8035c23704eSSong Gao {
8045c23704eSSong Gao     uint32_t fd;
8055c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
8065c23704eSSong Gao 
8075c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
8085c23704eSSong Gao     fd = float32_to_int32((uint32_t)fj, &env->fp_status);
8095c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
8105c23704eSSong Gao 
8115c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8125c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8135c23704eSSong Gao             fd = 0;
8145c23704eSSong Gao         }
8155c23704eSSong Gao     }
8165c23704eSSong Gao     update_fcsr0(env, GETPC());
8175c23704eSSong Gao     return (uint64_t)fd;
8185c23704eSSong Gao }
8195c23704eSSong Gao 
helper_ftint_l_d(CPULoongArchState * env,uint64_t fj)8205c23704eSSong Gao uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj)
8215c23704eSSong Gao {
8225c23704eSSong Gao     uint64_t fd;
8235c23704eSSong Gao 
8245c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
8255c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8265c23704eSSong Gao         if (float64_is_any_nan(fj)) {
8275c23704eSSong Gao             fd = 0;
8285c23704eSSong Gao         }
8295c23704eSSong Gao     }
8305c23704eSSong Gao     update_fcsr0(env, GETPC());
8315c23704eSSong Gao     return fd;
8325c23704eSSong Gao }
8335c23704eSSong Gao 
helper_ftint_l_s(CPULoongArchState * env,uint64_t fj)8345c23704eSSong Gao uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj)
8355c23704eSSong Gao {
8365c23704eSSong Gao     uint64_t fd;
8375c23704eSSong Gao 
8385c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
8395c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8405c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8415c23704eSSong Gao             fd = 0;
8425c23704eSSong Gao         }
8435c23704eSSong Gao     }
8445c23704eSSong Gao     update_fcsr0(env, GETPC());
8455c23704eSSong Gao     return fd;
8465c23704eSSong Gao }
8475c23704eSSong Gao 
helper_ftint_w_s(CPULoongArchState * env,uint64_t fj)8485c23704eSSong Gao uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj)
8495c23704eSSong Gao {
8505c23704eSSong Gao     uint64_t fd;
8515c23704eSSong Gao 
8525c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
8535c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8545c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8555c23704eSSong Gao             fd = 0;
8565c23704eSSong Gao         }
8575c23704eSSong Gao     }
8585c23704eSSong Gao     update_fcsr0(env, GETPC());
8595c23704eSSong Gao     return fd;
8605c23704eSSong Gao }
8615c23704eSSong Gao 
helper_ftint_w_d(CPULoongArchState * env,uint64_t fj)8625c23704eSSong Gao uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj)
8635c23704eSSong Gao {
8645c23704eSSong Gao     uint64_t fd;
8655c23704eSSong Gao 
8665c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
8675c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8685c23704eSSong Gao         if (float64_is_any_nan(fj)) {
8695c23704eSSong Gao             fd = 0;
8705c23704eSSong Gao         }
8715c23704eSSong Gao     }
8725c23704eSSong Gao     update_fcsr0(env, GETPC());
8735c23704eSSong Gao     return fd;
8745c23704eSSong Gao }
8755c23704eSSong Gao 
helper_set_rounding_mode(CPULoongArchState * env)8765c23704eSSong Gao void helper_set_rounding_mode(CPULoongArchState *env)
8775c23704eSSong Gao {
8785c23704eSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
8795c23704eSSong Gao                             &env->fp_status);
8805c23704eSSong Gao }
881