xref: /openbmc/qemu/target/loongarch/tcg/fpu_helper.c (revision 5c23704e)
1*5c23704eSSong Gao /* SPDX-License-Identifier: GPL-2.0-or-later */
2*5c23704eSSong Gao /*
3*5c23704eSSong Gao  * LoongArch float point emulation helpers for QEMU
4*5c23704eSSong Gao  *
5*5c23704eSSong Gao  * Copyright (c) 2021 Loongson Technology Corporation Limited
6*5c23704eSSong Gao  */
7*5c23704eSSong Gao 
8*5c23704eSSong Gao #include "qemu/osdep.h"
9*5c23704eSSong Gao #include "cpu.h"
10*5c23704eSSong Gao #include "exec/helper-proto.h"
11*5c23704eSSong Gao #include "exec/exec-all.h"
12*5c23704eSSong Gao #include "exec/cpu_ldst.h"
13*5c23704eSSong Gao #include "fpu/softfloat.h"
14*5c23704eSSong Gao #include "internals.h"
15*5c23704eSSong Gao 
nanbox_s(float32 fp)16*5c23704eSSong Gao static inline uint64_t nanbox_s(float32 fp)
17*5c23704eSSong Gao {
18*5c23704eSSong Gao     return fp | MAKE_64BIT_MASK(32, 32);
19*5c23704eSSong Gao }
20*5c23704eSSong Gao 
21*5c23704eSSong Gao /* Convert loongarch rounding mode in fcsr0 to IEEE library */
22*5c23704eSSong Gao static const FloatRoundMode ieee_rm[4] = {
23*5c23704eSSong Gao     float_round_nearest_even,
24*5c23704eSSong Gao     float_round_to_zero,
25*5c23704eSSong Gao     float_round_up,
26*5c23704eSSong Gao     float_round_down
27*5c23704eSSong Gao };
28*5c23704eSSong Gao 
restore_fp_status(CPULoongArchState * env)29*5c23704eSSong Gao void restore_fp_status(CPULoongArchState *env)
30*5c23704eSSong Gao {
31*5c23704eSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
32*5c23704eSSong Gao                             &env->fp_status);
33*5c23704eSSong Gao     set_flush_to_zero(0, &env->fp_status);
34*5c23704eSSong Gao }
35*5c23704eSSong Gao 
ieee_ex_to_loongarch(int xcpt)36*5c23704eSSong Gao int ieee_ex_to_loongarch(int xcpt)
37*5c23704eSSong Gao {
38*5c23704eSSong Gao     int ret = 0;
39*5c23704eSSong Gao     if (xcpt & float_flag_invalid) {
40*5c23704eSSong Gao         ret |= FP_INVALID;
41*5c23704eSSong Gao     }
42*5c23704eSSong Gao     if (xcpt & float_flag_overflow) {
43*5c23704eSSong Gao         ret |= FP_OVERFLOW;
44*5c23704eSSong Gao     }
45*5c23704eSSong Gao     if (xcpt & float_flag_underflow) {
46*5c23704eSSong Gao         ret |= FP_UNDERFLOW;
47*5c23704eSSong Gao     }
48*5c23704eSSong Gao     if (xcpt & float_flag_divbyzero) {
49*5c23704eSSong Gao         ret |= FP_DIV0;
50*5c23704eSSong Gao     }
51*5c23704eSSong Gao     if (xcpt & float_flag_inexact) {
52*5c23704eSSong Gao         ret |= FP_INEXACT;
53*5c23704eSSong Gao     }
54*5c23704eSSong Gao     return ret;
55*5c23704eSSong Gao }
56*5c23704eSSong Gao 
update_fcsr0_mask(CPULoongArchState * env,uintptr_t pc,int mask)57*5c23704eSSong Gao static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
58*5c23704eSSong Gao {
59*5c23704eSSong Gao     int flags = get_float_exception_flags(&env->fp_status);
60*5c23704eSSong Gao 
61*5c23704eSSong Gao     set_float_exception_flags(0, &env->fp_status);
62*5c23704eSSong Gao 
63*5c23704eSSong Gao     flags &= ~mask;
64*5c23704eSSong Gao 
65*5c23704eSSong Gao     if (!flags) {
66*5c23704eSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
67*5c23704eSSong Gao         return;
68*5c23704eSSong Gao     } else {
69*5c23704eSSong Gao         flags = ieee_ex_to_loongarch(flags);
70*5c23704eSSong Gao         SET_FP_CAUSE(env->fcsr0, flags);
71*5c23704eSSong Gao     }
72*5c23704eSSong Gao 
73*5c23704eSSong Gao     if (GET_FP_ENABLES(env->fcsr0) & flags) {
74*5c23704eSSong Gao         do_raise_exception(env, EXCCODE_FPE, pc);
75*5c23704eSSong Gao     } else {
76*5c23704eSSong Gao         UPDATE_FP_FLAGS(env->fcsr0, flags);
77*5c23704eSSong Gao     }
78*5c23704eSSong Gao }
79*5c23704eSSong Gao 
update_fcsr0(CPULoongArchState * env,uintptr_t pc)80*5c23704eSSong Gao static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
81*5c23704eSSong Gao {
82*5c23704eSSong Gao     update_fcsr0_mask(env, pc, 0);
83*5c23704eSSong Gao }
84*5c23704eSSong Gao 
helper_fadd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)85*5c23704eSSong Gao uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
86*5c23704eSSong Gao {
87*5c23704eSSong Gao     uint64_t fd;
88*5c23704eSSong Gao 
89*5c23704eSSong Gao     fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, &env->fp_status));
90*5c23704eSSong Gao     update_fcsr0(env, GETPC());
91*5c23704eSSong Gao     return fd;
92*5c23704eSSong Gao }
93*5c23704eSSong Gao 
helper_fadd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)94*5c23704eSSong Gao uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
95*5c23704eSSong Gao {
96*5c23704eSSong Gao     uint64_t fd;
97*5c23704eSSong Gao 
98*5c23704eSSong Gao     fd = float64_add(fj, fk, &env->fp_status);
99*5c23704eSSong Gao     update_fcsr0(env, GETPC());
100*5c23704eSSong Gao     return fd;
101*5c23704eSSong Gao }
102*5c23704eSSong Gao 
helper_fsub_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)103*5c23704eSSong Gao uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
104*5c23704eSSong Gao {
105*5c23704eSSong Gao     uint64_t fd;
106*5c23704eSSong Gao 
107*5c23704eSSong Gao     fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, &env->fp_status));
108*5c23704eSSong Gao     update_fcsr0(env, GETPC());
109*5c23704eSSong Gao     return fd;
110*5c23704eSSong Gao }
111*5c23704eSSong Gao 
helper_fsub_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)112*5c23704eSSong Gao uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
113*5c23704eSSong Gao {
114*5c23704eSSong Gao     uint64_t fd;
115*5c23704eSSong Gao 
116*5c23704eSSong Gao     fd = float64_sub(fj, fk, &env->fp_status);
117*5c23704eSSong Gao     update_fcsr0(env, GETPC());
118*5c23704eSSong Gao     return fd;
119*5c23704eSSong Gao }
120*5c23704eSSong Gao 
helper_fmul_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)121*5c23704eSSong Gao uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
122*5c23704eSSong Gao {
123*5c23704eSSong Gao     uint64_t fd;
124*5c23704eSSong Gao 
125*5c23704eSSong Gao     fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, &env->fp_status));
126*5c23704eSSong Gao     update_fcsr0(env, GETPC());
127*5c23704eSSong Gao     return fd;
128*5c23704eSSong Gao }
129*5c23704eSSong Gao 
helper_fmul_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)130*5c23704eSSong Gao uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
131*5c23704eSSong Gao {
132*5c23704eSSong Gao     uint64_t fd;
133*5c23704eSSong Gao 
134*5c23704eSSong Gao     fd = float64_mul(fj, fk, &env->fp_status);
135*5c23704eSSong Gao     update_fcsr0(env, GETPC());
136*5c23704eSSong Gao     return fd;
137*5c23704eSSong Gao }
138*5c23704eSSong Gao 
helper_fdiv_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)139*5c23704eSSong Gao uint64_t helper_fdiv_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
140*5c23704eSSong Gao {
141*5c23704eSSong Gao     uint64_t fd;
142*5c23704eSSong Gao 
143*5c23704eSSong Gao     fd = nanbox_s(float32_div((uint32_t)fj, (uint32_t)fk, &env->fp_status));
144*5c23704eSSong Gao     update_fcsr0(env, GETPC());
145*5c23704eSSong Gao     return fd;
146*5c23704eSSong Gao }
147*5c23704eSSong Gao 
helper_fdiv_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)148*5c23704eSSong Gao uint64_t helper_fdiv_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
149*5c23704eSSong Gao {
150*5c23704eSSong Gao     uint64_t fd;
151*5c23704eSSong Gao 
152*5c23704eSSong Gao     fd = float64_div(fj, fk, &env->fp_status);
153*5c23704eSSong Gao     update_fcsr0(env, GETPC());
154*5c23704eSSong Gao     return fd;
155*5c23704eSSong Gao }
156*5c23704eSSong Gao 
helper_fmax_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)157*5c23704eSSong Gao uint64_t helper_fmax_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
158*5c23704eSSong Gao {
159*5c23704eSSong Gao     uint64_t fd;
160*5c23704eSSong Gao 
161*5c23704eSSong Gao     fd = nanbox_s(float32_maxnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
162*5c23704eSSong Gao     update_fcsr0(env, GETPC());
163*5c23704eSSong Gao     return fd;
164*5c23704eSSong Gao }
165*5c23704eSSong Gao 
helper_fmax_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)166*5c23704eSSong Gao uint64_t helper_fmax_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
167*5c23704eSSong Gao {
168*5c23704eSSong Gao     uint64_t fd;
169*5c23704eSSong Gao 
170*5c23704eSSong Gao     fd = float64_maxnum(fj, fk, &env->fp_status);
171*5c23704eSSong Gao     update_fcsr0(env, GETPC());
172*5c23704eSSong Gao     return fd;
173*5c23704eSSong Gao }
174*5c23704eSSong Gao 
helper_fmin_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)175*5c23704eSSong Gao uint64_t helper_fmin_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
176*5c23704eSSong Gao {
177*5c23704eSSong Gao     uint64_t fd;
178*5c23704eSSong Gao 
179*5c23704eSSong Gao     fd = nanbox_s(float32_minnum((uint32_t)fj, (uint32_t)fk, &env->fp_status));
180*5c23704eSSong Gao     update_fcsr0(env, GETPC());
181*5c23704eSSong Gao     return fd;
182*5c23704eSSong Gao }
183*5c23704eSSong Gao 
helper_fmin_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)184*5c23704eSSong Gao uint64_t helper_fmin_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
185*5c23704eSSong Gao {
186*5c23704eSSong Gao     uint64_t fd;
187*5c23704eSSong Gao 
188*5c23704eSSong Gao     fd = float64_minnum(fj, fk, &env->fp_status);
189*5c23704eSSong Gao     update_fcsr0(env, GETPC());
190*5c23704eSSong Gao     return fd;
191*5c23704eSSong Gao }
192*5c23704eSSong Gao 
helper_fmaxa_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)193*5c23704eSSong Gao uint64_t helper_fmaxa_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
194*5c23704eSSong Gao {
195*5c23704eSSong Gao     uint64_t fd;
196*5c23704eSSong Gao 
197*5c23704eSSong Gao     fd = nanbox_s(float32_maxnummag((uint32_t)fj,
198*5c23704eSSong Gao                                     (uint32_t)fk, &env->fp_status));
199*5c23704eSSong Gao     update_fcsr0(env, GETPC());
200*5c23704eSSong Gao     return fd;
201*5c23704eSSong Gao }
202*5c23704eSSong Gao 
helper_fmaxa_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)203*5c23704eSSong Gao uint64_t helper_fmaxa_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
204*5c23704eSSong Gao {
205*5c23704eSSong Gao     uint64_t fd;
206*5c23704eSSong Gao 
207*5c23704eSSong Gao     fd = float64_maxnummag(fj, fk, &env->fp_status);
208*5c23704eSSong Gao     update_fcsr0(env, GETPC());
209*5c23704eSSong Gao     return fd;
210*5c23704eSSong Gao }
211*5c23704eSSong Gao 
helper_fmina_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)212*5c23704eSSong Gao uint64_t helper_fmina_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
213*5c23704eSSong Gao {
214*5c23704eSSong Gao     uint64_t fd;
215*5c23704eSSong Gao 
216*5c23704eSSong Gao     fd = nanbox_s(float32_minnummag((uint32_t)fj,
217*5c23704eSSong Gao                                     (uint32_t)fk, &env->fp_status));
218*5c23704eSSong Gao     update_fcsr0(env, GETPC());
219*5c23704eSSong Gao     return fd;
220*5c23704eSSong Gao }
221*5c23704eSSong Gao 
helper_fmina_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)222*5c23704eSSong Gao uint64_t helper_fmina_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
223*5c23704eSSong Gao {
224*5c23704eSSong Gao     uint64_t fd;
225*5c23704eSSong Gao 
226*5c23704eSSong Gao     fd = float64_minnummag(fj, fk, &env->fp_status);
227*5c23704eSSong Gao     update_fcsr0(env, GETPC());
228*5c23704eSSong Gao     return fd;
229*5c23704eSSong Gao }
230*5c23704eSSong Gao 
helper_fscaleb_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)231*5c23704eSSong Gao uint64_t helper_fscaleb_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
232*5c23704eSSong Gao {
233*5c23704eSSong Gao     uint64_t fd;
234*5c23704eSSong Gao     int32_t n = (int32_t)fk;
235*5c23704eSSong Gao 
236*5c23704eSSong Gao     fd = nanbox_s(float32_scalbn((uint32_t)fj,
237*5c23704eSSong Gao                                  n >  0x200 ?  0x200 :
238*5c23704eSSong Gao                                  n < -0x200 ? -0x200 : n,
239*5c23704eSSong Gao                                  &env->fp_status));
240*5c23704eSSong Gao     update_fcsr0(env, GETPC());
241*5c23704eSSong Gao     return fd;
242*5c23704eSSong Gao }
243*5c23704eSSong Gao 
helper_fscaleb_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)244*5c23704eSSong Gao uint64_t helper_fscaleb_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
245*5c23704eSSong Gao {
246*5c23704eSSong Gao     uint64_t fd;
247*5c23704eSSong Gao     int64_t n = (int64_t)fk;
248*5c23704eSSong Gao 
249*5c23704eSSong Gao     fd = float64_scalbn(fj,
250*5c23704eSSong Gao                         n >  0x1000 ?  0x1000 :
251*5c23704eSSong Gao                         n < -0x1000 ? -0x1000 : n,
252*5c23704eSSong Gao                         &env->fp_status);
253*5c23704eSSong Gao     update_fcsr0(env, GETPC());
254*5c23704eSSong Gao     return fd;
255*5c23704eSSong Gao }
256*5c23704eSSong Gao 
helper_fsqrt_s(CPULoongArchState * env,uint64_t fj)257*5c23704eSSong Gao uint64_t helper_fsqrt_s(CPULoongArchState *env, uint64_t fj)
258*5c23704eSSong Gao {
259*5c23704eSSong Gao     uint64_t fd;
260*5c23704eSSong Gao 
261*5c23704eSSong Gao     fd = nanbox_s(float32_sqrt((uint32_t)fj, &env->fp_status));
262*5c23704eSSong Gao     update_fcsr0(env, GETPC());
263*5c23704eSSong Gao     return fd;
264*5c23704eSSong Gao }
265*5c23704eSSong Gao 
helper_fsqrt_d(CPULoongArchState * env,uint64_t fj)266*5c23704eSSong Gao uint64_t helper_fsqrt_d(CPULoongArchState *env, uint64_t fj)
267*5c23704eSSong Gao {
268*5c23704eSSong Gao     uint64_t fd;
269*5c23704eSSong Gao 
270*5c23704eSSong Gao     fd = float64_sqrt(fj, &env->fp_status);
271*5c23704eSSong Gao     update_fcsr0(env, GETPC());
272*5c23704eSSong Gao     return fd;
273*5c23704eSSong Gao }
274*5c23704eSSong Gao 
helper_frecip_s(CPULoongArchState * env,uint64_t fj)275*5c23704eSSong Gao uint64_t helper_frecip_s(CPULoongArchState *env, uint64_t fj)
276*5c23704eSSong Gao {
277*5c23704eSSong Gao     uint64_t fd;
278*5c23704eSSong Gao 
279*5c23704eSSong Gao     fd = nanbox_s(float32_div(float32_one, (uint32_t)fj, &env->fp_status));
280*5c23704eSSong Gao     update_fcsr0(env, GETPC());
281*5c23704eSSong Gao     return fd;
282*5c23704eSSong Gao }
283*5c23704eSSong Gao 
helper_frecip_d(CPULoongArchState * env,uint64_t fj)284*5c23704eSSong Gao uint64_t helper_frecip_d(CPULoongArchState *env, uint64_t fj)
285*5c23704eSSong Gao {
286*5c23704eSSong Gao     uint64_t fd;
287*5c23704eSSong Gao 
288*5c23704eSSong Gao     fd = float64_div(float64_one, fj, &env->fp_status);
289*5c23704eSSong Gao     update_fcsr0(env, GETPC());
290*5c23704eSSong Gao     return fd;
291*5c23704eSSong Gao }
292*5c23704eSSong Gao 
helper_frsqrt_s(CPULoongArchState * env,uint64_t fj)293*5c23704eSSong Gao uint64_t helper_frsqrt_s(CPULoongArchState *env, uint64_t fj)
294*5c23704eSSong Gao {
295*5c23704eSSong Gao     uint64_t fd;
296*5c23704eSSong Gao     uint32_t fp;
297*5c23704eSSong Gao 
298*5c23704eSSong Gao     fp = float32_sqrt((uint32_t)fj, &env->fp_status);
299*5c23704eSSong Gao     fd = nanbox_s(float32_div(float32_one, fp, &env->fp_status));
300*5c23704eSSong Gao     update_fcsr0(env, GETPC());
301*5c23704eSSong Gao     return fd;
302*5c23704eSSong Gao }
303*5c23704eSSong Gao 
helper_frsqrt_d(CPULoongArchState * env,uint64_t fj)304*5c23704eSSong Gao uint64_t helper_frsqrt_d(CPULoongArchState *env, uint64_t fj)
305*5c23704eSSong Gao {
306*5c23704eSSong Gao     uint64_t fp, fd;
307*5c23704eSSong Gao 
308*5c23704eSSong Gao     fp = float64_sqrt(fj, &env->fp_status);
309*5c23704eSSong Gao     fd = float64_div(float64_one, fp, &env->fp_status);
310*5c23704eSSong Gao     update_fcsr0(env, GETPC());
311*5c23704eSSong Gao     return fd;
312*5c23704eSSong Gao }
313*5c23704eSSong Gao 
helper_flogb_s(CPULoongArchState * env,uint64_t fj)314*5c23704eSSong Gao uint64_t helper_flogb_s(CPULoongArchState *env, uint64_t fj)
315*5c23704eSSong Gao {
316*5c23704eSSong Gao     uint64_t fd;
317*5c23704eSSong Gao     uint32_t fp;
318*5c23704eSSong Gao     float_status *status = &env->fp_status;
319*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
320*5c23704eSSong Gao 
321*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, status);
322*5c23704eSSong Gao     fp = float32_log2((uint32_t)fj, status);
323*5c23704eSSong Gao     fd = nanbox_s(float32_round_to_int(fp, status));
324*5c23704eSSong Gao     set_float_rounding_mode(old_mode, status);
325*5c23704eSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
326*5c23704eSSong Gao     return fd;
327*5c23704eSSong Gao }
328*5c23704eSSong Gao 
helper_flogb_d(CPULoongArchState * env,uint64_t fj)329*5c23704eSSong Gao uint64_t helper_flogb_d(CPULoongArchState *env, uint64_t fj)
330*5c23704eSSong Gao {
331*5c23704eSSong Gao     uint64_t fd;
332*5c23704eSSong Gao     float_status *status = &env->fp_status;
333*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(status);
334*5c23704eSSong Gao 
335*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, status);
336*5c23704eSSong Gao     fd = float64_log2(fj, status);
337*5c23704eSSong Gao     fd = float64_round_to_int(fd, status);
338*5c23704eSSong Gao     set_float_rounding_mode(old_mode, status);
339*5c23704eSSong Gao     update_fcsr0_mask(env, GETPC(), float_flag_inexact);
340*5c23704eSSong Gao     return fd;
341*5c23704eSSong Gao }
342*5c23704eSSong Gao 
helper_fclass_s(CPULoongArchState * env,uint64_t fj)343*5c23704eSSong Gao uint64_t helper_fclass_s(CPULoongArchState *env, uint64_t fj)
344*5c23704eSSong Gao {
345*5c23704eSSong Gao     float32 f = fj;
346*5c23704eSSong Gao     bool sign = float32_is_neg(f);
347*5c23704eSSong Gao 
348*5c23704eSSong Gao     if (float32_is_infinity(f)) {
349*5c23704eSSong Gao         return sign ? 1 << 2 : 1 << 6;
350*5c23704eSSong Gao     } else if (float32_is_zero(f)) {
351*5c23704eSSong Gao         return sign ? 1 << 5 : 1 << 9;
352*5c23704eSSong Gao     } else if (float32_is_zero_or_denormal(f)) {
353*5c23704eSSong Gao         return sign ? 1 << 4 : 1 << 8;
354*5c23704eSSong Gao     } else if (float32_is_any_nan(f)) {
355*5c23704eSSong Gao         float_status s = { }; /* for snan_bit_is_one */
356*5c23704eSSong Gao         return float32_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
357*5c23704eSSong Gao     } else {
358*5c23704eSSong Gao         return sign ? 1 << 3 : 1 << 7;
359*5c23704eSSong Gao     }
360*5c23704eSSong Gao }
361*5c23704eSSong Gao 
helper_fclass_d(CPULoongArchState * env,uint64_t fj)362*5c23704eSSong Gao uint64_t helper_fclass_d(CPULoongArchState *env, uint64_t fj)
363*5c23704eSSong Gao {
364*5c23704eSSong Gao     float64 f = fj;
365*5c23704eSSong Gao     bool sign = float64_is_neg(f);
366*5c23704eSSong Gao 
367*5c23704eSSong Gao     if (float64_is_infinity(f)) {
368*5c23704eSSong Gao         return sign ? 1 << 2 : 1 << 6;
369*5c23704eSSong Gao     } else if (float64_is_zero(f)) {
370*5c23704eSSong Gao         return sign ? 1 << 5 : 1 << 9;
371*5c23704eSSong Gao     } else if (float64_is_zero_or_denormal(f)) {
372*5c23704eSSong Gao         return sign ? 1 << 4 : 1 << 8;
373*5c23704eSSong Gao     } else if (float64_is_any_nan(f)) {
374*5c23704eSSong Gao         float_status s = { }; /* for snan_bit_is_one */
375*5c23704eSSong Gao         return float64_is_quiet_nan(f, &s) ? 1 << 1 : 1 << 0;
376*5c23704eSSong Gao     } else {
377*5c23704eSSong Gao         return sign ? 1 << 3 : 1 << 7;
378*5c23704eSSong Gao     }
379*5c23704eSSong Gao }
380*5c23704eSSong Gao 
helper_fmuladd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)381*5c23704eSSong Gao uint64_t helper_fmuladd_s(CPULoongArchState *env, uint64_t fj,
382*5c23704eSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
383*5c23704eSSong Gao {
384*5c23704eSSong Gao     uint64_t fd;
385*5c23704eSSong Gao 
386*5c23704eSSong Gao     fd = nanbox_s(float32_muladd((uint32_t)fj, (uint32_t)fk,
387*5c23704eSSong Gao                                  (uint32_t)fa, flag, &env->fp_status));
388*5c23704eSSong Gao     update_fcsr0(env, GETPC());
389*5c23704eSSong Gao     return fd;
390*5c23704eSSong Gao }
391*5c23704eSSong Gao 
helper_fmuladd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)392*5c23704eSSong Gao uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t fj,
393*5c23704eSSong Gao                           uint64_t fk, uint64_t fa, uint32_t flag)
394*5c23704eSSong Gao {
395*5c23704eSSong Gao     uint64_t fd;
396*5c23704eSSong Gao 
397*5c23704eSSong Gao     fd = float64_muladd(fj, fk, fa, flag, &env->fp_status);
398*5c23704eSSong Gao     update_fcsr0(env, GETPC());
399*5c23704eSSong Gao     return fd;
400*5c23704eSSong Gao }
401*5c23704eSSong Gao 
fcmp_common(CPULoongArchState * env,FloatRelation cmp,uint32_t flags)402*5c23704eSSong Gao static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
403*5c23704eSSong Gao                             uint32_t flags)
404*5c23704eSSong Gao {
405*5c23704eSSong Gao     bool ret;
406*5c23704eSSong Gao 
407*5c23704eSSong Gao     switch (cmp) {
408*5c23704eSSong Gao     case float_relation_less:
409*5c23704eSSong Gao         ret = (flags & FCMP_LT);
410*5c23704eSSong Gao         break;
411*5c23704eSSong Gao     case float_relation_equal:
412*5c23704eSSong Gao         ret = (flags & FCMP_EQ);
413*5c23704eSSong Gao         break;
414*5c23704eSSong Gao     case float_relation_greater:
415*5c23704eSSong Gao         ret = (flags & FCMP_GT);
416*5c23704eSSong Gao         break;
417*5c23704eSSong Gao     case float_relation_unordered:
418*5c23704eSSong Gao         ret = (flags & FCMP_UN);
419*5c23704eSSong Gao         break;
420*5c23704eSSong Gao     default:
421*5c23704eSSong Gao         g_assert_not_reached();
422*5c23704eSSong Gao     }
423*5c23704eSSong Gao     update_fcsr0(env, GETPC());
424*5c23704eSSong Gao 
425*5c23704eSSong Gao     return ret;
426*5c23704eSSong Gao }
427*5c23704eSSong Gao 
428*5c23704eSSong Gao /* fcmp_cXXX_s */
helper_fcmp_c_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)429*5c23704eSSong Gao uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
430*5c23704eSSong Gao                          uint64_t fk, uint32_t flags)
431*5c23704eSSong Gao {
432*5c23704eSSong Gao     FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
433*5c23704eSSong Gao                                               (uint32_t)fk, &env->fp_status);
434*5c23704eSSong Gao     return fcmp_common(env, cmp, flags);
435*5c23704eSSong Gao }
436*5c23704eSSong Gao 
437*5c23704eSSong Gao /* fcmp_sXXX_s */
helper_fcmp_s_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)438*5c23704eSSong Gao uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
439*5c23704eSSong Gao                          uint64_t fk, uint32_t flags)
440*5c23704eSSong Gao {
441*5c23704eSSong Gao     FloatRelation cmp = float32_compare((uint32_t)fj,
442*5c23704eSSong Gao                                         (uint32_t)fk, &env->fp_status);
443*5c23704eSSong Gao     return fcmp_common(env, cmp, flags);
444*5c23704eSSong Gao }
445*5c23704eSSong Gao 
446*5c23704eSSong Gao /* fcmp_cXXX_d */
helper_fcmp_c_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)447*5c23704eSSong Gao uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
448*5c23704eSSong Gao                          uint64_t fk, uint32_t flags)
449*5c23704eSSong Gao {
450*5c23704eSSong Gao     FloatRelation cmp = float64_compare_quiet(fj, fk, &env->fp_status);
451*5c23704eSSong Gao     return fcmp_common(env, cmp, flags);
452*5c23704eSSong Gao }
453*5c23704eSSong Gao 
454*5c23704eSSong Gao /* fcmp_sXXX_d */
helper_fcmp_s_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)455*5c23704eSSong Gao uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
456*5c23704eSSong Gao                          uint64_t fk, uint32_t flags)
457*5c23704eSSong Gao {
458*5c23704eSSong Gao     FloatRelation cmp = float64_compare(fj, fk, &env->fp_status);
459*5c23704eSSong Gao     return fcmp_common(env, cmp, flags);
460*5c23704eSSong Gao }
461*5c23704eSSong Gao 
462*5c23704eSSong Gao /* floating point conversion */
helper_fcvt_s_d(CPULoongArchState * env,uint64_t fj)463*5c23704eSSong Gao uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
464*5c23704eSSong Gao {
465*5c23704eSSong Gao     uint64_t fd;
466*5c23704eSSong Gao 
467*5c23704eSSong Gao     fd = nanbox_s(float64_to_float32(fj, &env->fp_status));
468*5c23704eSSong Gao     update_fcsr0(env, GETPC());
469*5c23704eSSong Gao     return fd;
470*5c23704eSSong Gao }
471*5c23704eSSong Gao 
helper_fcvt_d_s(CPULoongArchState * env,uint64_t fj)472*5c23704eSSong Gao uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
473*5c23704eSSong Gao {
474*5c23704eSSong Gao     uint64_t fd;
475*5c23704eSSong Gao 
476*5c23704eSSong Gao     fd = float32_to_float64((uint32_t)fj, &env->fp_status);
477*5c23704eSSong Gao     update_fcsr0(env, GETPC());
478*5c23704eSSong Gao     return fd;
479*5c23704eSSong Gao }
480*5c23704eSSong Gao 
helper_ffint_s_w(CPULoongArchState * env,uint64_t fj)481*5c23704eSSong Gao uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
482*5c23704eSSong Gao {
483*5c23704eSSong Gao     uint64_t fd;
484*5c23704eSSong Gao 
485*5c23704eSSong Gao     fd = nanbox_s(int32_to_float32((int32_t)fj, &env->fp_status));
486*5c23704eSSong Gao     update_fcsr0(env, GETPC());
487*5c23704eSSong Gao     return fd;
488*5c23704eSSong Gao }
489*5c23704eSSong Gao 
helper_ffint_s_l(CPULoongArchState * env,uint64_t fj)490*5c23704eSSong Gao uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
491*5c23704eSSong Gao {
492*5c23704eSSong Gao     uint64_t fd;
493*5c23704eSSong Gao 
494*5c23704eSSong Gao     fd = nanbox_s(int64_to_float32(fj, &env->fp_status));
495*5c23704eSSong Gao     update_fcsr0(env, GETPC());
496*5c23704eSSong Gao     return fd;
497*5c23704eSSong Gao }
498*5c23704eSSong Gao 
helper_ffint_d_w(CPULoongArchState * env,uint64_t fj)499*5c23704eSSong Gao uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
500*5c23704eSSong Gao {
501*5c23704eSSong Gao     uint64_t fd;
502*5c23704eSSong Gao 
503*5c23704eSSong Gao     fd = int32_to_float64((int32_t)fj, &env->fp_status);
504*5c23704eSSong Gao     update_fcsr0(env, GETPC());
505*5c23704eSSong Gao     return fd;
506*5c23704eSSong Gao }
507*5c23704eSSong Gao 
helper_ffint_d_l(CPULoongArchState * env,uint64_t fj)508*5c23704eSSong Gao uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
509*5c23704eSSong Gao {
510*5c23704eSSong Gao     uint64_t fd;
511*5c23704eSSong Gao 
512*5c23704eSSong Gao     fd = int64_to_float64(fj, &env->fp_status);
513*5c23704eSSong Gao     update_fcsr0(env, GETPC());
514*5c23704eSSong Gao     return fd;
515*5c23704eSSong Gao }
516*5c23704eSSong Gao 
helper_frint_s(CPULoongArchState * env,uint64_t fj)517*5c23704eSSong Gao uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
518*5c23704eSSong Gao {
519*5c23704eSSong Gao     uint64_t fd;
520*5c23704eSSong Gao 
521*5c23704eSSong Gao     fd = (uint64_t)(float32_round_to_int((uint32_t)fj, &env->fp_status));
522*5c23704eSSong Gao     update_fcsr0(env, GETPC());
523*5c23704eSSong Gao     return fd;
524*5c23704eSSong Gao }
525*5c23704eSSong Gao 
helper_frint_d(CPULoongArchState * env,uint64_t fj)526*5c23704eSSong Gao uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
527*5c23704eSSong Gao {
528*5c23704eSSong Gao     uint64_t fd;
529*5c23704eSSong Gao 
530*5c23704eSSong Gao     fd = float64_round_to_int(fj, &env->fp_status);
531*5c23704eSSong Gao     update_fcsr0(env, GETPC());
532*5c23704eSSong Gao     return fd;
533*5c23704eSSong Gao }
534*5c23704eSSong Gao 
helper_ftintrm_l_d(CPULoongArchState * env,uint64_t fj)535*5c23704eSSong Gao uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
536*5c23704eSSong Gao {
537*5c23704eSSong Gao     uint64_t fd;
538*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
539*5c23704eSSong Gao 
540*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
541*5c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
542*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
543*5c23704eSSong Gao 
544*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
545*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
546*5c23704eSSong Gao             fd = 0;
547*5c23704eSSong Gao         }
548*5c23704eSSong Gao     }
549*5c23704eSSong Gao     update_fcsr0(env, GETPC());
550*5c23704eSSong Gao     return fd;
551*5c23704eSSong Gao }
552*5c23704eSSong Gao 
helper_ftintrm_l_s(CPULoongArchState * env,uint64_t fj)553*5c23704eSSong Gao uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
554*5c23704eSSong Gao {
555*5c23704eSSong Gao     uint64_t fd;
556*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
557*5c23704eSSong Gao 
558*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
559*5c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
560*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
561*5c23704eSSong Gao 
562*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
563*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
564*5c23704eSSong Gao             fd = 0;
565*5c23704eSSong Gao         }
566*5c23704eSSong Gao     }
567*5c23704eSSong Gao     update_fcsr0(env, GETPC());
568*5c23704eSSong Gao     return fd;
569*5c23704eSSong Gao }
570*5c23704eSSong Gao 
helper_ftintrm_w_d(CPULoongArchState * env,uint64_t fj)571*5c23704eSSong Gao uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
572*5c23704eSSong Gao {
573*5c23704eSSong Gao     uint64_t fd;
574*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
575*5c23704eSSong Gao 
576*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
577*5c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
578*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
579*5c23704eSSong Gao 
580*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
581*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
582*5c23704eSSong Gao             fd = 0;
583*5c23704eSSong Gao         }
584*5c23704eSSong Gao     }
585*5c23704eSSong Gao     update_fcsr0(env, GETPC());
586*5c23704eSSong Gao     return fd;
587*5c23704eSSong Gao }
588*5c23704eSSong Gao 
helper_ftintrm_w_s(CPULoongArchState * env,uint64_t fj)589*5c23704eSSong Gao uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
590*5c23704eSSong Gao {
591*5c23704eSSong Gao     uint64_t fd;
592*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
593*5c23704eSSong Gao 
594*5c23704eSSong Gao     set_float_rounding_mode(float_round_down, &env->fp_status);
595*5c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
596*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
597*5c23704eSSong Gao 
598*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
599*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
600*5c23704eSSong Gao             fd = 0;
601*5c23704eSSong Gao         }
602*5c23704eSSong Gao     }
603*5c23704eSSong Gao     update_fcsr0(env, GETPC());
604*5c23704eSSong Gao     return fd;
605*5c23704eSSong Gao }
606*5c23704eSSong Gao 
helper_ftintrp_l_d(CPULoongArchState * env,uint64_t fj)607*5c23704eSSong Gao uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
608*5c23704eSSong Gao {
609*5c23704eSSong Gao     uint64_t fd;
610*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
611*5c23704eSSong Gao 
612*5c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
613*5c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
614*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
615*5c23704eSSong Gao 
616*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
617*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
618*5c23704eSSong Gao             fd = 0;
619*5c23704eSSong Gao         }
620*5c23704eSSong Gao     }
621*5c23704eSSong Gao     update_fcsr0(env, GETPC());
622*5c23704eSSong Gao     return fd;
623*5c23704eSSong Gao }
624*5c23704eSSong Gao 
helper_ftintrp_l_s(CPULoongArchState * env,uint64_t fj)625*5c23704eSSong Gao uint64_t helper_ftintrp_l_s(CPULoongArchState *env, uint64_t fj)
626*5c23704eSSong Gao {
627*5c23704eSSong Gao     uint64_t fd;
628*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
629*5c23704eSSong Gao 
630*5c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
631*5c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
632*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
633*5c23704eSSong Gao 
634*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
635*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
636*5c23704eSSong Gao             fd = 0;
637*5c23704eSSong Gao         }
638*5c23704eSSong Gao     }
639*5c23704eSSong Gao     update_fcsr0(env, GETPC());
640*5c23704eSSong Gao     return fd;
641*5c23704eSSong Gao }
642*5c23704eSSong Gao 
helper_ftintrp_w_d(CPULoongArchState * env,uint64_t fj)643*5c23704eSSong Gao uint64_t helper_ftintrp_w_d(CPULoongArchState *env, uint64_t fj)
644*5c23704eSSong Gao {
645*5c23704eSSong Gao     uint64_t fd;
646*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
647*5c23704eSSong Gao 
648*5c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
649*5c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
650*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
651*5c23704eSSong Gao 
652*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
653*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
654*5c23704eSSong Gao             fd = 0;
655*5c23704eSSong Gao         }
656*5c23704eSSong Gao     }
657*5c23704eSSong Gao     update_fcsr0(env, GETPC());
658*5c23704eSSong Gao     return fd;
659*5c23704eSSong Gao }
660*5c23704eSSong Gao 
helper_ftintrp_w_s(CPULoongArchState * env,uint64_t fj)661*5c23704eSSong Gao uint64_t helper_ftintrp_w_s(CPULoongArchState *env, uint64_t fj)
662*5c23704eSSong Gao {
663*5c23704eSSong Gao     uint64_t fd;
664*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
665*5c23704eSSong Gao 
666*5c23704eSSong Gao     set_float_rounding_mode(float_round_up, &env->fp_status);
667*5c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
668*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
669*5c23704eSSong Gao 
670*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
671*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
672*5c23704eSSong Gao             fd = 0;
673*5c23704eSSong Gao         }
674*5c23704eSSong Gao     }
675*5c23704eSSong Gao     update_fcsr0(env, GETPC());
676*5c23704eSSong Gao     return fd;
677*5c23704eSSong Gao }
678*5c23704eSSong Gao 
helper_ftintrz_l_d(CPULoongArchState * env,uint64_t fj)679*5c23704eSSong Gao uint64_t helper_ftintrz_l_d(CPULoongArchState *env, uint64_t fj)
680*5c23704eSSong Gao {
681*5c23704eSSong Gao     uint64_t fd;
682*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
683*5c23704eSSong Gao 
684*5c23704eSSong Gao     fd = float64_to_int64_round_to_zero(fj, &env->fp_status);
685*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
686*5c23704eSSong Gao 
687*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
688*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
689*5c23704eSSong Gao             fd = 0;
690*5c23704eSSong Gao         }
691*5c23704eSSong Gao     }
692*5c23704eSSong Gao     update_fcsr0(env, GETPC());
693*5c23704eSSong Gao     return fd;
694*5c23704eSSong Gao }
695*5c23704eSSong Gao 
helper_ftintrz_l_s(CPULoongArchState * env,uint64_t fj)696*5c23704eSSong Gao uint64_t helper_ftintrz_l_s(CPULoongArchState *env, uint64_t fj)
697*5c23704eSSong Gao {
698*5c23704eSSong Gao     uint64_t fd;
699*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
700*5c23704eSSong Gao 
701*5c23704eSSong Gao     fd = float32_to_int64_round_to_zero((uint32_t)fj, &env->fp_status);
702*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
703*5c23704eSSong Gao 
704*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
705*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
706*5c23704eSSong Gao             fd = 0;
707*5c23704eSSong Gao         }
708*5c23704eSSong Gao     }
709*5c23704eSSong Gao     update_fcsr0(env, GETPC());
710*5c23704eSSong Gao     return fd;
711*5c23704eSSong Gao }
712*5c23704eSSong Gao 
helper_ftintrz_w_d(CPULoongArchState * env,uint64_t fj)713*5c23704eSSong Gao uint64_t helper_ftintrz_w_d(CPULoongArchState *env, uint64_t fj)
714*5c23704eSSong Gao {
715*5c23704eSSong Gao     uint64_t fd;
716*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
717*5c23704eSSong Gao 
718*5c23704eSSong Gao     fd = (uint64_t)float64_to_int32_round_to_zero(fj, &env->fp_status);
719*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
720*5c23704eSSong Gao 
721*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
722*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
723*5c23704eSSong Gao             fd = 0;
724*5c23704eSSong Gao         }
725*5c23704eSSong Gao     }
726*5c23704eSSong Gao     update_fcsr0(env, GETPC());
727*5c23704eSSong Gao     return fd;
728*5c23704eSSong Gao }
729*5c23704eSSong Gao 
helper_ftintrz_w_s(CPULoongArchState * env,uint64_t fj)730*5c23704eSSong Gao uint64_t helper_ftintrz_w_s(CPULoongArchState *env, uint64_t fj)
731*5c23704eSSong Gao {
732*5c23704eSSong Gao     uint32_t fd;
733*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
734*5c23704eSSong Gao 
735*5c23704eSSong Gao     fd = float32_to_int32_round_to_zero((uint32_t)fj, &env->fp_status);
736*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
737*5c23704eSSong Gao 
738*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
739*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
740*5c23704eSSong Gao             fd = 0;
741*5c23704eSSong Gao         }
742*5c23704eSSong Gao     }
743*5c23704eSSong Gao     update_fcsr0(env, GETPC());
744*5c23704eSSong Gao     return (uint64_t)fd;
745*5c23704eSSong Gao }
746*5c23704eSSong Gao 
helper_ftintrne_l_d(CPULoongArchState * env,uint64_t fj)747*5c23704eSSong Gao uint64_t helper_ftintrne_l_d(CPULoongArchState *env, uint64_t fj)
748*5c23704eSSong Gao {
749*5c23704eSSong Gao     uint64_t fd;
750*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
751*5c23704eSSong Gao 
752*5c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
753*5c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
754*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
755*5c23704eSSong Gao 
756*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
757*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
758*5c23704eSSong Gao             fd = 0;
759*5c23704eSSong Gao         }
760*5c23704eSSong Gao     }
761*5c23704eSSong Gao     update_fcsr0(env, GETPC());
762*5c23704eSSong Gao     return fd;
763*5c23704eSSong Gao }
764*5c23704eSSong Gao 
helper_ftintrne_l_s(CPULoongArchState * env,uint64_t fj)765*5c23704eSSong Gao uint64_t helper_ftintrne_l_s(CPULoongArchState *env, uint64_t fj)
766*5c23704eSSong Gao {
767*5c23704eSSong Gao     uint64_t fd;
768*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
769*5c23704eSSong Gao 
770*5c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
771*5c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
772*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
773*5c23704eSSong Gao 
774*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
775*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
776*5c23704eSSong Gao             fd = 0;
777*5c23704eSSong Gao         }
778*5c23704eSSong Gao     }
779*5c23704eSSong Gao     update_fcsr0(env, GETPC());
780*5c23704eSSong Gao     return fd;
781*5c23704eSSong Gao }
782*5c23704eSSong Gao 
helper_ftintrne_w_d(CPULoongArchState * env,uint64_t fj)783*5c23704eSSong Gao uint64_t helper_ftintrne_w_d(CPULoongArchState *env, uint64_t fj)
784*5c23704eSSong Gao {
785*5c23704eSSong Gao     uint64_t fd;
786*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
787*5c23704eSSong Gao 
788*5c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
789*5c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
790*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
791*5c23704eSSong Gao 
792*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
793*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
794*5c23704eSSong Gao             fd = 0;
795*5c23704eSSong Gao         }
796*5c23704eSSong Gao     }
797*5c23704eSSong Gao     update_fcsr0(env, GETPC());
798*5c23704eSSong Gao     return fd;
799*5c23704eSSong Gao }
800*5c23704eSSong Gao 
helper_ftintrne_w_s(CPULoongArchState * env,uint64_t fj)801*5c23704eSSong Gao uint64_t helper_ftintrne_w_s(CPULoongArchState *env, uint64_t fj)
802*5c23704eSSong Gao {
803*5c23704eSSong Gao     uint32_t fd;
804*5c23704eSSong Gao     FloatRoundMode old_mode = get_float_rounding_mode(&env->fp_status);
805*5c23704eSSong Gao 
806*5c23704eSSong Gao     set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
807*5c23704eSSong Gao     fd = float32_to_int32((uint32_t)fj, &env->fp_status);
808*5c23704eSSong Gao     set_float_rounding_mode(old_mode, &env->fp_status);
809*5c23704eSSong Gao 
810*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
811*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
812*5c23704eSSong Gao             fd = 0;
813*5c23704eSSong Gao         }
814*5c23704eSSong Gao     }
815*5c23704eSSong Gao     update_fcsr0(env, GETPC());
816*5c23704eSSong Gao     return (uint64_t)fd;
817*5c23704eSSong Gao }
818*5c23704eSSong Gao 
helper_ftint_l_d(CPULoongArchState * env,uint64_t fj)819*5c23704eSSong Gao uint64_t helper_ftint_l_d(CPULoongArchState *env, uint64_t fj)
820*5c23704eSSong Gao {
821*5c23704eSSong Gao     uint64_t fd;
822*5c23704eSSong Gao 
823*5c23704eSSong Gao     fd = float64_to_int64(fj, &env->fp_status);
824*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
825*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
826*5c23704eSSong Gao             fd = 0;
827*5c23704eSSong Gao         }
828*5c23704eSSong Gao     }
829*5c23704eSSong Gao     update_fcsr0(env, GETPC());
830*5c23704eSSong Gao     return fd;
831*5c23704eSSong Gao }
832*5c23704eSSong Gao 
helper_ftint_l_s(CPULoongArchState * env,uint64_t fj)833*5c23704eSSong Gao uint64_t helper_ftint_l_s(CPULoongArchState *env, uint64_t fj)
834*5c23704eSSong Gao {
835*5c23704eSSong Gao     uint64_t fd;
836*5c23704eSSong Gao 
837*5c23704eSSong Gao     fd = float32_to_int64((uint32_t)fj, &env->fp_status);
838*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
839*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
840*5c23704eSSong Gao             fd = 0;
841*5c23704eSSong Gao         }
842*5c23704eSSong Gao     }
843*5c23704eSSong Gao     update_fcsr0(env, GETPC());
844*5c23704eSSong Gao     return fd;
845*5c23704eSSong Gao }
846*5c23704eSSong Gao 
helper_ftint_w_s(CPULoongArchState * env,uint64_t fj)847*5c23704eSSong Gao uint64_t helper_ftint_w_s(CPULoongArchState *env, uint64_t fj)
848*5c23704eSSong Gao {
849*5c23704eSSong Gao     uint64_t fd;
850*5c23704eSSong Gao 
851*5c23704eSSong Gao     fd = (uint64_t)float32_to_int32((uint32_t)fj, &env->fp_status);
852*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
853*5c23704eSSong Gao         if (float32_is_any_nan((uint32_t)fj)) {
854*5c23704eSSong Gao             fd = 0;
855*5c23704eSSong Gao         }
856*5c23704eSSong Gao     }
857*5c23704eSSong Gao     update_fcsr0(env, GETPC());
858*5c23704eSSong Gao     return fd;
859*5c23704eSSong Gao }
860*5c23704eSSong Gao 
helper_ftint_w_d(CPULoongArchState * env,uint64_t fj)861*5c23704eSSong Gao uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj)
862*5c23704eSSong Gao {
863*5c23704eSSong Gao     uint64_t fd;
864*5c23704eSSong Gao 
865*5c23704eSSong Gao     fd = (uint64_t)float64_to_int32(fj, &env->fp_status);
866*5c23704eSSong Gao     if (get_float_exception_flags(&env->fp_status) & (float_flag_invalid)) {
867*5c23704eSSong Gao         if (float64_is_any_nan(fj)) {
868*5c23704eSSong Gao             fd = 0;
869*5c23704eSSong Gao         }
870*5c23704eSSong Gao     }
871*5c23704eSSong Gao     update_fcsr0(env, GETPC());
872*5c23704eSSong Gao     return fd;
873*5c23704eSSong Gao }
874*5c23704eSSong Gao 
helper_set_rounding_mode(CPULoongArchState * env)875*5c23704eSSong Gao void helper_set_rounding_mode(CPULoongArchState *env)
876*5c23704eSSong Gao {
877*5c23704eSSong Gao     set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
878*5c23704eSSong Gao                             &env->fp_status);
879*5c23704eSSong Gao }
880