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