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