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
nanbox_s(float32 fp)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
restore_fp_status(CPULoongArchState * env)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
ieee_ex_to_loongarch(int xcpt)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
update_fcsr0_mask(CPULoongArchState * env,uintptr_t pc,int mask)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
update_fcsr0(CPULoongArchState * env,uintptr_t pc)80 static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
81 {
82 update_fcsr0_mask(env, pc, 0);
83 }
84
helper_fadd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fadd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fsub_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fsub_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmul_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmul_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fdiv_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fdiv_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmax_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmax_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmin_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmin_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmaxa_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmaxa_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmina_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fmina_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fscaleb_s(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fscaleb_d(CPULoongArchState * env,uint64_t fj,uint64_t fk)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
helper_fsqrt_s(CPULoongArchState * env,uint64_t fj)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
helper_fsqrt_d(CPULoongArchState * env,uint64_t fj)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
helper_frecip_s(CPULoongArchState * env,uint64_t fj)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
helper_frecip_d(CPULoongArchState * env,uint64_t fj)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
helper_frsqrt_s(CPULoongArchState * env,uint64_t fj)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
helper_frsqrt_d(CPULoongArchState * env,uint64_t fj)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
helper_flogb_s(CPULoongArchState * env,uint64_t fj)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
helper_flogb_d(CPULoongArchState * env,uint64_t fj)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
helper_fclass_s(CPULoongArchState * env,uint64_t fj)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
helper_fclass_d(CPULoongArchState * env,uint64_t fj)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
helper_fmuladd_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)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
helper_fmuladd_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint64_t fa,uint32_t flag)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
fcmp_common(CPULoongArchState * env,FloatRelation cmp,uint32_t flags)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 */
helper_fcmp_c_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_s_s(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_c_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcmp_s_d(CPULoongArchState * env,uint64_t fj,uint64_t fk,uint32_t flags)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 */
helper_fcvt_s_d(CPULoongArchState * env,uint64_t fj)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
helper_fcvt_d_s(CPULoongArchState * env,uint64_t fj)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
helper_ffint_s_w(CPULoongArchState * env,uint64_t fj)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
helper_ffint_s_l(CPULoongArchState * env,uint64_t fj)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
helper_ffint_d_w(CPULoongArchState * env,uint64_t fj)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
helper_ffint_d_l(CPULoongArchState * env,uint64_t fj)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
helper_frint_s(CPULoongArchState * env,uint64_t fj)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
helper_frint_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrm_l_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrm_l_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrm_w_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrm_w_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrp_l_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrp_l_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrp_w_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrp_w_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrz_l_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrz_l_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrz_w_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrz_w_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrne_l_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrne_l_s(CPULoongArchState * env,uint64_t fj)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
helper_ftintrne_w_d(CPULoongArchState * env,uint64_t fj)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
helper_ftintrne_w_s(CPULoongArchState * env,uint64_t fj)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
helper_ftint_l_d(CPULoongArchState * env,uint64_t fj)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
helper_ftint_l_s(CPULoongArchState * env,uint64_t fj)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
helper_ftint_w_s(CPULoongArchState * env,uint64_t fj)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
helper_ftint_w_d(CPULoongArchState * env,uint64_t fj)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
helper_set_rounding_mode(CPULoongArchState * env)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