xref: /qemu/target/riscv/fpu_helper.c (revision 7cef6d686309e2792186504ae17cf4f3eb57ef68)
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