xref: /qemu/target/loongarch/tcg/fpu_helper.c (revision 84307cd6027c4602913177ff09aeefa4743b7234)
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"
11*42fa9665SPhilippe Mathieu-Daudé #include "accel/tcg/cpu-ldst.h"
12d578ca6cSSong Gao #include "fpu/softfloat.h"
13d578ca6cSSong Gao #include "internals.h"
14d578ca6cSSong Gao 
nanbox_s(float32 fp)15d578ca6cSSong Gao static inline uint64_t nanbox_s(float32 fp)
16d578ca6cSSong Gao {
17d578ca6cSSong Gao     return fp | MAKE_64BIT_MASK(32, 32);
18d578ca6cSSong Gao }
19d578ca6cSSong Gao 
20d578ca6cSSong Gao /* Convert loongarch rounding mode in fcsr0 to IEEE library */
21d578ca6cSSong Gao static const FloatRoundMode ieee_rm[4] = {
22d578ca6cSSong Gao     float_round_nearest_even,
23d578ca6cSSong Gao     float_round_to_zero,
24d578ca6cSSong Gao     float_round_up,
25d578ca6cSSong Gao     float_round_down
26d578ca6cSSong Gao };
27d578ca6cSSong Gao 
restore_fp_status(CPULoongArchState * env)28d578ca6cSSong Gao void restore_fp_status(CPULoongArchState *env)
29d578ca6cSSong Gao {
30d578ca6cSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
31d578ca6cSSong Gao                             &env->fp_status);
32d578ca6cSSong Gao     set_flush_to_zero(0, &env->fp_status);
331bb5257dSPeter Maydell     set_float_2nan_prop_rule(float_2nan_prop_s_ab, &env->fp_status);
340fb7fa29SPeter Maydell     /*
350fb7fa29SPeter Maydell      * For LoongArch systems that conform to IEEE754-2008, the (inf,zero,nan)
360fb7fa29SPeter Maydell      * case sets InvalidOp and returns the input value 'c'
370fb7fa29SPeter Maydell      */
380fb7fa29SPeter Maydell     set_float_infzeronan_rule(float_infzeronan_dnan_never, &env->fp_status);
399d0b8f96SPeter Maydell     set_float_3nan_prop_rule(float_3nan_prop_s_cab, &env->fp_status);
407d582aa7SPeter Maydell     /* Default NaN: sign bit clear, msb frac bit set */
417d582aa7SPeter Maydell     set_float_default_nan_pattern(0b01000000, &env->fp_status);
42d578ca6cSSong Gao }
43d578ca6cSSong Gao 
ieee_ex_to_loongarch(int xcpt)44aca67472SSong Gao int ieee_ex_to_loongarch(int xcpt)
45d578ca6cSSong Gao {
46d578ca6cSSong Gao     int ret = 0;
47d578ca6cSSong Gao     if (xcpt & float_flag_invalid) {
48d578ca6cSSong Gao         ret |= FP_INVALID;
49d578ca6cSSong Gao     }
50d578ca6cSSong Gao     if (xcpt & float_flag_overflow) {
51d578ca6cSSong Gao         ret |= FP_OVERFLOW;
52d578ca6cSSong Gao     }
53d578ca6cSSong Gao     if (xcpt & float_flag_underflow) {
54d578ca6cSSong Gao         ret |= FP_UNDERFLOW;
55d578ca6cSSong Gao     }
56d578ca6cSSong Gao     if (xcpt & float_flag_divbyzero) {
57d578ca6cSSong Gao         ret |= FP_DIV0;
58d578ca6cSSong Gao     }
59d578ca6cSSong Gao     if (xcpt & float_flag_inexact) {
60d578ca6cSSong Gao         ret |= FP_INEXACT;
61d578ca6cSSong Gao     }
62d578ca6cSSong Gao     return ret;
63d578ca6cSSong Gao }
64d578ca6cSSong Gao 
update_fcsr0_mask(CPULoongArchState * env,uintptr_t pc,int mask)65d578ca6cSSong Gao static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
66d578ca6cSSong Gao {
67d578ca6cSSong Gao     int flags = get_float_exception_flags(&env->fp_status);
68d578ca6cSSong Gao 
69d578ca6cSSong Gao     set_float_exception_flags(0, &env->fp_status);
70d578ca6cSSong Gao 
71d578ca6cSSong Gao     flags &= ~mask;
72d578ca6cSSong Gao 
73d578ca6cSSong Gao     if (!flags) {
74d578ca6cSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
75d578ca6cSSong Gao         return;
76d578ca6cSSong Gao     } else {
77d578ca6cSSong Gao         flags = ieee_ex_to_loongarch(flags);
78d578ca6cSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
79d578ca6cSSong Gao     }
80d578ca6cSSong Gao 
81d578ca6cSSong Gao     if (GET_FP_ENABLES(env->fcsr0) & flags) {
82d578ca6cSSong Gao         do_raise_exception(env, EXCCODE_FPE, pc);
83d578ca6cSSong Gao     } else {
84d578ca6cSSong Gao         UPDATE_FP_FLAGS(env->fcsr0, flags);
85d578ca6cSSong Gao     }
86d578ca6cSSong Gao }
87d578ca6cSSong Gao 
update_fcsr0(CPULoongArchState * env,uintptr_t pc)88d578ca6cSSong Gao static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
89d578ca6cSSong Gao {
90d578ca6cSSong Gao     update_fcsr0_mask(env, pc, 0);
91d578ca6cSSong Gao }
92d578ca6cSSong Gao 
helper_fadd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)93d578ca6cSSong Gao uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
94d578ca6cSSong Gao {
95d578ca6cSSong Gao     uint64_t fd;
96d578ca6cSSong Gao 
97d578ca6cSSong Gao     fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status));
98d578ca6cSSong Gao     update_fcsr0(env, GETPC());
99d578ca6cSSong Gao     return fd;
100d578ca6cSSong Gao }
101d578ca6cSSong Gao 
helper_fadd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)102d578ca6cSSong Gao uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
103d578ca6cSSong Gao {
104d578ca6cSSong Gao     uint64_t fd;
105d578ca6cSSong Gao 
106d578ca6cSSong Gao     fd = float64_add(fj, fk, &env->fp_status);
107d578ca6cSSong Gao     update_fcsr0(env, GETPC());
108d578ca6cSSong Gao     return fd;
109d578ca6cSSong Gao }
110d578ca6cSSong Gao 
helper_fsub_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)111d578ca6cSSong Gao uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
112d578ca6cSSong Gao {
113d578ca6cSSong Gao     uint64_t fd;
114d578ca6cSSong Gao 
115d578ca6cSSong Gao     fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status));
116d578ca6cSSong Gao     update_fcsr0(env, GETPC());
117d578ca6cSSong Gao     return fd;
118d578ca6cSSong Gao }
119d578ca6cSSong Gao 
helper_fsub_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)120d578ca6cSSong Gao uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
121d578ca6cSSong Gao {
122d578ca6cSSong Gao     uint64_t fd;
123d578ca6cSSong Gao 
124d578ca6cSSong Gao     fd = float64_sub(fj, fk, &env->fp_status);
125d578ca6cSSong Gao     update_fcsr0(env, GETPC());
126d578ca6cSSong Gao     return fd;
127d578ca6cSSong Gao }
128d578ca6cSSong Gao 
helper_fmul_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)129d578ca6cSSong Gao uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
130d578ca6cSSong Gao {
131d578ca6cSSong Gao     uint64_t fd;
132d578ca6cSSong Gao 
133d578ca6cSSong Gao     fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status));
134d578ca6cSSong Gao     update_fcsr0(env, GETPC());
135d578ca6cSSong Gao     return fd;
136d578ca6cSSong Gao }
137d578ca6cSSong Gao 
helper_fmul_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)138d578ca6cSSong Gao uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
139d578ca6cSSong Gao {
140d578ca6cSSong Gao     uint64_t fd;
141d578ca6cSSong Gao 
142d578ca6cSSong Gao     fd = float64_mul(fj, fk, &env->fp_status);
143d578ca6cSSong Gao     update_fcsr0(env, GETPC());
144d578ca6cSSong Gao     return fd;
145d578ca6cSSong Gao }
146d578ca6cSSong Gao 
helper_fdiv_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)147d578ca6cSSong Gao uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
148d578ca6cSSong Gao {
149d578ca6cSSong Gao     uint64_t fd;
150d578ca6cSSong Gao 
151d578ca6cSSong Gao     fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status));
152d578ca6cSSong Gao     update_fcsr0(env, GETPC());
153d578ca6cSSong Gao     return fd;
154d578ca6cSSong Gao }
155d578ca6cSSong Gao 
helper_fdiv_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)156d578ca6cSSong Gao uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
157d578ca6cSSong Gao {
158d578ca6cSSong Gao     uint64_t fd;
159d578ca6cSSong Gao 
160d578ca6cSSong Gao     fd = float64_div(fj, fk, &env->fp_status);
161d578ca6cSSong Gao     update_fcsr0(env, GETPC());
162d578ca6cSSong Gao     return fd;
163d578ca6cSSong Gao }
164d578ca6cSSong Gao 
helper_fmax_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)165d578ca6cSSong Gao uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
166d578ca6cSSong Gao {
167d578ca6cSSong Gao     uint64_t fd;
168d578ca6cSSong Gao 
169d578ca6cSSong Gao     fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
170d578ca6cSSong Gao     update_fcsr0(env, GETPC());
171d578ca6cSSong Gao     return fd;
172d578ca6cSSong Gao }
173d578ca6cSSong Gao 
helper_fmax_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)174d578ca6cSSong Gao uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
175d578ca6cSSong Gao {
176d578ca6cSSong Gao     uint64_t fd;
177d578ca6cSSong Gao 
178d578ca6cSSong Gao     fd = float64_maxnum(fj, fk, &env->fp_status);
179d578ca6cSSong Gao     update_fcsr0(env, GETPC());
180d578ca6cSSong Gao     return fd;
181d578ca6cSSong Gao }
182d578ca6cSSong Gao 
helper_fmin_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)183d578ca6cSSong Gao uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
184d578ca6cSSong Gao {
185d578ca6cSSong Gao     uint64_t fd;
186d578ca6cSSong Gao 
187d578ca6cSSong Gao     fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
188d578ca6cSSong Gao     update_fcsr0(env, GETPC());
189d578ca6cSSong Gao     return fd;
190d578ca6cSSong Gao }
191d578ca6cSSong Gao 
helper_fmin_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)192d578ca6cSSong Gao uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
193d578ca6cSSong Gao {
194d578ca6cSSong Gao     uint64_t fd;
195d578ca6cSSong Gao 
196d578ca6cSSong Gao     fd = float64_minnum(fj, fk, &env->fp_status);
197d578ca6cSSong Gao     update_fcsr0(env, GETPC());
198d578ca6cSSong Gao     return fd;
199d578ca6cSSong Gao }
200d578ca6cSSong Gao 
helper_fmaxa_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)201d578ca6cSSong Gao uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
202d578ca6cSSong Gao {
203d578ca6cSSong Gao     uint64_t fd;
204d578ca6cSSong Gao 
205d578ca6cSSong Gao     fd = nanbox_s(float32_maxnummag((uint32_t)fj,
206d578ca6cSSong Gao                                     (uint32_t)fk, &env->fp_status));
207d578ca6cSSong Gao     update_fcsr0(env, GETPC());
208d578ca6cSSong Gao     return fd;
209d578ca6cSSong Gao }
210d578ca6cSSong Gao 
helper_fmaxa_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)211d578ca6cSSong Gao uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
212d578ca6cSSong Gao {
213d578ca6cSSong Gao     uint64_t fd;
214d578ca6cSSong Gao 
215d578ca6cSSong Gao     fd = float64_maxnummag(fj, fk, &env->fp_status);
216d578ca6cSSong Gao     update_fcsr0(env, GETPC());
217d578ca6cSSong Gao     return fd;
218d578ca6cSSong Gao }
219d578ca6cSSong Gao 
helper_fmina_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)220d578ca6cSSong Gao uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
221d578ca6cSSong Gao {
222d578ca6cSSong Gao     uint64_t fd;
223d578ca6cSSong Gao 
224d578ca6cSSong Gao     fd = nanbox_s(float32_minnummag((uint32_t)fj,
225d578ca6cSSong Gao                                     (uint32_t)fk, &env->fp_status));
226d578ca6cSSong Gao     update_fcsr0(env, GETPC());
227d578ca6cSSong Gao     return fd;
228d578ca6cSSong Gao }
229d578ca6cSSong Gao 
helper_fmina_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)230d578ca6cSSong Gao uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
231d578ca6cSSong Gao {
232d578ca6cSSong Gao     uint64_t fd;
233d578ca6cSSong Gao 
234d578ca6cSSong Gao     fd = float64_minnummag(fj, fk, &env->fp_status);
235d578ca6cSSong Gao     update_fcsr0(env, GETPC());
236d578ca6cSSong Gao     return fd;
237d578ca6cSSong Gao }
238d578ca6cSSong Gao 
helper_fscaleb_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)239d578ca6cSSong Gao uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
240d578ca6cSSong Gao {
241d578ca6cSSong Gao     uint64_t fd;
242d578ca6cSSong Gao     int32_t n = (int32_t)fk;
243d578ca6cSSong Gao 
244d578ca6cSSong Gao     fd = nanbox_s(float32_scalbn((uint32_t)fj,
245d578ca6cSSong Gao                                  n >  0x200 ?  0x200 :
246d578ca6cSSong Gao                                  n < -0x200 ? -0x200 : n,
247d578ca6cSSong Gao                                  &env->fp_status));
248d578ca6cSSong Gao     update_fcsr0(env, GETPC());
249d578ca6cSSong Gao     return fd;
250d578ca6cSSong Gao }
251d578ca6cSSong Gao 
helper_fscaleb_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)252d578ca6cSSong Gao uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
253d578ca6cSSong Gao {
254d578ca6cSSong Gao     uint64_t fd;
255d578ca6cSSong Gao     int64_t n = (int64_t)fk;
256d578ca6cSSong Gao 
257d578ca6cSSong Gao     fd = float64_scalbn(fj,
258d578ca6cSSong Gao                         n >  0x1000 ?  0x1000 :
259d578ca6cSSong Gao                         n < -0x1000 ? -0x1000 : n,
260d578ca6cSSong Gao                         &env->fp_status);
261d578ca6cSSong Gao     update_fcsr0(env, GETPC());
262d578ca6cSSong Gao     return fd;
263d578ca6cSSong Gao }
264d578ca6cSSong Gao 
helper_fsqrt_s(CPULoongArchState * env,uint64_t fj)265d578ca6cSSong Gao uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj)
266d578ca6cSSong Gao {
267d578ca6cSSong Gao     uint64_t fd;
268d578ca6cSSong Gao 
269d578ca6cSSong Gao     fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status));
270d578ca6cSSong Gao     update_fcsr0(env, GETPC());
271d578ca6cSSong Gao     return fd;
272d578ca6cSSong Gao }
273d578ca6cSSong Gao 
helper_fsqrt_d(CPULoongArchState * env,uint64_t fj)274d578ca6cSSong Gao uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj)
275d578ca6cSSong Gao {
276d578ca6cSSong Gao     uint64_t fd;
277d578ca6cSSong Gao 
278d578ca6cSSong Gao     fd = float64_sqrt(fj, &env->fp_status);
279d578ca6cSSong Gao     update_fcsr0(env, GETPC());
280d578ca6cSSong Gao     return fd;
281d578ca6cSSong Gao }
282d578ca6cSSong Gao 
helper_frecip_s(CPULoongArchState * env,uint64_t fj)283d578ca6cSSong Gao uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj)
284d578ca6cSSong Gao {
285d578ca6cSSong Gao     uint64_t fd;
286d578ca6cSSong Gao 
287d578ca6cSSong Gao     fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status));
288d578ca6cSSong Gao     update_fcsr0(env, GETPC());
289d578ca6cSSong Gao     return fd;
290d578ca6cSSong Gao }
291d578ca6cSSong Gao 
helper_frecip_d(CPULoongArchState * env,uint64_t fj)292d578ca6cSSong Gao uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj)
293d578ca6cSSong Gao {
294d578ca6cSSong Gao     uint64_t fd;
295d578ca6cSSong Gao 
296d578ca6cSSong Gao     fd = float64_div(float64_one, fj, &env->fp_status);
297d578ca6cSSong Gao     update_fcsr0(env, GETPC());
298d578ca6cSSong Gao     return fd;
299d578ca6cSSong Gao }
300d578ca6cSSong Gao 
helper_frsqrt_s(CPULoongArchState * env,uint64_t fj)301d578ca6cSSong Gao uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj)
302d578ca6cSSong Gao {
303d578ca6cSSong Gao     uint64_t fd;
304d578ca6cSSong Gao     uint32_t fp;
305d578ca6cSSong Gao 
306d578ca6cSSong Gao     fp = float32_sqrt((uint32_t)fj, &env->fp_status);
307d578ca6cSSong Gao     fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status));
308d578ca6cSSong Gao     update_fcsr0(env, GETPC());
309d578ca6cSSong Gao     return fd;
310d578ca6cSSong Gao }
311d578ca6cSSong Gao 
helper_frsqrt_d(CPULoongArchState * env,uint64_t fj)312d578ca6cSSong Gao uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj)
313d578ca6cSSong Gao {
314d578ca6cSSong Gao     uint64_t fp, fd;
315d578ca6cSSong Gao 
316d578ca6cSSong Gao     fp = float64_sqrt(fj, &env->fp_status);
317d578ca6cSSong Gao     fd = float64_div(float64_one, fp, &env->fp_status);
318d578ca6cSSong Gao     update_fcsr0(env, GETPC());
319d578ca6cSSong Gao     return fd;
320d578ca6cSSong Gao }
321d578ca6cSSong Gao 
helper_flogb_s(CPULoongArchState * env,uint64_t fj)322d578ca6cSSong Gao uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj)
323d578ca6cSSong Gao {
324d578ca6cSSong Gao     uint64_t fd;
325d578ca6cSSong Gao     uint32_t fp;
326d578ca6cSSong Gao     float_status *status = &env->fp_status;
327d578ca6cSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
328d578ca6cSSong Gao 
329d578ca6cSSong Gao     set_float_rounding_mode(float_round_down, status);
330d578ca6cSSong Gao     fp = float32_log2((uint32_t)fj, status);
331d578ca6cSSong Gao     fd = nanbox_s(float32_round_to_int(fp, status));
332d578ca6cSSong Gao     set_float_rounding_mode(old_mode, status);
333d578ca6cSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
334d578ca6cSSong Gao     return fd;
335d578ca6cSSong Gao }
336d578ca6cSSong Gao 
helper_flogb_d(CPULoongArchState * env,uint64_t fj)337d578ca6cSSong Gao uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj)
338d578ca6cSSong Gao {
339d578ca6cSSong Gao     uint64_t fd;
340d578ca6cSSong Gao     float_status *status = &env->fp_status;
341d578ca6cSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
342d578ca6cSSong Gao 
343d578ca6cSSong Gao     set_float_rounding_mode(float_round_down, status);
344d578ca6cSSong Gao     fd = float64_log2(fj, status);
345d578ca6cSSong Gao     fd = float64_round_to_int(fd, status);
346d578ca6cSSong Gao     set_float_rounding_mode(old_mode, status);
347d578ca6cSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
348d578ca6cSSong Gao     return fd;
349d578ca6cSSong Gao }
350d578ca6cSSong Gao 
helper_fclass_s(CPULoongArchState * env,uint64_t fj)351d578ca6cSSong Gao uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
352d578ca6cSSong Gao {
353d578ca6cSSong Gao     float32 f = fj;
354d578ca6cSSong Gao     bool sign = float32_is_neg(f);
355d578ca6cSSong Gao 
356d578ca6cSSong Gao     if (float32_is_infinity(f)) {
357d578ca6cSSong Gao         return sign ? 1 << 2 : 1 << 6;
358d578ca6cSSong Gao     } else if (float32_is_zero(f)) {
359d578ca6cSSong Gao         return sign ? 1 << 5 : 1 << 9;
360d578ca6cSSong Gao     } else if (float32_is_zero_or_denormal(f)) {
361d578ca6cSSong Gao         return sign ? 1 << 4 : 1 << 8;
362d578ca6cSSong Gao     } else if (float32_is_any_nan(f)) {
363a0c42977SPeter Maydell         return float32_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
364d578ca6cSSong Gao     } else {
365d578ca6cSSong Gao         return sign ? 1 << 3 : 1 << 7;
366d578ca6cSSong Gao     }
367d578ca6cSSong Gao }
368d578ca6cSSong Gao 
helper_fclass_d(CPULoongArchState * env,uint64_t fj)369d578ca6cSSong Gao uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
370d578ca6cSSong Gao {
371d578ca6cSSong Gao     float64 f = fj;
372d578ca6cSSong Gao     bool sign = float64_is_neg(f);
373d578ca6cSSong Gao 
374d578ca6cSSong Gao     if (float64_is_infinity(f)) {
375d578ca6cSSong Gao         return sign ? 1 << 2 : 1 << 6;
376d578ca6cSSong Gao     } else if (float64_is_zero(f)) {
377d578ca6cSSong Gao         return sign ? 1 << 5 : 1 << 9;
378d578ca6cSSong Gao     } else if (float64_is_zero_or_denormal(f)) {
379d578ca6cSSong Gao         return sign ? 1 << 4 : 1 << 8;
380d578ca6cSSong Gao     } else if (float64_is_any_nan(f)) {
381a0c42977SPeter Maydell         return float64_is_quiet_nan(f, &env->fp_status) ? 1 << 1 : 1 << 0;
382d578ca6cSSong Gao     } else {
383d578ca6cSSong Gao         return sign ? 1 << 3 : 1 << 7;
384d578ca6cSSong Gao     }
385d578ca6cSSong Gao }
386d578ca6cSSong Gao 
helper_fmuladd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)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 
helper_fmuladd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)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 
fcmp_common(CPULoongArchState * env,FloatRelation cmp,uint32_t flags)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 */
helper_fcmp_c_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_s_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_c_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_s_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcvt_s_d(CPULoongArchState * env,uint64_t fj)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 
helper_fcvt_d_s(CPULoongArchState * env,uint64_t fj)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 
helper_ffint_s_w(CPULoongArchState * env,uint64_t fj)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 
helper_ffint_s_l(CPULoongArchState * env,uint64_t fj)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 
helper_ffint_d_w(CPULoongArchState * env,uint64_t fj)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 
helper_ffint_d_l(CPULoongArchState * env,uint64_t fj)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 
helper_frint_s(CPULoongArchState * env,uint64_t fj)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 
helper_frint_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrm_l_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrm_l_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrm_w_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrm_w_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrp_l_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrp_l_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrp_w_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrp_w_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrz_l_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrz_l_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrz_w_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrz_w_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrne_l_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrne_l_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrne_w_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftintrne_w_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftint_l_d(CPULoongArchState * env,uint64_t fj)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 
helper_ftint_l_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftint_w_s(CPULoongArchState * env,uint64_t fj)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 
helper_ftint_w_d(CPULoongArchState * env,uint64_t fj)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 
helper_set_rounding_mode(CPULoongArchState * env)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