2 * RISC-V translation routines for the RV64D 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
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_ZDINX_OR_D(ctx) do { \
22 if (!ctx->cfg_ptr->ext_zdinx) { \
23 REQUIRE_EXT(ctx, RVD); \
27 #define REQUIRE_EVEN(ctx, reg) do { \
28 if (ctx->cfg_ptr->ext_zdinx && (get_xl(ctx) == MXL_RV32) && \
34 static bool trans_fld(DisasContext *ctx, arg_fld *a)
39 REQUIRE_EXT(ctx, RVD);
41 addr = get_address(ctx, a->rs1, a->imm);
42 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ);
48 static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
53 REQUIRE_EXT(ctx, RVD);
55 addr = get_address(ctx, a->rs1, a->imm);
56 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ);
60 static bool trans_fmadd_d(DisasContext *ctx, arg_fmadd_d *a)
63 REQUIRE_ZDINX_OR_D(ctx);
64 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
66 TCGv_i64 dest = dest_fpr(ctx, a->rd);
67 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
68 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
69 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
71 gen_set_rm(ctx, a->rm);
72 gen_helper_fmadd_d(dest, cpu_env, src1, src2, src3);
73 gen_set_fpr_d(ctx, a->rd, dest);
78 static bool trans_fmsub_d(DisasContext *ctx, arg_fmsub_d *a)
81 REQUIRE_ZDINX_OR_D(ctx);
82 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
84 TCGv_i64 dest = dest_fpr(ctx, a->rd);
85 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
86 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
87 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
89 gen_set_rm(ctx, a->rm);
90 gen_helper_fmsub_d(dest, cpu_env, src1, src2, src3);
91 gen_set_fpr_d(ctx, a->rd, dest);
96 static bool trans_fnmsub_d(DisasContext *ctx, arg_fnmsub_d *a)
99 REQUIRE_ZDINX_OR_D(ctx);
100 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
102 TCGv_i64 dest = dest_fpr(ctx, a->rd);
103 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
104 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
105 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
107 gen_set_rm(ctx, a->rm);
108 gen_helper_fnmsub_d(dest, cpu_env, src1, src2, src3);
109 gen_set_fpr_d(ctx, a->rd, dest);
114 static bool trans_fnmadd_d(DisasContext *ctx, arg_fnmadd_d *a)
117 REQUIRE_ZDINX_OR_D(ctx);
118 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
120 TCGv_i64 dest = dest_fpr(ctx, a->rd);
121 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
122 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
123 TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
125 gen_set_rm(ctx, a->rm);
126 gen_helper_fnmadd_d(dest, cpu_env, src1, src2, src3);
127 gen_set_fpr_d(ctx, a->rd, dest);
132 static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a)
135 REQUIRE_ZDINX_OR_D(ctx);
136 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
138 TCGv_i64 dest = dest_fpr(ctx, a->rd);
139 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
140 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
142 gen_set_rm(ctx, a->rm);
143 gen_helper_fadd_d(dest, cpu_env, src1, src2);
144 gen_set_fpr_d(ctx, a->rd, dest);
149 static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a)
152 REQUIRE_ZDINX_OR_D(ctx);
153 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
155 TCGv_i64 dest = dest_fpr(ctx, a->rd);
156 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
157 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
159 gen_set_rm(ctx, a->rm);
160 gen_helper_fsub_d(dest, cpu_env, src1, src2);
161 gen_set_fpr_d(ctx, a->rd, dest);
166 static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a)
169 REQUIRE_ZDINX_OR_D(ctx);
170 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
172 TCGv_i64 dest = dest_fpr(ctx, a->rd);
173 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
174 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
176 gen_set_rm(ctx, a->rm);
177 gen_helper_fmul_d(dest, cpu_env, src1, src2);
178 gen_set_fpr_d(ctx, a->rd, dest);
183 static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a)
186 REQUIRE_ZDINX_OR_D(ctx);
187 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
189 TCGv_i64 dest = dest_fpr(ctx, a->rd);
190 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
191 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
193 gen_set_rm(ctx, a->rm);
194 gen_helper_fdiv_d(dest, cpu_env, src1, src2);
195 gen_set_fpr_d(ctx, a->rd, dest);
200 static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a)
203 REQUIRE_ZDINX_OR_D(ctx);
204 REQUIRE_EVEN(ctx, a->rd | a->rs1);
206 TCGv_i64 dest = dest_fpr(ctx, a->rd);
207 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
209 gen_set_rm(ctx, a->rm);
210 gen_helper_fsqrt_d(dest, cpu_env, src1);
211 gen_set_fpr_d(ctx, a->rd, dest);
216 static bool trans_fsgnj_d(DisasContext *ctx, arg_fsgnj_d *a)
219 REQUIRE_ZDINX_OR_D(ctx);
220 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
222 TCGv_i64 dest = dest_fpr(ctx, a->rd);
223 if (a->rs1 == a->rs2) { /* FMOV */
224 dest = get_fpr_d(ctx, a->rs1);
226 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
227 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
228 tcg_gen_deposit_i64(dest, src2, src1, 0, 63);
230 gen_set_fpr_d(ctx, a->rd, dest);
235 static bool trans_fsgnjn_d(DisasContext *ctx, arg_fsgnjn_d *a)
238 REQUIRE_ZDINX_OR_D(ctx);
239 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
241 TCGv_i64 dest = dest_fpr(ctx, a->rd);
242 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
244 if (a->rs1 == a->rs2) { /* FNEG */
245 tcg_gen_xori_i64(dest, src1, INT64_MIN);
247 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
248 TCGv_i64 t0 = tcg_temp_new_i64();
249 tcg_gen_not_i64(t0, src2);
250 tcg_gen_deposit_i64(dest, t0, src1, 0, 63);
251 tcg_temp_free_i64(t0);
253 gen_set_fpr_d(ctx, a->rd, dest);
258 static bool trans_fsgnjx_d(DisasContext *ctx, arg_fsgnjx_d *a)
261 REQUIRE_ZDINX_OR_D(ctx);
262 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
264 TCGv_i64 dest = dest_fpr(ctx, a->rd);
265 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
267 if (a->rs1 == a->rs2) { /* FABS */
268 tcg_gen_andi_i64(dest, src1, ~INT64_MIN);
270 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
271 TCGv_i64 t0 = tcg_temp_new_i64();
272 tcg_gen_andi_i64(t0, src2, INT64_MIN);
273 tcg_gen_xor_i64(dest, src1, t0);
274 tcg_temp_free_i64(t0);
276 gen_set_fpr_d(ctx, a->rd, dest);
281 static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a)
284 REQUIRE_ZDINX_OR_D(ctx);
285 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
287 TCGv_i64 dest = dest_fpr(ctx, a->rd);
288 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
289 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
291 gen_helper_fmin_d(dest, cpu_env, src1, src2);
292 gen_set_fpr_d(ctx, a->rd, dest);
297 static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a)
300 REQUIRE_ZDINX_OR_D(ctx);
301 REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
303 TCGv_i64 dest = dest_fpr(ctx, a->rd);
304 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
305 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
307 gen_helper_fmax_d(dest, cpu_env, src1, src2);
308 gen_set_fpr_d(ctx, a->rd, dest);
313 static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a)
316 REQUIRE_ZDINX_OR_D(ctx);
317 REQUIRE_EVEN(ctx, a->rs1);
319 TCGv_i64 dest = dest_fpr(ctx, a->rd);
320 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
322 gen_set_rm(ctx, a->rm);
323 gen_helper_fcvt_s_d(dest, cpu_env, src1);
324 gen_set_fpr_hs(ctx, a->rd, dest);
329 static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a)
332 REQUIRE_ZDINX_OR_D(ctx);
333 REQUIRE_EVEN(ctx, a->rd);
335 TCGv_i64 dest = dest_fpr(ctx, a->rd);
336 TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
338 gen_set_rm(ctx, a->rm);
339 gen_helper_fcvt_d_s(dest, cpu_env, src1);
340 gen_set_fpr_d(ctx, a->rd, dest);
345 static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a)
348 REQUIRE_ZDINX_OR_D(ctx);
349 REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
351 TCGv dest = dest_gpr(ctx, a->rd);
352 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
353 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
355 gen_helper_feq_d(dest, cpu_env, src1, src2);
356 gen_set_gpr(ctx, a->rd, dest);
360 static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a)
363 REQUIRE_ZDINX_OR_D(ctx);
364 REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
366 TCGv dest = dest_gpr(ctx, a->rd);
367 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
368 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
370 gen_helper_flt_d(dest, cpu_env, src1, src2);
371 gen_set_gpr(ctx, a->rd, dest);
375 static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a)
378 REQUIRE_ZDINX_OR_D(ctx);
379 REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
381 TCGv dest = dest_gpr(ctx, a->rd);
382 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
383 TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
385 gen_helper_fle_d(dest, cpu_env, src1, src2);
386 gen_set_gpr(ctx, a->rd, dest);
390 static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a)
393 REQUIRE_ZDINX_OR_D(ctx);
394 REQUIRE_EVEN(ctx, a->rs1);
396 TCGv dest = dest_gpr(ctx, a->rd);
397 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
399 gen_helper_fclass_d(dest, src1);
400 gen_set_gpr(ctx, a->rd, dest);
404 static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a)
407 REQUIRE_ZDINX_OR_D(ctx);
408 REQUIRE_EVEN(ctx, a->rs1);
410 TCGv dest = dest_gpr(ctx, a->rd);
411 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
413 gen_set_rm(ctx, a->rm);
414 gen_helper_fcvt_w_d(dest, cpu_env, src1);
415 gen_set_gpr(ctx, a->rd, dest);
419 static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a)
422 REQUIRE_ZDINX_OR_D(ctx);
423 REQUIRE_EVEN(ctx, a->rs1);
425 TCGv dest = dest_gpr(ctx, a->rd);
426 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
428 gen_set_rm(ctx, a->rm);
429 gen_helper_fcvt_wu_d(dest, cpu_env, src1);
430 gen_set_gpr(ctx, a->rd, dest);
434 static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a)
437 REQUIRE_ZDINX_OR_D(ctx);
438 REQUIRE_EVEN(ctx, a->rd);
440 TCGv_i64 dest = dest_fpr(ctx, a->rd);
441 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
443 gen_set_rm(ctx, a->rm);
444 gen_helper_fcvt_d_w(dest, cpu_env, src);
445 gen_set_fpr_d(ctx, a->rd, dest);
451 static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a)
454 REQUIRE_ZDINX_OR_D(ctx);
455 REQUIRE_EVEN(ctx, a->rd);
457 TCGv_i64 dest = dest_fpr(ctx, a->rd);
458 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
460 gen_set_rm(ctx, a->rm);
461 gen_helper_fcvt_d_wu(dest, cpu_env, src);
462 gen_set_fpr_d(ctx, a->rd, dest);
468 static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
472 REQUIRE_ZDINX_OR_D(ctx);
473 REQUIRE_EVEN(ctx, a->rs1);
475 TCGv dest = dest_gpr(ctx, a->rd);
476 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
478 gen_set_rm(ctx, a->rm);
479 gen_helper_fcvt_l_d(dest, cpu_env, src1);
480 gen_set_gpr(ctx, a->rd, dest);
484 static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
488 REQUIRE_ZDINX_OR_D(ctx);
489 REQUIRE_EVEN(ctx, a->rs1);
491 TCGv dest = dest_gpr(ctx, a->rd);
492 TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
494 gen_set_rm(ctx, a->rm);
495 gen_helper_fcvt_lu_d(dest, cpu_env, src1);
496 gen_set_gpr(ctx, a->rd, dest);
500 static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a)
504 REQUIRE_EXT(ctx, RVD);
506 #ifdef TARGET_RISCV64
507 gen_set_gpr(ctx, a->rd, cpu_fpr[a->rs1]);
510 qemu_build_not_reached();
514 static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
518 REQUIRE_ZDINX_OR_D(ctx);
519 REQUIRE_EVEN(ctx, a->rd);
521 TCGv_i64 dest = dest_fpr(ctx, a->rd);
522 TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
524 gen_set_rm(ctx, a->rm);
525 gen_helper_fcvt_d_l(dest, cpu_env, src);
526 gen_set_fpr_d(ctx, a->rd, dest);
532 static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
536 REQUIRE_ZDINX_OR_D(ctx);
537 REQUIRE_EVEN(ctx, a->rd);
539 TCGv_i64 dest = dest_fpr(ctx, a->rd);
540 TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
542 gen_set_rm(ctx, a->rm);
543 gen_helper_fcvt_d_lu(dest, cpu_env, src);
544 gen_set_fpr_d(ctx, a->rd, dest);
550 static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
554 REQUIRE_EXT(ctx, RVD);
556 #ifdef TARGET_RISCV64
557 tcg_gen_mov_tl(cpu_fpr[a->rd], get_gpr(ctx, a->rs1, EXT_NONE));
561 qemu_build_not_reached();