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
riscv_cpu_get_fflags(CPURISCVState * env)26 target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
27 {
28 int soft = get_float_exception_flags(&env->fp_status);
29 target_ulong 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
riscv_cpu_set_fflags(CPURISCVState * env,target_ulong hard)40 void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong 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
helper_set_rounding_mode(CPURISCVState * env,uint32_t rm)53 void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
54 {
55 int softrm;
56
57 if (rm == RISCV_FRM_DYN) {
58 rm = env->frm;
59 }
60 switch (rm) {
61 case RISCV_FRM_RNE:
62 softrm = float_round_nearest_even;
63 break;
64 case RISCV_FRM_RTZ:
65 softrm = float_round_to_zero;
66 break;
67 case RISCV_FRM_RDN:
68 softrm = float_round_down;
69 break;
70 case RISCV_FRM_RUP:
71 softrm = float_round_up;
72 break;
73 case RISCV_FRM_RMM:
74 softrm = float_round_ties_away;
75 break;
76 default:
77 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
78 }
79
80 set_float_rounding_mode(softrm, &env->fp_status);
81 }
82
helper_set_rounding_mode_chkfrm(CPURISCVState * env,uint32_t rm)83 void helper_set_rounding_mode_chkfrm(CPURISCVState *env, uint32_t rm)
84 {
85 int softrm;
86
87 /* Always validate frm, even if rm != DYN. */
88 if (unlikely(env->frm >= 5)) {
89 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
90 }
91 if (rm == RISCV_FRM_DYN) {
92 rm = env->frm;
93 }
94 switch (rm) {
95 case RISCV_FRM_RNE:
96 softrm = float_round_nearest_even;
97 break;
98 case RISCV_FRM_RTZ:
99 softrm = float_round_to_zero;
100 break;
101 case RISCV_FRM_RDN:
102 softrm = float_round_down;
103 break;
104 case RISCV_FRM_RUP:
105 softrm = float_round_up;
106 break;
107 case RISCV_FRM_RMM:
108 softrm = float_round_ties_away;
109 break;
110 case RISCV_FRM_ROD:
111 softrm = float_round_to_odd;
112 break;
113 default:
114 g_assert_not_reached();
115 }
116
117 set_float_rounding_mode(softrm, &env->fp_status);
118 }
119
do_fmadd_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2,uint64_t rs3,int flags)120 static uint64_t do_fmadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
121 uint64_t rs3, int flags)
122 {
123 float16 frs1 = check_nanbox_h(env, rs1);
124 float16 frs2 = check_nanbox_h(env, rs2);
125 float16 frs3 = check_nanbox_h(env, rs3);
126 return nanbox_h(env, float16_muladd(frs1, frs2, frs3, flags,
127 &env->fp_status));
128 }
129
do_fmadd_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2,uint64_t rs3,int flags)130 static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2,
131 uint64_t rs3, int flags)
132 {
133 float32 frs1 = check_nanbox_s(env, rs1);
134 float32 frs2 = check_nanbox_s(env, rs2);
135 float32 frs3 = check_nanbox_s(env, rs3);
136 return nanbox_s(env, float32_muladd(frs1, frs2, frs3, flags,
137 &env->fp_status));
138 }
139
helper_fmadd_s(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)140 uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
141 uint64_t frs3)
142 {
143 return do_fmadd_s(env, frs1, frs2, frs3, 0);
144 }
145
helper_fmadd_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)146 uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
147 uint64_t frs3)
148 {
149 return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
150 }
151
helper_fmadd_h(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)152 uint64_t helper_fmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
153 uint64_t frs3)
154 {
155 return do_fmadd_h(env, frs1, frs2, frs3, 0);
156 }
157
helper_fmsub_s(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)158 uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
159 uint64_t frs3)
160 {
161 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c);
162 }
163
helper_fmsub_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)164 uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
165 uint64_t frs3)
166 {
167 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c,
168 &env->fp_status);
169 }
170
helper_fmsub_h(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)171 uint64_t helper_fmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
172 uint64_t frs3)
173 {
174 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_c);
175 }
176
helper_fnmsub_s(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)177 uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
178 uint64_t frs3)
179 {
180 return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product);
181 }
182
helper_fnmsub_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)183 uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
184 uint64_t frs3)
185 {
186 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product,
187 &env->fp_status);
188 }
189
helper_fnmsub_h(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)190 uint64_t helper_fnmsub_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
191 uint64_t frs3)
192 {
193 return do_fmadd_h(env, frs1, frs2, frs3, float_muladd_negate_product);
194 }
195
helper_fnmadd_s(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)196 uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
197 uint64_t frs3)
198 {
199 return do_fmadd_s(env, frs1, frs2, frs3,
200 float_muladd_negate_c | float_muladd_negate_product);
201 }
202
helper_fnmadd_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)203 uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
204 uint64_t frs3)
205 {
206 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c |
207 float_muladd_negate_product, &env->fp_status);
208 }
209
helper_fnmadd_h(CPURISCVState * env,uint64_t frs1,uint64_t frs2,uint64_t frs3)210 uint64_t helper_fnmadd_h(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
211 uint64_t frs3)
212 {
213 return do_fmadd_h(env, frs1, frs2, frs3,
214 float_muladd_negate_c | float_muladd_negate_product);
215 }
216
helper_fadd_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)217 uint64_t helper_fadd_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
218 {
219 float32 frs1 = check_nanbox_s(env, rs1);
220 float32 frs2 = check_nanbox_s(env, rs2);
221 return nanbox_s(env, float32_add(frs1, frs2, &env->fp_status));
222 }
223
helper_fsub_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)224 uint64_t helper_fsub_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
225 {
226 float32 frs1 = check_nanbox_s(env, rs1);
227 float32 frs2 = check_nanbox_s(env, rs2);
228 return nanbox_s(env, float32_sub(frs1, frs2, &env->fp_status));
229 }
230
helper_fmul_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)231 uint64_t helper_fmul_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
232 {
233 float32 frs1 = check_nanbox_s(env, rs1);
234 float32 frs2 = check_nanbox_s(env, rs2);
235 return nanbox_s(env, float32_mul(frs1, frs2, &env->fp_status));
236 }
237
helper_fdiv_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)238 uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
239 {
240 float32 frs1 = check_nanbox_s(env, rs1);
241 float32 frs2 = check_nanbox_s(env, rs2);
242 return nanbox_s(env, float32_div(frs1, frs2, &env->fp_status));
243 }
244
helper_fmin_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)245 uint64_t helper_fmin_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
246 {
247 float32 frs1 = check_nanbox_s(env, rs1);
248 float32 frs2 = check_nanbox_s(env, rs2);
249 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
250 float32_minnum(frs1, frs2, &env->fp_status) :
251 float32_minimum_number(frs1, frs2, &env->fp_status));
252 }
253
helper_fminm_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)254 uint64_t helper_fminm_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 float32 ret = float32_min(frs1, frs2, &env->fp_status);
259 return nanbox_s(env, ret);
260 }
261
helper_fmax_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)262 uint64_t helper_fmax_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
263 {
264 float32 frs1 = check_nanbox_s(env, rs1);
265 float32 frs2 = check_nanbox_s(env, rs2);
266 return nanbox_s(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
267 float32_maxnum(frs1, frs2, &env->fp_status) :
268 float32_maximum_number(frs1, frs2, &env->fp_status));
269 }
270
helper_fmaxm_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)271 uint64_t helper_fmaxm_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
272 {
273 float32 frs1 = check_nanbox_s(env, rs1);
274 float32 frs2 = check_nanbox_s(env, rs2);
275 float32 ret = float32_max(frs1, frs2, &env->fp_status);
276 return nanbox_s(env, ret);
277 }
278
helper_fsqrt_s(CPURISCVState * env,uint64_t rs1)279 uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t rs1)
280 {
281 float32 frs1 = check_nanbox_s(env, rs1);
282 return nanbox_s(env, float32_sqrt(frs1, &env->fp_status));
283 }
284
helper_fle_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)285 target_ulong helper_fle_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
286 {
287 float32 frs1 = check_nanbox_s(env, rs1);
288 float32 frs2 = check_nanbox_s(env, rs2);
289 return float32_le(frs1, frs2, &env->fp_status);
290 }
291
helper_fleq_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)292 target_ulong helper_fleq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
293 {
294 float32 frs1 = check_nanbox_s(env, rs1);
295 float32 frs2 = check_nanbox_s(env, rs2);
296 return float32_le_quiet(frs1, frs2, &env->fp_status);
297 }
298
helper_flt_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)299 target_ulong helper_flt_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
300 {
301 float32 frs1 = check_nanbox_s(env, rs1);
302 float32 frs2 = check_nanbox_s(env, rs2);
303 return float32_lt(frs1, frs2, &env->fp_status);
304 }
305
helper_fltq_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)306 target_ulong helper_fltq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
307 {
308 float32 frs1 = check_nanbox_s(env, rs1);
309 float32 frs2 = check_nanbox_s(env, rs2);
310 return float32_lt_quiet(frs1, frs2, &env->fp_status);
311 }
312
helper_feq_s(CPURISCVState * env,uint64_t rs1,uint64_t rs2)313 target_ulong helper_feq_s(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
314 {
315 float32 frs1 = check_nanbox_s(env, rs1);
316 float32 frs2 = check_nanbox_s(env, rs2);
317 return float32_eq_quiet(frs1, frs2, &env->fp_status);
318 }
319
helper_fcvt_w_s(CPURISCVState * env,uint64_t rs1)320 target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t rs1)
321 {
322 float32 frs1 = check_nanbox_s(env, rs1);
323 return float32_to_int32(frs1, &env->fp_status);
324 }
325
helper_fcvt_wu_s(CPURISCVState * env,uint64_t rs1)326 target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t rs1)
327 {
328 float32 frs1 = check_nanbox_s(env, rs1);
329 return (int32_t)float32_to_uint32(frs1, &env->fp_status);
330 }
331
helper_fcvt_l_s(CPURISCVState * env,uint64_t rs1)332 target_ulong helper_fcvt_l_s(CPURISCVState *env, uint64_t rs1)
333 {
334 float32 frs1 = check_nanbox_s(env, rs1);
335 return float32_to_int64(frs1, &env->fp_status);
336 }
337
helper_fcvt_lu_s(CPURISCVState * env,uint64_t rs1)338 target_ulong helper_fcvt_lu_s(CPURISCVState *env, uint64_t rs1)
339 {
340 float32 frs1 = check_nanbox_s(env, rs1);
341 return float32_to_uint64(frs1, &env->fp_status);
342 }
343
helper_fcvt_s_w(CPURISCVState * env,target_ulong rs1)344 uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
345 {
346 return nanbox_s(env, int32_to_float32((int32_t)rs1, &env->fp_status));
347 }
348
helper_fcvt_s_wu(CPURISCVState * env,target_ulong rs1)349 uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
350 {
351 return nanbox_s(env, uint32_to_float32((uint32_t)rs1, &env->fp_status));
352 }
353
helper_fcvt_s_l(CPURISCVState * env,target_ulong rs1)354 uint64_t helper_fcvt_s_l(CPURISCVState *env, target_ulong rs1)
355 {
356 return nanbox_s(env, int64_to_float32(rs1, &env->fp_status));
357 }
358
helper_fcvt_s_lu(CPURISCVState * env,target_ulong rs1)359 uint64_t helper_fcvt_s_lu(CPURISCVState *env, target_ulong rs1)
360 {
361 return nanbox_s(env, uint64_to_float32(rs1, &env->fp_status));
362 }
363
helper_fclass_s(CPURISCVState * env,uint64_t rs1)364 target_ulong helper_fclass_s(CPURISCVState *env, uint64_t rs1)
365 {
366 float32 frs1 = check_nanbox_s(env, rs1);
367 return fclass_s(frs1);
368 }
369
helper_fround_s(CPURISCVState * env,uint64_t rs1)370 uint64_t helper_fround_s(CPURISCVState *env, uint64_t rs1)
371 {
372 float_status *fs = &env->fp_status;
373 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
374 float32 frs1 = check_nanbox_s(env, rs1);
375
376 frs1 = float32_round_to_int(frs1, fs);
377
378 /* Restore the original NX flag. */
379 uint16_t flags = get_float_exception_flags(fs);
380 flags &= ~float_flag_inexact;
381 flags |= nx_old;
382 set_float_exception_flags(flags, fs);
383
384 return nanbox_s(env, frs1);
385 }
386
helper_froundnx_s(CPURISCVState * env,uint64_t rs1)387 uint64_t helper_froundnx_s(CPURISCVState *env, uint64_t rs1)
388 {
389 float32 frs1 = check_nanbox_s(env, rs1);
390 frs1 = float32_round_to_int(frs1, &env->fp_status);
391 return nanbox_s(env, frs1);
392 }
393
helper_fadd_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)394 uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
395 {
396 return float64_add(frs1, frs2, &env->fp_status);
397 }
398
helper_fsub_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)399 uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
400 {
401 return float64_sub(frs1, frs2, &env->fp_status);
402 }
403
helper_fmul_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)404 uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
405 {
406 return float64_mul(frs1, frs2, &env->fp_status);
407 }
408
helper_fdiv_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)409 uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
410 {
411 return float64_div(frs1, frs2, &env->fp_status);
412 }
413
helper_fmin_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)414 uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
415 {
416 return env->priv_ver < PRIV_VERSION_1_11_0 ?
417 float64_minnum(frs1, frs2, &env->fp_status) :
418 float64_minimum_number(frs1, frs2, &env->fp_status);
419 }
420
helper_fminm_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)421 uint64_t helper_fminm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
422 {
423 return float64_min(frs1, frs2, &env->fp_status);
424 }
425
helper_fmax_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)426 uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
427 {
428 return env->priv_ver < PRIV_VERSION_1_11_0 ?
429 float64_maxnum(frs1, frs2, &env->fp_status) :
430 float64_maximum_number(frs1, frs2, &env->fp_status);
431 }
432
helper_fmaxm_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)433 uint64_t helper_fmaxm_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
434 {
435 return float64_max(frs1, frs2, &env->fp_status);
436 }
437
helper_fcvt_s_d(CPURISCVState * env,uint64_t rs1)438 uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
439 {
440 return nanbox_s(env, float64_to_float32(rs1, &env->fp_status));
441 }
442
helper_fcvt_d_s(CPURISCVState * env,uint64_t rs1)443 uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
444 {
445 float32 frs1 = check_nanbox_s(env, rs1);
446 return float32_to_float64(frs1, &env->fp_status);
447 }
448
helper_fsqrt_d(CPURISCVState * env,uint64_t frs1)449 uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
450 {
451 return float64_sqrt(frs1, &env->fp_status);
452 }
453
helper_fle_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)454 target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
455 {
456 return float64_le(frs1, frs2, &env->fp_status);
457 }
458
helper_fleq_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)459 target_ulong helper_fleq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
460 {
461 return float64_le_quiet(frs1, frs2, &env->fp_status);
462 }
463
helper_flt_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)464 target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
465 {
466 return float64_lt(frs1, frs2, &env->fp_status);
467 }
468
helper_fltq_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)469 target_ulong helper_fltq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
470 {
471 return float64_lt_quiet(frs1, frs2, &env->fp_status);
472 }
473
helper_feq_d(CPURISCVState * env,uint64_t frs1,uint64_t frs2)474 target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
475 {
476 return float64_eq_quiet(frs1, frs2, &env->fp_status);
477 }
478
helper_fcvt_w_d(CPURISCVState * env,uint64_t frs1)479 target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1)
480 {
481 return float64_to_int32(frs1, &env->fp_status);
482 }
483
helper_fcvtmod_w_d(CPURISCVState * env,uint64_t value)484 uint64_t helper_fcvtmod_w_d(CPURISCVState *env, uint64_t value)
485 {
486 return float64_to_int32_modulo(value, float_round_to_zero, &env->fp_status);
487 }
488
helper_fcvt_wu_d(CPURISCVState * env,uint64_t frs1)489 target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
490 {
491 return (int32_t)float64_to_uint32(frs1, &env->fp_status);
492 }
493
helper_fcvt_l_d(CPURISCVState * env,uint64_t frs1)494 target_ulong helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
495 {
496 return float64_to_int64(frs1, &env->fp_status);
497 }
498
helper_fcvt_lu_d(CPURISCVState * env,uint64_t frs1)499 target_ulong helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
500 {
501 return float64_to_uint64(frs1, &env->fp_status);
502 }
503
helper_fcvt_d_w(CPURISCVState * env,target_ulong rs1)504 uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
505 {
506 return int32_to_float64((int32_t)rs1, &env->fp_status);
507 }
508
helper_fcvt_d_wu(CPURISCVState * env,target_ulong rs1)509 uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
510 {
511 return uint32_to_float64((uint32_t)rs1, &env->fp_status);
512 }
513
helper_fcvt_d_l(CPURISCVState * env,target_ulong rs1)514 uint64_t helper_fcvt_d_l(CPURISCVState *env, target_ulong rs1)
515 {
516 return int64_to_float64(rs1, &env->fp_status);
517 }
518
helper_fcvt_d_lu(CPURISCVState * env,target_ulong rs1)519 uint64_t helper_fcvt_d_lu(CPURISCVState *env, target_ulong rs1)
520 {
521 return uint64_to_float64(rs1, &env->fp_status);
522 }
523
helper_fclass_d(uint64_t frs1)524 target_ulong helper_fclass_d(uint64_t frs1)
525 {
526 return fclass_d(frs1);
527 }
528
helper_fround_d(CPURISCVState * env,uint64_t frs1)529 uint64_t helper_fround_d(CPURISCVState *env, uint64_t frs1)
530 {
531 float_status *fs = &env->fp_status;
532 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
533
534 frs1 = float64_round_to_int(frs1, fs);
535
536 /* Restore the original NX flag. */
537 uint16_t flags = get_float_exception_flags(fs);
538 flags &= ~float_flag_inexact;
539 flags |= nx_old;
540 set_float_exception_flags(flags, fs);
541
542 return frs1;
543 }
544
helper_froundnx_d(CPURISCVState * env,uint64_t frs1)545 uint64_t helper_froundnx_d(CPURISCVState *env, uint64_t frs1)
546 {
547 return float64_round_to_int(frs1, &env->fp_status);
548 }
549
helper_fadd_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)550 uint64_t helper_fadd_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
551 {
552 float16 frs1 = check_nanbox_h(env, rs1);
553 float16 frs2 = check_nanbox_h(env, rs2);
554 return nanbox_h(env, float16_add(frs1, frs2, &env->fp_status));
555 }
556
helper_fsub_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)557 uint64_t helper_fsub_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
558 {
559 float16 frs1 = check_nanbox_h(env, rs1);
560 float16 frs2 = check_nanbox_h(env, rs2);
561 return nanbox_h(env, float16_sub(frs1, frs2, &env->fp_status));
562 }
563
helper_fmul_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)564 uint64_t helper_fmul_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
565 {
566 float16 frs1 = check_nanbox_h(env, rs1);
567 float16 frs2 = check_nanbox_h(env, rs2);
568 return nanbox_h(env, float16_mul(frs1, frs2, &env->fp_status));
569 }
570
helper_fdiv_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)571 uint64_t helper_fdiv_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
572 {
573 float16 frs1 = check_nanbox_h(env, rs1);
574 float16 frs2 = check_nanbox_h(env, rs2);
575 return nanbox_h(env, float16_div(frs1, frs2, &env->fp_status));
576 }
577
helper_fmin_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)578 uint64_t helper_fmin_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
579 {
580 float16 frs1 = check_nanbox_h(env, rs1);
581 float16 frs2 = check_nanbox_h(env, rs2);
582 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
583 float16_minnum(frs1, frs2, &env->fp_status) :
584 float16_minimum_number(frs1, frs2, &env->fp_status));
585 }
586
helper_fminm_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)587 uint64_t helper_fminm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
588 {
589 float16 frs1 = check_nanbox_h(env, rs1);
590 float16 frs2 = check_nanbox_h(env, rs2);
591 float16 ret = float16_min(frs1, frs2, &env->fp_status);
592 return nanbox_h(env, ret);
593 }
594
helper_fmax_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)595 uint64_t helper_fmax_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
596 {
597 float16 frs1 = check_nanbox_h(env, rs1);
598 float16 frs2 = check_nanbox_h(env, rs2);
599 return nanbox_h(env, env->priv_ver < PRIV_VERSION_1_11_0 ?
600 float16_maxnum(frs1, frs2, &env->fp_status) :
601 float16_maximum_number(frs1, frs2, &env->fp_status));
602 }
603
helper_fmaxm_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)604 uint64_t helper_fmaxm_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
605 {
606 float16 frs1 = check_nanbox_h(env, rs1);
607 float16 frs2 = check_nanbox_h(env, rs2);
608 float16 ret = float16_max(frs1, frs2, &env->fp_status);
609 return nanbox_h(env, ret);
610 }
611
helper_fsqrt_h(CPURISCVState * env,uint64_t rs1)612 uint64_t helper_fsqrt_h(CPURISCVState *env, uint64_t rs1)
613 {
614 float16 frs1 = check_nanbox_h(env, rs1);
615 return nanbox_h(env, float16_sqrt(frs1, &env->fp_status));
616 }
617
helper_fle_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)618 target_ulong helper_fle_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
619 {
620 float16 frs1 = check_nanbox_h(env, rs1);
621 float16 frs2 = check_nanbox_h(env, rs2);
622 return float16_le(frs1, frs2, &env->fp_status);
623 }
624
helper_fleq_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)625 target_ulong helper_fleq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
626 {
627 float16 frs1 = check_nanbox_h(env, rs1);
628 float16 frs2 = check_nanbox_h(env, rs2);
629 return float16_le_quiet(frs1, frs2, &env->fp_status);
630 }
631
helper_flt_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)632 target_ulong helper_flt_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
633 {
634 float16 frs1 = check_nanbox_h(env, rs1);
635 float16 frs2 = check_nanbox_h(env, rs2);
636 return float16_lt(frs1, frs2, &env->fp_status);
637 }
638
helper_fltq_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)639 target_ulong helper_fltq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
640 {
641 float16 frs1 = check_nanbox_h(env, rs1);
642 float16 frs2 = check_nanbox_h(env, rs2);
643 return float16_lt_quiet(frs1, frs2, &env->fp_status);
644 }
645
helper_feq_h(CPURISCVState * env,uint64_t rs1,uint64_t rs2)646 target_ulong helper_feq_h(CPURISCVState *env, uint64_t rs1, uint64_t rs2)
647 {
648 float16 frs1 = check_nanbox_h(env, rs1);
649 float16 frs2 = check_nanbox_h(env, rs2);
650 return float16_eq_quiet(frs1, frs2, &env->fp_status);
651 }
652
helper_fclass_h(CPURISCVState * env,uint64_t rs1)653 target_ulong helper_fclass_h(CPURISCVState *env, uint64_t rs1)
654 {
655 float16 frs1 = check_nanbox_h(env, rs1);
656 return fclass_h(frs1);
657 }
658
helper_fround_h(CPURISCVState * env,uint64_t rs1)659 uint64_t helper_fround_h(CPURISCVState *env, uint64_t rs1)
660 {
661 float_status *fs = &env->fp_status;
662 uint16_t nx_old = get_float_exception_flags(fs) & float_flag_inexact;
663 float16 frs1 = check_nanbox_h(env, rs1);
664
665 frs1 = float16_round_to_int(frs1, fs);
666
667 /* Restore the original NX flag. */
668 uint16_t flags = get_float_exception_flags(fs);
669 flags &= ~float_flag_inexact;
670 flags |= nx_old;
671 set_float_exception_flags(flags, fs);
672
673 return nanbox_h(env, frs1);
674 }
675
helper_froundnx_h(CPURISCVState * env,uint64_t rs1)676 uint64_t helper_froundnx_h(CPURISCVState *env, uint64_t rs1)
677 {
678 float16 frs1 = check_nanbox_h(env, rs1);
679 frs1 = float16_round_to_int(frs1, &env->fp_status);
680 return nanbox_h(env, frs1);
681 }
682
helper_fcvt_w_h(CPURISCVState * env,uint64_t rs1)683 target_ulong helper_fcvt_w_h(CPURISCVState *env, uint64_t rs1)
684 {
685 float16 frs1 = check_nanbox_h(env, rs1);
686 return float16_to_int32(frs1, &env->fp_status);
687 }
688
helper_fcvt_wu_h(CPURISCVState * env,uint64_t rs1)689 target_ulong helper_fcvt_wu_h(CPURISCVState *env, uint64_t rs1)
690 {
691 float16 frs1 = check_nanbox_h(env, rs1);
692 return (int32_t)float16_to_uint32(frs1, &env->fp_status);
693 }
694
helper_fcvt_l_h(CPURISCVState * env,uint64_t rs1)695 target_ulong helper_fcvt_l_h(CPURISCVState *env, uint64_t rs1)
696 {
697 float16 frs1 = check_nanbox_h(env, rs1);
698 return float16_to_int64(frs1, &env->fp_status);
699 }
700
helper_fcvt_lu_h(CPURISCVState * env,uint64_t rs1)701 target_ulong helper_fcvt_lu_h(CPURISCVState *env, uint64_t rs1)
702 {
703 float16 frs1 = check_nanbox_h(env, rs1);
704 return float16_to_uint64(frs1, &env->fp_status);
705 }
706
helper_fcvt_h_w(CPURISCVState * env,target_ulong rs1)707 uint64_t helper_fcvt_h_w(CPURISCVState *env, target_ulong rs1)
708 {
709 return nanbox_h(env, int32_to_float16((int32_t)rs1, &env->fp_status));
710 }
711
helper_fcvt_h_wu(CPURISCVState * env,target_ulong rs1)712 uint64_t helper_fcvt_h_wu(CPURISCVState *env, target_ulong rs1)
713 {
714 return nanbox_h(env, uint32_to_float16((uint32_t)rs1, &env->fp_status));
715 }
716
helper_fcvt_h_l(CPURISCVState * env,target_ulong rs1)717 uint64_t helper_fcvt_h_l(CPURISCVState *env, target_ulong rs1)
718 {
719 return nanbox_h(env, int64_to_float16(rs1, &env->fp_status));
720 }
721
helper_fcvt_h_lu(CPURISCVState * env,target_ulong rs1)722 uint64_t helper_fcvt_h_lu(CPURISCVState *env, target_ulong rs1)
723 {
724 return nanbox_h(env, uint64_to_float16(rs1, &env->fp_status));
725 }
726
helper_fcvt_h_s(CPURISCVState * env,uint64_t rs1)727 uint64_t helper_fcvt_h_s(CPURISCVState *env, uint64_t rs1)
728 {
729 float32 frs1 = check_nanbox_s(env, rs1);
730 return nanbox_h(env, float32_to_float16(frs1, true, &env->fp_status));
731 }
732
helper_fcvt_s_h(CPURISCVState * env,uint64_t rs1)733 uint64_t helper_fcvt_s_h(CPURISCVState *env, uint64_t rs1)
734 {
735 float16 frs1 = check_nanbox_h(env, rs1);
736 return nanbox_s(env, float16_to_float32(frs1, true, &env->fp_status));
737 }
738
helper_fcvt_h_d(CPURISCVState * env,uint64_t rs1)739 uint64_t helper_fcvt_h_d(CPURISCVState *env, uint64_t rs1)
740 {
741 return nanbox_h(env, float64_to_float16(rs1, true, &env->fp_status));
742 }
743
helper_fcvt_d_h(CPURISCVState * env,uint64_t rs1)744 uint64_t helper_fcvt_d_h(CPURISCVState *env, uint64_t rs1)
745 {
746 float16 frs1 = check_nanbox_h(env, rs1);
747 return float16_to_float64(frs1, true, &env->fp_status);
748 }
749
helper_fcvt_bf16_s(CPURISCVState * env,uint64_t rs1)750 uint64_t helper_fcvt_bf16_s(CPURISCVState *env, uint64_t rs1)
751 {
752 float32 frs1 = check_nanbox_s(env, rs1);
753 return nanbox_h(env, float32_to_bfloat16(frs1, &env->fp_status));
754 }
755
helper_fcvt_s_bf16(CPURISCVState * env,uint64_t rs1)756 uint64_t helper_fcvt_s_bf16(CPURISCVState *env, uint64_t rs1)
757 {
758 float16 frs1 = check_nanbox_h(env, rs1);
759 return nanbox_s(env, bfloat16_to_float32(frs1, &env->fp_status));
760 }
761