1 /*
2  * RISC-V translation routines for the RVXI Base Integer Instruction Set.
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 
trans_illegal(DisasContext * ctx,arg_empty * a)21 static bool trans_illegal(DisasContext *ctx, arg_empty *a)
22 {
23     gen_exception_illegal(ctx);
24     return true;
25 }
26 
trans_lui(DisasContext * ctx,arg_lui * a)27 static bool trans_lui(DisasContext *ctx, arg_lui *a)
28 {
29     gen_set_gpr_const(a->rd, a->imm);
30     return true;
31 }
32 
trans_auipc(DisasContext * ctx,arg_auipc * a)33 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
34 {
35 #ifdef TARGET_CHERI
36     if (ctx->capmode) {
37         TCGv_i32 dst = tcg_const_i32(a->rd);
38         TCGv new_cursor = tcg_const_tl(a->imm + ctx->base.pc_next);
39         gen_helper_auipcc(cpu_env, dst, new_cursor);
40         tcg_temp_free(new_cursor);
41         tcg_temp_free_i32(dst);
42         return true;
43     }
44 #endif
45     // AUIPC returns a value relative to PCC.base
46     gen_set_gpr_const(a->rd, a->imm + ctx->base.pc_next - pcc_base(ctx));
47     return true;
48 }
49 
trans_jal(DisasContext * ctx,arg_jal * a)50 static bool trans_jal(DisasContext *ctx, arg_jal *a)
51 {
52     gen_jal(ctx, a->rd, a->imm);
53     return true;
54 }
55 
trans_jalr(DisasContext * ctx,arg_jalr * a)56 static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
57 {
58     /* no chaining with JALR */
59     TCGLabel *misaligned = NULL;
60     TCGv t0 = tcg_temp_new();
61 
62 
63     gen_get_gpr(cpu_pc, a->rs1);
64     // For CHERI the jump destination is an offset relative to PCC.base
65     tcg_gen_addi_tl(cpu_pc, cpu_pc, a->imm + pcc_base(ctx));
66     tcg_gen_andi_tl(cpu_pc, cpu_pc, (target_ulong)-2);
67     gen_mark_pc_updated();
68 
69     if (!has_ext(ctx, RVC)) {
70         misaligned = gen_new_label();
71         tcg_gen_andi_tl(t0, cpu_pc, 0x2);
72         tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
73     }
74 
75     // For CHERI the result is an offset relative to PCC.base
76     gen_set_gpr_const(a->rd, ctx->pc_succ_insn - pcc_base(ctx));
77     gen_rvfi_dii_validate_jump(ctx);
78     lookup_and_goto_ptr(ctx);
79 
80     if (misaligned) {
81         gen_set_label(misaligned);
82         gen_exception_inst_addr_mis(ctx);
83     }
84     ctx->base.is_jmp = DISAS_NORETURN;
85 
86     tcg_temp_free(t0);
87     return true;
88 }
89 
trans_compr_jalr(DisasContext * ctx,arg_jalr * a)90 static bool trans_compr_jalr(DisasContext *ctx, arg_jalr *a)
91 {
92 #ifdef TARGET_CHERI
93     // In capmode c.jalr is c.cjalr and uses capability registers
94     // TODO: this function could be removed if jalr was made mode-dependent
95     if (ctx->capmode) {
96         tcg_debug_assert(a->imm == 0);
97         arg_cjalr cjalr_arg = {.rd = a->rd, .rs1 = a->rs1};
98         return trans_cjalr(ctx, &cjalr_arg);
99     }
100 #endif
101     return trans_jalr(ctx, a);
102 }
103 
104 
gen_branch(DisasContext * ctx,arg_b * a,TCGCond cond)105 static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
106 {
107     TCGLabel *l = gen_new_label();
108     TCGv source1, source2;
109     source1 = tcg_temp_new();
110     source2 = tcg_temp_new();
111     gen_get_gpr(source1, a->rs1);
112     gen_get_gpr(source2, a->rs2);
113 
114     tcg_gen_brcond_tl(cond, source1, source2, l);
115     gen_goto_tb(ctx, 1, ctx->pc_succ_insn);
116     gen_set_label(l); /* branch taken */
117 
118     gen_rvfi_dii_validate_jump(ctx);
119     if (!has_ext(ctx, RVC) && ((ctx->base.pc_next + a->imm) & 0x3)) {
120         /* misaligned */
121         gen_exception_inst_addr_mis(ctx);
122     } else {
123         gen_goto_tb(ctx, 0, ctx->base.pc_next + a->imm);
124     }
125     ctx->base.is_jmp = DISAS_NORETURN;
126 
127     tcg_temp_free(source1);
128     tcg_temp_free(source2);
129 
130     return true;
131 }
132 
trans_beq(DisasContext * ctx,arg_beq * a)133 static bool trans_beq(DisasContext *ctx, arg_beq *a)
134 {
135     return gen_branch(ctx, a, TCG_COND_EQ);
136 }
137 
trans_bne(DisasContext * ctx,arg_bne * a)138 static bool trans_bne(DisasContext *ctx, arg_bne *a)
139 {
140     return gen_branch(ctx, a, TCG_COND_NE);
141 }
142 
trans_blt(DisasContext * ctx,arg_blt * a)143 static bool trans_blt(DisasContext *ctx, arg_blt *a)
144 {
145     return gen_branch(ctx, a, TCG_COND_LT);
146 }
147 
trans_bge(DisasContext * ctx,arg_bge * a)148 static bool trans_bge(DisasContext *ctx, arg_bge *a)
149 {
150     return gen_branch(ctx, a, TCG_COND_GE);
151 }
152 
trans_bltu(DisasContext * ctx,arg_bltu * a)153 static bool trans_bltu(DisasContext *ctx, arg_bltu *a)
154 {
155     return gen_branch(ctx, a, TCG_COND_LTU);
156 }
157 
trans_bgeu(DisasContext * ctx,arg_bgeu * a)158 static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
159 {
160     return gen_branch(ctx, a, TCG_COND_GEU);
161 }
162 
gen_load(DisasContext * ctx,arg_lb * a,MemOp memop)163 static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
164 {
165 #ifdef TARGET_CHERI
166     if (ctx->capmode) {
167         // TODO: LD is LC for RV32
168         return gen_cap_load(ctx, a->rd, a->rs1, a->imm, memop);
169     }
170 #endif
171     TCGv t0 = tcg_temp_new();
172     TCGv t1 = tcg_temp_new();
173     gen_get_gpr(t0, a->rs1);
174     tcg_gen_addi_tl(t0, t0, a->imm);
175 
176 #ifdef TARGET_CHERI
177     tcg_gen_qemu_ld_ddc_tl(t1, /* Update addr in-place */ NULL, t0, ctx->mem_idx, memop);
178 #else
179     tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, memop);
180 #endif
181     gen_set_gpr(a->rd, t1);
182     tcg_temp_free(t0);
183     tcg_temp_free(t1);
184     return true;
185 }
186 
trans_lb(DisasContext * ctx,arg_lb * a)187 static bool trans_lb(DisasContext *ctx, arg_lb *a)
188 {
189     return gen_load(ctx, a, MO_SB);
190 }
191 
trans_lh(DisasContext * ctx,arg_lh * a)192 static bool trans_lh(DisasContext *ctx, arg_lh *a)
193 {
194     return gen_load(ctx, a, MO_TESW);
195 }
196 
trans_lw(DisasContext * ctx,arg_lw * a)197 static bool trans_lw(DisasContext *ctx, arg_lw *a)
198 {
199     return gen_load(ctx, a, MO_TESL);
200 }
201 
trans_lbu(DisasContext * ctx,arg_lbu * a)202 static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
203 {
204     return gen_load(ctx, a, MO_UB);
205 }
206 
trans_lhu(DisasContext * ctx,arg_lhu * a)207 static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
208 {
209     return gen_load(ctx, a, MO_TEUW);
210 }
211 
gen_store(DisasContext * ctx,arg_sb * a,MemOp memop)212 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
213 {
214 #ifdef TARGET_CHERI
215     if (ctx->capmode) {
216         // TODO: SD is SC for RV32
217         return gen_cap_store(ctx, a->rs1, a->rs2, a->imm, memop);
218     }
219 #endif
220     TCGv t0 = tcg_temp_new();
221     TCGv dat = tcg_temp_new();
222     gen_get_gpr(t0, a->rs1);
223     tcg_gen_addi_tl(t0, t0, a->imm);
224     gen_get_gpr(dat, a->rs2);
225 
226 #ifdef TARGET_CHERI
227     tcg_gen_qemu_st_ddc_tl(dat, /* Update addr in-place */ NULL, t0,
228                            ctx->mem_idx, memop);
229 #else
230     tcg_gen_qemu_st_tl(dat, t0, ctx->mem_idx, memop);
231 #endif
232     tcg_temp_free(t0);
233     tcg_temp_free(dat);
234     return true;
235 }
236 
237 
trans_sb(DisasContext * ctx,arg_sb * a)238 static bool trans_sb(DisasContext *ctx, arg_sb *a)
239 {
240     return gen_store(ctx, a, MO_SB);
241 }
242 
trans_sh(DisasContext * ctx,arg_sh * a)243 static bool trans_sh(DisasContext *ctx, arg_sh *a)
244 {
245     return gen_store(ctx, a, MO_TESW);
246 }
247 
trans_sw(DisasContext * ctx,arg_sw * a)248 static bool trans_sw(DisasContext *ctx, arg_sw *a)
249 {
250     return gen_store(ctx, a, MO_TESL);
251 }
252 
253 #ifdef TARGET_RISCV64
trans_lwu(DisasContext * ctx,arg_lwu * a)254 static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
255 {
256     return gen_load(ctx, a, MO_TEUL);
257 }
258 
trans_ld(DisasContext * ctx,arg_ld * a)259 static bool trans_ld(DisasContext *ctx, arg_ld *a)
260 {
261     return gen_load(ctx, a, MO_TEQ);
262 }
263 
trans_sd(DisasContext * ctx,arg_sd * a)264 static bool trans_sd(DisasContext *ctx, arg_sd *a)
265 {
266     return gen_store(ctx, a, MO_TEQ);
267 }
268 #endif
269 
trans_addi(DisasContext * ctx,arg_addi * a)270 static bool trans_addi(DisasContext *ctx, arg_addi *a)
271 {
272     return gen_arith_imm_fn(ctx, a, &tcg_gen_addi_tl);
273 }
274 
gen_slt(TCGv ret,TCGv s1,TCGv s2)275 static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
276 {
277     tcg_gen_setcond_tl(TCG_COND_LT, ret, s1, s2);
278 }
279 
gen_sltu(TCGv ret,TCGv s1,TCGv s2)280 static void gen_sltu(TCGv ret, TCGv s1, TCGv s2)
281 {
282     tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2);
283 }
284 
285 
trans_slti(DisasContext * ctx,arg_slti * a)286 static bool trans_slti(DisasContext *ctx, arg_slti *a)
287 {
288     return gen_arith_imm_tl(ctx, a, &gen_slt);
289 }
290 
trans_sltiu(DisasContext * ctx,arg_sltiu * a)291 static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
292 {
293     return gen_arith_imm_tl(ctx, a, &gen_sltu);
294 }
295 
trans_xori(DisasContext * ctx,arg_xori * a)296 static bool trans_xori(DisasContext *ctx, arg_xori *a)
297 {
298     return gen_arith_imm_fn(ctx, a, &tcg_gen_xori_tl);
299 }
trans_ori(DisasContext * ctx,arg_ori * a)300 static bool trans_ori(DisasContext *ctx, arg_ori *a)
301 {
302     return gen_arith_imm_fn(ctx, a, &tcg_gen_ori_tl);
303 }
trans_andi(DisasContext * ctx,arg_andi * a)304 static bool trans_andi(DisasContext *ctx, arg_andi *a)
305 {
306     return gen_arith_imm_fn(ctx, a, &tcg_gen_andi_tl);
307 }
trans_slli(DisasContext * ctx,arg_slli * a)308 static bool trans_slli(DisasContext *ctx, arg_slli *a)
309 {
310     if (a->shamt >= TARGET_LONG_BITS) {
311         return false;
312     }
313 
314     if (a->rd != 0) {
315         TCGv t = tcg_temp_new();
316         gen_get_gpr(t, a->rs1);
317 
318         tcg_gen_shli_tl(t, t, a->shamt);
319 
320         gen_set_gpr(a->rd, t);
321         tcg_temp_free(t);
322     } /* NOP otherwise */
323     return true;
324 }
325 
trans_srli(DisasContext * ctx,arg_srli * a)326 static bool trans_srli(DisasContext *ctx, arg_srli *a)
327 {
328     if (a->shamt >= TARGET_LONG_BITS) {
329         return false;
330     }
331 
332     if (a->rd != 0) {
333         TCGv t = tcg_temp_new();
334         gen_get_gpr(t, a->rs1);
335 
336         tcg_gen_shri_tl(t, t, a->shamt);
337         gen_set_gpr(a->rd, t);
338         tcg_temp_free(t);
339     } /* NOP otherwise */
340     return true;
341 }
342 
trans_srai(DisasContext * ctx,arg_srai * a)343 static bool trans_srai(DisasContext *ctx, arg_srai *a)
344 {
345     if (a->shamt >= TARGET_LONG_BITS) {
346         return false;
347     }
348 
349     if (a->rd != 0) {
350         TCGv t = tcg_temp_new();
351         gen_get_gpr(t, a->rs1);
352 
353         tcg_gen_sari_tl(t, t, a->shamt);
354         gen_set_gpr(a->rd, t);
355         tcg_temp_free(t);
356     } /* NOP otherwise */
357     return true;
358 }
359 
trans_add(DisasContext * ctx,arg_add * a)360 static bool trans_add(DisasContext *ctx, arg_add *a)
361 {
362     return gen_arith(ctx, a, &tcg_gen_add_tl);
363 }
364 
trans_sub(DisasContext * ctx,arg_sub * a)365 static bool trans_sub(DisasContext *ctx, arg_sub *a)
366 {
367     return gen_arith(ctx, a, &tcg_gen_sub_tl);
368 }
369 
trans_sll(DisasContext * ctx,arg_sll * a)370 static bool trans_sll(DisasContext *ctx, arg_sll *a)
371 {
372     return gen_shift(ctx, a, &tcg_gen_shl_tl);
373 }
374 
trans_slt(DisasContext * ctx,arg_slt * a)375 static bool trans_slt(DisasContext *ctx, arg_slt *a)
376 {
377     return gen_arith(ctx, a, &gen_slt);
378 }
379 
trans_sltu(DisasContext * ctx,arg_sltu * a)380 static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
381 {
382     return gen_arith(ctx, a, &gen_sltu);
383 }
384 
trans_xor(DisasContext * ctx,arg_xor * a)385 static bool trans_xor(DisasContext *ctx, arg_xor *a)
386 {
387     return gen_arith(ctx, a, &tcg_gen_xor_tl);
388 }
389 
trans_srl(DisasContext * ctx,arg_srl * a)390 static bool trans_srl(DisasContext *ctx, arg_srl *a)
391 {
392     return gen_shift(ctx, a, &tcg_gen_shr_tl);
393 }
394 
trans_sra(DisasContext * ctx,arg_sra * a)395 static bool trans_sra(DisasContext *ctx, arg_sra *a)
396 {
397     return gen_shift(ctx, a, &tcg_gen_sar_tl);
398 }
399 
trans_or(DisasContext * ctx,arg_or * a)400 static bool trans_or(DisasContext *ctx, arg_or *a)
401 {
402     return gen_arith(ctx, a, &tcg_gen_or_tl);
403 }
404 
trans_and(DisasContext * ctx,arg_and * a)405 static bool trans_and(DisasContext *ctx, arg_and *a)
406 {
407     return gen_arith(ctx, a, &tcg_gen_and_tl);
408 }
409 
410 #ifdef TARGET_RISCV64
trans_addiw(DisasContext * ctx,arg_addiw * a)411 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
412 {
413     return gen_arith_imm_tl(ctx, a, &gen_addw);
414 }
415 
trans_slliw(DisasContext * ctx,arg_slliw * a)416 static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
417 {
418     TCGv source1;
419     source1 = tcg_temp_new();
420     gen_get_gpr(source1, a->rs1);
421 
422     tcg_gen_shli_tl(source1, source1, a->shamt);
423     tcg_gen_ext32s_tl(source1, source1);
424     gen_set_gpr(a->rd, source1);
425 
426     tcg_temp_free(source1);
427     return true;
428 }
429 
trans_srliw(DisasContext * ctx,arg_srliw * a)430 static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
431 {
432     TCGv t = tcg_temp_new();
433     gen_get_gpr(t, a->rs1);
434     tcg_gen_extract_tl(t, t, a->shamt, 32 - a->shamt);
435     /* sign-extend for W instructions */
436     tcg_gen_ext32s_tl(t, t);
437     gen_set_gpr(a->rd, t);
438     tcg_temp_free(t);
439     return true;
440 }
441 
trans_sraiw(DisasContext * ctx,arg_sraiw * a)442 static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
443 {
444     TCGv t = tcg_temp_new();
445     gen_get_gpr(t, a->rs1);
446     tcg_gen_sextract_tl(t, t, a->shamt, 32 - a->shamt);
447     gen_set_gpr(a->rd, t);
448     tcg_temp_free(t);
449     return true;
450 }
451 
trans_addw(DisasContext * ctx,arg_addw * a)452 static bool trans_addw(DisasContext *ctx, arg_addw *a)
453 {
454     return gen_arith(ctx, a, &gen_addw);
455 }
456 
trans_subw(DisasContext * ctx,arg_subw * a)457 static bool trans_subw(DisasContext *ctx, arg_subw *a)
458 {
459     return gen_arith(ctx, a, &gen_subw);
460 }
461 
trans_sllw(DisasContext * ctx,arg_sllw * a)462 static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
463 {
464     TCGv source1 = tcg_temp_new();
465     TCGv source2 = tcg_temp_new();
466 
467     gen_get_gpr(source1, a->rs1);
468     gen_get_gpr(source2, a->rs2);
469 
470     tcg_gen_andi_tl(source2, source2, 0x1F);
471     tcg_gen_shl_tl(source1, source1, source2);
472 
473     tcg_gen_ext32s_tl(source1, source1);
474     gen_set_gpr(a->rd, source1);
475     tcg_temp_free(source1);
476     tcg_temp_free(source2);
477     return true;
478 }
479 
trans_srlw(DisasContext * ctx,arg_srlw * a)480 static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
481 {
482     TCGv source1 = tcg_temp_new();
483     TCGv source2 = tcg_temp_new();
484 
485     gen_get_gpr(source1, a->rs1);
486     gen_get_gpr(source2, a->rs2);
487 
488     /* clear upper 32 */
489     tcg_gen_ext32u_tl(source1, source1);
490     tcg_gen_andi_tl(source2, source2, 0x1F);
491     tcg_gen_shr_tl(source1, source1, source2);
492 
493     tcg_gen_ext32s_tl(source1, source1);
494     gen_set_gpr(a->rd, source1);
495     tcg_temp_free(source1);
496     tcg_temp_free(source2);
497     return true;
498 }
499 
trans_sraw(DisasContext * ctx,arg_sraw * a)500 static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
501 {
502     TCGv source1 = tcg_temp_new();
503     TCGv source2 = tcg_temp_new();
504 
505     gen_get_gpr(source1, a->rs1);
506     gen_get_gpr(source2, a->rs2);
507 
508     /*
509      * first, trick to get it to act like working on 32 bits (get rid of
510      * upper 32, sign extend to fill space)
511      */
512     tcg_gen_ext32s_tl(source1, source1);
513     tcg_gen_andi_tl(source2, source2, 0x1F);
514     tcg_gen_sar_tl(source1, source1, source2);
515 
516     gen_set_gpr(a->rd, source1);
517     tcg_temp_free(source1);
518     tcg_temp_free(source2);
519 
520     return true;
521 }
522 #endif
523 
trans_fence(DisasContext * ctx,arg_fence * a)524 static bool trans_fence(DisasContext *ctx, arg_fence *a)
525 {
526     /* FENCE is a full memory barrier. */
527     tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
528     return true;
529 }
530 
trans_fence_i(DisasContext * ctx,arg_fence_i * a)531 static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
532 {
533     if (!ctx->ext_ifencei) {
534         return false;
535     }
536 
537     /*
538      * FENCE_I is a no-op in QEMU,
539      * however we need to end the translation block
540      */
541     gen_update_cpu_pc(ctx->pc_succ_insn);
542     exit_tb(ctx);
543     ctx->base.is_jmp = DISAS_NORETURN;
544     return true;
545 }
546 
547 #define RISCV_OP_CSR_PRE do {\
548     source1 = tcg_temp_new(); \
549     csr_store = tcg_temp_new(); \
550     dest = tcg_temp_new(); \
551     rs1_pass = tcg_temp_new(); \
552     gen_get_gpr(source1, a->rs1); \
553     gen_update_cpu_pc(ctx->base.pc_next); \
554     tcg_gen_movi_tl(rs1_pass, a->rs1); \
555     tcg_gen_movi_tl(csr_store, a->csr); \
556     gen_io_start();\
557 } while (0)
558 
559 #define RISCV_OP_CSR_POST do {\
560     gen_set_gpr(a->rd, dest); \
561     gen_update_cpu_pc(ctx->pc_succ_insn); \
562     exit_tb(ctx); \
563     ctx->base.is_jmp = DISAS_NORETURN; \
564     tcg_temp_free(source1); \
565     tcg_temp_free(csr_store); \
566     tcg_temp_free(dest); \
567     tcg_temp_free(rs1_pass); \
568 } while (0)
569 
570 
trans_csrrw(DisasContext * ctx,arg_csrrw * a)571 static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
572 {
573     TCGv source1, csr_store, dest, rs1_pass;
574     RISCV_OP_CSR_PRE;
575     gen_helper_csrrw(dest, cpu_env, source1, csr_store);
576     RISCV_OP_CSR_POST;
577     return true;
578 }
579 
trans_csrrs(DisasContext * ctx,arg_csrrs * a)580 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
581 {
582     TCGv source1, csr_store, dest, rs1_pass;
583     RISCV_OP_CSR_PRE;
584     gen_helper_csrrs(dest, cpu_env, source1, csr_store, rs1_pass);
585     RISCV_OP_CSR_POST;
586     return true;
587 }
588 
trans_csrrc(DisasContext * ctx,arg_csrrc * a)589 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
590 {
591     TCGv source1, csr_store, dest, rs1_pass;
592     RISCV_OP_CSR_PRE;
593     gen_helper_csrrc(dest, cpu_env, source1, csr_store, rs1_pass);
594     RISCV_OP_CSR_POST;
595     return true;
596 }
597 
trans_csrrwi(DisasContext * ctx,arg_csrrwi * a)598 static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a)
599 {
600     TCGv source1, csr_store, dest, rs1_pass;
601     RISCV_OP_CSR_PRE;
602     gen_helper_csrrw(dest, cpu_env, rs1_pass, csr_store);
603     RISCV_OP_CSR_POST;
604     return true;
605 }
606 
trans_csrrsi(DisasContext * ctx,arg_csrrsi * a)607 static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a)
608 {
609     TCGv source1, csr_store, dest, rs1_pass;
610     RISCV_OP_CSR_PRE;
611     gen_helper_csrrs(dest, cpu_env, rs1_pass, csr_store, rs1_pass);
612     RISCV_OP_CSR_POST;
613     return true;
614 }
615 
trans_csrrci(DisasContext * ctx,arg_csrrci * a)616 static bool trans_csrrci(DisasContext *ctx, arg_csrrci *a)
617 {
618     TCGv source1, csr_store, dest, rs1_pass;
619     RISCV_OP_CSR_PRE;
620     gen_helper_csrrc(dest, cpu_env, rs1_pass, csr_store, rs1_pass);
621     RISCV_OP_CSR_POST;
622     return true;
623 }
624