xref: /qemu/target/loongarch/tcg/fpu_helper.c (revision 10dcb08b03863221faa41f4f1aa835cdca441b96)
1d578ca6cSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
2d578ca6cSSong Gao /*
3d578ca6cSSong Gao  * LoongArch float point emulation helpers for QEMU
4d578ca6cSSong Gao  *
5d578ca6cSSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
6d578ca6cSSong Gao  */
7d578ca6cSSong Gao 
8d578ca6cSSong Gao #include "qemu/osdep.h"
9d578ca6cSSong Gao #include "cpu.h"
10d578ca6cSSong Gao #include "exec/helper-proto.h"
11d578ca6cSSong Gao #include "exec/exec-all.h"
12d578ca6cSSong Gao #include "exec/cpu_ldst.h"
13d578ca6cSSong Gao #include "fpu/softfloat.h"
14d578ca6cSSong Gao #include "internals.h"
15d578ca6cSSong Gao 
16d578ca6cSSong Gao static inline uint64_t nanbox_s(float32 fp)
17d578ca6cSSong Gao {
18d578ca6cSSong Gao     return fp | MAKE_64BIT_MASK(32, 32);
19d578ca6cSSong Gao }
20d578ca6cSSong Gao 
21d578ca6cSSong Gao /* Convert loongarch rounding mode in fcsr0 to IEEE library */
22d578ca6cSSong Gao static const FloatRoundMode ieee_rm[4] = {
23d578ca6cSSong Gao     float_round_nearest_even,
24d578ca6cSSong Gao     float_round_to_zero,
25d578ca6cSSong Gao     float_round_up,
26d578ca6cSSong Gao     float_round_down
27d578ca6cSSong Gao };
28d578ca6cSSong Gao 
29d578ca6cSSong Gao void restore_fp_status(CPULoongArchState *env)
30d578ca6cSSong Gao {
31d578ca6cSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
32d578ca6cSSong Gao                             &env->fp_status);
33d578ca6cSSong Gao     set_flush_to_zero(0, &env->fp_status);
34d578ca6cSSong Gao }
35d578ca6cSSong Gao 
36d578ca6cSSong Gao static int ieee_ex_to_loongarch(int xcpt)
37d578ca6cSSong Gao {
38d578ca6cSSong Gao     int ret = 0;
39d578ca6cSSong Gao     if (xcpt & float_flag_invalid) {
40d578ca6cSSong Gao         ret |= FP_INVALID;
41d578ca6cSSong Gao     }
42d578ca6cSSong Gao     if (xcpt & float_flag_overflow) {
43d578ca6cSSong Gao         ret |= FP_OVERFLOW;
44d578ca6cSSong Gao     }
45d578ca6cSSong Gao     if (xcpt & float_flag_underflow) {
46d578ca6cSSong Gao         ret |= FP_UNDERFLOW;
47d578ca6cSSong Gao     }
48d578ca6cSSong Gao     if (xcpt & float_flag_divbyzero) {
49d578ca6cSSong Gao         ret |= FP_DIV0;
50d578ca6cSSong Gao     }
51d578ca6cSSong Gao     if (xcpt & float_flag_inexact) {
52d578ca6cSSong Gao         ret |= FP_INEXACT;
53d578ca6cSSong Gao     }
54d578ca6cSSong Gao     return ret;
55d578ca6cSSong Gao }
56d578ca6cSSong Gao 
57d578ca6cSSong Gao static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
58d578ca6cSSong Gao {
59d578ca6cSSong Gao     int flags = get_float_exception_flags(&env->fp_status);
60d578ca6cSSong Gao 
61d578ca6cSSong Gao     set_float_exception_flags(0, &env->fp_status);
62d578ca6cSSong Gao 
63d578ca6cSSong Gao     flags &= ~mask;
64d578ca6cSSong Gao 
65d578ca6cSSong Gao     if (!flags) {
66d578ca6cSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
67d578ca6cSSong Gao         return;
68d578ca6cSSong Gao     } else {
69d578ca6cSSong Gao         flags = ieee_ex_to_loongarch(flags);
70d578ca6cSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
71d578ca6cSSong Gao     }
72d578ca6cSSong Gao 
73d578ca6cSSong Gao     if (GET_FP_ENABLES(env->fcsr0) & flags) {
74d578ca6cSSong Gao         do_raise_exception(env, EXCCODE_FPE, pc);
75d578ca6cSSong Gao     } else {
76d578ca6cSSong Gao         UPDATE_FP_FLAGS(env->fcsr0, flags);
77d578ca6cSSong Gao     }
78d578ca6cSSong Gao }
79d578ca6cSSong Gao 
80d578ca6cSSong Gao static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
81d578ca6cSSong Gao {
82d578ca6cSSong Gao     update_fcsr0_mask(env, pc, 0);
83d578ca6cSSong Gao }
84d578ca6cSSong Gao 
85d578ca6cSSong Gao uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
86d578ca6cSSong Gao {
87d578ca6cSSong Gao     uint64_t fd;
88d578ca6cSSong Gao 
89d578ca6cSSong Gao     fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status));
90d578ca6cSSong Gao     update_fcsr0(env, GETPC());
91d578ca6cSSong Gao     return fd;
92d578ca6cSSong Gao }
93d578ca6cSSong Gao 
94d578ca6cSSong Gao uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
95d578ca6cSSong Gao {
96d578ca6cSSong Gao     uint64_t fd;
97d578ca6cSSong Gao 
98d578ca6cSSong Gao     fd = float64_add(fj, fk, &env->fp_status);
99d578ca6cSSong Gao     update_fcsr0(env, GETPC());
100d578ca6cSSong Gao     return fd;
101d578ca6cSSong Gao }
102d578ca6cSSong Gao 
103d578ca6cSSong Gao uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
104d578ca6cSSong Gao {
105d578ca6cSSong Gao     uint64_t fd;
106d578ca6cSSong Gao 
107d578ca6cSSong Gao     fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status));
108d578ca6cSSong Gao     update_fcsr0(env, GETPC());
109d578ca6cSSong Gao     return fd;
110d578ca6cSSong Gao }
111d578ca6cSSong Gao 
112d578ca6cSSong Gao uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
113d578ca6cSSong Gao {
114d578ca6cSSong Gao     uint64_t fd;
115d578ca6cSSong Gao 
116d578ca6cSSong Gao     fd = float64_sub(fj, fk, &env->fp_status);
117d578ca6cSSong Gao     update_fcsr0(env, GETPC());
118d578ca6cSSong Gao     return fd;
119d578ca6cSSong Gao }
120d578ca6cSSong Gao 
121d578ca6cSSong Gao uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
122d578ca6cSSong Gao {
123d578ca6cSSong Gao     uint64_t fd;
124d578ca6cSSong Gao 
125d578ca6cSSong Gao     fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status));
126d578ca6cSSong Gao     update_fcsr0(env, GETPC());
127d578ca6cSSong Gao     return fd;
128d578ca6cSSong Gao }
129d578ca6cSSong Gao 
130d578ca6cSSong Gao uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
131d578ca6cSSong Gao {
132d578ca6cSSong Gao     uint64_t fd;
133d578ca6cSSong Gao 
134d578ca6cSSong Gao     fd = float64_mul(fj, fk, &env->fp_status);
135d578ca6cSSong Gao     update_fcsr0(env, GETPC());
136d578ca6cSSong Gao     return fd;
137d578ca6cSSong Gao }
138d578ca6cSSong Gao 
139d578ca6cSSong Gao uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
140d578ca6cSSong Gao {
141d578ca6cSSong Gao     uint64_t fd;
142d578ca6cSSong Gao 
143d578ca6cSSong Gao     fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status));
144d578ca6cSSong Gao     update_fcsr0(env, GETPC());
145d578ca6cSSong Gao     return fd;
146d578ca6cSSong Gao }
147d578ca6cSSong Gao 
148d578ca6cSSong Gao uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
149d578ca6cSSong Gao {
150d578ca6cSSong Gao     uint64_t fd;
151d578ca6cSSong Gao 
152d578ca6cSSong Gao     fd = float64_div(fj, fk, &env->fp_status);
153d578ca6cSSong Gao     update_fcsr0(env, GETPC());
154d578ca6cSSong Gao     return fd;
155d578ca6cSSong Gao }
156d578ca6cSSong Gao 
157d578ca6cSSong Gao uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
158d578ca6cSSong Gao {
159d578ca6cSSong Gao     uint64_t fd;
160d578ca6cSSong Gao 
161d578ca6cSSong Gao     fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
162d578ca6cSSong Gao     update_fcsr0(env, GETPC());
163d578ca6cSSong Gao     return fd;
164d578ca6cSSong Gao }
165d578ca6cSSong Gao 
166d578ca6cSSong Gao uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
167d578ca6cSSong Gao {
168d578ca6cSSong Gao     uint64_t fd;
169d578ca6cSSong Gao 
170d578ca6cSSong Gao     fd = float64_maxnum(fj, fk, &env->fp_status);
171d578ca6cSSong Gao     update_fcsr0(env, GETPC());
172d578ca6cSSong Gao     return fd;
173d578ca6cSSong Gao }
174d578ca6cSSong Gao 
175d578ca6cSSong Gao uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
176d578ca6cSSong Gao {
177d578ca6cSSong Gao     uint64_t fd;
178d578ca6cSSong Gao 
179d578ca6cSSong Gao     fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
180d578ca6cSSong Gao     update_fcsr0(env, GETPC());
181d578ca6cSSong Gao     return fd;
182d578ca6cSSong Gao }
183d578ca6cSSong Gao 
184d578ca6cSSong Gao uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
185d578ca6cSSong Gao {
186d578ca6cSSong Gao     uint64_t fd;
187d578ca6cSSong Gao 
188d578ca6cSSong Gao     fd = float64_minnum(fj, fk, &env->fp_status);
189d578ca6cSSong Gao     update_fcsr0(env, GETPC());
190d578ca6cSSong Gao     return fd;
191d578ca6cSSong Gao }
192d578ca6cSSong Gao 
193d578ca6cSSong Gao uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
194d578ca6cSSong Gao {
195d578ca6cSSong Gao     uint64_t fd;
196d578ca6cSSong Gao 
197d578ca6cSSong Gao     fd = nanbox_s(float32_maxnummag((uint32_t)fj,
198d578ca6cSSong Gao                                     (uint32_t)fk, &env->fp_status));
199d578ca6cSSong Gao     update_fcsr0(env, GETPC());
200d578ca6cSSong Gao     return fd;
201d578ca6cSSong Gao }
202d578ca6cSSong Gao 
203d578ca6cSSong Gao uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
204d578ca6cSSong Gao {
205d578ca6cSSong Gao     uint64_t fd;
206d578ca6cSSong Gao 
207d578ca6cSSong Gao     fd = float64_maxnummag(fj, fk, &env->fp_status);
208d578ca6cSSong Gao     update_fcsr0(env, GETPC());
209d578ca6cSSong Gao     return fd;
210d578ca6cSSong Gao }
211d578ca6cSSong Gao 
212d578ca6cSSong Gao uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
213d578ca6cSSong Gao {
214d578ca6cSSong Gao     uint64_t fd;
215d578ca6cSSong Gao 
216d578ca6cSSong Gao     fd = nanbox_s(float32_minnummag((uint32_t)fj,
217d578ca6cSSong Gao                                     (uint32_t)fk, &env->fp_status));
218d578ca6cSSong Gao     update_fcsr0(env, GETPC());
219d578ca6cSSong Gao     return fd;
220d578ca6cSSong Gao }
221d578ca6cSSong Gao 
222d578ca6cSSong Gao uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
223d578ca6cSSong Gao {
224d578ca6cSSong Gao     uint64_t fd;
225d578ca6cSSong Gao 
226d578ca6cSSong Gao     fd = float64_minnummag(fj, fk, &env->fp_status);
227d578ca6cSSong Gao     update_fcsr0(env, GETPC());
228d578ca6cSSong Gao     return fd;
229d578ca6cSSong Gao }
230d578ca6cSSong Gao 
231d578ca6cSSong Gao uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
232d578ca6cSSong Gao {
233d578ca6cSSong Gao     uint64_t fd;
234d578ca6cSSong Gao     int32_t n = (int32_t)fk;
235d578ca6cSSong Gao 
236d578ca6cSSong Gao     fd = nanbox_s(float32_scalbn((uint32_t)fj,
237d578ca6cSSong Gao                                  n >  0x200 ?  0x200 :
238d578ca6cSSong Gao                                  n < -0x200 ? -0x200 : n,
239d578ca6cSSong Gao                                  &env->fp_status));
240d578ca6cSSong Gao     update_fcsr0(env, GETPC());
241d578ca6cSSong Gao     return fd;
242d578ca6cSSong Gao }
243d578ca6cSSong Gao 
244d578ca6cSSong Gao uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
245d578ca6cSSong Gao {
246d578ca6cSSong Gao     uint64_t fd;
247d578ca6cSSong Gao     int64_t n = (int64_t)fk;
248d578ca6cSSong Gao 
249d578ca6cSSong Gao     fd = float64_scalbn(fj,
250d578ca6cSSong Gao                         n >  0x1000 ?  0x1000 :
251d578ca6cSSong Gao                         n < -0x1000 ? -0x1000 : n,
252d578ca6cSSong Gao                         &env->fp_status);
253d578ca6cSSong Gao     update_fcsr0(env, GETPC());
254d578ca6cSSong Gao     return fd;
255d578ca6cSSong Gao }
256d578ca6cSSong Gao 
257d578ca6cSSong Gao uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj)
258d578ca6cSSong Gao {
259d578ca6cSSong Gao     uint64_t fd;
260d578ca6cSSong Gao 
261d578ca6cSSong Gao     fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status));
262d578ca6cSSong Gao     update_fcsr0(env, GETPC());
263d578ca6cSSong Gao     return fd;
264d578ca6cSSong Gao }
265d578ca6cSSong Gao 
266d578ca6cSSong Gao uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj)
267d578ca6cSSong Gao {
268d578ca6cSSong Gao     uint64_t fd;
269d578ca6cSSong Gao 
270d578ca6cSSong Gao     fd = float64_sqrt(fj, &env->fp_status);
271d578ca6cSSong Gao     update_fcsr0(env, GETPC());
272d578ca6cSSong Gao     return fd;
273d578ca6cSSong Gao }
274d578ca6cSSong Gao 
275d578ca6cSSong Gao uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj)
276d578ca6cSSong Gao {
277d578ca6cSSong Gao     uint64_t fd;
278d578ca6cSSong Gao 
279d578ca6cSSong Gao     fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status));
280d578ca6cSSong Gao     update_fcsr0(env, GETPC());
281d578ca6cSSong Gao     return fd;
282d578ca6cSSong Gao }
283d578ca6cSSong Gao 
284d578ca6cSSong Gao uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj)
285d578ca6cSSong Gao {
286d578ca6cSSong Gao     uint64_t fd;
287d578ca6cSSong Gao 
288d578ca6cSSong Gao     fd = float64_div(float64_one, fj, &env->fp_status);
289d578ca6cSSong Gao     update_fcsr0(env, GETPC());
290d578ca6cSSong Gao     return fd;
291d578ca6cSSong Gao }
292d578ca6cSSong Gao 
293d578ca6cSSong Gao uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj)
294d578ca6cSSong Gao {
295d578ca6cSSong Gao     uint64_t fd;
296d578ca6cSSong Gao     uint32_t fp;
297d578ca6cSSong Gao 
298d578ca6cSSong Gao     fp = float32_sqrt((uint32_t)fj, &env->fp_status);
299d578ca6cSSong Gao     fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status));
300d578ca6cSSong Gao     update_fcsr0(env, GETPC());
301d578ca6cSSong Gao     return fd;
302d578ca6cSSong Gao }
303d578ca6cSSong Gao 
304d578ca6cSSong Gao uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj)
305d578ca6cSSong Gao {
306d578ca6cSSong Gao     uint64_t fp, fd;
307d578ca6cSSong Gao 
308d578ca6cSSong Gao     fp = float64_sqrt(fj, &env->fp_status);
309d578ca6cSSong Gao     fd = float64_div(float64_one, fp, &env->fp_status);
310d578ca6cSSong Gao     update_fcsr0(env, GETPC());
311d578ca6cSSong Gao     return fd;
312d578ca6cSSong Gao }
313d578ca6cSSong Gao 
314d578ca6cSSong Gao uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj)
315d578ca6cSSong Gao {
316d578ca6cSSong Gao     uint64_t fd;
317d578ca6cSSong Gao     uint32_t fp;
318d578ca6cSSong Gao     float_status *status = &env->fp_status;
319d578ca6cSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
320d578ca6cSSong Gao 
321d578ca6cSSong Gao     set_float_rounding_mode(float_round_down, status);
322d578ca6cSSong Gao     fp = float32_log2((uint32_t)fj, status);
323d578ca6cSSong Gao     fd = nanbox_s(float32_round_to_int(fp, status));
324d578ca6cSSong Gao     set_float_rounding_mode(old_mode, status);
325d578ca6cSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
326d578ca6cSSong Gao     return fd;
327d578ca6cSSong Gao }
328d578ca6cSSong Gao 
329d578ca6cSSong Gao uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj)
330d578ca6cSSong Gao {
331d578ca6cSSong Gao     uint64_t fd;
332d578ca6cSSong Gao     float_status *status = &env->fp_status;
333d578ca6cSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
334d578ca6cSSong Gao 
335d578ca6cSSong Gao     set_float_rounding_mode(float_round_down, status);
336d578ca6cSSong Gao     fd = float64_log2(fj, status);
337d578ca6cSSong Gao     fd = float64_round_to_int(fd, status);
338d578ca6cSSong Gao     set_float_rounding_mode(old_mode, status);
339d578ca6cSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
340d578ca6cSSong Gao     return fd;
341d578ca6cSSong Gao }
342d578ca6cSSong Gao 
343d578ca6cSSong Gao uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
344d578ca6cSSong Gao {
345d578ca6cSSong Gao     float32 f = fj;
346d578ca6cSSong Gao     bool sign = float32_is_neg(f);
347d578ca6cSSong Gao 
348d578ca6cSSong Gao     if (float32_is_infinity(f)) {
349d578ca6cSSong Gao         return sign ? 1 << 2 : 1 << 6;
350d578ca6cSSong Gao     } else if (float32_is_zero(f)) {
351d578ca6cSSong Gao         return sign ? 1 << 5 : 1 << 9;
352d578ca6cSSong Gao     } else if (float32_is_zero_or_denormal(f)) {
353d578ca6cSSong Gao         return sign ? 1 << 4 : 1 << 8;
354d578ca6cSSong Gao     } else if (float32_is_any_nan(f)) {
355d578ca6cSSong Gao         float_status s = { }; /* for snan_bit_is_one */
356d578ca6cSSong Gao         return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
357d578ca6cSSong Gao     } else {
358d578ca6cSSong Gao         return sign ? 1 << 3 : 1 << 7;
359d578ca6cSSong Gao     }
360d578ca6cSSong Gao }
361d578ca6cSSong Gao 
362d578ca6cSSong Gao uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
363d578ca6cSSong Gao {
364d578ca6cSSong Gao     float64 f = fj;
365d578ca6cSSong Gao     bool sign = float64_is_neg(f);
366d578ca6cSSong Gao 
367d578ca6cSSong Gao     if (float64_is_infinity(f)) {
368d578ca6cSSong Gao         return sign ? 1 << 2 : 1 << 6;
369d578ca6cSSong Gao     } else if (float64_is_zero(f)) {
370d578ca6cSSong Gao         return sign ? 1 << 5 : 1 << 9;
371d578ca6cSSong Gao     } else if (float64_is_zero_or_denormal(f)) {
372d578ca6cSSong Gao         return sign ? 1 << 4 : 1 << 8;
373d578ca6cSSong Gao     } else if (float64_is_any_nan(f)) {
374d578ca6cSSong Gao         float_status s = { }; /* for snan_bit_is_one */
375d578ca6cSSong Gao         return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
376d578ca6cSSong Gao     } else {
377d578ca6cSSong Gao         return sign ? 1 << 3 : 1 << 7;
378d578ca6cSSong Gao     }
379d578ca6cSSong Gao }
380d578ca6cSSong Gao 
381d578ca6cSSong Gao uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj,
382d578ca6cSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
383d578ca6cSSong Gao {
384d578ca6cSSong Gao     uint64_t fd;
385d578ca6cSSong Gao 
386d578ca6cSSong Gao     fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk,
387d578ca6cSSong Gao                                  (uint32_t)fa, flag, &env->fp_status));
388d578ca6cSSong Gao     update_fcsr0(env, GETPC());
389d578ca6cSSong Gao     return fd;
390d578ca6cSSong Gao }
391d578ca6cSSong Gao 
392d578ca6cSSong Gao uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
393d578ca6cSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
394d578ca6cSSong Gao {
395d578ca6cSSong Gao     uint64_t fd;
396d578ca6cSSong Gao 
397d578ca6cSSong Gao     fd = float64_muladd(fj, fk, fa, flag, &env->fp_status);
398d578ca6cSSong Gao     update_fcsr0(env, GETPC());
399d578ca6cSSong Gao     return fd;
400d578ca6cSSong Gao }
4019b741076SSong Gao 
4029b741076SSong Gao static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
4039b741076SSong Gao                             uint32_t flags)
4049b741076SSong Gao {
4059b741076SSong Gao     bool ret;
4069b741076SSong Gao 
4079b741076SSong Gao     switch (cmp) {
4089b741076SSong Gao     case float_relation_less:
4099b741076SSong Gao         ret = (flags & FCMP_LT);
4109b741076SSong Gao         break;
4119b741076SSong Gao     case float_relation_equal:
4129b741076SSong Gao         ret = (flags & FCMP_EQ);
4139b741076SSong Gao         break;
4149b741076SSong Gao     case float_relation_greater:
4159b741076SSong Gao         ret = (flags & FCMP_GT);
4169b741076SSong Gao         break;
4179b741076SSong Gao     case float_relation_unordered:
4189b741076SSong Gao         ret = (flags & FCMP_UN);
4199b741076SSong Gao         break;
4209b741076SSong Gao     default:
4219b741076SSong Gao         g_assert_not_reached();
4229b741076SSong Gao     }
4239b741076SSong Gao     update_fcsr0(env, GETPC());
4249b741076SSong Gao 
4259b741076SSong Gao     return ret;
4269b741076SSong Gao }
4279b741076SSong Gao 
4289b741076SSong Gao /* fcmp_cXXX_s */
4299b741076SSong Gao uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
4309b741076SSong Gao                          uint64_t fk, uint32_t flags)
4319b741076SSong Gao {
4329b741076SSong Gao     FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
4339b741076SSong Gao                                               (uint32_t)fk, &env->fp_status);
4349b741076SSong Gao     return fcmp_common(env, cmp, flags);
4359b741076SSong Gao }
4369b741076SSong Gao 
4379b741076SSong Gao /* fcmp_sXXX_s */
4389b741076SSong Gao uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
4399b741076SSong Gao                          uint64_t fk, uint32_t flags)
4409b741076SSong Gao {
4419b741076SSong Gao     FloatRelation cmp = float32_compare((uint32_t)fj,
4429b741076SSong Gao                                         (uint32_t)fk, &env->fp_status);
4439b741076SSong Gao     return fcmp_common(env, cmp, flags);
4449b741076SSong Gao }
4459b741076SSong Gao 
4469b741076SSong Gao /* fcmp_cXXX_d */
4479b741076SSong Gao uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
4489b741076SSong Gao                          uint64_t fk, uint32_t flags)
4499b741076SSong Gao {
4509b741076SSong Gao     FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status);
4519b741076SSong Gao     return fcmp_common(env, cmp, flags);
4529b741076SSong Gao }
4539b741076SSong Gao 
4549b741076SSong Gao /* fcmp_sXXX_d */
4559b741076SSong Gao uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
4569b741076SSong Gao                          uint64_t fk, uint32_t flags)
4579b741076SSong Gao {
4589b741076SSong Gao     FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
4599b741076SSong Gao     return fcmp_common(env, cmp, flags);
4609b741076SSong Gao }
4617c1f8870SSong Gao 
4627c1f8870SSong Gao /* floating point conversion */
4637c1f8870SSong Gao uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
4647c1f8870SSong Gao {
4657c1f8870SSong Gao     uint64_t fd;
4667c1f8870SSong Gao 
4677c1f8870SSong Gao     fd = nanbox_s(float64_to_float32(fj, &env->fp_status));
4687c1f8870SSong Gao     update_fcsr0(env, GETPC());
4697c1f8870SSong Gao     return fd;
4707c1f8870SSong Gao }
4717c1f8870SSong Gao 
4727c1f8870SSong Gao uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
4737c1f8870SSong Gao {
4747c1f8870SSong Gao     uint64_t fd;
4757c1f8870SSong Gao 
4767c1f8870SSong Gao     fd = float32_to_float64((uint32_t)fj, &env->fp_status);
4777c1f8870SSong Gao     update_fcsr0(env, GETPC());
4787c1f8870SSong Gao     return fd;
4797c1f8870SSong Gao }
4807c1f8870SSong Gao 
4817c1f8870SSong Gao uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
4827c1f8870SSong Gao {
4837c1f8870SSong Gao     uint64_t fd;
4847c1f8870SSong Gao 
4857c1f8870SSong Gao     fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status));
4867c1f8870SSong Gao     update_fcsr0(env, GETPC());
4877c1f8870SSong Gao     return fd;
4887c1f8870SSong Gao }
4897c1f8870SSong Gao 
4907c1f8870SSong Gao uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
4917c1f8870SSong Gao {
4927c1f8870SSong Gao     uint64_t fd;
4937c1f8870SSong Gao 
4947c1f8870SSong Gao     fd = nanbox_s(int64_to_float32(fj, &env->fp_status));
4957c1f8870SSong Gao     update_fcsr0(env, GETPC());
4967c1f8870SSong Gao     return fd;
4977c1f8870SSong Gao }
4987c1f8870SSong Gao 
4997c1f8870SSong Gao uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
5007c1f8870SSong Gao {
5017c1f8870SSong Gao     uint64_t fd;
5027c1f8870SSong Gao 
5037c1f8870SSong Gao     fd = int32_to_float64((int32_t)fj, &env->fp_status);
5047c1f8870SSong Gao     update_fcsr0(env, GETPC());
5057c1f8870SSong Gao     return fd;
5067c1f8870SSong Gao }
5077c1f8870SSong Gao 
5087c1f8870SSong Gao uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
5097c1f8870SSong Gao {
5107c1f8870SSong Gao     uint64_t fd;
5117c1f8870SSong Gao 
5127c1f8870SSong Gao     fd = int64_to_float64(fj, &env->fp_status);
5137c1f8870SSong Gao     update_fcsr0(env, GETPC());
5147c1f8870SSong Gao     return fd;
5157c1f8870SSong Gao }
5167c1f8870SSong Gao 
5177c1f8870SSong Gao uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
5187c1f8870SSong Gao {
5197c1f8870SSong Gao     uint64_t fd;
5207c1f8870SSong Gao 
5217c1f8870SSong Gao     fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status));
5227c1f8870SSong Gao     update_fcsr0(env, GETPC());
5237c1f8870SSong Gao     return fd;
5247c1f8870SSong Gao }
5257c1f8870SSong Gao 
5267c1f8870SSong Gao uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
5277c1f8870SSong Gao {
5287c1f8870SSong Gao     uint64_t fd;
5297c1f8870SSong Gao 
5307c1f8870SSong Gao     fd = float64_round_to_int(fj, &env->fp_status);
5317c1f8870SSong Gao     update_fcsr0(env, GETPC());
5327c1f8870SSong Gao     return fd;
5337c1f8870SSong Gao }
5347c1f8870SSong Gao 
5357c1f8870SSong Gao uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
5367c1f8870SSong Gao {
5377c1f8870SSong Gao     uint64_t fd;
5387c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5397c1f8870SSong Gao 
5407c1f8870SSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5417c1f8870SSong Gao     fd = float64_to_int64(fj, &env->fp_status);
5427c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5437c1f8870SSong Gao 
5449fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5459fad2071SSong Gao         if (float64_is_any_nan(fj)) {
5469fad2071SSong Gao             fd = 0;
5479fad2071SSong Gao         }
5487c1f8870SSong Gao     }
5497c1f8870SSong Gao     update_fcsr0(env, GETPC());
5507c1f8870SSong Gao     return fd;
5517c1f8870SSong Gao }
5527c1f8870SSong Gao 
5537c1f8870SSong Gao uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
5547c1f8870SSong Gao {
5557c1f8870SSong Gao     uint64_t fd;
5567c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5577c1f8870SSong Gao 
5587c1f8870SSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5597c1f8870SSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
5607c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5617c1f8870SSong Gao 
5629fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5639fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
5649fad2071SSong Gao             fd = 0;
5659fad2071SSong Gao         }
5667c1f8870SSong Gao     }
5677c1f8870SSong Gao     update_fcsr0(env, GETPC());
5687c1f8870SSong Gao     return fd;
5697c1f8870SSong Gao }
5707c1f8870SSong Gao 
5717c1f8870SSong Gao uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
5727c1f8870SSong Gao {
5737c1f8870SSong Gao     uint64_t fd;
5747c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5757c1f8870SSong Gao 
5767c1f8870SSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5777c1f8870SSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
5787c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5797c1f8870SSong Gao 
5809fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5819fad2071SSong Gao         if (float64_is_any_nan(fj)) {
5829fad2071SSong Gao             fd = 0;
5839fad2071SSong Gao         }
5847c1f8870SSong Gao     }
5857c1f8870SSong Gao     update_fcsr0(env, GETPC());
5867c1f8870SSong Gao     return fd;
5877c1f8870SSong Gao }
5887c1f8870SSong Gao 
5897c1f8870SSong Gao uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
5907c1f8870SSong Gao {
5917c1f8870SSong Gao     uint64_t fd;
5927c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
5937c1f8870SSong Gao 
5947c1f8870SSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
5957c1f8870SSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
5967c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
5977c1f8870SSong Gao 
5989fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
5999fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6009fad2071SSong Gao             fd = 0;
6019fad2071SSong Gao         }
6027c1f8870SSong Gao     }
6037c1f8870SSong Gao     update_fcsr0(env, GETPC());
6047c1f8870SSong Gao     return fd;
6057c1f8870SSong Gao }
6067c1f8870SSong Gao 
6077c1f8870SSong Gao uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
6087c1f8870SSong Gao {
6097c1f8870SSong Gao     uint64_t fd;
6107c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6117c1f8870SSong Gao 
6127c1f8870SSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6137c1f8870SSong Gao     fd = float64_to_int64(fj, &env->fp_status);
6147c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6157c1f8870SSong Gao 
6169fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6179fad2071SSong Gao         if (float64_is_any_nan(fj)) {
6189fad2071SSong Gao             fd = 0;
6199fad2071SSong Gao         }
6207c1f8870SSong Gao     }
6217c1f8870SSong Gao     update_fcsr0(env, GETPC());
6227c1f8870SSong Gao     return fd;
6237c1f8870SSong Gao }
6247c1f8870SSong Gao 
6257c1f8870SSong Gao uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj)
6267c1f8870SSong Gao {
6277c1f8870SSong Gao     uint64_t fd;
6287c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6297c1f8870SSong Gao 
6307c1f8870SSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6317c1f8870SSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
6327c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6337c1f8870SSong Gao 
6349fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6359fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6369fad2071SSong Gao             fd = 0;
6379fad2071SSong Gao         }
6387c1f8870SSong Gao     }
6397c1f8870SSong Gao     update_fcsr0(env, GETPC());
6407c1f8870SSong Gao     return fd;
6417c1f8870SSong Gao }
6427c1f8870SSong Gao 
6437c1f8870SSong Gao uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj)
6447c1f8870SSong Gao {
6457c1f8870SSong Gao     uint64_t fd;
6467c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6477c1f8870SSong Gao 
6487c1f8870SSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6497c1f8870SSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
6507c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6517c1f8870SSong Gao 
6529fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6539fad2071SSong Gao         if (float64_is_any_nan(fj)) {
6549fad2071SSong Gao             fd = 0;
6559fad2071SSong Gao         }
6567c1f8870SSong Gao     }
6577c1f8870SSong Gao     update_fcsr0(env, GETPC());
6587c1f8870SSong Gao     return fd;
6597c1f8870SSong Gao }
6607c1f8870SSong Gao 
6617c1f8870SSong Gao uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj)
6627c1f8870SSong Gao {
6637c1f8870SSong Gao     uint64_t fd;
6647c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6657c1f8870SSong Gao 
6667c1f8870SSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
6677c1f8870SSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
6687c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6697c1f8870SSong Gao 
6709fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6719fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
6729fad2071SSong Gao             fd = 0;
6739fad2071SSong Gao         }
6747c1f8870SSong Gao     }
6757c1f8870SSong Gao     update_fcsr0(env, GETPC());
6767c1f8870SSong Gao     return fd;
6777c1f8870SSong Gao }
6787c1f8870SSong Gao 
6797c1f8870SSong Gao uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj)
6807c1f8870SSong Gao {
6817c1f8870SSong Gao     uint64_t fd;
6827c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
6837c1f8870SSong Gao 
6847c1f8870SSong Gao     fd = float64_to_int64_round_to_zero(fj, &env->fp_status);
6857c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
6867c1f8870SSong Gao 
6879fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
6889fad2071SSong Gao         if (float64_is_any_nan(fj)) {
6899fad2071SSong Gao             fd = 0;
6909fad2071SSong Gao         }
6917c1f8870SSong Gao     }
6927c1f8870SSong Gao     update_fcsr0(env, GETPC());
6937c1f8870SSong Gao     return fd;
6947c1f8870SSong Gao }
6957c1f8870SSong Gao 
6967c1f8870SSong Gao uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj)
6977c1f8870SSong Gao {
6987c1f8870SSong Gao     uint64_t fd;
6997c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7007c1f8870SSong Gao 
7017c1f8870SSong Gao     fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status);
7027c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7037c1f8870SSong Gao 
7049fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7059fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7069fad2071SSong Gao             fd = 0;
7079fad2071SSong Gao         }
7087c1f8870SSong Gao     }
7097c1f8870SSong Gao     update_fcsr0(env, GETPC());
7107c1f8870SSong Gao     return fd;
7117c1f8870SSong Gao }
7127c1f8870SSong Gao 
7137c1f8870SSong Gao uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj)
7147c1f8870SSong Gao {
7157c1f8870SSong Gao     uint64_t fd;
7167c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7177c1f8870SSong Gao 
7187c1f8870SSong Gao     fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status);
7197c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7207c1f8870SSong Gao 
7219fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7229fad2071SSong Gao         if (float64_is_any_nan(fj)) {
7239fad2071SSong Gao             fd = 0;
7249fad2071SSong Gao         }
7257c1f8870SSong Gao     }
7267c1f8870SSong Gao     update_fcsr0(env, GETPC());
7277c1f8870SSong Gao     return fd;
7287c1f8870SSong Gao }
7297c1f8870SSong Gao 
7307c1f8870SSong Gao uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj)
7317c1f8870SSong Gao {
7327c1f8870SSong Gao     uint32_t fd;
7337c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7347c1f8870SSong Gao 
7357c1f8870SSong Gao     fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status);
7367c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7377c1f8870SSong Gao 
7389fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7399fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7409fad2071SSong Gao             fd = 0;
7419fad2071SSong Gao         }
7427c1f8870SSong Gao     }
7437c1f8870SSong Gao     update_fcsr0(env, GETPC());
7447c1f8870SSong Gao     return (uint64_t)fd;
7457c1f8870SSong Gao }
7467c1f8870SSong Gao 
7477c1f8870SSong Gao uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj)
7487c1f8870SSong Gao {
7497c1f8870SSong Gao     uint64_t fd;
7507c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7517c1f8870SSong Gao 
7527c1f8870SSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7537c1f8870SSong Gao     fd = float64_to_int64(fj, &env->fp_status);
7547c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7557c1f8870SSong Gao 
7569fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7579fad2071SSong Gao         if (float64_is_any_nan(fj)) {
7589fad2071SSong Gao             fd = 0;
7599fad2071SSong Gao         }
7607c1f8870SSong Gao     }
7617c1f8870SSong Gao     update_fcsr0(env, GETPC());
7627c1f8870SSong Gao     return fd;
7637c1f8870SSong Gao }
7647c1f8870SSong Gao 
7657c1f8870SSong Gao uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj)
7667c1f8870SSong Gao {
7677c1f8870SSong Gao     uint64_t fd;
7687c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7697c1f8870SSong Gao 
7707c1f8870SSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7717c1f8870SSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
7727c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7737c1f8870SSong Gao 
7749fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7759fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
7769fad2071SSong Gao             fd = 0;
7779fad2071SSong Gao         }
7787c1f8870SSong Gao     }
7797c1f8870SSong Gao     update_fcsr0(env, GETPC());
7807c1f8870SSong Gao     return fd;
7817c1f8870SSong Gao }
7827c1f8870SSong Gao 
7837c1f8870SSong Gao uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj)
7847c1f8870SSong Gao {
7857c1f8870SSong Gao     uint64_t fd;
7867c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
7877c1f8870SSong Gao 
7887c1f8870SSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
7897c1f8870SSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
7907c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
7917c1f8870SSong Gao 
7929fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
7939fad2071SSong Gao         if (float64_is_any_nan(fj)) {
7949fad2071SSong Gao             fd = 0;
7959fad2071SSong Gao         }
7967c1f8870SSong Gao     }
7977c1f8870SSong Gao     update_fcsr0(env, GETPC());
7987c1f8870SSong Gao     return fd;
7997c1f8870SSong Gao }
8007c1f8870SSong Gao 
8017c1f8870SSong Gao uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj)
8027c1f8870SSong Gao {
8037c1f8870SSong Gao     uint32_t fd;
8047c1f8870SSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
8057c1f8870SSong Gao 
8067c1f8870SSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
8077c1f8870SSong Gao     fd = float32_to_int32((uint32_t)fj, &env->fp_status);
8087c1f8870SSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
8097c1f8870SSong Gao 
8109fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8119fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8129fad2071SSong Gao             fd = 0;
8139fad2071SSong Gao         }
8147c1f8870SSong Gao     }
8157c1f8870SSong Gao     update_fcsr0(env, GETPC());
8167c1f8870SSong Gao     return (uint64_t)fd;
8177c1f8870SSong Gao }
8187c1f8870SSong Gao 
8197c1f8870SSong Gao uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj)
8207c1f8870SSong Gao {
8217c1f8870SSong Gao     uint64_t fd;
8227c1f8870SSong Gao 
8237c1f8870SSong Gao     fd = float64_to_int64(fj, &env->fp_status);
8249fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8259fad2071SSong Gao         if (float64_is_any_nan(fj)) {
8269fad2071SSong Gao             fd = 0;
8279fad2071SSong Gao         }
8287c1f8870SSong Gao     }
8297c1f8870SSong Gao     update_fcsr0(env, GETPC());
8307c1f8870SSong Gao     return fd;
8317c1f8870SSong Gao }
8327c1f8870SSong Gao 
8337c1f8870SSong Gao uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj)
8347c1f8870SSong Gao {
8357c1f8870SSong Gao     uint64_t fd;
8367c1f8870SSong Gao 
8377c1f8870SSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
8389fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8399fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8409fad2071SSong Gao             fd = 0;
8419fad2071SSong Gao         }
8427c1f8870SSong Gao     }
8437c1f8870SSong Gao     update_fcsr0(env, GETPC());
8447c1f8870SSong Gao     return fd;
8457c1f8870SSong Gao }
8467c1f8870SSong Gao 
8477c1f8870SSong Gao uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj)
8487c1f8870SSong Gao {
8497c1f8870SSong Gao     uint64_t fd;
8507c1f8870SSong Gao 
8517c1f8870SSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
8529fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8539fad2071SSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
8549fad2071SSong Gao             fd = 0;
8559fad2071SSong Gao         }
8567c1f8870SSong Gao     }
8577c1f8870SSong Gao     update_fcsr0(env, GETPC());
8587c1f8870SSong Gao     return fd;
8597c1f8870SSong Gao }
8607c1f8870SSong Gao 
8617c1f8870SSong Gao uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj)
8627c1f8870SSong Gao {
8637c1f8870SSong Gao     uint64_t fd;
8647c1f8870SSong Gao 
8657c1f8870SSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
8669fad2071SSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
8679fad2071SSong Gao         if (float64_is_any_nan(fj)) {
8689fad2071SSong Gao             fd = 0;
8699fad2071SSong Gao         }
8707c1f8870SSong Gao     }
8717c1f8870SSong Gao     update_fcsr0(env, GETPC());
8727c1f8870SSong Gao     return fd;
8737c1f8870SSong Gao }
874b7dabd56SSong Gao 
87510dcb08bSRichard Henderson void helper_set_rounding_mode(CPULoongArchState *env)
876b7dabd56SSong Gao {
87710dcb08bSRichard Henderson     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
878b7dabd56SSong Gao                             &env->fp_status);
879b7dabd56SSong Gao }
880