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