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