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