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