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