target/riscv: rvv: Add mask agnostic for vector mask instructions
[qemu.git] / target / riscv / insn_trans / trans_rvd.c.inc
blob1397c1ce1c8ae9053300408755d486db0edf6305
1 /*
2  * RISC-V translation routines for the RV64D Standard Extension.
3  *
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
7  *
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.
11  *
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.
16  *
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/>.
19  */
21 #define REQUIRE_ZDINX_OR_D(ctx) do { \
22     if (!ctx->cfg_ptr->ext_zdinx) { \
23         REQUIRE_EXT(ctx, RVD); \
24     } \
25 } while (0)
27 #define REQUIRE_EVEN(ctx, reg) do { \
28     if (ctx->cfg_ptr->ext_zdinx && (get_xl(ctx) == MXL_RV32) && \
29         ((reg) & 0x1)) { \
30         return false; \
31     } \
32 } while (0)
34 static bool trans_fld(DisasContext *ctx, arg_fld *a)
36     TCGv addr;
38     REQUIRE_FPU;
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);
44     mark_fs_dirty(ctx);
45     return true;
48 static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
50     TCGv addr;
52     REQUIRE_FPU;
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);
57     return true;
60 static bool trans_fmadd_d(DisasContext *ctx, arg_fmadd_d *a)
62     REQUIRE_FPU;
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);
74     mark_fs_dirty(ctx);
75     return true;
78 static bool trans_fmsub_d(DisasContext *ctx, arg_fmsub_d *a)
80     REQUIRE_FPU;
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);
92     mark_fs_dirty(ctx);
93     return true;
96 static bool trans_fnmsub_d(DisasContext *ctx, arg_fnmsub_d *a)
98     REQUIRE_FPU;
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);
110     mark_fs_dirty(ctx);
111     return true;
114 static bool trans_fnmadd_d(DisasContext *ctx, arg_fnmadd_d *a)
116     REQUIRE_FPU;
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);
128     mark_fs_dirty(ctx);
129     return true;
132 static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a)
134     REQUIRE_FPU;
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);
145     mark_fs_dirty(ctx);
146     return true;
149 static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a)
151     REQUIRE_FPU;
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);
162     mark_fs_dirty(ctx);
163     return true;
166 static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a)
168     REQUIRE_FPU;
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);
179     mark_fs_dirty(ctx);
180     return true;
183 static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a)
185     REQUIRE_FPU;
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);
196     mark_fs_dirty(ctx);
197     return true;
200 static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a)
202     REQUIRE_FPU;
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);
212     mark_fs_dirty(ctx);
213     return true;
216 static bool trans_fsgnj_d(DisasContext *ctx, arg_fsgnj_d *a)
218     REQUIRE_FPU;
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);
225     } else {
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);
229     }
230     gen_set_fpr_d(ctx, a->rd, dest);
231     mark_fs_dirty(ctx);
232     return true;
235 static bool trans_fsgnjn_d(DisasContext *ctx, arg_fsgnjn_d *a)
237     REQUIRE_FPU;
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);
246     } else {
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);
252     }
253     gen_set_fpr_d(ctx, a->rd, dest);
254     mark_fs_dirty(ctx);
255     return true;
258 static bool trans_fsgnjx_d(DisasContext *ctx, arg_fsgnjx_d *a)
260     REQUIRE_FPU;
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);
269     } else {
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);
275     }
276     gen_set_fpr_d(ctx, a->rd, dest);
277     mark_fs_dirty(ctx);
278     return true;
281 static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a)
283     REQUIRE_FPU;
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);
293     mark_fs_dirty(ctx);
294     return true;
297 static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a)
299     REQUIRE_FPU;
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);
309     mark_fs_dirty(ctx);
310     return true;
313 static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a)
315     REQUIRE_FPU;
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);
325     mark_fs_dirty(ctx);
326     return true;
329 static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a)
331     REQUIRE_FPU;
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);
341     mark_fs_dirty(ctx);
342     return true;
345 static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a)
347     REQUIRE_FPU;
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);
357     return true;
360 static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a)
362     REQUIRE_FPU;
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);
372     return true;
375 static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a)
377     REQUIRE_FPU;
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);
387     return true;
390 static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a)
392     REQUIRE_FPU;
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);
401     return true;
404 static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a)
406     REQUIRE_FPU;
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);
416     return true;
419 static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a)
421     REQUIRE_FPU;
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);
431     return true;
434 static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a)
436     REQUIRE_FPU;
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);
447     mark_fs_dirty(ctx);
448     return true;
451 static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a)
453     REQUIRE_FPU;
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);
464     mark_fs_dirty(ctx);
465     return true;
468 static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
470     REQUIRE_64BIT(ctx);
471     REQUIRE_FPU;
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);
481     return true;
484 static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
486     REQUIRE_64BIT(ctx);
487     REQUIRE_FPU;
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);
497     return true;
500 static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a)
502     REQUIRE_64BIT(ctx);
503     REQUIRE_FPU;
504     REQUIRE_EXT(ctx, RVD);
506 #ifdef TARGET_RISCV64
507     gen_set_gpr(ctx, a->rd, cpu_fpr[a->rs1]);
508     return true;
509 #else
510     qemu_build_not_reached();
511 #endif
514 static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
516     REQUIRE_64BIT(ctx);
517     REQUIRE_FPU;
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);
528     mark_fs_dirty(ctx);
529     return true;
532 static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
534     REQUIRE_64BIT(ctx);
535     REQUIRE_FPU;
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);
546     mark_fs_dirty(ctx);
547     return true;
550 static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
552     REQUIRE_64BIT(ctx);
553     REQUIRE_FPU;
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));
558     mark_fs_dirty(ctx);
559     return true;
560 #else
561     qemu_build_not_reached();
562 #endif