]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/fpu_helper.c
Merge remote-tracking branch 'remotes/armbru/tags/pull-monitor-2019-07-02-v2' into...
[mirror_qemu.git] / target / riscv / fpu_helper.c
CommitLineData
f798f1e2
MC
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"
f798f1e2
MC
20#include "cpu.h"
21#include "qemu/host-utils.h"
22#include "exec/exec-all.h"
23#include "exec/helper-proto.h"
24
fb738839 25target_ulong riscv_cpu_get_fflags(CPURISCVState *env)
f798f1e2
MC
26{
27 int soft = get_float_exception_flags(&env->fp_status);
28 target_ulong hard = 0;
29
30 hard |= (soft & float_flag_inexact) ? FPEXC_NX : 0;
31 hard |= (soft & float_flag_underflow) ? FPEXC_UF : 0;
32 hard |= (soft & float_flag_overflow) ? FPEXC_OF : 0;
33 hard |= (soft & float_flag_divbyzero) ? FPEXC_DZ : 0;
34 hard |= (soft & float_flag_invalid) ? FPEXC_NV : 0;
35
36 return hard;
37}
38
fb738839 39void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong hard)
f798f1e2
MC
40{
41 int soft = 0;
42
43 soft |= (hard & FPEXC_NX) ? float_flag_inexact : 0;
44 soft |= (hard & FPEXC_UF) ? float_flag_underflow : 0;
45 soft |= (hard & FPEXC_OF) ? float_flag_overflow : 0;
46 soft |= (hard & FPEXC_DZ) ? float_flag_divbyzero : 0;
47 soft |= (hard & FPEXC_NV) ? float_flag_invalid : 0;
48
49 set_float_exception_flags(soft, &env->fp_status);
50}
51
52void helper_set_rounding_mode(CPURISCVState *env, uint32_t rm)
53{
54 int softrm;
55
56 if (rm == 7) {
57 rm = env->frm;
58 }
59 switch (rm) {
60 case 0:
61 softrm = float_round_nearest_even;
62 break;
63 case 1:
64 softrm = float_round_to_zero;
65 break;
66 case 2:
67 softrm = float_round_down;
68 break;
69 case 3:
70 softrm = float_round_up;
71 break;
72 case 4:
73 softrm = float_round_ties_away;
74 break;
75 default:
fb738839 76 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
f798f1e2
MC
77 }
78
79 set_float_rounding_mode(softrm, &env->fp_status);
80}
81
82uint64_t helper_fmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
83 uint64_t frs3)
84{
85 return float32_muladd(frs1, frs2, frs3, 0, &env->fp_status);
86}
87
88uint64_t helper_fmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
89 uint64_t frs3)
90{
91 return float64_muladd(frs1, frs2, frs3, 0, &env->fp_status);
92}
93
94uint64_t helper_fmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
95 uint64_t frs3)
96{
97 return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c,
98 &env->fp_status);
99}
100
101uint64_t helper_fmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
102 uint64_t frs3)
103{
104 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c,
105 &env->fp_status);
106}
107
108uint64_t helper_fnmsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
109 uint64_t frs3)
110{
111 return float32_muladd(frs1, frs2, frs3, float_muladd_negate_product,
112 &env->fp_status);
113}
114
115uint64_t helper_fnmsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
116 uint64_t frs3)
117{
118 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_product,
119 &env->fp_status);
120}
121
122uint64_t helper_fnmadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
123 uint64_t frs3)
124{
125 return float32_muladd(frs1, frs2, frs3, float_muladd_negate_c |
126 float_muladd_negate_product, &env->fp_status);
127}
128
129uint64_t helper_fnmadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2,
130 uint64_t frs3)
131{
132 return float64_muladd(frs1, frs2, frs3, float_muladd_negate_c |
133 float_muladd_negate_product, &env->fp_status);
134}
135
136uint64_t helper_fadd_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
137{
138 return float32_add(frs1, frs2, &env->fp_status);
139}
140
141uint64_t helper_fsub_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
142{
143 return float32_sub(frs1, frs2, &env->fp_status);
144}
145
146uint64_t helper_fmul_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
147{
148 return float32_mul(frs1, frs2, &env->fp_status);
149}
150
151uint64_t helper_fdiv_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
152{
153 return float32_div(frs1, frs2, &env->fp_status);
154}
155
156uint64_t helper_fmin_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
157{
158 return float32_minnum(frs1, frs2, &env->fp_status);
159}
160
161uint64_t helper_fmax_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
162{
163 return float32_maxnum(frs1, frs2, &env->fp_status);
164}
165
166uint64_t helper_fsqrt_s(CPURISCVState *env, uint64_t frs1)
167{
168 return float32_sqrt(frs1, &env->fp_status);
169}
170
171target_ulong helper_fle_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
172{
173 return float32_le(frs1, frs2, &env->fp_status);
174}
175
176target_ulong helper_flt_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
177{
178 return float32_lt(frs1, frs2, &env->fp_status);
179}
180
181target_ulong helper_feq_s(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
182{
183 return float32_eq_quiet(frs1, frs2, &env->fp_status);
184}
185
186target_ulong helper_fcvt_w_s(CPURISCVState *env, uint64_t frs1)
187{
188 return float32_to_int32(frs1, &env->fp_status);
189}
190
191target_ulong helper_fcvt_wu_s(CPURISCVState *env, uint64_t frs1)
192{
193 return (int32_t)float32_to_uint32(frs1, &env->fp_status);
194}
195
196#if defined(TARGET_RISCV64)
197uint64_t helper_fcvt_l_s(CPURISCVState *env, uint64_t frs1)
198{
199 return float32_to_int64(frs1, &env->fp_status);
200}
201
202uint64_t helper_fcvt_lu_s(CPURISCVState *env, uint64_t frs1)
203{
204 return float32_to_uint64(frs1, &env->fp_status);
205}
206#endif
207
208uint64_t helper_fcvt_s_w(CPURISCVState *env, target_ulong rs1)
209{
210 return int32_to_float32((int32_t)rs1, &env->fp_status);
211}
212
213uint64_t helper_fcvt_s_wu(CPURISCVState *env, target_ulong rs1)
214{
215 return uint32_to_float32((uint32_t)rs1, &env->fp_status);
216}
217
218#if defined(TARGET_RISCV64)
219uint64_t helper_fcvt_s_l(CPURISCVState *env, uint64_t rs1)
220{
221 return int64_to_float32(rs1, &env->fp_status);
222}
223
224uint64_t helper_fcvt_s_lu(CPURISCVState *env, uint64_t rs1)
225{
226 return uint64_to_float32(rs1, &env->fp_status);
227}
228#endif
229
230target_ulong helper_fclass_s(uint64_t frs1)
231{
232 float32 f = frs1;
233 bool sign = float32_is_neg(f);
234
235 if (float32_is_infinity(f)) {
236 return sign ? 1 << 0 : 1 << 7;
237 } else if (float32_is_zero(f)) {
238 return sign ? 1 << 3 : 1 << 4;
239 } else if (float32_is_zero_or_denormal(f)) {
240 return sign ? 1 << 2 : 1 << 5;
241 } else if (float32_is_any_nan(f)) {
242 float_status s = { }; /* for snan_bit_is_one */
243 return float32_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
244 } else {
245 return sign ? 1 << 1 : 1 << 6;
246 }
247}
248
249uint64_t helper_fadd_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
250{
251 return float64_add(frs1, frs2, &env->fp_status);
252}
253
254uint64_t helper_fsub_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
255{
256 return float64_sub(frs1, frs2, &env->fp_status);
257}
258
259uint64_t helper_fmul_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
260{
261 return float64_mul(frs1, frs2, &env->fp_status);
262}
263
264uint64_t helper_fdiv_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
265{
266 return float64_div(frs1, frs2, &env->fp_status);
267}
268
269uint64_t helper_fmin_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
270{
271 return float64_minnum(frs1, frs2, &env->fp_status);
272}
273
274uint64_t helper_fmax_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
275{
276 return float64_maxnum(frs1, frs2, &env->fp_status);
277}
278
279uint64_t helper_fcvt_s_d(CPURISCVState *env, uint64_t rs1)
280{
cab32112 281 return float64_to_float32(rs1, &env->fp_status);
f798f1e2
MC
282}
283
284uint64_t helper_fcvt_d_s(CPURISCVState *env, uint64_t rs1)
285{
cab32112 286 return float32_to_float64(rs1, &env->fp_status);
f798f1e2
MC
287}
288
289uint64_t helper_fsqrt_d(CPURISCVState *env, uint64_t frs1)
290{
291 return float64_sqrt(frs1, &env->fp_status);
292}
293
294target_ulong helper_fle_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
295{
296 return float64_le(frs1, frs2, &env->fp_status);
297}
298
299target_ulong helper_flt_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
300{
301 return float64_lt(frs1, frs2, &env->fp_status);
302}
303
304target_ulong helper_feq_d(CPURISCVState *env, uint64_t frs1, uint64_t frs2)
305{
306 return float64_eq_quiet(frs1, frs2, &env->fp_status);
307}
308
309target_ulong helper_fcvt_w_d(CPURISCVState *env, uint64_t frs1)
310{
311 return float64_to_int32(frs1, &env->fp_status);
312}
313
314target_ulong helper_fcvt_wu_d(CPURISCVState *env, uint64_t frs1)
315{
316 return (int32_t)float64_to_uint32(frs1, &env->fp_status);
317}
318
319#if defined(TARGET_RISCV64)
320uint64_t helper_fcvt_l_d(CPURISCVState *env, uint64_t frs1)
321{
322 return float64_to_int64(frs1, &env->fp_status);
323}
324
325uint64_t helper_fcvt_lu_d(CPURISCVState *env, uint64_t frs1)
326{
327 return float64_to_uint64(frs1, &env->fp_status);
328}
329#endif
330
331uint64_t helper_fcvt_d_w(CPURISCVState *env, target_ulong rs1)
332{
333 return int32_to_float64((int32_t)rs1, &env->fp_status);
334}
335
336uint64_t helper_fcvt_d_wu(CPURISCVState *env, target_ulong rs1)
337{
338 return uint32_to_float64((uint32_t)rs1, &env->fp_status);
339}
340
341#if defined(TARGET_RISCV64)
342uint64_t helper_fcvt_d_l(CPURISCVState *env, uint64_t rs1)
343{
344 return int64_to_float64(rs1, &env->fp_status);
345}
346
347uint64_t helper_fcvt_d_lu(CPURISCVState *env, uint64_t rs1)
348{
349 return uint64_to_float64(rs1, &env->fp_status);
350}
351#endif
352
353target_ulong helper_fclass_d(uint64_t frs1)
354{
355 float64 f = frs1;
356 bool sign = float64_is_neg(f);
357
358 if (float64_is_infinity(f)) {
359 return sign ? 1 << 0 : 1 << 7;
360 } else if (float64_is_zero(f)) {
361 return sign ? 1 << 3 : 1 << 4;
362 } else if (float64_is_zero_or_denormal(f)) {
363 return sign ? 1 << 2 : 1 << 5;
364 } else if (float64_is_any_nan(f)) {
365 float_status s = { }; /* for snan_bit_is_one */
366 return float64_is_quiet_nan(f, &s) ? 1 << 9 : 1 << 8;
367 } else {
368 return sign ? 1 << 1 : 1 << 6;
369 }
370}