xref: /qemu/target/riscv/fpu_helper.c (revision 9921e3d3306c344aceeabe074d5bcaafcc6acafb)
1f798f1e2SMichael Clark /*
2f798f1e2SMichael Clark  * RISC-V FPU Emulation Helpers for QEMU.
3f798f1e2SMichael Clark  *
4f798f1e2SMichael Clark  * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5f798f1e2SMichael Clark  *
6f798f1e2SMichael Clark  * This program is free software; you can redistribute it and/or modify it
7f798f1e2SMichael Clark  * under the terms and conditions of the GNU General Public License,
8f798f1e2SMichael Clark  * version 2 or later, as published by the Free Software Foundation.
9f798f1e2SMichael Clark  *
10f798f1e2SMichael Clark  * This program is distributed in the hope it will be useful, but WITHOUT
11f798f1e2SMichael Clark  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12f798f1e2SMichael Clark  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13f798f1e2SMichael Clark  * more details.
14f798f1e2SMichael Clark  *
15f798f1e2SMichael Clark  * You should have received a copy of the GNU General Public License along with
16f798f1e2SMichael Clark  * this program.  If not, see <http://www.gnu.org/licenses/>.
17f798f1e2SMichael Clark  */
18f798f1e2SMichael Clark 
19f798f1e2SMichael Clark #include "qemu/osdep.h"
20f798f1e2SMichael Clark #include "cpu.h"
21f798f1e2SMichael Clark #include "qemu/host-utils.h"
22f798f1e2SMichael Clark #include "exec/exec-all.h"
23f798f1e2SMichael Clark #include "exec/helper-proto.h"
24135b03cbSAlex Bennée #include "fpu/softfloat.h"
25121ddbb3SLIU Zhiwei #include "internals.h"
26f798f1e2SMichael Clark 
27fb738839SMichael Clark target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
28f798f1e2SMichael Clark {
29f798f1e2SMichael Clark     int soft = get_float_exception_flags(&env->fp_status);
30f798f1e2SMichael Clark     target_ulong hard = 0;
31f798f1e2SMichael Clark 
32f798f1e2SMichael Clark     hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
33f798f1e2SMichael Clark     hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
34f798f1e2SMichael Clark     hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
35f798f1e2SMichael Clark     hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
36f798f1e2SMichael Clark     hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
37f798f1e2SMichael Clark 
38f798f1e2SMichael Clark     return hard;
39f798f1e2SMichael Clark }
40f798f1e2SMichael Clark 
41fb738839SMichael Clark void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
42f798f1e2SMichael Clark {
43f798f1e2SMichael Clark     int soft = 0;
44f798f1e2SMichael Clark 
45f798f1e2SMichael Clark     soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
46f798f1e2SMichael Clark     soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
47f798f1e2SMichael Clark     soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
48f798f1e2SMichael Clark     soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
49f798f1e2SMichael Clark     soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
50f798f1e2SMichael Clark 
51f798f1e2SMichael Clark     set_float_exception_flags(soft, &env->fp_status);
52f798f1e2SMichael Clark }
53f798f1e2SMichael Clark 
54f798f1e2SMichael Clark void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
55f798f1e2SMichael Clark {
56f798f1e2SMichael Clark     int softrm;
57f798f1e2SMichael Clark 
58f798f1e2SMichael Clark     if (rm == 7) {
59f798f1e2SMichael Clark         rm = env->frm;
60f798f1e2SMichael Clark     }
61f798f1e2SMichael Clark     switch (rm) {
62f798f1e2SMichael Clark     case 0:
63f798f1e2SMichael Clark         softrm = float_round_nearest_even;
64f798f1e2SMichael Clark         break;
65f798f1e2SMichael Clark     case 1:
66f798f1e2SMichael Clark         softrm = float_round_to_zero;
67f798f1e2SMichael Clark         break;
68f798f1e2SMichael Clark     case 2:
69f798f1e2SMichael Clark         softrm = float_round_down;
70f798f1e2SMichael Clark         break;
71f798f1e2SMichael Clark     case 3:
72f798f1e2SMichael Clark         softrm = float_round_up;
73f798f1e2SMichael Clark         break;
74f798f1e2SMichael Clark     case 4:
75f798f1e2SMichael Clark         softrm = float_round_ties_away;
76f798f1e2SMichael Clark         break;
77f798f1e2SMichael Clark     default:
78fb738839SMichael Clark         riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
79f798f1e2SMichael Clark     }
80f798f1e2SMichael Clark 
81f798f1e2SMichael Clark     set_float_rounding_mode(softrm, &env->fp_status);
82f798f1e2SMichael Clark }
83f798f1e2SMichael Clark 
84*9921e3d3SRichard Henderson static uint64_t do_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
85*9921e3d3SRichard Henderson                            uint64_t frs3, int flags)
86*9921e3d3SRichard Henderson {
87*9921e3d3SRichard Henderson     return nanbox_s(float32_muladd(frs1, frs2, frs3, flags, &env->fp_status));
88*9921e3d3SRichard Henderson }
89*9921e3d3SRichard Henderson 
90f798f1e2SMichael Clark uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
91f798f1e2SMichael Clark                         uint64_t frs3)
92f798f1e2SMichael Clark {
93*9921e3d3SRichard Henderson     return do_fmadd_s(env, frs1, frs2, frs3, 0);
94f798f1e2SMichael Clark }
95f798f1e2SMichael Clark 
96f798f1e2SMichael Clark uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
97f798f1e2SMichael Clark                         uint64_t frs3)
98f798f1e2SMichael Clark {
99f798f1e2SMichael Clark     return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
100f798f1e2SMichael Clark }
101f798f1e2SMichael Clark 
102f798f1e2SMichael Clark uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
103f798f1e2SMichael Clark                         uint64_t frs3)
104f798f1e2SMichael Clark {
105*9921e3d3SRichard Henderson     return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_c);
106f798f1e2SMichael Clark }
107f798f1e2SMichael Clark 
108f798f1e2SMichael Clark uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
109f798f1e2SMichael Clark                         uint64_t frs3)
110f798f1e2SMichael Clark {
111f798f1e2SMichael Clark     return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c,
112f798f1e2SMichael Clark                           &env->fp_status);
113f798f1e2SMichael Clark }
114f798f1e2SMichael Clark 
115f798f1e2SMichael Clark uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
116f798f1e2SMichael Clark                          uint64_t frs3)
117f798f1e2SMichael Clark {
118*9921e3d3SRichard Henderson     return do_fmadd_s(env, frs1, frs2, frs3, float_muladd_negate_product);
119f798f1e2SMichael Clark }
120f798f1e2SMichael Clark 
121f798f1e2SMichael Clark uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
122f798f1e2SMichael Clark                          uint64_t frs3)
123f798f1e2SMichael Clark {
124f798f1e2SMichael Clark     return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product,
125f798f1e2SMichael Clark                           &env->fp_status);
126f798f1e2SMichael Clark }
127f798f1e2SMichael Clark 
128f798f1e2SMichael Clark uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
129f798f1e2SMichael Clark                          uint64_t frs3)
130f798f1e2SMichael Clark {
131*9921e3d3SRichard Henderson     return do_fmadd_s(env, frs1, frs2, frs3,
132*9921e3d3SRichard Henderson                       float_muladd_negate_c | float_muladd_negate_product);
133f798f1e2SMichael Clark }
134f798f1e2SMichael Clark 
135f798f1e2SMichael Clark uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
136f798f1e2SMichael Clark                          uint64_t frs3)
137f798f1e2SMichael Clark {
138f798f1e2SMichael Clark     return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c |
139f798f1e2SMichael Clark                           float_muladd_negate_product, &env->fp_status);
140f798f1e2SMichael Clark }
141f798f1e2SMichael Clark 
142f798f1e2SMichael Clark uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
143f798f1e2SMichael Clark {
144*9921e3d3SRichard Henderson     return nanbox_s(float32_add(frs1, frs2, &env->fp_status));
145f798f1e2SMichael Clark }
146f798f1e2SMichael Clark 
147f798f1e2SMichael Clark uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
148f798f1e2SMichael Clark {
149*9921e3d3SRichard Henderson     return nanbox_s(float32_sub(frs1, frs2, &env->fp_status));
150f798f1e2SMichael Clark }
151f798f1e2SMichael Clark 
152f798f1e2SMichael Clark uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
153f798f1e2SMichael Clark {
154*9921e3d3SRichard Henderson     return nanbox_s(float32_mul(frs1, frs2, &env->fp_status));
155f798f1e2SMichael Clark }
156f798f1e2SMichael Clark 
157f798f1e2SMichael Clark uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
158f798f1e2SMichael Clark {
159*9921e3d3SRichard Henderson     return nanbox_s(float32_div(frs1, frs2, &env->fp_status));
160f798f1e2SMichael Clark }
161f798f1e2SMichael Clark 
162f798f1e2SMichael Clark uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
163f798f1e2SMichael Clark {
164*9921e3d3SRichard Henderson     return nanbox_s(float32_minnum(frs1, frs2, &env->fp_status));
165f798f1e2SMichael Clark }
166f798f1e2SMichael Clark 
167f798f1e2SMichael Clark uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
168f798f1e2SMichael Clark {
169*9921e3d3SRichard Henderson     return nanbox_s(float32_maxnum(frs1, frs2, &env->fp_status));
170f798f1e2SMichael Clark }
171f798f1e2SMichael Clark 
172f798f1e2SMichael Clark uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1)
173f798f1e2SMichael Clark {
174*9921e3d3SRichard Henderson     return nanbox_s(float32_sqrt(frs1, &env->fp_status));
175f798f1e2SMichael Clark }
176f798f1e2SMichael Clark 
177f798f1e2SMichael Clark target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
178f798f1e2SMichael Clark {
179f798f1e2SMichael Clark     return float32_le(frs1, frs2, &env->fp_status);
180f798f1e2SMichael Clark }
181f798f1e2SMichael Clark 
182f798f1e2SMichael Clark target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
183f798f1e2SMichael Clark {
184f798f1e2SMichael Clark     return float32_lt(frs1, frs2, &env->fp_status);
185f798f1e2SMichael Clark }
186f798f1e2SMichael Clark 
187f798f1e2SMichael Clark target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
188f798f1e2SMichael Clark {
189f798f1e2SMichael Clark     return float32_eq_quiet(frs1, frs2, &env->fp_status);
190f798f1e2SMichael Clark }
191f798f1e2SMichael Clark 
192f798f1e2SMichael Clark target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1)
193f798f1e2SMichael Clark {
194f798f1e2SMichael Clark     return float32_to_int32(frs1, &env->fp_status);
195f798f1e2SMichael Clark }
196f798f1e2SMichael Clark 
197f798f1e2SMichael Clark target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1)
198f798f1e2SMichael Clark {
199f798f1e2SMichael Clark     return (int32_t)float32_to_uint32(frs1, &env->fp_status);
200f798f1e2SMichael Clark }
201f798f1e2SMichael Clark 
202f798f1e2SMichael Clark #if defined(TARGET_RISCV64)
203f798f1e2SMichael Clark uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1)
204f798f1e2SMichael Clark {
205f798f1e2SMichael Clark     return float32_to_int64(frs1, &env->fp_status);
206f798f1e2SMichael Clark }
207f798f1e2SMichael Clark 
208f798f1e2SMichael Clark uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1)
209f798f1e2SMichael Clark {
210f798f1e2SMichael Clark     return float32_to_uint64(frs1, &env->fp_status);
211f798f1e2SMichael Clark }
212f798f1e2SMichael Clark #endif
213f798f1e2SMichael Clark 
214f798f1e2SMichael Clark uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
215f798f1e2SMichael Clark {
216*9921e3d3SRichard Henderson     return nanbox_s(int32_to_float32((int32_t)rs1, &env->fp_status));
217f798f1e2SMichael Clark }
218f798f1e2SMichael Clark 
219f798f1e2SMichael Clark uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
220f798f1e2SMichael Clark {
221*9921e3d3SRichard Henderson     return nanbox_s(uint32_to_float32((uint32_t)rs1, &env->fp_status));
222f798f1e2SMichael Clark }
223f798f1e2SMichael Clark 
224f798f1e2SMichael Clark #if defined(TARGET_RISCV64)
225f798f1e2SMichael Clark uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
226f798f1e2SMichael Clark {
227*9921e3d3SRichard Henderson     return nanbox_s(int64_to_float32(rs1, &env->fp_status));
228f798f1e2SMichael Clark }
229f798f1e2SMichael Clark 
230f798f1e2SMichael Clark uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)
231f798f1e2SMichael Clark {
232*9921e3d3SRichard Henderson     return nanbox_s(uint64_to_float32(rs1, &env->fp_status));
233f798f1e2SMichael Clark }
234f798f1e2SMichael Clark #endif
235f798f1e2SMichael Clark 
236f798f1e2SMichael Clark target_ulong helper_fclass_s(uint64_t frs1)
237f798f1e2SMichael Clark {
238121ddbb3SLIU Zhiwei     return fclass_s(frs1);
239f798f1e2SMichael Clark }
240f798f1e2SMichael Clark 
241f798f1e2SMichael Clark uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
242f798f1e2SMichael Clark {
243f798f1e2SMichael Clark     return float64_add(frs1, frs2, &env->fp_status);
244f798f1e2SMichael Clark }
245f798f1e2SMichael Clark 
246f798f1e2SMichael Clark uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
247f798f1e2SMichael Clark {
248f798f1e2SMichael Clark     return float64_sub(frs1, frs2, &env->fp_status);
249f798f1e2SMichael Clark }
250f798f1e2SMichael Clark 
251f798f1e2SMichael Clark uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
252f798f1e2SMichael Clark {
253f798f1e2SMichael Clark     return float64_mul(frs1, frs2, &env->fp_status);
254f798f1e2SMichael Clark }
255f798f1e2SMichael Clark 
256f798f1e2SMichael Clark uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
257f798f1e2SMichael Clark {
258f798f1e2SMichael Clark     return float64_div(frs1, frs2, &env->fp_status);
259f798f1e2SMichael Clark }
260f798f1e2SMichael Clark 
261f798f1e2SMichael Clark uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
262f798f1e2SMichael Clark {
263f798f1e2SMichael Clark     return float64_minnum(frs1, frs2, &env->fp_status);
264f798f1e2SMichael Clark }
265f798f1e2SMichael Clark 
266f798f1e2SMichael Clark uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
267f798f1e2SMichael Clark {
268f798f1e2SMichael Clark     return float64_maxnum(frs1, frs2, &env->fp_status);
269f798f1e2SMichael Clark }
270f798f1e2SMichael Clark 
271f798f1e2SMichael Clark uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
272f798f1e2SMichael Clark {
273*9921e3d3SRichard Henderson     return nanbox_s(float64_to_float32(rs1, &env->fp_status));
274f798f1e2SMichael Clark }
275f798f1e2SMichael Clark 
276f798f1e2SMichael Clark uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
277f798f1e2SMichael Clark {
278cab32112SRichard Henderson     return float32_to_float64(rs1, &env->fp_status);
279f798f1e2SMichael Clark }
280f798f1e2SMichael Clark 
281f798f1e2SMichael Clark uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
282f798f1e2SMichael Clark {
283f798f1e2SMichael Clark     return float64_sqrt(frs1, &env->fp_status);
284f798f1e2SMichael Clark }
285f798f1e2SMichael Clark 
286f798f1e2SMichael Clark target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
287f798f1e2SMichael Clark {
288f798f1e2SMichael Clark     return float64_le(frs1, frs2, &env->fp_status);
289f798f1e2SMichael Clark }
290f798f1e2SMichael Clark 
291f798f1e2SMichael Clark target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
292f798f1e2SMichael Clark {
293f798f1e2SMichael Clark     return float64_lt(frs1, frs2, &env->fp_status);
294f798f1e2SMichael Clark }
295f798f1e2SMichael Clark 
296f798f1e2SMichael Clark target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
297f798f1e2SMichael Clark {
298f798f1e2SMichael Clark     return float64_eq_quiet(frs1, frs2, &env->fp_status);
299f798f1e2SMichael Clark }
300f798f1e2SMichael Clark 
301f798f1e2SMichael Clark target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1)
302f798f1e2SMichael Clark {
303f798f1e2SMichael Clark     return float64_to_int32(frs1, &env->fp_status);
304f798f1e2SMichael Clark }
305f798f1e2SMichael Clark 
306f798f1e2SMichael Clark target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
307f798f1e2SMichael Clark {
308f798f1e2SMichael Clark     return (int32_t)float64_to_uint32(frs1, &env->fp_status);
309f798f1e2SMichael Clark }
310f798f1e2SMichael Clark 
311f798f1e2SMichael Clark #if defined(TARGET_RISCV64)
312f798f1e2SMichael Clark uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
313f798f1e2SMichael Clark {
314f798f1e2SMichael Clark     return float64_to_int64(frs1, &env->fp_status);
315f798f1e2SMichael Clark }
316f798f1e2SMichael Clark 
317f798f1e2SMichael Clark uint64_t helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
318f798f1e2SMichael Clark {
319f798f1e2SMichael Clark     return float64_to_uint64(frs1, &env->fp_status);
320f798f1e2SMichael Clark }
321f798f1e2SMichael Clark #endif
322f798f1e2SMichael Clark 
323f798f1e2SMichael Clark uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
324f798f1e2SMichael Clark {
325f798f1e2SMichael Clark     return int32_to_float64((int32_t)rs1, &env->fp_status);
326f798f1e2SMichael Clark }
327f798f1e2SMichael Clark 
328f798f1e2SMichael Clark uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
329f798f1e2SMichael Clark {
330f798f1e2SMichael Clark     return uint32_to_float64((uint32_t)rs1, &env->fp_status);
331f798f1e2SMichael Clark }
332f798f1e2SMichael Clark 
333f798f1e2SMichael Clark #if defined(TARGET_RISCV64)
334f798f1e2SMichael Clark uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1)
335f798f1e2SMichael Clark {
336f798f1e2SMichael Clark     return int64_to_float64(rs1, &env->fp_status);
337f798f1e2SMichael Clark }
338f798f1e2SMichael Clark 
339f798f1e2SMichael Clark uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1)
340f798f1e2SMichael Clark {
341f798f1e2SMichael Clark     return uint64_to_float64(rs1, &env->fp_status);
342f798f1e2SMichael Clark }
343f798f1e2SMichael Clark #endif
344f798f1e2SMichael Clark 
345f798f1e2SMichael Clark target_ulong helper_fclass_d(uint64_t frs1)
346f798f1e2SMichael Clark {
347121ddbb3SLIU Zhiwei     return fclass_d(frs1);
348f798f1e2SMichael Clark }
349