master
c 861 lines 27.1 KB
Raw
1 /*
2 * RISC-V FPU Emulation Helpers for QEMU.
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "qemu/osdep.h"
20 #include "cpu.h"
21 #include "qemu/host-utils.h"
22 #include "exec/helper-proto.h"
23 #include "fpu/softfloat.h"
24 #include "internals.h"
25
26 uint8_t riscv_cpu_get_fflags(CPURISCVState *env)
27 {
28 int soft = get_float_exception_flags(&env->fp_status);
29 uint8_t hard = 0;
30
31 hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
32 hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
33 hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
34 hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
35 hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
36
37 return hard;
38 }
39
40 void riscv_cpu_set_fflags(CPURISCVState *env, uint8_t hard)
41 {
42 int soft = 0;
43
44 soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
45 soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
46 soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
47 soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
48 soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
49
50 set_float_exception_flags(soft, &env->fp_status);
51 }
52
53 #ifndef CONFIG_USER_ONLY
54 void riscv_cpu_check_fflags(CPURISCVState *env,
55 FloatExceptionFlags pre_fflag)
56 {
57 if (get_float_exception_flags(&env->fp_status) & ~pre_fflag) {
58 env->mstatus |= MSTATUS_FS;
59 if (env->virt_enabled) {
60 env->mstatus_hs |= MSTATUS_FS;
61 }
62 }
63 }
64 #else
65 void riscv_cpu_check_fflags(CPURISCVState *env,
66 FloatExceptionFlags pre_fflag) {}
67 #endif
68
69 void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
70 {
71 FloatRoundMode softrm;
72
73 if (rm == RISCV_FRM_DYN) {
74 rm = env->frm;
75 }
76 switch (rm) {
77 case RISCV_FRM_RNE:
78 softrm = float_round_nearest_even;
79 break;
80 case RISCV_FRM_RTZ:
81 softrm = float_round_to_zero;
82 break;
83 case RISCV_FRM_RDN:
84 softrm = float_round_down;
85 break;
86 case RISCV_FRM_RUP:
87 softrm = float_round_up;
88 break;
89 case RISCV_FRM_RMM:
90 softrm = float_round_ties_away;
91 break;
92 default:
93 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
94 }
95
96 set_float_rounding_mode(softrm, &env->fp_status);
97 }
98
99 void helper_set_rounding_mode_chkfrm(CPURISCVState *env, uint32_t rm)
100 {
101 FloatRoundMode softrm;
102
103 /* Always validate frm, even if rm != DYN. */
104 if (unlikely(env->frm >= 5)) {
105 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
106 }
107 if (rm == RISCV_FRM_DYN) {
108 rm = env->frm;
109 }
110 switch (rm) {
111 case RISCV_FRM_RNE:
112 softrm = float_round_nearest_even;
113 break;
114 case RISCV_FRM_RTZ:
115 softrm = float_round_to_zero;
116 break;
117 case RISCV_FRM_RDN:
118 softrm = float_round_down;
119 break;
120 case RISCV_FRM_RUP:
121 softrm = float_round_up;
122 break;
123 case RISCV_FRM_RMM:
124 softrm = float_round_ties_away;
125 break;
126 case RISCV_FRM_ROD:
127 softrm = float_round_to_odd;
128 break;
129 default:
130 g_assert_not_reached();
131 }
132
133 set_float_rounding_mode(softrm, &env->fp_status);
134 }
135
136 static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
137 uint64_t rs3, int flags)
138 {
139 float16 frs1 = check_nanbox_h(env, rs1);
140 float16 frs2 = check_nanbox_h(env, rs2);
141 float16 frs3 = check_nanbox_h(env, rs3);
142 return nanbox_h(env, float16_muladd(frs1, frs2, frs3, flags,
143 &env->fp_status));
144 }
145
146 static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
147 uint64_t rs3, int flags)
148 {
149 float32 frs1 = check_nanbox_s(env, rs1);
150 float32 frs2 = check_nanbox_s(env, rs2);
151 float32 frs3 = check_nanbox_s(env, rs3);
152 return nanbox_s(env, float32_muladd(frs1, frs2, frs3, flags,
153 &env->fp_status));
154 }
155
156 uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
157 uint64_t frs3)
158 {
159 return do_fmadd_s(env, frs1, frs2, frs3, 0);
160 }
161
162 uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
163 uint64_t frs3)
164 {
165 return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
166 }
167
168 uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
169 uint64_t frs3)
170 {
171 return do_fmadd_h(env, frs1, frs2, frs3, 0);
172 }
173
174 uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
175 uint64_t frs3)
176 {
177 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c);
178 }
179
180 uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
181 uint64_t frs3)
182 {
183 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c,
184 &env->fp_status);
185 }
186
187 uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
188 uint64_t frs3)
189 {
190 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c);
191 }
192
193 uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
194 uint64_t frs3)
195 {
196 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product);
197 }
198
199 uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
200 uint64_t frs3)
201 {
202 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product,
203 &env->fp_status);
204 }
205
206 uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
207 uint64_t frs3)
208 {
209 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product);
210 }
211
212 uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
213 uint64_t frs3)
214 {
215 return do_fmadd_s(env, frs1, frs2, frs3,
216 float_muladd_negate_c | float_muladd_negate_product);
217 }
218
219 uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
220 uint64_t frs3)
221 {
222 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c |
223 float_muladd_negate_product, &env->fp_status);
224 }
225
226 uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
227 uint64_t frs3)
228 {
229 return do_fmadd_h(env, frs1, frs2, frs3,
230 float_muladd_negate_c | float_muladd_negate_product);
231 }
232
233 uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
234 {
235 float32 frs1 = check_nanbox_s(env, rs1);
236 float32 frs2 = check_nanbox_s(env, rs2);
237 return nanbox_s(env, float32_add(frs1, frs2, &env->fp_status));
238 }
239
240 uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
241 {
242 float32 frs1 = check_nanbox_s(env, rs1);
243 float32 frs2 = check_nanbox_s(env, rs2);
244 return nanbox_s(env, float32_sub(frs1, frs2, &env->fp_status));
245 }
246
247 uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
248 {
249 float32 frs1 = check_nanbox_s(env, rs1);
250 float32 frs2 = check_nanbox_s(env, rs2);
251 return nanbox_s(env, float32_mul(frs1, frs2, &env->fp_status));
252 }
253
254 uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
255 {
256 float32 frs1 = check_nanbox_s(env, rs1);
257 float32 frs2 = check_nanbox_s(env, rs2);
258 return nanbox_s(env, float32_div(frs1, frs2, &env->fp_status));
259 }
260
261 uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
262 {
263 float32 frs1 = check_nanbox_s(env, rs1);
264 float32 frs2 = check_nanbox_s(env, rs2);
265 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
266 float32_minnum(frs1, frs2, &env->fp_status) :
267 float32_minimum_number(frs1, frs2, &env->fp_status));
268 }
269
270 uint64_t helper_fminm_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
271 {
272 float32 frs1 = check_nanbox_s(env, rs1);
273 float32 frs2 = check_nanbox_s(env, rs2);
274 float32 ret = float32_min(frs1, frs2, &env->fp_status);
275 return nanbox_s(env, ret);
276 }
277
278 uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
279 {
280 float32 frs1 = check_nanbox_s(env, rs1);
281 float32 frs2 = check_nanbox_s(env, rs2);
282 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
283 float32_maxnum(frs1, frs2, &env->fp_status) :
284 float32_maximum_number(frs1, frs2, &env->fp_status));
285 }
286
287 uint64_t helper_fmaxm_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
288 {
289 float32 frs1 = check_nanbox_s(env, rs1);
290 float32 frs2 = check_nanbox_s(env, rs2);
291 float32 ret = float32_max(frs1, frs2, &env->fp_status);
292 return nanbox_s(env, ret);
293 }
294
295 uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
296 {
297 float32 frs1 = check_nanbox_s(env, rs1);
298 return nanbox_s(env, float32_sqrt(frs1, &env->fp_status));
299 }
300
301 target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
302 {
303 float32 frs1 = check_nanbox_s(env, rs1);
304 float32 frs2 = check_nanbox_s(env, rs2);
305 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
306 target_ulong ret = float32_le(frs1, frs2, &env->fp_status);
307 riscv_cpu_check_fflags(env, pre_fflag);
308 return ret;
309 }
310
311 target_ulong helper_fleq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
312 {
313 float32 frs1 = check_nanbox_s(env, rs1);
314 float32 frs2 = check_nanbox_s(env, rs2);
315 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
316 target_ulong ret = float32_le_quiet(frs1, frs2, &env->fp_status);
317 riscv_cpu_check_fflags(env, pre_fflag);
318 return ret;
319 }
320
321 target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
322 {
323 float32 frs1 = check_nanbox_s(env, rs1);
324 float32 frs2 = check_nanbox_s(env, rs2);
325 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
326 target_ulong ret = float32_lt(frs1, frs2, &env->fp_status);
327 riscv_cpu_check_fflags(env, pre_fflag);
328 return ret;
329 }
330
331 target_ulong helper_fltq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
332 {
333 float32 frs1 = check_nanbox_s(env, rs1);
334 float32 frs2 = check_nanbox_s(env, rs2);
335 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
336 target_ulong ret = float32_lt_quiet(frs1, frs2, &env->fp_status);
337 riscv_cpu_check_fflags(env, pre_fflag);
338 return ret;
339 }
340
341 target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
342 {
343 float32 frs1 = check_nanbox_s(env, rs1);
344 float32 frs2 = check_nanbox_s(env, rs2);
345 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
346 target_ulong ret = float32_eq_quiet(frs1, frs2, &env->fp_status);
347 riscv_cpu_check_fflags(env, pre_fflag);
348 return ret;
349 }
350
351 target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)
352 {
353 float32 frs1 = check_nanbox_s(env, rs1);
354 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
355 target_ulong ret = float32_to_int32(frs1, &env->fp_status);
356 riscv_cpu_check_fflags(env, pre_fflag);
357 return ret;
358 }
359
360 target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
361 {
362 float32 frs1 = check_nanbox_s(env, rs1);
363 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
364 target_ulong ret = (int32_t)float32_to_uint32(frs1, &env->fp_status);
365 riscv_cpu_check_fflags(env, pre_fflag);
366 return ret;
367 }
368
369 target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
370 {
371 float32 frs1 = check_nanbox_s(env, rs1);
372 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
373 target_ulong ret = float32_to_int64(frs1, &env->fp_status);
374 riscv_cpu_check_fflags(env, pre_fflag);
375 return ret;
376 }
377
378 target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
379 {
380 float32 frs1 = check_nanbox_s(env, rs1);
381 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
382 target_ulong ret = float32_to_uint64(frs1, &env->fp_status);
383 riscv_cpu_check_fflags(env, pre_fflag);
384 return ret;
385 }
386
387 uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
388 {
389 return nanbox_s(env, int32_to_float32((int32_t)rs1, &env->fp_status));
390 }
391
392 uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
393 {
394 return nanbox_s(env, uint32_to_float32((uint32_t)rs1, &env->fp_status));
395 }
396
397 uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1)
398 {
399 return nanbox_s(env, int64_to_float32(rs1, &env->fp_status));
400 }
401
402 uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1)
403 {
404 return nanbox_s(env, uint64_to_float32(rs1, &env->fp_status));
405 }
406
407 target_ulong helper_fclass_s(CPURISCVState *env, uint64_t rs1)
408 {
409 float32 frs1 = check_nanbox_s(env, rs1);
410 return fclass_s(frs1);
411 }
412
413 uint64_t helper_fround_s(CPURISCVState *env, uint64_t rs1)
414 {
415 float_status *fs = &env->fp_status;
416 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
417 float32 frs1 = check_nanbox_s(env, rs1);
418
419 frs1 = float32_round_to_int(frs1, fs);
420
421 /* Restore the original NX flag. */
422 uint16_t flags = get_float_exception_flags(fs);
423 flags &= ~float_flag_inexact;
424 flags |= nx_old;
425 set_float_exception_flags(flags, fs);
426
427 return nanbox_s(env, frs1);
428 }
429
430 uint64_t helper_froundnx_s(CPURISCVState *env, uint64_t rs1)
431 {
432 float32 frs1 = check_nanbox_s(env, rs1);
433 frs1 = float32_round_to_int(frs1, &env->fp_status);
434 return nanbox_s(env, frs1);
435 }
436
437 uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
438 {
439 return float64_add(frs1, frs2, &env->fp_status);
440 }
441
442 uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
443 {
444 return float64_sub(frs1, frs2, &env->fp_status);
445 }
446
447 uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
448 {
449 return float64_mul(frs1, frs2, &env->fp_status);
450 }
451
452 uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
453 {
454 return float64_div(frs1, frs2, &env->fp_status);
455 }
456
457 uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
458 {
459 return env->priv_ver < PRIV_VERSION_1_11_0 ?
460 float64_minnum(frs1, frs2, &env->fp_status) :
461 float64_minimum_number(frs1, frs2, &env->fp_status);
462 }
463
464 uint64_t helper_fminm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
465 {
466 return float64_min(frs1, frs2, &env->fp_status);
467 }
468
469 uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
470 {
471 return env->priv_ver < PRIV_VERSION_1_11_0 ?
472 float64_maxnum(frs1, frs2, &env->fp_status) :
473 float64_maximum_number(frs1, frs2, &env->fp_status);
474 }
475
476 uint64_t helper_fmaxm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
477 {
478 return float64_max(frs1, frs2, &env->fp_status);
479 }
480
481 uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
482 {
483 return nanbox_s(env, float64_to_float32(rs1, &env->fp_status));
484 }
485
486 uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
487 {
488 float32 frs1 = check_nanbox_s(env, rs1);
489 return float32_to_float64(frs1, &env->fp_status);
490 }
491
492 uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
493 {
494 return float64_sqrt(frs1, &env->fp_status);
495 }
496
497 target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
498 {
499 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
500 target_ulong ret = float64_le(frs1, frs2, &env->fp_status);
501 riscv_cpu_check_fflags(env, pre_fflag);
502 return ret;
503 }
504
505 target_ulong helper_fleq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
506 {
507 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
508 target_ulong ret = float64_le_quiet(frs1, frs2, &env->fp_status);
509 riscv_cpu_check_fflags(env, pre_fflag);
510 return ret;
511 }
512
513 target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
514 {
515 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
516 target_ulong ret = float64_lt(frs1, frs2, &env->fp_status);
517 riscv_cpu_check_fflags(env, pre_fflag);
518 return ret;
519 }
520
521 target_ulong helper_fltq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
522 {
523 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
524 target_ulong ret = float64_lt_quiet(frs1, frs2, &env->fp_status);
525 riscv_cpu_check_fflags(env, pre_fflag);
526 return ret;
527 }
528
529 target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
530 {
531 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
532 target_ulong ret = float64_eq_quiet(frs1, frs2, &env->fp_status);
533 riscv_cpu_check_fflags(env, pre_fflag);
534 return ret;
535 }
536
537 target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1)
538 {
539 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
540 target_ulong ret = float64_to_int32(frs1, &env->fp_status);
541 riscv_cpu_check_fflags(env, pre_fflag);
542 return ret;
543 }
544
545 uint64_t helper_fcvtmod_w_d(CPURISCVState *env, uint64_t value)
546 {
547 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
548 uint64_t ret = float64_to_int32_modulo(value, float_round_to_zero,
549 &env->fp_status);
550 riscv_cpu_check_fflags(env, pre_fflag);
551 return ret;
552 }
553
554 target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
555 {
556 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
557 target_ulong ret = (int32_t)float64_to_uint32(frs1, &env->fp_status);
558 riscv_cpu_check_fflags(env, pre_fflag);
559 return ret;
560 }
561
562 target_ulong helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
563 {
564 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
565 target_ulong ret = float64_to_int64(frs1, &env->fp_status);
566 riscv_cpu_check_fflags(env, pre_fflag);
567 return ret;
568 }
569
570 target_ulong helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
571 {
572 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
573 target_ulong ret = float64_to_uint64(frs1, &env->fp_status);
574 riscv_cpu_check_fflags(env, pre_fflag);
575 return ret;
576 }
577
578 uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
579 {
580 return int32_to_float64((int32_t)rs1, &env->fp_status);
581 }
582
583 uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
584 {
585 return uint32_to_float64((uint32_t)rs1, &env->fp_status);
586 }
587
588 uint64_t helper_fcvt_d_l(CPURISCVState *env, target_ulong rs1)
589 {
590 return int64_to_float64(rs1, &env->fp_status);
591 }
592
593 uint64_t helper_fcvt_d_lu(CPURISCVState *env, target_ulong rs1)
594 {
595 return uint64_to_float64(rs1, &env->fp_status);
596 }
597
598 target_ulong helper_fclass_d(uint64_t frs1)
599 {
600 return fclass_d(frs1);
601 }
602
603 uint64_t helper_fround_d(CPURISCVState *env, uint64_t frs1)
604 {
605 float_status *fs = &env->fp_status;
606 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
607
608 frs1 = float64_round_to_int(frs1, fs);
609
610 /* Restore the original NX flag. */
611 uint16_t flags = get_float_exception_flags(fs);
612 flags &= ~float_flag_inexact;
613 flags |= nx_old;
614 set_float_exception_flags(flags, fs);
615
616 return frs1;
617 }
618
619 uint64_t helper_froundnx_d(CPURISCVState *env, uint64_t frs1)
620 {
621 return float64_round_to_int(frs1, &env->fp_status);
622 }
623
624 uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
625 {
626 float16 frs1 = check_nanbox_h(env, rs1);
627 float16 frs2 = check_nanbox_h(env, rs2);
628 return nanbox_h(env, float16_add(frs1, frs2, &env->fp_status));
629 }
630
631 uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
632 {
633 float16 frs1 = check_nanbox_h(env, rs1);
634 float16 frs2 = check_nanbox_h(env, rs2);
635 return nanbox_h(env, float16_sub(frs1, frs2, &env->fp_status));
636 }
637
638 uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
639 {
640 float16 frs1 = check_nanbox_h(env, rs1);
641 float16 frs2 = check_nanbox_h(env, rs2);
642 return nanbox_h(env, float16_mul(frs1, frs2, &env->fp_status));
643 }
644
645 uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
646 {
647 float16 frs1 = check_nanbox_h(env, rs1);
648 float16 frs2 = check_nanbox_h(env, rs2);
649 return nanbox_h(env, float16_div(frs1, frs2, &env->fp_status));
650 }
651
652 uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
653 {
654 float16 frs1 = check_nanbox_h(env, rs1);
655 float16 frs2 = check_nanbox_h(env, rs2);
656 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
657 float16_minnum(frs1, frs2, &env->fp_status) :
658 float16_minimum_number(frs1, frs2, &env->fp_status));
659 }
660
661 uint64_t helper_fminm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
662 {
663 float16 frs1 = check_nanbox_h(env, rs1);
664 float16 frs2 = check_nanbox_h(env, rs2);
665 float16 ret = float16_min(frs1, frs2, &env->fp_status);
666 return nanbox_h(env, ret);
667 }
668
669 uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
670 {
671 float16 frs1 = check_nanbox_h(env, rs1);
672 float16 frs2 = check_nanbox_h(env, rs2);
673 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
674 float16_maxnum(frs1, frs2, &env->fp_status) :
675 float16_maximum_number(frs1, frs2, &env->fp_status));
676 }
677
678 uint64_t helper_fmaxm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
679 {
680 float16 frs1 = check_nanbox_h(env, rs1);
681 float16 frs2 = check_nanbox_h(env, rs2);
682 float16 ret = float16_max(frs1, frs2, &env->fp_status);
683 return nanbox_h(env, ret);
684 }
685
686 uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
687 {
688 float16 frs1 = check_nanbox_h(env, rs1);
689 return nanbox_h(env, float16_sqrt(frs1, &env->fp_status));
690 }
691
692 target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
693 {
694 float16 frs1 = check_nanbox_h(env, rs1);
695 float16 frs2 = check_nanbox_h(env, rs2);
696 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
697 target_ulong ret = float16_le(frs1, frs2, &env->fp_status);
698 riscv_cpu_check_fflags(env, pre_fflag);
699 return ret;
700 }
701
702 target_ulong helper_fleq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
703 {
704 float16 frs1 = check_nanbox_h(env, rs1);
705 float16 frs2 = check_nanbox_h(env, rs2);
706 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
707 target_ulong ret = float16_le_quiet(frs1, frs2, &env->fp_status);
708 riscv_cpu_check_fflags(env, pre_fflag);
709 return ret;
710 }
711
712 target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
713 {
714 float16 frs1 = check_nanbox_h(env, rs1);
715 float16 frs2 = check_nanbox_h(env, rs2);
716 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
717 target_ulong ret = float16_lt(frs1, frs2, &env->fp_status);
718 riscv_cpu_check_fflags(env, pre_fflag);
719 return ret;
720 }
721
722 target_ulong helper_fltq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
723 {
724 float16 frs1 = check_nanbox_h(env, rs1);
725 float16 frs2 = check_nanbox_h(env, rs2);
726 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
727 target_ulong ret = float16_lt_quiet(frs1, frs2, &env->fp_status);
728 riscv_cpu_check_fflags(env, pre_fflag);
729 return ret;
730 }
731
732 target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
733 {
734 float16 frs1 = check_nanbox_h(env, rs1);
735 float16 frs2 = check_nanbox_h(env, rs2);
736 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
737 target_ulong ret = float16_eq_quiet(frs1, frs2, &env->fp_status);
738 riscv_cpu_check_fflags(env, pre_fflag);
739 return ret;
740 }
741
742 target_ulong helper_fclass_h(CPURISCVState *env, uint64_t rs1)
743 {
744 float16 frs1 = check_nanbox_h(env, rs1);
745 return fclass_h(frs1);
746 }
747
748 uint64_t helper_fround_h(CPURISCVState *env, uint64_t rs1)
749 {
750 float_status *fs = &env->fp_status;
751 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
752 float16 frs1 = check_nanbox_h(env, rs1);
753
754 frs1 = float16_round_to_int(frs1, fs);
755
756 /* Restore the original NX flag. */
757 uint16_t flags = get_float_exception_flags(fs);
758 flags &= ~float_flag_inexact;
759 flags |= nx_old;
760 set_float_exception_flags(flags, fs);
761
762 return nanbox_h(env, frs1);
763 }
764
765 uint64_t helper_froundnx_h(CPURISCVState *env, uint64_t rs1)
766 {
767 float16 frs1 = check_nanbox_h(env, rs1);
768 frs1 = float16_round_to_int(frs1, &env->fp_status);
769 return nanbox_h(env, frs1);
770 }
771
772 target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
773 {
774 float16 frs1 = check_nanbox_h(env, rs1);
775 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
776 target_ulong ret = float16_to_int32(frs1, &env->fp_status);
777 riscv_cpu_check_fflags(env, pre_fflag);
778 return ret;
779 }
780
781 target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
782 {
783 float16 frs1 = check_nanbox_h(env, rs1);
784 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
785 target_ulong ret = (int32_t)float16_to_uint32(frs1, &env->fp_status);
786 riscv_cpu_check_fflags(env, pre_fflag);
787 return ret;
788 }
789
790 target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
791 {
792 float16 frs1 = check_nanbox_h(env, rs1);
793 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
794 target_ulong ret = float16_to_int64(frs1, &env->fp_status);
795 riscv_cpu_check_fflags(env, pre_fflag);
796 return ret;
797 }
798
799 target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
800 {
801 float16 frs1 = check_nanbox_h(env, rs1);
802 FloatExceptionFlags pre_fflag = get_float_exception_flags(&env->fp_status);
803 target_ulong ret = float16_to_uint64(frs1, &env->fp_status);
804 riscv_cpu_check_fflags(env, pre_fflag);
805 return ret;
806 }
807
808 uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
809 {
810 return nanbox_h(env, int32_to_float16((int32_t)rs1, &env->fp_status));
811 }
812
813 uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
814 {
815 return nanbox_h(env, uint32_to_float16((uint32_t)rs1, &env->fp_status));
816 }
817
818 uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1)
819 {
820 return nanbox_h(env, int64_to_float16(rs1, &env->fp_status));
821 }
822
823 uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1)
824 {
825 return nanbox_h(env, uint64_to_float16(rs1, &env->fp_status));
826 }
827
828 uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
829 {
830 float32 frs1 = check_nanbox_s(env, rs1);
831 return nanbox_h(env, float32_to_float16(frs1, true, &env->fp_status));
832 }
833
834 uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
835 {
836 float16 frs1 = check_nanbox_h(env, rs1);
837 return nanbox_s(env, float16_to_float32(frs1, true, &env->fp_status));
838 }
839
840 uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
841 {
842 return nanbox_h(env, float64_to_float16(rs1, true, &env->fp_status));
843 }
844
845 uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
846 {
847 float16 frs1 = check_nanbox_h(env, rs1);
848 return float16_to_float64(frs1, true, &env->fp_status);
849 }
850
851 uint64_t helper_fcvt_bf16_s(CPURISCVState *env, uint64_t rs1)
852 {
853 float32 frs1 = check_nanbox_s(env, rs1);
854 return nanbox_h(env, float32_to_bfloat16(frs1, &env->fp_status));
855 }
856
857 uint64_t helper_fcvt_s_bf16(CPURISCVState *env, uint64_t rs1)
858 {
859 float16 frs1 = check_nanbox_bf16(env, rs1);
860 return nanbox_s(env, bfloat16_to_float32(frs1, &env->fp_status));
861 }