1d578ca6cSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */ 2d578ca6cSSong Gao /* 3d578ca6cSSong Gao * LoongArch float point emulation helpers for QEMU 4d578ca6cSSong Gao * 5d578ca6cSSong Gao * Copyright (c) 2021 Loongson Technology Corporation Limited 6d578ca6cSSong Gao */ 7d578ca6cSSong Gao 8d578ca6cSSong Gao #include "qemu/osdep.h" 9d578ca6cSSong Gao #include "cpu.h" 10d578ca6cSSong Gao #include "exec/helper-proto.h" 11d578ca6cSSong Gao #include "exec/exec-all.h" 12d578ca6cSSong Gao #include "exec/cpu_ldst.h" 13d578ca6cSSong Gao #include "fpu/softfloat.h" 14d578ca6cSSong Gao #include "internals.h" 15d578ca6cSSong Gao 16d578ca6cSSong Gao static inline uint64_t nanbox_s(float32 fp) 17d578ca6cSSong Gao { 18d578ca6cSSong Gao return fp | MAKE_64BIT_MASK(32, 32); 19d578ca6cSSong Gao } 20d578ca6cSSong Gao 21d578ca6cSSong Gao /* Convert loongarch rounding mode in fcsr0 to IEEE library */ 22d578ca6cSSong Gao static const FloatRoundMode ieee_rm[4] = { 23d578ca6cSSong Gao float_round_nearest_even, 24d578ca6cSSong Gao float_round_to_zero, 25d578ca6cSSong Gao float_round_up, 26d578ca6cSSong Gao float_round_down 27d578ca6cSSong Gao }; 28d578ca6cSSong Gao 29d578ca6cSSong Gao void restore_fp_status(CPULoongArchState *env) 30d578ca6cSSong Gao { 31d578ca6cSSong Gao set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], 32d578ca6cSSong Gao &env->fp_status); 33d578ca6cSSong Gao set_flush_to_zero(0, &env->fp_status); 341bb5257dSPeter Maydell set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status); 35*0fb7fa29SPeter Maydell /* 36*0fb7fa29SPeter Maydell * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan) 37*0fb7fa29SPeter Maydell * case sets InvalidOp and returns the input value 'c' 38*0fb7fa29SPeter Maydell */ 39*0fb7fa29SPeter Maydell set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status); 40d578ca6cSSong Gao } 41d578ca6cSSong Gao 42aca67472SSong Gao int ieee_ex_to_loongarch(int xcpt) 43d578ca6cSSong Gao { 44d578ca6cSSong Gao int ret = 0; 45d578ca6cSSong Gao if (xcpt & float_flag_invalid) { 46d578ca6cSSong Gao ret |= FP_INVALID; 47d578ca6cSSong Gao } 48d578ca6cSSong Gao if (xcpt & float_flag_overflow) { 49d578ca6cSSong Gao ret |= FP_OVERFLOW; 50d578ca6cSSong Gao } 51d578ca6cSSong Gao if (xcpt & float_flag_underflow) { 52d578ca6cSSong Gao ret |= FP_UNDERFLOW; 53d578ca6cSSong Gao } 54d578ca6cSSong Gao if (xcpt & float_flag_divbyzero) { 55d578ca6cSSong Gao ret |= FP_DIV0; 56d578ca6cSSong Gao } 57d578ca6cSSong Gao if (xcpt & float_flag_inexact) { 58d578ca6cSSong Gao ret |= FP_INEXACT; 59d578ca6cSSong Gao } 60d578ca6cSSong Gao return ret; 61d578ca6cSSong Gao } 62d578ca6cSSong Gao 63d578ca6cSSong Gao static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask) 64d578ca6cSSong Gao { 65d578ca6cSSong Gao int flags = get_float_exception_flags(&env->fp_status); 66d578ca6cSSong Gao 67d578ca6cSSong Gao set_float_exception_flags(0, &env->fp_status); 68d578ca6cSSong Gao 69d578ca6cSSong Gao flags &= ~mask; 70d578ca6cSSong Gao 71d578ca6cSSong Gao if (!flags) { 72d578ca6cSSong Gao SET_FP_CAUSE(env->fcsr0, flags); 73d578ca6cSSong Gao return; 74d578ca6cSSong Gao } else { 75d578ca6cSSong Gao flags = ieee_ex_to_loongarch(flags); 76d578ca6cSSong Gao SET_FP_CAUSE(env->fcsr0, flags); 77d578ca6cSSong Gao } 78d578ca6cSSong Gao 79d578ca6cSSong Gao if (GET_FP_ENABLES(env->fcsr0) & flags) { 80d578ca6cSSong Gao do_raise_exception(env, EXCCODE_FPE, pc); 81d578ca6cSSong Gao } else { 82d578ca6cSSong Gao UPDATE_FP_FLAGS(env->fcsr0, flags); 83d578ca6cSSong Gao } 84d578ca6cSSong Gao } 85d578ca6cSSong Gao 86d578ca6cSSong Gao static void update_fcsr0(CPULoongArchState *env, uintptr_t pc) 87d578ca6cSSong Gao { 88d578ca6cSSong Gao update_fcsr0_mask(env, pc, 0); 89d578ca6cSSong Gao } 90d578ca6cSSong Gao 91d578ca6cSSong Gao uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 92d578ca6cSSong Gao { 93d578ca6cSSong Gao uint64_t fd; 94d578ca6cSSong Gao 95d578ca6cSSong Gao fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 96d578ca6cSSong Gao update_fcsr0(env, GETPC()); 97d578ca6cSSong Gao return fd; 98d578ca6cSSong Gao } 99d578ca6cSSong Gao 100d578ca6cSSong Gao uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 101d578ca6cSSong Gao { 102d578ca6cSSong Gao uint64_t fd; 103d578ca6cSSong Gao 104d578ca6cSSong Gao fd = float64_add(fj, fk, &env->fp_status); 105d578ca6cSSong Gao update_fcsr0(env, GETPC()); 106d578ca6cSSong Gao return fd; 107d578ca6cSSong Gao } 108d578ca6cSSong Gao 109d578ca6cSSong Gao uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 110d578ca6cSSong Gao { 111d578ca6cSSong Gao uint64_t fd; 112d578ca6cSSong Gao 113d578ca6cSSong Gao fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 114d578ca6cSSong Gao update_fcsr0(env, GETPC()); 115d578ca6cSSong Gao return fd; 116d578ca6cSSong Gao } 117d578ca6cSSong Gao 118d578ca6cSSong Gao uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 119d578ca6cSSong Gao { 120d578ca6cSSong Gao uint64_t fd; 121d578ca6cSSong Gao 122d578ca6cSSong Gao fd = float64_sub(fj, fk, &env->fp_status); 123d578ca6cSSong Gao update_fcsr0(env, GETPC()); 124d578ca6cSSong Gao return fd; 125d578ca6cSSong Gao } 126d578ca6cSSong Gao 127d578ca6cSSong Gao uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 128d578ca6cSSong Gao { 129d578ca6cSSong Gao uint64_t fd; 130d578ca6cSSong Gao 131d578ca6cSSong Gao fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 132d578ca6cSSong Gao update_fcsr0(env, GETPC()); 133d578ca6cSSong Gao return fd; 134d578ca6cSSong Gao } 135d578ca6cSSong Gao 136d578ca6cSSong Gao uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 137d578ca6cSSong Gao { 138d578ca6cSSong Gao uint64_t fd; 139d578ca6cSSong Gao 140d578ca6cSSong Gao fd = float64_mul(fj, fk, &env->fp_status); 141d578ca6cSSong Gao update_fcsr0(env, GETPC()); 142d578ca6cSSong Gao return fd; 143d578ca6cSSong Gao } 144d578ca6cSSong Gao 145d578ca6cSSong Gao uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 146d578ca6cSSong Gao { 147d578ca6cSSong Gao uint64_t fd; 148d578ca6cSSong Gao 149d578ca6cSSong Gao fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 150d578ca6cSSong Gao update_fcsr0(env, GETPC()); 151d578ca6cSSong Gao return fd; 152d578ca6cSSong Gao } 153d578ca6cSSong Gao 154d578ca6cSSong Gao uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 155d578ca6cSSong Gao { 156d578ca6cSSong Gao uint64_t fd; 157d578ca6cSSong Gao 158d578ca6cSSong Gao fd = float64_div(fj, fk, &env->fp_status); 159d578ca6cSSong Gao update_fcsr0(env, GETPC()); 160d578ca6cSSong Gao return fd; 161d578ca6cSSong Gao } 162d578ca6cSSong Gao 163d578ca6cSSong Gao uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 164d578ca6cSSong Gao { 165d578ca6cSSong Gao uint64_t fd; 166d578ca6cSSong Gao 167d578ca6cSSong Gao fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 168d578ca6cSSong Gao update_fcsr0(env, GETPC()); 169d578ca6cSSong Gao return fd; 170d578ca6cSSong Gao } 171d578ca6cSSong Gao 172d578ca6cSSong Gao uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 173d578ca6cSSong Gao { 174d578ca6cSSong Gao uint64_t fd; 175d578ca6cSSong Gao 176d578ca6cSSong Gao fd = float64_maxnum(fj, fk, &env->fp_status); 177d578ca6cSSong Gao update_fcsr0(env, GETPC()); 178d578ca6cSSong Gao return fd; 179d578ca6cSSong Gao } 180d578ca6cSSong Gao 181d578ca6cSSong Gao uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 182d578ca6cSSong Gao { 183d578ca6cSSong Gao uint64_t fd; 184d578ca6cSSong Gao 185d578ca6cSSong Gao fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status)); 186d578ca6cSSong Gao update_fcsr0(env, GETPC()); 187d578ca6cSSong Gao return fd; 188d578ca6cSSong Gao } 189d578ca6cSSong Gao 190d578ca6cSSong Gao uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 191d578ca6cSSong Gao { 192d578ca6cSSong Gao uint64_t fd; 193d578ca6cSSong Gao 194d578ca6cSSong Gao fd = float64_minnum(fj, fk, &env->fp_status); 195d578ca6cSSong Gao update_fcsr0(env, GETPC()); 196d578ca6cSSong Gao return fd; 197d578ca6cSSong Gao } 198d578ca6cSSong Gao 199d578ca6cSSong Gao uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 200d578ca6cSSong Gao { 201d578ca6cSSong Gao uint64_t fd; 202d578ca6cSSong Gao 203d578ca6cSSong Gao fd = nanbox_s(float32_maxnummag((uint32_t)fj, 204d578ca6cSSong Gao (uint32_t)fk, &env->fp_status)); 205d578ca6cSSong Gao update_fcsr0(env, GETPC()); 206d578ca6cSSong Gao return fd; 207d578ca6cSSong Gao } 208d578ca6cSSong Gao 209d578ca6cSSong Gao uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 210d578ca6cSSong Gao { 211d578ca6cSSong Gao uint64_t fd; 212d578ca6cSSong Gao 213d578ca6cSSong Gao fd = float64_maxnummag(fj, fk, &env->fp_status); 214d578ca6cSSong Gao update_fcsr0(env, GETPC()); 215d578ca6cSSong Gao return fd; 216d578ca6cSSong Gao } 217d578ca6cSSong Gao 218d578ca6cSSong Gao uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 219d578ca6cSSong Gao { 220d578ca6cSSong Gao uint64_t fd; 221d578ca6cSSong Gao 222d578ca6cSSong Gao fd = nanbox_s(float32_minnummag((uint32_t)fj, 223d578ca6cSSong Gao (uint32_t)fk, &env->fp_status)); 224d578ca6cSSong Gao update_fcsr0(env, GETPC()); 225d578ca6cSSong Gao return fd; 226d578ca6cSSong Gao } 227d578ca6cSSong Gao 228d578ca6cSSong Gao uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 229d578ca6cSSong Gao { 230d578ca6cSSong Gao uint64_t fd; 231d578ca6cSSong Gao 232d578ca6cSSong Gao fd = float64_minnummag(fj, fk, &env->fp_status); 233d578ca6cSSong Gao update_fcsr0(env, GETPC()); 234d578ca6cSSong Gao return fd; 235d578ca6cSSong Gao } 236d578ca6cSSong Gao 237d578ca6cSSong Gao uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk) 238d578ca6cSSong Gao { 239d578ca6cSSong Gao uint64_t fd; 240d578ca6cSSong Gao int32_t n = (int32_t)fk; 241d578ca6cSSong Gao 242d578ca6cSSong Gao fd = nanbox_s(float32_scalbn((uint32_t)fj, 243d578ca6cSSong Gao n > 0x200 ? 0x200 : 244d578ca6cSSong Gao n < -0x200 ? -0x200 : n, 245d578ca6cSSong Gao &env->fp_status)); 246d578ca6cSSong Gao update_fcsr0(env, GETPC()); 247d578ca6cSSong Gao return fd; 248d578ca6cSSong Gao } 249d578ca6cSSong Gao 250d578ca6cSSong Gao uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk) 251d578ca6cSSong Gao { 252d578ca6cSSong Gao uint64_t fd; 253d578ca6cSSong Gao int64_t n = (int64_t)fk; 254d578ca6cSSong Gao 255d578ca6cSSong Gao fd = float64_scalbn(fj, 256d578ca6cSSong Gao n > 0x1000 ? 0x1000 : 257d578ca6cSSong Gao n < -0x1000 ? -0x1000 : n, 258d578ca6cSSong Gao &env->fp_status); 259d578ca6cSSong Gao update_fcsr0(env, GETPC()); 260d578ca6cSSong Gao return fd; 261d578ca6cSSong Gao } 262d578ca6cSSong Gao 263d578ca6cSSong Gao uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj) 264d578ca6cSSong Gao { 265d578ca6cSSong Gao uint64_t fd; 266d578ca6cSSong Gao 267d578ca6cSSong Gao fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status)); 268d578ca6cSSong Gao update_fcsr0(env, GETPC()); 269d578ca6cSSong Gao return fd; 270d578ca6cSSong Gao } 271d578ca6cSSong Gao 272d578ca6cSSong Gao uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj) 273d578ca6cSSong Gao { 274d578ca6cSSong Gao uint64_t fd; 275d578ca6cSSong Gao 276d578ca6cSSong Gao fd = float64_sqrt(fj, &env->fp_status); 277d578ca6cSSong Gao update_fcsr0(env, GETPC()); 278d578ca6cSSong Gao return fd; 279d578ca6cSSong Gao } 280d578ca6cSSong Gao 281d578ca6cSSong Gao uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj) 282d578ca6cSSong Gao { 283d578ca6cSSong Gao uint64_t fd; 284d578ca6cSSong Gao 285d578ca6cSSong Gao fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status)); 286d578ca6cSSong Gao update_fcsr0(env, GETPC()); 287d578ca6cSSong Gao return fd; 288d578ca6cSSong Gao } 289d578ca6cSSong Gao 290d578ca6cSSong Gao uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj) 291d578ca6cSSong Gao { 292d578ca6cSSong Gao uint64_t fd; 293d578ca6cSSong Gao 294d578ca6cSSong Gao fd = float64_div(float64_one, fj, &env->fp_status); 295d578ca6cSSong Gao update_fcsr0(env, GETPC()); 296d578ca6cSSong Gao return fd; 297d578ca6cSSong Gao } 298d578ca6cSSong Gao 299d578ca6cSSong Gao uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj) 300d578ca6cSSong Gao { 301d578ca6cSSong Gao uint64_t fd; 302d578ca6cSSong Gao uint32_t fp; 303d578ca6cSSong Gao 304d578ca6cSSong Gao fp = float32_sqrt((uint32_t)fj, &env->fp_status); 305d578ca6cSSong Gao fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status)); 306d578ca6cSSong Gao update_fcsr0(env, GETPC()); 307d578ca6cSSong Gao return fd; 308d578ca6cSSong Gao } 309d578ca6cSSong Gao 310d578ca6cSSong Gao uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj) 311d578ca6cSSong Gao { 312d578ca6cSSong Gao uint64_t fp, fd; 313d578ca6cSSong Gao 314d578ca6cSSong Gao fp = float64_sqrt(fj, &env->fp_status); 315d578ca6cSSong Gao fd = float64_div(float64_one, fp, &env->fp_status); 316d578ca6cSSong Gao update_fcsr0(env, GETPC()); 317d578ca6cSSong Gao return fd; 318d578ca6cSSong Gao } 319d578ca6cSSong Gao 320d578ca6cSSong Gao uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj) 321d578ca6cSSong Gao { 322d578ca6cSSong Gao uint64_t fd; 323d578ca6cSSong Gao uint32_t fp; 324d578ca6cSSong Gao float_status *status = &env->fp_status; 325d578ca6cSSong Gao FloatRoundMode old_mode = get_float_rounding_mode(status); 326d578ca6cSSong Gao 327d578ca6cSSong Gao set_float_rounding_mode(float_round_down, status); 328d578ca6cSSong Gao fp = float32_log2((uint32_t)fj, status); 329d578ca6cSSong Gao fd = nanbox_s(float32_round_to_int(fp, status)); 330d578ca6cSSong Gao set_float_rounding_mode(old_mode, status); 331d578ca6cSSong Gao update_fcsr0_mask(env, GETPC(), float_flag_inexact); 332d578ca6cSSong Gao return fd; 333d578ca6cSSong Gao } 334d578ca6cSSong Gao 335d578ca6cSSong Gao uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj) 336d578ca6cSSong Gao { 337d578ca6cSSong Gao uint64_t fd; 338d578ca6cSSong Gao float_status *status = &env->fp_status; 339d578ca6cSSong Gao FloatRoundMode old_mode = get_float_rounding_mode(status); 340d578ca6cSSong Gao 341d578ca6cSSong Gao set_float_rounding_mode(float_round_down, status); 342d578ca6cSSong Gao fd = float64_log2(fj, status); 343d578ca6cSSong Gao fd = float64_round_to_int(fd, status); 344d578ca6cSSong Gao set_float_rounding_mode(old_mode, status); 345d578ca6cSSong Gao update_fcsr0_mask(env, GETPC(), float_flag_inexact); 346d578ca6cSSong Gao return fd; 347d578ca6cSSong Gao } 348d578ca6cSSong Gao 349d578ca6cSSong Gao uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj) 350d578ca6cSSong Gao { 351d578ca6cSSong Gao float32 f = fj; 352d578ca6cSSong Gao bool sign = float32_is_neg(f); 353d578ca6cSSong Gao 354d578ca6cSSong Gao if (float32_is_infinity(f)) { 355d578ca6cSSong Gao return sign ? 1 << 2 : 1 << 6; 356d578ca6cSSong Gao } else if (float32_is_zero(f)) { 357d578ca6cSSong Gao return sign ? 1 << 5 : 1 << 9; 358d578ca6cSSong Gao } else if (float32_is_zero_or_denormal(f)) { 359d578ca6cSSong Gao return sign ? 1 << 4 : 1 << 8; 360d578ca6cSSong Gao } else if (float32_is_any_nan(f)) { 361d578ca6cSSong Gao float_status s = { }; /* for snan_bit_is_one */ 362d578ca6cSSong Gao return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0; 363d578ca6cSSong Gao } else { 364d578ca6cSSong Gao return sign ? 1 << 3 : 1 << 7; 365d578ca6cSSong Gao } 366d578ca6cSSong Gao } 367d578ca6cSSong Gao 368d578ca6cSSong Gao uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj) 369d578ca6cSSong Gao { 370d578ca6cSSong Gao float64 f = fj; 371d578ca6cSSong Gao bool sign = float64_is_neg(f); 372d578ca6cSSong Gao 373d578ca6cSSong Gao if (float64_is_infinity(f)) { 374d578ca6cSSong Gao return sign ? 1 << 2 : 1 << 6; 375d578ca6cSSong Gao } else if (float64_is_zero(f)) { 376d578ca6cSSong Gao return sign ? 1 << 5 : 1 << 9; 377d578ca6cSSong Gao } else if (float64_is_zero_or_denormal(f)) { 378d578ca6cSSong Gao return sign ? 1 << 4 : 1 << 8; 379d578ca6cSSong Gao } else if (float64_is_any_nan(f)) { 380d578ca6cSSong Gao float_status s = { }; /* for snan_bit_is_one */ 381d578ca6cSSong Gao return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0; 382d578ca6cSSong Gao } else { 383d578ca6cSSong Gao return sign ? 1 << 3 : 1 << 7; 384d578ca6cSSong Gao } 385d578ca6cSSong Gao } 386d578ca6cSSong Gao 387d578ca6cSSong Gao uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj, 388d578ca6cSSong Gao uint64_t fk, uint64_t fa, uint32_t flag) 389d578ca6cSSong Gao { 390d578ca6cSSong Gao uint64_t fd; 391d578ca6cSSong Gao 392d578ca6cSSong Gao fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk, 393d578ca6cSSong Gao (uint32_t)fa, flag, &env->fp_status)); 394d578ca6cSSong Gao update_fcsr0(env, GETPC()); 395d578ca6cSSong Gao return fd; 396d578ca6cSSong Gao } 397d578ca6cSSong Gao 398d578ca6cSSong Gao uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj, 399d578ca6cSSong Gao uint64_t fk, uint64_t fa, uint32_t flag) 400d578ca6cSSong Gao { 401d578ca6cSSong Gao uint64_t fd; 402d578ca6cSSong Gao 403d578ca6cSSong Gao fd = float64_muladd(fj, fk, fa, flag, &env->fp_status); 404d578ca6cSSong Gao update_fcsr0(env, GETPC()); 405d578ca6cSSong Gao return fd; 406d578ca6cSSong Gao } 4079b741076SSong Gao 4089b741076SSong Gao static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp, 4099b741076SSong Gao uint32_t flags) 4109b741076SSong Gao { 4119b741076SSong Gao bool ret; 4129b741076SSong Gao 4139b741076SSong Gao switch (cmp) { 4149b741076SSong Gao case float_relation_less: 4159b741076SSong Gao ret = (flags & FCMP_LT); 4169b741076SSong Gao break; 4179b741076SSong Gao case float_relation_equal: 4189b741076SSong Gao ret = (flags & FCMP_EQ); 4199b741076SSong Gao break; 4209b741076SSong Gao case float_relation_greater: 4219b741076SSong Gao ret = (flags & FCMP_GT); 4229b741076SSong Gao break; 4239b741076SSong Gao case float_relation_unordered: 4249b741076SSong Gao ret = (flags & FCMP_UN); 4259b741076SSong Gao break; 4269b741076SSong Gao default: 4279b741076SSong Gao g_assert_not_reached(); 4289b741076SSong Gao } 4299b741076SSong Gao update_fcsr0(env, GETPC()); 4309b741076SSong Gao 4319b741076SSong Gao return ret; 4329b741076SSong Gao } 4339b741076SSong Gao 4349b741076SSong Gao /* fcmp_cXXX_s */ 4359b741076SSong Gao uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj, 4369b741076SSong Gao uint64_t fk, uint32_t flags) 4379b741076SSong Gao { 4389b741076SSong Gao FloatRelation cmp = float32_compare_quiet((uint32_t)fj, 4399b741076SSong Gao (uint32_t)fk, &env->fp_status); 4409b741076SSong Gao return fcmp_common(env, cmp, flags); 4419b741076SSong Gao } 4429b741076SSong Gao 4439b741076SSong Gao /* fcmp_sXXX_s */ 4449b741076SSong Gao uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj, 4459b741076SSong Gao uint64_t fk, uint32_t flags) 4469b741076SSong Gao { 4479b741076SSong Gao FloatRelation cmp = float32_compare((uint32_t)fj, 4489b741076SSong Gao (uint32_t)fk, &env->fp_status); 4499b741076SSong Gao return fcmp_common(env, cmp, flags); 4509b741076SSong Gao } 4519b741076SSong Gao 4529b741076SSong Gao /* fcmp_cXXX_d */ 4539b741076SSong Gao uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj, 4549b741076SSong Gao uint64_t fk, uint32_t flags) 4559b741076SSong Gao { 4569b741076SSong Gao FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status); 4579b741076SSong Gao return fcmp_common(env, cmp, flags); 4589b741076SSong Gao } 4599b741076SSong Gao 4609b741076SSong Gao /* fcmp_sXXX_d */ 4619b741076SSong Gao uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj, 4629b741076SSong Gao uint64_t fk, uint32_t flags) 4639b741076SSong Gao { 4649b741076SSong Gao FloatRelation cmp = float64_compare(fj, fk, &env->fp_status); 4659b741076SSong Gao return fcmp_common(env, cmp, flags); 4669b741076SSong Gao } 4677c1f8870SSong Gao 4687c1f8870SSong Gao /* floating point conversion */ 4697c1f8870SSong Gao uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj) 4707c1f8870SSong Gao { 4717c1f8870SSong Gao uint64_t fd; 4727c1f8870SSong Gao 4737c1f8870SSong Gao fd = nanbox_s(float64_to_float32(fj, &env->fp_status)); 4747c1f8870SSong Gao update_fcsr0(env, GETPC()); 4757c1f8870SSong Gao return fd; 4767c1f8870SSong Gao } 4777c1f8870SSong Gao 4787c1f8870SSong Gao uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj) 4797c1f8870SSong Gao { 4807c1f8870SSong Gao uint64_t fd; 4817c1f8870SSong Gao 4827c1f8870SSong Gao fd = float32_to_float64((uint32_t)fj, &env->fp_status); 4837c1f8870SSong Gao update_fcsr0(env, GETPC()); 4847c1f8870SSong Gao return fd; 4857c1f8870SSong Gao } 4867c1f8870SSong Gao 4877c1f8870SSong Gao uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj) 4887c1f8870SSong Gao { 4897c1f8870SSong Gao uint64_t fd; 4907c1f8870SSong Gao 4917c1f8870SSong Gao fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status)); 4927c1f8870SSong Gao update_fcsr0(env, GETPC()); 4937c1f8870SSong Gao return fd; 4947c1f8870SSong Gao } 4957c1f8870SSong Gao 4967c1f8870SSong Gao uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj) 4977c1f8870SSong Gao { 4987c1f8870SSong Gao uint64_t fd; 4997c1f8870SSong Gao 5007c1f8870SSong Gao fd = nanbox_s(int64_to_float32(fj, &env->fp_status)); 5017c1f8870SSong Gao update_fcsr0(env, GETPC()); 5027c1f8870SSong Gao return fd; 5037c1f8870SSong Gao } 5047c1f8870SSong Gao 5057c1f8870SSong Gao uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj) 5067c1f8870SSong Gao { 5077c1f8870SSong Gao uint64_t fd; 5087c1f8870SSong Gao 5097c1f8870SSong Gao fd = int32_to_float64((int32_t)fj, &env->fp_status); 5107c1f8870SSong Gao update_fcsr0(env, GETPC()); 5117c1f8870SSong Gao return fd; 5127c1f8870SSong Gao } 5137c1f8870SSong Gao 5147c1f8870SSong Gao uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj) 5157c1f8870SSong Gao { 5167c1f8870SSong Gao uint64_t fd; 5177c1f8870SSong Gao 5187c1f8870SSong Gao fd = int64_to_float64(fj, &env->fp_status); 5197c1f8870SSong Gao update_fcsr0(env, GETPC()); 5207c1f8870SSong Gao return fd; 5217c1f8870SSong Gao } 5227c1f8870SSong Gao 5237c1f8870SSong Gao uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj) 5247c1f8870SSong Gao { 5257c1f8870SSong Gao uint64_t fd; 5267c1f8870SSong Gao 5277c1f8870SSong Gao fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status)); 5287c1f8870SSong Gao update_fcsr0(env, GETPC()); 5297c1f8870SSong Gao return fd; 5307c1f8870SSong Gao } 5317c1f8870SSong Gao 5327c1f8870SSong Gao uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj) 5337c1f8870SSong Gao { 5347c1f8870SSong Gao uint64_t fd; 5357c1f8870SSong Gao 5367c1f8870SSong Gao fd = float64_round_to_int(fj, &env->fp_status); 5377c1f8870SSong Gao update_fcsr0(env, GETPC()); 5387c1f8870SSong Gao return fd; 5397c1f8870SSong Gao } 5407c1f8870SSong Gao 5417c1f8870SSong Gao uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj) 5427c1f8870SSong Gao { 5437c1f8870SSong Gao uint64_t fd; 5447c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 5457c1f8870SSong Gao 5467c1f8870SSong Gao set_float_rounding_mode(float_round_down, &env->fp_status); 5477c1f8870SSong Gao fd = float64_to_int64(fj, &env->fp_status); 5487c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 5497c1f8870SSong Gao 5509fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 5519fad2071SSong Gao if (float64_is_any_nan(fj)) { 5529fad2071SSong Gao fd = 0; 5539fad2071SSong Gao } 5547c1f8870SSong Gao } 5557c1f8870SSong Gao update_fcsr0(env, GETPC()); 5567c1f8870SSong Gao return fd; 5577c1f8870SSong Gao } 5587c1f8870SSong Gao 5597c1f8870SSong Gao uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj) 5607c1f8870SSong Gao { 5617c1f8870SSong Gao uint64_t fd; 5627c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 5637c1f8870SSong Gao 5647c1f8870SSong Gao set_float_rounding_mode(float_round_down, &env->fp_status); 5657c1f8870SSong Gao fd = float32_to_int64((uint32_t)fj, &env->fp_status); 5667c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 5677c1f8870SSong Gao 5689fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 5699fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 5709fad2071SSong Gao fd = 0; 5719fad2071SSong Gao } 5727c1f8870SSong Gao } 5737c1f8870SSong Gao update_fcsr0(env, GETPC()); 5747c1f8870SSong Gao return fd; 5757c1f8870SSong Gao } 5767c1f8870SSong Gao 5777c1f8870SSong Gao uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj) 5787c1f8870SSong Gao { 5797c1f8870SSong Gao uint64_t fd; 5807c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 5817c1f8870SSong Gao 5827c1f8870SSong Gao set_float_rounding_mode(float_round_down, &env->fp_status); 5837c1f8870SSong Gao fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 5847c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 5857c1f8870SSong Gao 5869fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 5879fad2071SSong Gao if (float64_is_any_nan(fj)) { 5889fad2071SSong Gao fd = 0; 5899fad2071SSong Gao } 5907c1f8870SSong Gao } 5917c1f8870SSong Gao update_fcsr0(env, GETPC()); 5927c1f8870SSong Gao return fd; 5937c1f8870SSong Gao } 5947c1f8870SSong Gao 5957c1f8870SSong Gao uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj) 5967c1f8870SSong Gao { 5977c1f8870SSong Gao uint64_t fd; 5987c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 5997c1f8870SSong Gao 6007c1f8870SSong Gao set_float_rounding_mode(float_round_down, &env->fp_status); 6017c1f8870SSong Gao fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 6027c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6037c1f8870SSong Gao 6049fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6059fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 6069fad2071SSong Gao fd = 0; 6079fad2071SSong Gao } 6087c1f8870SSong Gao } 6097c1f8870SSong Gao update_fcsr0(env, GETPC()); 6107c1f8870SSong Gao return fd; 6117c1f8870SSong Gao } 6127c1f8870SSong Gao 6137c1f8870SSong Gao uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj) 6147c1f8870SSong Gao { 6157c1f8870SSong Gao uint64_t fd; 6167c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 6177c1f8870SSong Gao 6187c1f8870SSong Gao set_float_rounding_mode(float_round_up, &env->fp_status); 6197c1f8870SSong Gao fd = float64_to_int64(fj, &env->fp_status); 6207c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6217c1f8870SSong Gao 6229fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6239fad2071SSong Gao if (float64_is_any_nan(fj)) { 6249fad2071SSong Gao fd = 0; 6259fad2071SSong Gao } 6267c1f8870SSong Gao } 6277c1f8870SSong Gao update_fcsr0(env, GETPC()); 6287c1f8870SSong Gao return fd; 6297c1f8870SSong Gao } 6307c1f8870SSong Gao 6317c1f8870SSong Gao uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj) 6327c1f8870SSong Gao { 6337c1f8870SSong Gao uint64_t fd; 6347c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 6357c1f8870SSong Gao 6367c1f8870SSong Gao set_float_rounding_mode(float_round_up, &env->fp_status); 6377c1f8870SSong Gao fd = float32_to_int64((uint32_t)fj, &env->fp_status); 6387c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6397c1f8870SSong Gao 6409fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6419fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 6429fad2071SSong Gao fd = 0; 6439fad2071SSong Gao } 6447c1f8870SSong Gao } 6457c1f8870SSong Gao update_fcsr0(env, GETPC()); 6467c1f8870SSong Gao return fd; 6477c1f8870SSong Gao } 6487c1f8870SSong Gao 6497c1f8870SSong Gao uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj) 6507c1f8870SSong Gao { 6517c1f8870SSong Gao uint64_t fd; 6527c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 6537c1f8870SSong Gao 6547c1f8870SSong Gao set_float_rounding_mode(float_round_up, &env->fp_status); 6557c1f8870SSong Gao fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 6567c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6577c1f8870SSong Gao 6589fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6599fad2071SSong Gao if (float64_is_any_nan(fj)) { 6609fad2071SSong Gao fd = 0; 6619fad2071SSong Gao } 6627c1f8870SSong Gao } 6637c1f8870SSong Gao update_fcsr0(env, GETPC()); 6647c1f8870SSong Gao return fd; 6657c1f8870SSong Gao } 6667c1f8870SSong Gao 6677c1f8870SSong Gao uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj) 6687c1f8870SSong Gao { 6697c1f8870SSong Gao uint64_t fd; 6707c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 6717c1f8870SSong Gao 6727c1f8870SSong Gao set_float_rounding_mode(float_round_up, &env->fp_status); 6737c1f8870SSong Gao fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 6747c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6757c1f8870SSong Gao 6769fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6779fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 6789fad2071SSong Gao fd = 0; 6799fad2071SSong Gao } 6807c1f8870SSong Gao } 6817c1f8870SSong Gao update_fcsr0(env, GETPC()); 6827c1f8870SSong Gao return fd; 6837c1f8870SSong Gao } 6847c1f8870SSong Gao 6857c1f8870SSong Gao uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj) 6867c1f8870SSong Gao { 6877c1f8870SSong Gao uint64_t fd; 6887c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 6897c1f8870SSong Gao 6907c1f8870SSong Gao fd = float64_to_int64_round_to_zero(fj, &env->fp_status); 6917c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 6927c1f8870SSong Gao 6939fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 6949fad2071SSong Gao if (float64_is_any_nan(fj)) { 6959fad2071SSong Gao fd = 0; 6969fad2071SSong Gao } 6977c1f8870SSong Gao } 6987c1f8870SSong Gao update_fcsr0(env, GETPC()); 6997c1f8870SSong Gao return fd; 7007c1f8870SSong Gao } 7017c1f8870SSong Gao 7027c1f8870SSong Gao uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj) 7037c1f8870SSong Gao { 7047c1f8870SSong Gao uint64_t fd; 7057c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7067c1f8870SSong Gao 7077c1f8870SSong Gao fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status); 7087c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7097c1f8870SSong Gao 7109fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7119fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 7129fad2071SSong Gao fd = 0; 7139fad2071SSong Gao } 7147c1f8870SSong Gao } 7157c1f8870SSong Gao update_fcsr0(env, GETPC()); 7167c1f8870SSong Gao return fd; 7177c1f8870SSong Gao } 7187c1f8870SSong Gao 7197c1f8870SSong Gao uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj) 7207c1f8870SSong Gao { 7217c1f8870SSong Gao uint64_t fd; 7227c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7237c1f8870SSong Gao 7247c1f8870SSong Gao fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status); 7257c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7267c1f8870SSong Gao 7279fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7289fad2071SSong Gao if (float64_is_any_nan(fj)) { 7299fad2071SSong Gao fd = 0; 7309fad2071SSong Gao } 7317c1f8870SSong Gao } 7327c1f8870SSong Gao update_fcsr0(env, GETPC()); 7337c1f8870SSong Gao return fd; 7347c1f8870SSong Gao } 7357c1f8870SSong Gao 7367c1f8870SSong Gao uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj) 7377c1f8870SSong Gao { 7387c1f8870SSong Gao uint32_t fd; 7397c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7407c1f8870SSong Gao 7417c1f8870SSong Gao fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status); 7427c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7437c1f8870SSong Gao 7449fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7459fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 7469fad2071SSong Gao fd = 0; 7479fad2071SSong Gao } 7487c1f8870SSong Gao } 7497c1f8870SSong Gao update_fcsr0(env, GETPC()); 7507c1f8870SSong Gao return (uint64_t)fd; 7517c1f8870SSong Gao } 7527c1f8870SSong Gao 7537c1f8870SSong Gao uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj) 7547c1f8870SSong Gao { 7557c1f8870SSong Gao uint64_t fd; 7567c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7577c1f8870SSong Gao 7587c1f8870SSong Gao set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 7597c1f8870SSong Gao fd = float64_to_int64(fj, &env->fp_status); 7607c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7617c1f8870SSong Gao 7629fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7639fad2071SSong Gao if (float64_is_any_nan(fj)) { 7649fad2071SSong Gao fd = 0; 7659fad2071SSong Gao } 7667c1f8870SSong Gao } 7677c1f8870SSong Gao update_fcsr0(env, GETPC()); 7687c1f8870SSong Gao return fd; 7697c1f8870SSong Gao } 7707c1f8870SSong Gao 7717c1f8870SSong Gao uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj) 7727c1f8870SSong Gao { 7737c1f8870SSong Gao uint64_t fd; 7747c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7757c1f8870SSong Gao 7767c1f8870SSong Gao set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 7777c1f8870SSong Gao fd = float32_to_int64((uint32_t)fj, &env->fp_status); 7787c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7797c1f8870SSong Gao 7809fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7819fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 7829fad2071SSong Gao fd = 0; 7839fad2071SSong Gao } 7847c1f8870SSong Gao } 7857c1f8870SSong Gao update_fcsr0(env, GETPC()); 7867c1f8870SSong Gao return fd; 7877c1f8870SSong Gao } 7887c1f8870SSong Gao 7897c1f8870SSong Gao uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj) 7907c1f8870SSong Gao { 7917c1f8870SSong Gao uint64_t fd; 7927c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 7937c1f8870SSong Gao 7947c1f8870SSong Gao set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 7957c1f8870SSong Gao fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 7967c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 7977c1f8870SSong Gao 7989fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 7999fad2071SSong Gao if (float64_is_any_nan(fj)) { 8009fad2071SSong Gao fd = 0; 8019fad2071SSong Gao } 8027c1f8870SSong Gao } 8037c1f8870SSong Gao update_fcsr0(env, GETPC()); 8047c1f8870SSong Gao return fd; 8057c1f8870SSong Gao } 8067c1f8870SSong Gao 8077c1f8870SSong Gao uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj) 8087c1f8870SSong Gao { 8097c1f8870SSong Gao uint32_t fd; 8107c1f8870SSong Gao FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status); 8117c1f8870SSong Gao 8127c1f8870SSong Gao set_float_rounding_mode(float_round_nearest_even, &env->fp_status); 8137c1f8870SSong Gao fd = float32_to_int32((uint32_t)fj, &env->fp_status); 8147c1f8870SSong Gao set_float_rounding_mode(old_mode, &env->fp_status); 8157c1f8870SSong Gao 8169fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 8179fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 8189fad2071SSong Gao fd = 0; 8199fad2071SSong Gao } 8207c1f8870SSong Gao } 8217c1f8870SSong Gao update_fcsr0(env, GETPC()); 8227c1f8870SSong Gao return (uint64_t)fd; 8237c1f8870SSong Gao } 8247c1f8870SSong Gao 8257c1f8870SSong Gao uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj) 8267c1f8870SSong Gao { 8277c1f8870SSong Gao uint64_t fd; 8287c1f8870SSong Gao 8297c1f8870SSong Gao fd = float64_to_int64(fj, &env->fp_status); 8309fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 8319fad2071SSong Gao if (float64_is_any_nan(fj)) { 8329fad2071SSong Gao fd = 0; 8339fad2071SSong Gao } 8347c1f8870SSong Gao } 8357c1f8870SSong Gao update_fcsr0(env, GETPC()); 8367c1f8870SSong Gao return fd; 8377c1f8870SSong Gao } 8387c1f8870SSong Gao 8397c1f8870SSong Gao uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj) 8407c1f8870SSong Gao { 8417c1f8870SSong Gao uint64_t fd; 8427c1f8870SSong Gao 8437c1f8870SSong Gao fd = float32_to_int64((uint32_t)fj, &env->fp_status); 8449fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 8459fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 8469fad2071SSong Gao fd = 0; 8479fad2071SSong Gao } 8487c1f8870SSong Gao } 8497c1f8870SSong Gao update_fcsr0(env, GETPC()); 8507c1f8870SSong Gao return fd; 8517c1f8870SSong Gao } 8527c1f8870SSong Gao 8537c1f8870SSong Gao uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj) 8547c1f8870SSong Gao { 8557c1f8870SSong Gao uint64_t fd; 8567c1f8870SSong Gao 8577c1f8870SSong Gao fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status); 8589fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 8599fad2071SSong Gao if (float32_is_any_nan((uint32_t)fj)) { 8609fad2071SSong Gao fd = 0; 8619fad2071SSong Gao } 8627c1f8870SSong Gao } 8637c1f8870SSong Gao update_fcsr0(env, GETPC()); 8647c1f8870SSong Gao return fd; 8657c1f8870SSong Gao } 8667c1f8870SSong Gao 8677c1f8870SSong Gao uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) 8687c1f8870SSong Gao { 8697c1f8870SSong Gao uint64_t fd; 8707c1f8870SSong Gao 8717c1f8870SSong Gao fd = (uint64_t)float64_to_int32(fj, &env->fp_status); 8729fad2071SSong Gao if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) { 8739fad2071SSong Gao if (float64_is_any_nan(fj)) { 8749fad2071SSong Gao fd = 0; 8759fad2071SSong Gao } 8767c1f8870SSong Gao } 8777c1f8870SSong Gao update_fcsr0(env, GETPC()); 8787c1f8870SSong Gao return fd; 8797c1f8870SSong Gao } 880b7dabd56SSong Gao 88110dcb08bSRichard Henderson void helper_set_rounding_mode(CPULoongArchState *env) 882b7dabd56SSong Gao { 88310dcb08bSRichard Henderson set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], 884b7dabd56SSong Gao &env->fp_status); 885b7dabd56SSong Gao } 886