xref: /qemu/target/loongarch/tcg/fpu_helper.c (revision 42fa9665e598c268a7ccfab5b92636618d9574ec)
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