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