hw/display/sm501: Always map the UART0
[qemu/ar7.git] / target / riscv / insn_trans / trans_rvf.inc.c
blob172dbfa919b6392a6c02d6cfcf06c7d6da02f4f6
1 /*
2 * RISC-V translation routines for the RV64F Standard Extension.
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 * Copyright (c) 2018 Peer Adelt, peer.adelt@hni.uni-paderborn.de
6 * Bastian Koppelmann, kbastian@mail.uni-paderborn.de
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2 or later, as published by the Free Software Foundation.
12 * This program is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program. If not, see <http://www.gnu.org/licenses/>.
21 #define REQUIRE_FPU do {\
22 if (ctx->mstatus_fs == 0) \
23 return false; \
24 } while (0)
26 static bool trans_flw(DisasContext *ctx, arg_flw *a)
28 TCGv t0 = tcg_temp_new();
29 gen_get_gpr(t0, a->rs1);
30 REQUIRE_FPU;
31 REQUIRE_EXT(ctx, RVF);
32 tcg_gen_addi_tl(t0, t0, a->imm);
34 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], t0, ctx->mem_idx, MO_TEUL);
35 /* RISC-V requires NaN-boxing of narrower width floating point values */
36 tcg_gen_ori_i64(cpu_fpr[a->rd], cpu_fpr[a->rd], 0xffffffff00000000ULL);
38 tcg_temp_free(t0);
39 mark_fs_dirty(ctx);
40 return true;
43 static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
45 TCGv t0 = tcg_temp_new();
46 gen_get_gpr(t0, a->rs1);
48 REQUIRE_FPU;
49 REQUIRE_EXT(ctx, RVF);
50 tcg_gen_addi_tl(t0, t0, a->imm);
52 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUL);
54 tcg_temp_free(t0);
55 mark_fs_dirty(ctx);
56 return true;
59 static bool trans_fmadd_s(DisasContext *ctx, arg_fmadd_s *a)
61 REQUIRE_FPU;
62 REQUIRE_EXT(ctx, RVF);
63 gen_set_rm(ctx, a->rm);
64 gen_helper_fmadd_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
65 cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
66 mark_fs_dirty(ctx);
67 return true;
70 static bool trans_fmsub_s(DisasContext *ctx, arg_fmsub_s *a)
72 REQUIRE_FPU;
73 REQUIRE_EXT(ctx, RVF);
74 gen_set_rm(ctx, a->rm);
75 gen_helper_fmsub_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
76 cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
77 mark_fs_dirty(ctx);
78 return true;
81 static bool trans_fnmsub_s(DisasContext *ctx, arg_fnmsub_s *a)
83 REQUIRE_FPU;
84 REQUIRE_EXT(ctx, RVF);
85 gen_set_rm(ctx, a->rm);
86 gen_helper_fnmsub_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
87 cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
88 mark_fs_dirty(ctx);
89 return true;
92 static bool trans_fnmadd_s(DisasContext *ctx, arg_fnmadd_s *a)
94 REQUIRE_FPU;
95 REQUIRE_EXT(ctx, RVF);
96 gen_set_rm(ctx, a->rm);
97 gen_helper_fnmadd_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
98 cpu_fpr[a->rs2], cpu_fpr[a->rs3]);
99 mark_fs_dirty(ctx);
100 return true;
103 static bool trans_fadd_s(DisasContext *ctx, arg_fadd_s *a)
105 REQUIRE_FPU;
106 REQUIRE_EXT(ctx, RVF);
108 gen_set_rm(ctx, a->rm);
109 gen_helper_fadd_s(cpu_fpr[a->rd], cpu_env,
110 cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
111 mark_fs_dirty(ctx);
112 return true;
115 static bool trans_fsub_s(DisasContext *ctx, arg_fsub_s *a)
117 REQUIRE_FPU;
118 REQUIRE_EXT(ctx, RVF);
120 gen_set_rm(ctx, a->rm);
121 gen_helper_fsub_s(cpu_fpr[a->rd], cpu_env,
122 cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
123 mark_fs_dirty(ctx);
124 return true;
127 static bool trans_fmul_s(DisasContext *ctx, arg_fmul_s *a)
129 REQUIRE_FPU;
130 REQUIRE_EXT(ctx, RVF);
132 gen_set_rm(ctx, a->rm);
133 gen_helper_fmul_s(cpu_fpr[a->rd], cpu_env,
134 cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
135 mark_fs_dirty(ctx);
136 return true;
139 static bool trans_fdiv_s(DisasContext *ctx, arg_fdiv_s *a)
141 REQUIRE_FPU;
142 REQUIRE_EXT(ctx, RVF);
144 gen_set_rm(ctx, a->rm);
145 gen_helper_fdiv_s(cpu_fpr[a->rd], cpu_env,
146 cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
147 mark_fs_dirty(ctx);
148 return true;
151 static bool trans_fsqrt_s(DisasContext *ctx, arg_fsqrt_s *a)
153 REQUIRE_FPU;
154 REQUIRE_EXT(ctx, RVF);
156 gen_set_rm(ctx, a->rm);
157 gen_helper_fsqrt_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1]);
158 mark_fs_dirty(ctx);
159 return true;
162 static bool trans_fsgnj_s(DisasContext *ctx, arg_fsgnj_s *a)
164 REQUIRE_FPU;
165 REQUIRE_EXT(ctx, RVF);
166 if (a->rs1 == a->rs2) { /* FMOV */
167 tcg_gen_mov_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1]);
168 } else { /* FSGNJ */
169 tcg_gen_deposit_i64(cpu_fpr[a->rd], cpu_fpr[a->rs2], cpu_fpr[a->rs1],
170 0, 31);
172 mark_fs_dirty(ctx);
173 return true;
176 static bool trans_fsgnjn_s(DisasContext *ctx, arg_fsgnjn_s *a)
178 REQUIRE_FPU;
179 REQUIRE_EXT(ctx, RVF);
180 if (a->rs1 == a->rs2) { /* FNEG */
181 tcg_gen_xori_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], INT32_MIN);
182 } else {
183 TCGv_i64 t0 = tcg_temp_new_i64();
184 tcg_gen_not_i64(t0, cpu_fpr[a->rs2]);
185 tcg_gen_deposit_i64(cpu_fpr[a->rd], t0, cpu_fpr[a->rs1], 0, 31);
186 tcg_temp_free_i64(t0);
188 mark_fs_dirty(ctx);
189 return true;
192 static bool trans_fsgnjx_s(DisasContext *ctx, arg_fsgnjx_s *a)
194 REQUIRE_FPU;
195 REQUIRE_EXT(ctx, RVF);
196 if (a->rs1 == a->rs2) { /* FABS */
197 tcg_gen_andi_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], ~INT32_MIN);
198 } else {
199 TCGv_i64 t0 = tcg_temp_new_i64();
200 tcg_gen_andi_i64(t0, cpu_fpr[a->rs2], INT32_MIN);
201 tcg_gen_xor_i64(cpu_fpr[a->rd], cpu_fpr[a->rs1], t0);
202 tcg_temp_free_i64(t0);
204 mark_fs_dirty(ctx);
205 return true;
208 static bool trans_fmin_s(DisasContext *ctx, arg_fmin_s *a)
210 REQUIRE_FPU;
211 REQUIRE_EXT(ctx, RVF);
213 gen_helper_fmin_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
214 cpu_fpr[a->rs2]);
215 mark_fs_dirty(ctx);
216 return true;
219 static bool trans_fmax_s(DisasContext *ctx, arg_fmax_s *a)
221 REQUIRE_FPU;
222 REQUIRE_EXT(ctx, RVF);
224 gen_helper_fmax_s(cpu_fpr[a->rd], cpu_env, cpu_fpr[a->rs1],
225 cpu_fpr[a->rs2]);
226 mark_fs_dirty(ctx);
227 return true;
230 static bool trans_fcvt_w_s(DisasContext *ctx, arg_fcvt_w_s *a)
232 REQUIRE_FPU;
233 REQUIRE_EXT(ctx, RVF);
235 TCGv t0 = tcg_temp_new();
236 gen_set_rm(ctx, a->rm);
237 gen_helper_fcvt_w_s(t0, cpu_env, cpu_fpr[a->rs1]);
238 gen_set_gpr(a->rd, t0);
239 tcg_temp_free(t0);
241 return true;
244 static bool trans_fcvt_wu_s(DisasContext *ctx, arg_fcvt_wu_s *a)
246 REQUIRE_FPU;
247 REQUIRE_EXT(ctx, RVF);
249 TCGv t0 = tcg_temp_new();
250 gen_set_rm(ctx, a->rm);
251 gen_helper_fcvt_wu_s(t0, cpu_env, cpu_fpr[a->rs1]);
252 gen_set_gpr(a->rd, t0);
253 tcg_temp_free(t0);
255 return true;
258 static bool trans_fmv_x_w(DisasContext *ctx, arg_fmv_x_w *a)
260 /* NOTE: This was FMV.X.S in an earlier version of the ISA spec! */
261 REQUIRE_FPU;
262 REQUIRE_EXT(ctx, RVF);
264 TCGv t0 = tcg_temp_new();
266 #if defined(TARGET_RISCV64)
267 tcg_gen_ext32s_tl(t0, cpu_fpr[a->rs1]);
268 #else
269 tcg_gen_extrl_i64_i32(t0, cpu_fpr[a->rs1]);
270 #endif
272 gen_set_gpr(a->rd, t0);
273 tcg_temp_free(t0);
275 return true;
278 static bool trans_feq_s(DisasContext *ctx, arg_feq_s *a)
280 REQUIRE_FPU;
281 REQUIRE_EXT(ctx, RVF);
282 TCGv t0 = tcg_temp_new();
283 gen_helper_feq_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
284 gen_set_gpr(a->rd, t0);
285 tcg_temp_free(t0);
286 return true;
289 static bool trans_flt_s(DisasContext *ctx, arg_flt_s *a)
291 REQUIRE_FPU;
292 REQUIRE_EXT(ctx, RVF);
293 TCGv t0 = tcg_temp_new();
294 gen_helper_flt_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
295 gen_set_gpr(a->rd, t0);
296 tcg_temp_free(t0);
297 return true;
300 static bool trans_fle_s(DisasContext *ctx, arg_fle_s *a)
302 REQUIRE_FPU;
303 REQUIRE_EXT(ctx, RVF);
304 TCGv t0 = tcg_temp_new();
305 gen_helper_fle_s(t0, cpu_env, cpu_fpr[a->rs1], cpu_fpr[a->rs2]);
306 gen_set_gpr(a->rd, t0);
307 tcg_temp_free(t0);
308 return true;
311 static bool trans_fclass_s(DisasContext *ctx, arg_fclass_s *a)
313 REQUIRE_FPU;
314 REQUIRE_EXT(ctx, RVF);
316 TCGv t0 = tcg_temp_new();
318 gen_helper_fclass_s(t0, cpu_fpr[a->rs1]);
320 gen_set_gpr(a->rd, t0);
321 tcg_temp_free(t0);
323 return true;
326 static bool trans_fcvt_s_w(DisasContext *ctx, arg_fcvt_s_w *a)
328 REQUIRE_FPU;
329 REQUIRE_EXT(ctx, RVF);
331 TCGv t0 = tcg_temp_new();
332 gen_get_gpr(t0, a->rs1);
334 gen_set_rm(ctx, a->rm);
335 gen_helper_fcvt_s_w(cpu_fpr[a->rd], cpu_env, t0);
337 mark_fs_dirty(ctx);
338 tcg_temp_free(t0);
340 return true;
343 static bool trans_fcvt_s_wu(DisasContext *ctx, arg_fcvt_s_wu *a)
345 REQUIRE_FPU;
346 REQUIRE_EXT(ctx, RVF);
348 TCGv t0 = tcg_temp_new();
349 gen_get_gpr(t0, a->rs1);
351 gen_set_rm(ctx, a->rm);
352 gen_helper_fcvt_s_wu(cpu_fpr[a->rd], cpu_env, t0);
354 mark_fs_dirty(ctx);
355 tcg_temp_free(t0);
357 return true;
360 static bool trans_fmv_w_x(DisasContext *ctx, arg_fmv_w_x *a)
362 /* NOTE: This was FMV.S.X in an earlier version of the ISA spec! */
363 REQUIRE_FPU;
364 REQUIRE_EXT(ctx, RVF);
366 TCGv t0 = tcg_temp_new();
367 gen_get_gpr(t0, a->rs1);
369 #if defined(TARGET_RISCV64)
370 tcg_gen_mov_i64(cpu_fpr[a->rd], t0);
371 #else
372 tcg_gen_extu_i32_i64(cpu_fpr[a->rd], t0);
373 #endif
375 mark_fs_dirty(ctx);
376 tcg_temp_free(t0);
378 return true;
381 #ifdef TARGET_RISCV64
382 static bool trans_fcvt_l_s(DisasContext *ctx, arg_fcvt_l_s *a)
384 REQUIRE_FPU;
385 REQUIRE_EXT(ctx, RVF);
387 TCGv t0 = tcg_temp_new();
388 gen_set_rm(ctx, a->rm);
389 gen_helper_fcvt_l_s(t0, cpu_env, cpu_fpr[a->rs1]);
390 gen_set_gpr(a->rd, t0);
391 tcg_temp_free(t0);
392 return true;
395 static bool trans_fcvt_lu_s(DisasContext *ctx, arg_fcvt_lu_s *a)
397 REQUIRE_FPU;
398 REQUIRE_EXT(ctx, RVF);
400 TCGv t0 = tcg_temp_new();
401 gen_set_rm(ctx, a->rm);
402 gen_helper_fcvt_lu_s(t0, cpu_env, cpu_fpr[a->rs1]);
403 gen_set_gpr(a->rd, t0);
404 tcg_temp_free(t0);
405 return true;
408 static bool trans_fcvt_s_l(DisasContext *ctx, arg_fcvt_s_l *a)
410 REQUIRE_FPU;
411 REQUIRE_EXT(ctx, RVF);
413 TCGv t0 = tcg_temp_new();
414 gen_get_gpr(t0, a->rs1);
416 gen_set_rm(ctx, a->rm);
417 gen_helper_fcvt_s_l(cpu_fpr[a->rd], cpu_env, t0);
419 mark_fs_dirty(ctx);
420 tcg_temp_free(t0);
421 return true;
424 static bool trans_fcvt_s_lu(DisasContext *ctx, arg_fcvt_s_lu *a)
426 REQUIRE_FPU;
427 REQUIRE_EXT(ctx, RVF);
429 TCGv t0 = tcg_temp_new();
430 gen_get_gpr(t0, a->rs1);
432 gen_set_rm(ctx, a->rm);
433 gen_helper_fcvt_s_lu(cpu_fpr[a->rd], cpu_env, t0);
435 mark_fs_dirty(ctx);
436 tcg_temp_free(t0);
437 return true;
439 #endif