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