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