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 */
20
21#define REQUIRE_ZDINX_OR_D(ctx) do { \
22    if (!ctx->cfg_ptr->ext_zdinx) { \
23        REQUIRE_EXT(ctx, RVD); \
24    } \
25} while (0)
26
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)
33
34#define REQUIRE_ZCD_OR_DC(ctx) do { \
35    if (!ctx->cfg_ptr->ext_zcd) { \
36        if (!has_ext(ctx, RVD) || !has_ext(ctx, RVC)) { \
37            return false; \
38        } \
39    } \
40} while (0)
41
42static bool trans_fld(DisasContext *ctx, arg_fld *a)
43{
44    TCGv addr;
45    MemOp memop = MO_TEUQ;
46
47    REQUIRE_FPU;
48    REQUIRE_EXT(ctx, RVD);
49
50    if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) {
51        memop |= MO_ATOM_WITHIN16;
52    }
53
54    decode_save_opc(ctx);
55    addr = get_address(ctx, a->rs1, a->imm);
56    tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, memop);
57
58    mark_fs_dirty(ctx);
59    return true;
60}
61
62static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
63{
64    TCGv addr;
65    MemOp memop = MO_TEUQ;
66
67    REQUIRE_FPU;
68    REQUIRE_EXT(ctx, RVD);
69
70    if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) {
71        memop |= MO_ATOM_WITHIN16;
72    }
73
74    decode_save_opc(ctx);
75    addr = get_address(ctx, a->rs1, a->imm);
76    tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, memop);
77    return true;
78}
79
80static bool trans_c_fld(DisasContext *ctx, arg_fld *a)
81{
82    REQUIRE_ZCD_OR_DC(ctx);
83    return trans_fld(ctx, a);
84}
85
86static bool trans_c_fsd(DisasContext *ctx, arg_fsd *a)
87{
88    REQUIRE_ZCD_OR_DC(ctx);
89    return trans_fsd(ctx, a);
90}
91
92static bool trans_fmadd_d(DisasContext *ctx, arg_fmadd_d *a)
93{
94    REQUIRE_FPU;
95    REQUIRE_ZDINX_OR_D(ctx);
96    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
97
98    TCGv_i64 dest = dest_fpr(ctx, a->rd);
99    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
100    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
101    TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
102
103    gen_set_rm(ctx, a->rm);
104    gen_helper_fmadd_d(dest, tcg_env, src1, src2, src3);
105    gen_set_fpr_d(ctx, a->rd, dest);
106    mark_fs_dirty(ctx);
107    return true;
108}
109
110static bool trans_fmsub_d(DisasContext *ctx, arg_fmsub_d *a)
111{
112    REQUIRE_FPU;
113    REQUIRE_ZDINX_OR_D(ctx);
114    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
115
116    TCGv_i64 dest = dest_fpr(ctx, a->rd);
117    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
118    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
119    TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
120
121    gen_set_rm(ctx, a->rm);
122    gen_helper_fmsub_d(dest, tcg_env, src1, src2, src3);
123    gen_set_fpr_d(ctx, a->rd, dest);
124    mark_fs_dirty(ctx);
125    return true;
126}
127
128static bool trans_fnmsub_d(DisasContext *ctx, arg_fnmsub_d *a)
129{
130    REQUIRE_FPU;
131    REQUIRE_ZDINX_OR_D(ctx);
132    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
133
134    TCGv_i64 dest = dest_fpr(ctx, a->rd);
135    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
136    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
137    TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
138
139    gen_set_rm(ctx, a->rm);
140    gen_helper_fnmsub_d(dest, tcg_env, src1, src2, src3);
141    gen_set_fpr_d(ctx, a->rd, dest);
142    mark_fs_dirty(ctx);
143    return true;
144}
145
146static bool trans_fnmadd_d(DisasContext *ctx, arg_fnmadd_d *a)
147{
148    REQUIRE_FPU;
149    REQUIRE_ZDINX_OR_D(ctx);
150    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2 | a->rs3);
151
152    TCGv_i64 dest = dest_fpr(ctx, a->rd);
153    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
154    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
155    TCGv_i64 src3 = get_fpr_d(ctx, a->rs3);
156
157    gen_set_rm(ctx, a->rm);
158    gen_helper_fnmadd_d(dest, tcg_env, src1, src2, src3);
159    gen_set_fpr_d(ctx, a->rd, dest);
160    mark_fs_dirty(ctx);
161    return true;
162}
163
164static bool trans_fadd_d(DisasContext *ctx, arg_fadd_d *a)
165{
166    REQUIRE_FPU;
167    REQUIRE_ZDINX_OR_D(ctx);
168    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
169
170    TCGv_i64 dest = dest_fpr(ctx, a->rd);
171    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
172    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
173
174    gen_set_rm(ctx, a->rm);
175    gen_helper_fadd_d(dest, tcg_env, src1, src2);
176    gen_set_fpr_d(ctx, a->rd, dest);
177    mark_fs_dirty(ctx);
178    return true;
179}
180
181static bool trans_fsub_d(DisasContext *ctx, arg_fsub_d *a)
182{
183    REQUIRE_FPU;
184    REQUIRE_ZDINX_OR_D(ctx);
185    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
186
187    TCGv_i64 dest = dest_fpr(ctx, a->rd);
188    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
189    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
190
191    gen_set_rm(ctx, a->rm);
192    gen_helper_fsub_d(dest, tcg_env, src1, src2);
193    gen_set_fpr_d(ctx, a->rd, dest);
194    mark_fs_dirty(ctx);
195    return true;
196}
197
198static bool trans_fmul_d(DisasContext *ctx, arg_fmul_d *a)
199{
200    REQUIRE_FPU;
201    REQUIRE_ZDINX_OR_D(ctx);
202    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
203
204    TCGv_i64 dest = dest_fpr(ctx, a->rd);
205    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
206    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
207
208    gen_set_rm(ctx, a->rm);
209    gen_helper_fmul_d(dest, tcg_env, src1, src2);
210    gen_set_fpr_d(ctx, a->rd, dest);
211    mark_fs_dirty(ctx);
212    return true;
213}
214
215static bool trans_fdiv_d(DisasContext *ctx, arg_fdiv_d *a)
216{
217    REQUIRE_FPU;
218    REQUIRE_ZDINX_OR_D(ctx);
219    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
220
221    TCGv_i64 dest = dest_fpr(ctx, a->rd);
222    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
223    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
224
225    gen_set_rm(ctx, a->rm);
226    gen_helper_fdiv_d(dest, tcg_env, src1, src2);
227    gen_set_fpr_d(ctx, a->rd, dest);
228    mark_fs_dirty(ctx);
229    return true;
230}
231
232static bool trans_fsqrt_d(DisasContext *ctx, arg_fsqrt_d *a)
233{
234    REQUIRE_FPU;
235    REQUIRE_ZDINX_OR_D(ctx);
236    REQUIRE_EVEN(ctx, a->rd | a->rs1);
237
238    TCGv_i64 dest = dest_fpr(ctx, a->rd);
239    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
240
241    gen_set_rm(ctx, a->rm);
242    gen_helper_fsqrt_d(dest, tcg_env, src1);
243    gen_set_fpr_d(ctx, a->rd, dest);
244    mark_fs_dirty(ctx);
245    return true;
246}
247
248static bool trans_fsgnj_d(DisasContext *ctx, arg_fsgnj_d *a)
249{
250    REQUIRE_FPU;
251    REQUIRE_ZDINX_OR_D(ctx);
252    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
253
254    TCGv_i64 dest = dest_fpr(ctx, a->rd);
255    if (a->rs1 == a->rs2) { /* FMOV */
256        dest = get_fpr_d(ctx, a->rs1);
257    } else {
258        TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
259        TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
260        tcg_gen_deposit_i64(dest, src2, src1, 0, 63);
261    }
262    gen_set_fpr_d(ctx, a->rd, dest);
263    mark_fs_dirty(ctx);
264    return true;
265}
266
267static bool trans_fsgnjn_d(DisasContext *ctx, arg_fsgnjn_d *a)
268{
269    REQUIRE_FPU;
270    REQUIRE_ZDINX_OR_D(ctx);
271    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
272
273    TCGv_i64 dest = dest_fpr(ctx, a->rd);
274    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
275
276    if (a->rs1 == a->rs2) { /* FNEG */
277        tcg_gen_xori_i64(dest, src1, INT64_MIN);
278    } else {
279        TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
280        TCGv_i64 t0 = tcg_temp_new_i64();
281        tcg_gen_not_i64(t0, src2);
282        tcg_gen_deposit_i64(dest, t0, src1, 0, 63);
283    }
284    gen_set_fpr_d(ctx, a->rd, dest);
285    mark_fs_dirty(ctx);
286    return true;
287}
288
289static bool trans_fsgnjx_d(DisasContext *ctx, arg_fsgnjx_d *a)
290{
291    REQUIRE_FPU;
292    REQUIRE_ZDINX_OR_D(ctx);
293    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
294
295    TCGv_i64 dest = dest_fpr(ctx, a->rd);
296    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
297
298    if (a->rs1 == a->rs2) { /* FABS */
299        tcg_gen_andi_i64(dest, src1, ~INT64_MIN);
300    } else {
301        TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
302        TCGv_i64 t0 = tcg_temp_new_i64();
303        tcg_gen_andi_i64(t0, src2, INT64_MIN);
304        tcg_gen_xor_i64(dest, src1, t0);
305    }
306    gen_set_fpr_d(ctx, a->rd, dest);
307    mark_fs_dirty(ctx);
308    return true;
309}
310
311static bool trans_fmin_d(DisasContext *ctx, arg_fmin_d *a)
312{
313    REQUIRE_FPU;
314    REQUIRE_ZDINX_OR_D(ctx);
315    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
316
317    TCGv_i64 dest = dest_fpr(ctx, a->rd);
318    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
319    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
320
321    gen_helper_fmin_d(dest, tcg_env, src1, src2);
322    gen_set_fpr_d(ctx, a->rd, dest);
323    mark_fs_dirty(ctx);
324    return true;
325}
326
327static bool trans_fmax_d(DisasContext *ctx, arg_fmax_d *a)
328{
329    REQUIRE_FPU;
330    REQUIRE_ZDINX_OR_D(ctx);
331    REQUIRE_EVEN(ctx, a->rd | a->rs1 | a->rs2);
332
333    TCGv_i64 dest = dest_fpr(ctx, a->rd);
334    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
335    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
336
337    gen_helper_fmax_d(dest, tcg_env, src1, src2);
338    gen_set_fpr_d(ctx, a->rd, dest);
339    mark_fs_dirty(ctx);
340    return true;
341}
342
343static bool trans_fcvt_s_d(DisasContext *ctx, arg_fcvt_s_d *a)
344{
345    REQUIRE_FPU;
346    REQUIRE_ZDINX_OR_D(ctx);
347    REQUIRE_EVEN(ctx, a->rs1);
348
349    TCGv_i64 dest = dest_fpr(ctx, a->rd);
350    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
351
352    gen_set_rm(ctx, a->rm);
353    gen_helper_fcvt_s_d(dest, tcg_env, src1);
354    gen_set_fpr_hs(ctx, a->rd, dest);
355    mark_fs_dirty(ctx);
356    return true;
357}
358
359static bool trans_fcvt_d_s(DisasContext *ctx, arg_fcvt_d_s *a)
360{
361    REQUIRE_FPU;
362    REQUIRE_ZDINX_OR_D(ctx);
363    REQUIRE_EVEN(ctx, a->rd);
364
365    TCGv_i64 dest = dest_fpr(ctx, a->rd);
366    TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
367
368    gen_set_rm(ctx, a->rm);
369    gen_helper_fcvt_d_s(dest, tcg_env, src1);
370    gen_set_fpr_d(ctx, a->rd, dest);
371    mark_fs_dirty(ctx);
372    return true;
373}
374
375static bool trans_feq_d(DisasContext *ctx, arg_feq_d *a)
376{
377    REQUIRE_FPU;
378    REQUIRE_ZDINX_OR_D(ctx);
379    REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
380
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);
384
385    gen_helper_feq_d(dest, tcg_env, src1, src2);
386    gen_set_gpr(ctx, a->rd, dest);
387    return true;
388}
389
390static bool trans_flt_d(DisasContext *ctx, arg_flt_d *a)
391{
392    REQUIRE_FPU;
393    REQUIRE_ZDINX_OR_D(ctx);
394    REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
395
396    TCGv dest = dest_gpr(ctx, a->rd);
397    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
398    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
399
400    gen_helper_flt_d(dest, tcg_env, src1, src2);
401    gen_set_gpr(ctx, a->rd, dest);
402    return true;
403}
404
405static bool trans_fle_d(DisasContext *ctx, arg_fle_d *a)
406{
407    REQUIRE_FPU;
408    REQUIRE_ZDINX_OR_D(ctx);
409    REQUIRE_EVEN(ctx, a->rs1 | a->rs2);
410
411    TCGv dest = dest_gpr(ctx, a->rd);
412    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
413    TCGv_i64 src2 = get_fpr_d(ctx, a->rs2);
414
415    gen_helper_fle_d(dest, tcg_env, src1, src2);
416    gen_set_gpr(ctx, a->rd, dest);
417    return true;
418}
419
420static bool trans_fclass_d(DisasContext *ctx, arg_fclass_d *a)
421{
422    REQUIRE_FPU;
423    REQUIRE_ZDINX_OR_D(ctx);
424    REQUIRE_EVEN(ctx, a->rs1);
425
426    TCGv dest = dest_gpr(ctx, a->rd);
427    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
428
429    gen_helper_fclass_d(dest, src1);
430    gen_set_gpr(ctx, a->rd, dest);
431    return true;
432}
433
434static bool trans_fcvt_w_d(DisasContext *ctx, arg_fcvt_w_d *a)
435{
436    REQUIRE_FPU;
437    REQUIRE_ZDINX_OR_D(ctx);
438    REQUIRE_EVEN(ctx, a->rs1);
439
440    TCGv dest = dest_gpr(ctx, a->rd);
441    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
442
443    gen_set_rm(ctx, a->rm);
444    gen_helper_fcvt_w_d(dest, tcg_env, src1);
445    gen_set_gpr(ctx, a->rd, dest);
446    return true;
447}
448
449static bool trans_fcvt_wu_d(DisasContext *ctx, arg_fcvt_wu_d *a)
450{
451    REQUIRE_FPU;
452    REQUIRE_ZDINX_OR_D(ctx);
453    REQUIRE_EVEN(ctx, a->rs1);
454
455    TCGv dest = dest_gpr(ctx, a->rd);
456    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
457
458    gen_set_rm(ctx, a->rm);
459    gen_helper_fcvt_wu_d(dest, tcg_env, src1);
460    gen_set_gpr(ctx, a->rd, dest);
461    return true;
462}
463
464static bool trans_fcvt_d_w(DisasContext *ctx, arg_fcvt_d_w *a)
465{
466    REQUIRE_FPU;
467    REQUIRE_ZDINX_OR_D(ctx);
468    REQUIRE_EVEN(ctx, a->rd);
469
470    TCGv_i64 dest = dest_fpr(ctx, a->rd);
471    TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
472
473    gen_set_rm(ctx, a->rm);
474    gen_helper_fcvt_d_w(dest, tcg_env, src);
475    gen_set_fpr_d(ctx, a->rd, dest);
476
477    mark_fs_dirty(ctx);
478    return true;
479}
480
481static bool trans_fcvt_d_wu(DisasContext *ctx, arg_fcvt_d_wu *a)
482{
483    REQUIRE_FPU;
484    REQUIRE_ZDINX_OR_D(ctx);
485    REQUIRE_EVEN(ctx, a->rd);
486
487    TCGv_i64 dest = dest_fpr(ctx, a->rd);
488    TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
489
490    gen_set_rm(ctx, a->rm);
491    gen_helper_fcvt_d_wu(dest, tcg_env, src);
492    gen_set_fpr_d(ctx, a->rd, dest);
493
494    mark_fs_dirty(ctx);
495    return true;
496}
497
498static bool trans_fcvt_l_d(DisasContext *ctx, arg_fcvt_l_d *a)
499{
500    REQUIRE_64BIT(ctx);
501    REQUIRE_FPU;
502    REQUIRE_ZDINX_OR_D(ctx);
503    REQUIRE_EVEN(ctx, a->rs1);
504
505    TCGv dest = dest_gpr(ctx, a->rd);
506    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
507
508    gen_set_rm(ctx, a->rm);
509    gen_helper_fcvt_l_d(dest, tcg_env, src1);
510    gen_set_gpr(ctx, a->rd, dest);
511    return true;
512}
513
514static bool trans_fcvt_lu_d(DisasContext *ctx, arg_fcvt_lu_d *a)
515{
516    REQUIRE_64BIT(ctx);
517    REQUIRE_FPU;
518    REQUIRE_ZDINX_OR_D(ctx);
519    REQUIRE_EVEN(ctx, a->rs1);
520
521    TCGv dest = dest_gpr(ctx, a->rd);
522    TCGv_i64 src1 = get_fpr_d(ctx, a->rs1);
523
524    gen_set_rm(ctx, a->rm);
525    gen_helper_fcvt_lu_d(dest, tcg_env, src1);
526    gen_set_gpr(ctx, a->rd, dest);
527    return true;
528}
529
530static bool trans_fmv_x_d(DisasContext *ctx, arg_fmv_x_d *a)
531{
532    REQUIRE_64BIT(ctx);
533    REQUIRE_FPU;
534    REQUIRE_EXT(ctx, RVD);
535
536#ifdef TARGET_RISCV64
537    gen_set_gpr(ctx, a->rd, cpu_fpr[a->rs1]);
538    return true;
539#else
540    qemu_build_not_reached();
541#endif
542}
543
544static bool trans_fcvt_d_l(DisasContext *ctx, arg_fcvt_d_l *a)
545{
546    REQUIRE_64BIT(ctx);
547    REQUIRE_FPU;
548    REQUIRE_ZDINX_OR_D(ctx);
549    REQUIRE_EVEN(ctx, a->rd);
550
551    TCGv_i64 dest = dest_fpr(ctx, a->rd);
552    TCGv src = get_gpr(ctx, a->rs1, EXT_SIGN);
553
554    gen_set_rm(ctx, a->rm);
555    gen_helper_fcvt_d_l(dest, tcg_env, src);
556    gen_set_fpr_d(ctx, a->rd, dest);
557
558    mark_fs_dirty(ctx);
559    return true;
560}
561
562static bool trans_fcvt_d_lu(DisasContext *ctx, arg_fcvt_d_lu *a)
563{
564    REQUIRE_64BIT(ctx);
565    REQUIRE_FPU;
566    REQUIRE_ZDINX_OR_D(ctx);
567    REQUIRE_EVEN(ctx, a->rd);
568
569    TCGv_i64 dest = dest_fpr(ctx, a->rd);
570    TCGv src = get_gpr(ctx, a->rs1, EXT_ZERO);
571
572    gen_set_rm(ctx, a->rm);
573    gen_helper_fcvt_d_lu(dest, tcg_env, src);
574    gen_set_fpr_d(ctx, a->rd, dest);
575
576    mark_fs_dirty(ctx);
577    return true;
578}
579
580static bool trans_fmv_d_x(DisasContext *ctx, arg_fmv_d_x *a)
581{
582    REQUIRE_64BIT(ctx);
583    REQUIRE_FPU;
584    REQUIRE_EXT(ctx, RVD);
585
586#ifdef TARGET_RISCV64
587    tcg_gen_mov_tl(cpu_fpr[a->rd], get_gpr(ctx, a->rs1, EXT_NONE));
588    mark_fs_dirty(ctx);
589    return true;
590#else
591    qemu_build_not_reached();
592#endif
593}
594