master
inc 1,251 lines 34.7 KB
Raw
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
21 static bool trans_illegal(DisasContext *ctx, arg_empty *a)
22 {
23 gen_exception_illegal(ctx);
24 return true;
25 }
26
27 static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
28 {
29 REQUIRE_64_OR_128BIT(ctx);
30 return trans_illegal(ctx, a);
31 }
32
33 static bool trans_lui(DisasContext *ctx, arg_lui *a)
34 {
35 gen_set_gpri(ctx, a->rd, a->imm);
36 return true;
37 }
38
39 static bool trans_lpad(DisasContext *ctx, arg_lpad *a)
40 {
41 /*
42 * fcfi_lp_expected can set only if fcfi was eanbled.
43 * translate further only if fcfi_lp_expected set.
44 * lpad comes from NOP space anyways, so return true if
45 * fcfi_lp_expected is false.
46 */
47 if (!ctx->fcfi_lp_expected) {
48 return true;
49 }
50
51 ctx->fcfi_lp_expected = false;
52 if ((ctx->base.pc_next) & 0x3) {
53 /*
54 * misaligned, according to spec we should raise sw check exception
55 */
56 tcg_gen_st8_i32(tcg_constant_i32(RISCV_EXCP_SW_CHECK_FCFI_TVAL),
57 tcg_env, offsetof(CPURISCVState, sw_check_code));
58 gen_helper_raise_exception(tcg_env,
59 tcg_constant_i32(RISCV_EXCP_SW_CHECK));
60 return true;
61 }
62
63 /* per spec, label check performed only when embedded label non-zero */
64 if (a->label != 0) {
65 TCGLabel *skip = gen_new_label();
66 TCGv tmp = tcg_temp_new();
67 tcg_gen_extract_tl(tmp, get_gpr(ctx, xT2, EXT_NONE), 12, 20);
68 tcg_gen_brcondi_tl(TCG_COND_EQ, tmp, a->label, skip);
69 tcg_gen_st8_i32(tcg_constant_i32(RISCV_EXCP_SW_CHECK_FCFI_TVAL),
70 tcg_env, offsetof(CPURISCVState, sw_check_code));
71 gen_helper_raise_exception(tcg_env,
72 tcg_constant_i32(RISCV_EXCP_SW_CHECK));
73 gen_set_label(skip);
74 }
75
76 tcg_gen_st8_tl(tcg_constant_tl(0), tcg_env,
77 offsetof(CPURISCVState, elp));
78
79 return true;
80 }
81
82 static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
83 {
84 TCGv target_pc = dest_gpr(ctx, a->rd);
85 gen_pc_plus_diff(target_pc, ctx, a->imm);
86 gen_set_gpr(ctx, a->rd, target_pc);
87 return true;
88 }
89
90 static bool trans_jal(DisasContext *ctx, arg_jal *a)
91 {
92 gen_jal(ctx, a->rd, a->imm);
93 return true;
94 }
95
96 #ifndef CONFIG_USER_ONLY
97 /*
98 * Indirect calls
99 * - jalr x1, rs where rs != x5;
100 * - jalr x5, rs where rs != x1;
101 * - c.jalr rs1 where rs1 != x5;
102 *
103 * Indirect jumps
104 * - jalr x0, rs where rs != x1 and rs != x5;
105 * - c.jr rs1 where rs1 != x1 and rs1 != x5.
106 *
107 * Returns
108 * - jalr rd, rs where (rs == x1 or rs == x5) and rd != x1 and rd != x5;
109 * - c.jr rs1 where rs1 == x1 or rs1 == x5.
110 *
111 * Co-routine swap
112 * - jalr x1, x5;
113 * - jalr x5, x1;
114 * - c.jalr x5.
115 *
116 * Other indirect jumps
117 * - jalr rd, rs where rs != x1, rs != x5, rd != x0, rd != x1 and rd != x5.
118 */
119 static void gen_ctr_jalr(DisasContext *ctx, arg_jalr *a, TCGv dest)
120 {
121 TCGv src = tcg_temp_new();
122 TCGv type;
123
124 if ((a->rd == 1 && a->rs1 != 5) || (a->rd == 5 && a->rs1 != 1)) {
125 type = tcg_constant_tl(CTRDATA_TYPE_INDIRECT_CALL);
126 } else if (a->rd == 0 && a->rs1 != 1 && a->rs1 != 5) {
127 type = tcg_constant_tl(CTRDATA_TYPE_INDIRECT_JUMP);
128 } else if ((a->rs1 == 1 || a->rs1 == 5) && (a->rd != 1 && a->rd != 5)) {
129 type = tcg_constant_tl(CTRDATA_TYPE_RETURN);
130 } else if ((a->rs1 == 1 && a->rd == 5) || (a->rs1 == 5 && a->rd == 1)) {
131 type = tcg_constant_tl(CTRDATA_TYPE_CO_ROUTINE_SWAP);
132 } else {
133 type = tcg_constant_tl(CTRDATA_TYPE_OTHER_INDIRECT_JUMP);
134 }
135
136 gen_pc_plus_diff(src, ctx, 0);
137 gen_helper_ctr_add_entry(tcg_env, src, dest, type);
138 }
139 #endif
140
141 static bool trans_jalr(DisasContext *ctx, arg_jalr *a)
142 {
143 TCGLabel *misaligned = NULL;
144 TCGv target_pc = tcg_temp_new();
145 TCGv succ_pc = dest_gpr(ctx, a->rd);
146
147 tcg_gen_addi_tl(target_pc, get_gpr(ctx, a->rs1, EXT_NONE), a->imm);
148 tcg_gen_andi_tl(target_pc, target_pc, (target_ulong)-2);
149
150 if (get_xl(ctx) == MXL_RV32) {
151 tcg_gen_ext32s_tl(target_pc, target_pc);
152 }
153
154 if (!riscv_cpu_allow_16bit_insn(ctx->cfg_ptr,
155 ctx->priv_ver,
156 ctx->misa_ext)) {
157 TCGv t0 = tcg_temp_new();
158
159 misaligned = gen_new_label();
160 tcg_gen_andi_tl(t0, target_pc, 0x2);
161 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x0, misaligned);
162 }
163
164 gen_pc_plus_diff(succ_pc, ctx, ctx->cur_insn_len);
165 gen_set_gpr(ctx, a->rd, succ_pc);
166
167 #ifndef CONFIG_USER_ONLY
168 if (ctx->cfg_ptr->ext_smctr || ctx->cfg_ptr->ext_ssctr) {
169 gen_ctr_jalr(ctx, a, target_pc);
170 }
171 #endif
172
173 tcg_gen_mov_tl(cpu_pc, target_pc);
174 if (ctx->fcfi_enabled) {
175 /*
176 * return from functions (i.e. rs1 == xRA || rs1 == xT0) are not
177 * tracked. zicfilp introduces sw guarded branch as well. sw guarded
178 * branch are not tracked. rs1 == xT2 is a sw guarded branch.
179 */
180 if (a->rs1 != xRA && a->rs1 != xT0 && a->rs1 != xT2) {
181 tcg_gen_st8_tl(tcg_constant_tl(1),
182 tcg_env, offsetof(CPURISCVState, elp));
183 }
184 }
185
186 lookup_and_goto_ptr(ctx);
187
188 if (misaligned) {
189 gen_set_label(misaligned);
190 gen_exception_inst_addr_mis(ctx, target_pc);
191 }
192 ctx->base.is_jmp = DISAS_NORETURN;
193
194 return true;
195 }
196
197 static TCGCond gen_compare_i128(bool bz, TCGv rl,
198 TCGv al, TCGv ah, TCGv bl, TCGv bh,
199 TCGCond cond)
200 {
201 TCGv rh = tcg_temp_new();
202 bool invert = false;
203
204 switch (cond) {
205 case TCG_COND_EQ:
206 case TCG_COND_NE:
207 if (bz) {
208 tcg_gen_or_tl(rl, al, ah);
209 } else {
210 tcg_gen_xor_tl(rl, al, bl);
211 tcg_gen_xor_tl(rh, ah, bh);
212 tcg_gen_or_tl(rl, rl, rh);
213 }
214 break;
215
216 case TCG_COND_GE:
217 case TCG_COND_LT:
218 if (bz) {
219 tcg_gen_mov_tl(rl, ah);
220 } else {
221 TCGv tmp = tcg_temp_new();
222
223 tcg_gen_sub2_tl(rl, rh, al, ah, bl, bh);
224 tcg_gen_xor_tl(rl, rh, ah);
225 tcg_gen_xor_tl(tmp, ah, bh);
226 tcg_gen_and_tl(rl, rl, tmp);
227 tcg_gen_xor_tl(rl, rh, rl);
228 }
229 break;
230
231 case TCG_COND_LTU:
232 invert = true;
233 /* fallthrough */
234 case TCG_COND_GEU:
235 {
236 TCGv tmp = tcg_temp_new();
237 TCGv zero = tcg_constant_tl(0);
238 TCGv one = tcg_constant_tl(1);
239
240 cond = TCG_COND_NE;
241 /* borrow in to second word */
242 tcg_gen_setcond_tl(TCG_COND_LTU, tmp, al, bl);
243 /* seed third word with 1, which will be result */
244 tcg_gen_sub2_tl(tmp, rh, ah, one, tmp, zero);
245 tcg_gen_sub2_tl(tmp, rl, tmp, rh, bh, zero);
246 }
247 break;
248
249 default:
250 g_assert_not_reached();
251 }
252
253 if (invert) {
254 cond = tcg_invert_cond(cond);
255 }
256 return cond;
257 }
258
259 static void gen_setcond_i128(TCGv rl, TCGv rh,
260 TCGv src1l, TCGv src1h,
261 TCGv src2l, TCGv src2h,
262 TCGCond cond)
263 {
264 cond = gen_compare_i128(false, rl, src1l, src1h, src2l, src2h, cond);
265 tcg_gen_setcondi_tl(cond, rl, rl, 0);
266 tcg_gen_movi_tl(rh, 0);
267 }
268
269 static bool gen_branch(DisasContext *ctx, arg_b *a, TCGCond cond)
270 {
271 TCGLabel *l = gen_new_label();
272 TCGv src1 = get_gpr(ctx, a->rs1, EXT_SIGN);
273 TCGv src2 = get_gpr(ctx, a->rs2, EXT_SIGN);
274 target_ulong orig_pc_save = ctx->pc_save;
275
276 if (get_xl(ctx) == MXL_RV128) {
277 TCGv src1h = get_gprh(ctx, a->rs1);
278 TCGv src2h = get_gprh(ctx, a->rs2);
279 TCGv tmp = tcg_temp_new();
280
281 cond = gen_compare_i128(a->rs2 == 0,
282 tmp, src1, src1h, src2, src2h, cond);
283 tcg_gen_brcondi_tl(cond, tmp, 0, l);
284 } else {
285 tcg_gen_brcond_tl(cond, src1, src2, l);
286 }
287
288 #ifndef CONFIG_USER_ONLY
289 if (ctx->cfg_ptr->ext_smctr || ctx->cfg_ptr->ext_ssctr) {
290 TCGv type = tcg_constant_tl(CTRDATA_TYPE_NONTAKEN_BRANCH);
291 TCGv dest = tcg_temp_new();
292 TCGv src = tcg_temp_new();
293
294 gen_pc_plus_diff(src, ctx, 0);
295 gen_pc_plus_diff(dest, ctx, ctx->cur_insn_len);
296 gen_helper_ctr_add_entry(tcg_env, src, dest, type);
297 }
298 #endif
299
300 gen_goto_tb(ctx, 1, ctx->cur_insn_len);
301 ctx->pc_save = orig_pc_save;
302
303 gen_set_label(l); /* branch taken */
304
305 if (!riscv_cpu_allow_16bit_insn(ctx->cfg_ptr,
306 ctx->priv_ver,
307 ctx->misa_ext) &&
308 (a->imm & 0x3)) {
309 /* misaligned */
310 TCGv target_pc = tcg_temp_new();
311 gen_pc_plus_diff(target_pc, ctx, a->imm);
312 gen_exception_inst_addr_mis(ctx, target_pc);
313 } else {
314 #ifndef CONFIG_USER_ONLY
315 if (ctx->cfg_ptr->ext_smctr || ctx->cfg_ptr->ext_ssctr) {
316 TCGv type = tcg_constant_tl(CTRDATA_TYPE_TAKEN_BRANCH);
317 TCGv dest = tcg_temp_new();
318 TCGv src = tcg_temp_new();
319
320 gen_pc_plus_diff(src, ctx, 0);
321 gen_pc_plus_diff(dest, ctx, a->imm);
322 gen_helper_ctr_add_entry(tcg_env, src, dest, type);
323 }
324 #endif
325 gen_goto_tb(ctx, 0, a->imm);
326 }
327 ctx->pc_save = -1;
328 ctx->base.is_jmp = DISAS_NORETURN;
329
330 return true;
331 }
332
333 static bool trans_beq(DisasContext *ctx, arg_beq *a)
334 {
335 return gen_branch(ctx, a, TCG_COND_EQ);
336 }
337
338 static bool trans_bne(DisasContext *ctx, arg_bne *a)
339 {
340 return gen_branch(ctx, a, TCG_COND_NE);
341 }
342
343 static bool trans_blt(DisasContext *ctx, arg_blt *a)
344 {
345 return gen_branch(ctx, a, TCG_COND_LT);
346 }
347
348 static bool trans_bge(DisasContext *ctx, arg_bge *a)
349 {
350 return gen_branch(ctx, a, TCG_COND_GE);
351 }
352
353 static bool trans_bltu(DisasContext *ctx, arg_bltu *a)
354 {
355 return gen_branch(ctx, a, TCG_COND_LTU);
356 }
357
358 static bool trans_bgeu(DisasContext *ctx, arg_bgeu *a)
359 {
360 return gen_branch(ctx, a, TCG_COND_GEU);
361 }
362
363 static bool gen_load_tl(DisasContext *ctx, arg_lb *a, MemOp memop)
364 {
365 TCGv dest = dest_gpr(ctx, a->rd);
366 TCGv addr = get_address(ctx, a->rs1, a->imm);
367
368 tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, memop);
369 gen_set_gpr(ctx, a->rd, dest);
370 return true;
371 }
372
373 /* Compute only 64-bit addresses to use the address translation mechanism */
374 static bool gen_load_i128(DisasContext *ctx, arg_lb *a, MemOp memop)
375 {
376 TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
377 TCGv destl = dest_gpr(ctx, a->rd);
378 TCGv desth = dest_gprh(ctx, a->rd);
379 TCGv addrl = tcg_temp_new();
380 TCGv_i128 t16 = tcg_temp_new_i128();
381 TCGv_i64 tl = tcg_temp_new_i64();
382 TCGv_i64 th = tcg_temp_new_i64();
383
384 tcg_gen_addi_tl(addrl, src1l, a->imm);
385
386 if ((memop & MO_SIZE) <= MO_64) {
387 tcg_gen_qemu_ld_tl(destl, addrl, ctx->mem_idx, memop);
388 if (memop & MO_SIGN) {
389 tcg_gen_sari_tl(desth, destl, 63);
390 } else {
391 tcg_gen_movi_tl(desth, 0);
392 }
393 } else {
394 tcg_gen_qemu_ld_i128(t16, addrl, ctx->mem_idx, memop);
395 if (ctx->mo_endianness == MO_LE) {
396 tcg_gen_extr_i128_i64(tl, th, t16);
397 } else {
398 tcg_gen_extr_i128_i64(th, tl, t16);
399 }
400 tcg_gen_trunc_i64_tl(destl, tl);
401 tcg_gen_trunc_i64_tl(desth, th);
402 }
403
404 gen_set_gpr128(ctx, a->rd, destl, desth);
405 return true;
406 }
407
408 static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop)
409 {
410 bool out;
411
412 memop |= ctx->mo_endianness;
413 if (ctx->cfg_ptr->ext_zama16b) {
414 memop |= MO_ATOM_WITHIN16;
415 }
416 if (!ctx->cfg_ptr->ext_zicclsm) {
417 memop |= MO_ALIGN;
418 }
419 decode_save_opc(ctx, 0);
420 if (get_xl(ctx) == MXL_RV128) {
421 out = gen_load_i128(ctx, a, memop);
422 } else {
423 out = gen_load_tl(ctx, a, memop);
424 }
425
426 if (ctx->ztso) {
427 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
428 }
429
430 return out;
431 }
432
433 static bool trans_lb(DisasContext *ctx, arg_lb *a)
434 {
435 return gen_load(ctx, a, MO_SB);
436 }
437
438 static bool trans_lh(DisasContext *ctx, arg_lh *a)
439 {
440 return gen_load(ctx, a, MO_SW);
441 }
442
443 static bool trans_lw(DisasContext *ctx, arg_lw *a)
444 {
445 return gen_load(ctx, a, MO_SL);
446 }
447
448 static bool trans_ld(DisasContext *ctx, arg_ld *a)
449 {
450 REQUIRE_64_OR_128BIT(ctx);
451 return gen_load(ctx, a, MO_SQ);
452 }
453
454 static bool trans_lq(DisasContext *ctx, arg_lq *a)
455 {
456 REQUIRE_128BIT(ctx);
457 return gen_load(ctx, a, MO_UO);
458 }
459
460 static bool trans_lbu(DisasContext *ctx, arg_lbu *a)
461 {
462 return gen_load(ctx, a, MO_UB);
463 }
464
465 static bool trans_lhu(DisasContext *ctx, arg_lhu *a)
466 {
467 return gen_load(ctx, a, MO_UW);
468 }
469
470 static bool trans_lwu(DisasContext *ctx, arg_lwu *a)
471 {
472 REQUIRE_64_OR_128BIT(ctx);
473 return gen_load(ctx, a, MO_UL);
474 }
475
476 static bool trans_ldu(DisasContext *ctx, arg_ldu *a)
477 {
478 REQUIRE_128BIT(ctx);
479 return gen_load(ctx, a, MO_UQ);
480 }
481
482 static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop)
483 {
484 TCGv addr = get_address(ctx, a->rs1, a->imm);
485 TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
486
487 if (ctx->ztso) {
488 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
489 }
490
491 tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop);
492 return true;
493 }
494
495 static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop)
496 {
497 TCGv src1l = get_gpr(ctx, a->rs1, EXT_NONE);
498 TCGv src2l = get_gpr(ctx, a->rs2, EXT_NONE);
499 TCGv src2h = get_gprh(ctx, a->rs2);
500 TCGv addrl = tcg_temp_new();
501 TCGv_i128 t16 = tcg_temp_new_i128();
502 TCGv_i64 tl = tcg_temp_new_i64();
503 TCGv_i64 th = tcg_temp_new_i64();
504
505 tcg_gen_addi_tl(addrl, src1l, a->imm);
506
507 if ((memop & MO_SIZE) <= MO_64) {
508 tcg_gen_qemu_st_tl(src2l, addrl, ctx->mem_idx, memop);
509 } else {
510
511 tcg_gen_ext_tl_i64(tl, src2l);
512 tcg_gen_ext_tl_i64(th, src2h);
513
514 if (ctx->mo_endianness == MO_LE) {
515 tcg_gen_concat_i64_i128(t16, tl, th);
516 } else {
517 tcg_gen_concat_i64_i128(t16, th, tl);
518 }
519 tcg_gen_qemu_st_i128(t16, addrl, ctx->mem_idx, memop);
520 }
521 return true;
522 }
523
524 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop)
525 {
526 memop |= ctx->mo_endianness;
527 if (ctx->cfg_ptr->ext_zama16b) {
528 memop |= MO_ATOM_WITHIN16;
529 }
530 if (!ctx->cfg_ptr->ext_zicclsm) {
531 memop |= MO_ALIGN;
532 }
533 decode_save_opc(ctx, 0);
534 if (get_xl(ctx) == MXL_RV128) {
535 return gen_store_i128(ctx, a, memop);
536 } else {
537 return gen_store_tl(ctx, a, memop);
538 }
539 }
540
541 static bool trans_sb(DisasContext *ctx, arg_sb *a)
542 {
543 return gen_store(ctx, a, MO_SB);
544 }
545
546 static bool trans_sh(DisasContext *ctx, arg_sh *a)
547 {
548 return gen_store(ctx, a, MO_SW);
549 }
550
551 static bool trans_sw(DisasContext *ctx, arg_sw *a)
552 {
553 return gen_store(ctx, a, MO_SL);
554 }
555
556 static bool trans_sd(DisasContext *ctx, arg_sd *a)
557 {
558 REQUIRE_64_OR_128BIT(ctx);
559 return gen_store(ctx, a, MO_UQ);
560 }
561
562 static bool trans_sq(DisasContext *ctx, arg_sq *a)
563 {
564 REQUIRE_128BIT(ctx);
565 return gen_store(ctx, a, MO_UO);
566 }
567
568 static bool trans_addd(DisasContext *ctx, arg_addd *a)
569 {
570 REQUIRE_128BIT(ctx);
571 ctx->ol = MXL_RV64;
572 return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL);
573 }
574
575 static bool trans_addid(DisasContext *ctx, arg_addid *a)
576 {
577 REQUIRE_128BIT(ctx);
578 ctx->ol = MXL_RV64;
579 return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL);
580 }
581
582 static bool trans_subd(DisasContext *ctx, arg_subd *a)
583 {
584 REQUIRE_128BIT(ctx);
585 ctx->ol = MXL_RV64;
586 return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL);
587 }
588
589 static void gen_addi2_i128(TCGv retl, TCGv reth,
590 TCGv srcl, TCGv srch, target_long imm)
591 {
592 TCGv imml = tcg_constant_tl(imm);
593 TCGv immh = tcg_constant_tl(-(imm < 0));
594 tcg_gen_add2_tl(retl, reth, srcl, srch, imml, immh);
595 }
596
597 static bool trans_addi(DisasContext *ctx, arg_addi *a)
598 {
599 return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, gen_addi2_i128);
600 }
601
602 static void gen_slt(TCGv ret, TCGv s1, TCGv s2)
603 {
604 tcg_gen_setcond_tl(TCG_COND_LT, ret, s1, s2);
605 }
606
607 static void gen_slt_i128(TCGv retl, TCGv reth,
608 TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h)
609 {
610 gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LT);
611 }
612
613 static void gen_sltu(TCGv ret, TCGv s1, TCGv s2)
614 {
615 tcg_gen_setcond_tl(TCG_COND_LTU, ret, s1, s2);
616 }
617
618 static void gen_sltu_i128(TCGv retl, TCGv reth,
619 TCGv s1l, TCGv s1h, TCGv s2l, TCGv s2h)
620 {
621 gen_setcond_i128(retl, reth, s1l, s1h, s2l, s2h, TCG_COND_LTU);
622 }
623
624 static bool trans_slti(DisasContext *ctx, arg_slti *a)
625 {
626 return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128);
627 }
628
629 static bool trans_sltiu(DisasContext *ctx, arg_sltiu *a)
630 {
631 return gen_arith_imm_tl(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128);
632 }
633
634 static bool trans_xori(DisasContext *ctx, arg_xori *a)
635 {
636 return gen_logic_imm_fn(ctx, a, tcg_gen_xori_tl);
637 }
638
639 static bool trans_ori(DisasContext *ctx, arg_ori *a)
640 {
641 return gen_logic_imm_fn(ctx, a, tcg_gen_ori_tl);
642 }
643
644 static bool trans_andi(DisasContext *ctx, arg_andi *a)
645 {
646 return gen_logic_imm_fn(ctx, a, tcg_gen_andi_tl);
647 }
648
649 static void gen_slli_i128(TCGv retl, TCGv reth,
650 TCGv src1l, TCGv src1h,
651 target_long shamt)
652 {
653 if (shamt >= 64) {
654 tcg_gen_shli_tl(reth, src1l, shamt - 64);
655 tcg_gen_movi_tl(retl, 0);
656 } else {
657 tcg_gen_extract2_tl(reth, src1l, src1h, 64 - shamt);
658 tcg_gen_shli_tl(retl, src1l, shamt);
659 }
660 }
661
662 static bool trans_slli(DisasContext *ctx, arg_slli *a)
663 {
664 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, gen_slli_i128);
665 }
666
667 static void gen_srliw(TCGv dst, TCGv src, target_long shamt)
668 {
669 tcg_gen_extract_tl(dst, src, shamt, 32 - shamt);
670 }
671
672 static void gen_srli_i128(TCGv retl, TCGv reth,
673 TCGv src1l, TCGv src1h,
674 target_long shamt)
675 {
676 if (shamt >= 64) {
677 tcg_gen_shri_tl(retl, src1h, shamt - 64);
678 tcg_gen_movi_tl(reth, 0);
679 } else {
680 tcg_gen_extract2_tl(retl, src1l, src1h, shamt);
681 tcg_gen_shri_tl(reth, src1h, shamt);
682 }
683 }
684
685 static bool trans_srli(DisasContext *ctx, arg_srli *a)
686 {
687 return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
688 tcg_gen_shri_tl, gen_srliw, gen_srli_i128);
689 }
690
691 static void gen_sraiw(TCGv dst, TCGv src, target_long shamt)
692 {
693 tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt);
694 }
695
696 static void gen_srai_i128(TCGv retl, TCGv reth,
697 TCGv src1l, TCGv src1h,
698 target_long shamt)
699 {
700 if (shamt >= 64) {
701 tcg_gen_sari_tl(retl, src1h, shamt - 64);
702 tcg_gen_sari_tl(reth, src1h, 63);
703 } else {
704 tcg_gen_extract2_tl(retl, src1l, src1h, shamt);
705 tcg_gen_sari_tl(reth, src1h, shamt);
706 }
707 }
708
709 static bool trans_srai(DisasContext *ctx, arg_srai *a)
710 {
711 return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE,
712 tcg_gen_sari_tl, gen_sraiw, gen_srai_i128);
713 }
714
715 static bool trans_add(DisasContext *ctx, arg_add *a)
716 {
717 return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, tcg_gen_add2_tl);
718 }
719
720 static bool trans_sub(DisasContext *ctx, arg_sub *a)
721 {
722 return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, tcg_gen_sub2_tl);
723 }
724
725 static void gen_sll_i128(TCGv destl, TCGv desth,
726 TCGv src1l, TCGv src1h, TCGv shamt)
727 {
728 TCGv ls = tcg_temp_new();
729 TCGv rs = tcg_temp_new();
730 TCGv hs = tcg_temp_new();
731 TCGv ll = tcg_temp_new();
732 TCGv lr = tcg_temp_new();
733 TCGv h0 = tcg_temp_new();
734 TCGv h1 = tcg_temp_new();
735 TCGv zero = tcg_constant_tl(0);
736
737 tcg_gen_andi_tl(hs, shamt, 64);
738 tcg_gen_andi_tl(ls, shamt, 63);
739 tcg_gen_neg_tl(shamt, shamt);
740 tcg_gen_andi_tl(rs, shamt, 63);
741
742 tcg_gen_shl_tl(ll, src1l, ls);
743 tcg_gen_shl_tl(h0, src1h, ls);
744 tcg_gen_shr_tl(lr, src1l, rs);
745 tcg_gen_movcond_tl(TCG_COND_NE, lr, shamt, zero, lr, zero);
746 tcg_gen_or_tl(h1, h0, lr);
747
748 tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, zero, ll);
749 tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, ll, h1);
750 }
751
752 static bool trans_sll(DisasContext *ctx, arg_sll *a)
753 {
754 return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, gen_sll_i128);
755 }
756
757 static bool trans_slt(DisasContext *ctx, arg_slt *a)
758 {
759 return gen_arith(ctx, a, EXT_SIGN, gen_slt, gen_slt_i128);
760 }
761
762 static bool trans_sltu(DisasContext *ctx, arg_sltu *a)
763 {
764 return gen_arith(ctx, a, EXT_SIGN, gen_sltu, gen_sltu_i128);
765 }
766
767 static void gen_srl_i128(TCGv destl, TCGv desth,
768 TCGv src1l, TCGv src1h, TCGv shamt)
769 {
770 TCGv ls = tcg_temp_new();
771 TCGv rs = tcg_temp_new();
772 TCGv hs = tcg_temp_new();
773 TCGv ll = tcg_temp_new();
774 TCGv lr = tcg_temp_new();
775 TCGv h0 = tcg_temp_new();
776 TCGv h1 = tcg_temp_new();
777 TCGv zero = tcg_constant_tl(0);
778
779 tcg_gen_andi_tl(hs, shamt, 64);
780 tcg_gen_andi_tl(rs, shamt, 63);
781 tcg_gen_neg_tl(shamt, shamt);
782 tcg_gen_andi_tl(ls, shamt, 63);
783
784 tcg_gen_shr_tl(lr, src1l, rs);
785 tcg_gen_shr_tl(h1, src1h, rs);
786 tcg_gen_shl_tl(ll, src1h, ls);
787 tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero);
788 tcg_gen_or_tl(h0, ll, lr);
789
790 tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0);
791 tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, zero, h1);
792 }
793
794 static bool trans_srl(DisasContext *ctx, arg_srl *a)
795 {
796 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, gen_srl_i128);
797 }
798
799 static void gen_sra_i128(TCGv destl, TCGv desth,
800 TCGv src1l, TCGv src1h, TCGv shamt)
801 {
802 TCGv ls = tcg_temp_new();
803 TCGv rs = tcg_temp_new();
804 TCGv hs = tcg_temp_new();
805 TCGv ll = tcg_temp_new();
806 TCGv lr = tcg_temp_new();
807 TCGv h0 = tcg_temp_new();
808 TCGv h1 = tcg_temp_new();
809 TCGv zero = tcg_constant_tl(0);
810
811 tcg_gen_andi_tl(hs, shamt, 64);
812 tcg_gen_andi_tl(rs, shamt, 63);
813 tcg_gen_neg_tl(shamt, shamt);
814 tcg_gen_andi_tl(ls, shamt, 63);
815
816 tcg_gen_shr_tl(lr, src1l, rs);
817 tcg_gen_sar_tl(h1, src1h, rs);
818 tcg_gen_shl_tl(ll, src1h, ls);
819 tcg_gen_movcond_tl(TCG_COND_NE, ll, shamt, zero, ll, zero);
820 tcg_gen_or_tl(h0, ll, lr);
821 tcg_gen_sari_tl(lr, src1h, 63);
822
823 tcg_gen_movcond_tl(TCG_COND_NE, destl, hs, zero, h1, h0);
824 tcg_gen_movcond_tl(TCG_COND_NE, desth, hs, zero, lr, h1);
825 }
826
827 static bool trans_sra(DisasContext *ctx, arg_sra *a)
828 {
829 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, gen_sra_i128);
830 }
831
832 static bool trans_xor(DisasContext *ctx, arg_xor *a)
833 {
834 return gen_logic(ctx, a, tcg_gen_xor_tl);
835 }
836
837 static bool trans_or(DisasContext *ctx, arg_or *a)
838 {
839 return gen_logic(ctx, a, tcg_gen_or_tl);
840 }
841
842 static bool trans_and(DisasContext *ctx, arg_and *a)
843 {
844 return gen_logic(ctx, a, tcg_gen_and_tl);
845 }
846
847 static bool trans_addiw(DisasContext *ctx, arg_addiw *a)
848 {
849 REQUIRE_64_OR_128BIT(ctx);
850 ctx->ol = MXL_RV32;
851 return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl, NULL);
852 }
853
854 static bool trans_slliw(DisasContext *ctx, arg_slliw *a)
855 {
856 REQUIRE_64_OR_128BIT(ctx);
857 ctx->ol = MXL_RV32;
858 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL);
859 }
860
861 static bool trans_srliw(DisasContext *ctx, arg_srliw *a)
862 {
863 REQUIRE_64_OR_128BIT(ctx);
864 ctx->ol = MXL_RV32;
865 return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw, NULL);
866 }
867
868 static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a)
869 {
870 REQUIRE_64_OR_128BIT(ctx);
871 ctx->ol = MXL_RV32;
872 return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw, NULL);
873 }
874
875 static bool trans_sllid(DisasContext *ctx, arg_sllid *a)
876 {
877 REQUIRE_128BIT(ctx);
878 ctx->ol = MXL_RV64;
879 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl, NULL);
880 }
881
882 static bool trans_srlid(DisasContext *ctx, arg_srlid *a)
883 {
884 REQUIRE_128BIT(ctx);
885 ctx->ol = MXL_RV64;
886 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shri_tl, NULL);
887 }
888
889 static bool trans_sraid(DisasContext *ctx, arg_sraid *a)
890 {
891 REQUIRE_128BIT(ctx);
892 ctx->ol = MXL_RV64;
893 return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_sari_tl, NULL);
894 }
895
896 static bool trans_addw(DisasContext *ctx, arg_addw *a)
897 {
898 REQUIRE_64_OR_128BIT(ctx);
899 ctx->ol = MXL_RV32;
900 return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl, NULL);
901 }
902
903 static bool trans_subw(DisasContext *ctx, arg_subw *a)
904 {
905 REQUIRE_64_OR_128BIT(ctx);
906 ctx->ol = MXL_RV32;
907 return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl, NULL);
908 }
909
910 static bool trans_sllw(DisasContext *ctx, arg_sllw *a)
911 {
912 REQUIRE_64_OR_128BIT(ctx);
913 ctx->ol = MXL_RV32;
914 return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL);
915 }
916
917 static bool trans_srlw(DisasContext *ctx, arg_srlw *a)
918 {
919 REQUIRE_64_OR_128BIT(ctx);
920 ctx->ol = MXL_RV32;
921 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL);
922 }
923
924 static bool trans_sraw(DisasContext *ctx, arg_sraw *a)
925 {
926 REQUIRE_64_OR_128BIT(ctx);
927 ctx->ol = MXL_RV32;
928 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL);
929 }
930
931 static bool trans_slld(DisasContext *ctx, arg_slld *a)
932 {
933 REQUIRE_128BIT(ctx);
934 ctx->ol = MXL_RV64;
935 return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl, NULL);
936 }
937
938 static bool trans_srld(DisasContext *ctx, arg_srld *a)
939 {
940 REQUIRE_128BIT(ctx);
941 ctx->ol = MXL_RV64;
942 return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl, NULL);
943 }
944
945 static bool trans_srad(DisasContext *ctx, arg_srad *a)
946 {
947 REQUIRE_128BIT(ctx);
948 ctx->ol = MXL_RV64;
949 return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL);
950 }
951
952 static bool trans_pause(DisasContext *ctx, arg_pause *a)
953 {
954 if (!ctx->cfg_ptr->ext_zihintpause) {
955 return false;
956 }
957
958 /*
959 * PAUSE is a no-op in QEMU,
960 * end the TB and return to main loop
961 */
962 gen_update_pc(ctx, ctx->cur_insn_len);
963 exit_tb(ctx);
964 ctx->base.is_jmp = DISAS_NORETURN;
965
966 return true;
967 }
968
969 static bool trans_fence(DisasContext *ctx, arg_fence *a)
970 {
971 /* FENCE is a full memory barrier. */
972 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
973 return true;
974 }
975
976 static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
977 {
978 if (!ctx->cfg_ptr->ext_zifencei) {
979 return false;
980 }
981
982 /*
983 * FENCE_I is a no-op in QEMU,
984 * however we need to end the translation block
985 */
986 gen_update_pc(ctx, ctx->cur_insn_len);
987 exit_tb(ctx);
988 ctx->base.is_jmp = DISAS_NORETURN;
989 return true;
990 }
991
992 static bool do_csr_post(DisasContext *ctx)
993 {
994 /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
995 decode_save_opc(ctx, 0);
996 /* We may have changed important cpu state -- exit to main loop. */
997 gen_update_pc(ctx, ctx->cur_insn_len);
998 exit_tb(ctx);
999 ctx->base.is_jmp = DISAS_NORETURN;
1000 return true;
1001 }
1002
1003 static bool do_csrr(DisasContext *ctx, int rd, int rc)
1004 {
1005 TCGv dest = dest_gpr(ctx, rd);
1006 TCGv_i32 csr = tcg_constant_i32(rc);
1007
1008 translator_io_start(&ctx->base);
1009 gen_helper_csrr(dest, tcg_env, csr);
1010 gen_set_gpr(ctx, rd, dest);
1011 return do_csr_post(ctx);
1012 }
1013
1014 static bool do_csrw(DisasContext *ctx, int rc, TCGv src)
1015 {
1016 TCGv_i32 csr = tcg_constant_i32(rc);
1017
1018 translator_io_start(&ctx->base);
1019 gen_helper_csrw(tcg_env, csr, src);
1020 return do_csr_post(ctx);
1021 }
1022
1023 static bool do_csrrw(DisasContext *ctx, int rd, int rc, TCGv src, TCGv mask)
1024 {
1025 TCGv dest = dest_gpr(ctx, rd);
1026 TCGv_i32 csr = tcg_constant_i32(rc);
1027
1028 translator_io_start(&ctx->base);
1029 gen_helper_csrrw(dest, tcg_env, csr, src, mask);
1030 gen_set_gpr(ctx, rd, dest);
1031 return do_csr_post(ctx);
1032 }
1033
1034 static bool do_csrr_i128(DisasContext *ctx, int rd, int rc)
1035 {
1036 TCGv destl = dest_gpr(ctx, rd);
1037 TCGv desth = dest_gprh(ctx, rd);
1038 TCGv_i32 csr = tcg_constant_i32(rc);
1039 TCGv_i64 wide_desth = tcg_temp_new_i64();
1040
1041 translator_io_start(&ctx->base);
1042 gen_helper_csrr_i128(destl, tcg_env, csr);
1043 tcg_gen_ld_i64(wide_desth, tcg_env, offsetof(CPURISCVState, retxh));
1044 tcg_gen_trunc_i64_tl(desth, wide_desth);
1045 gen_set_gpr128(ctx, rd, destl, desth);
1046 return do_csr_post(ctx);
1047 }
1048
1049 static bool do_csrw_i128(DisasContext *ctx, int rc, TCGv srcl, TCGv srch)
1050 {
1051 TCGv_i32 csr = tcg_constant_i32(rc);
1052
1053 translator_io_start(&ctx->base);
1054 gen_helper_csrw_i128(tcg_env, csr, srcl, srch);
1055 return do_csr_post(ctx);
1056 }
1057
1058 static bool do_csrrw_i128(DisasContext *ctx, int rd, int rc,
1059 TCGv srcl, TCGv srch, TCGv maskl, TCGv maskh)
1060 {
1061 TCGv destl = dest_gpr(ctx, rd);
1062 TCGv desth = dest_gprh(ctx, rd);
1063 TCGv_i32 csr = tcg_constant_i32(rc);
1064 TCGv_i64 wide_desth = tcg_temp_new_i64();
1065
1066 translator_io_start(&ctx->base);
1067 gen_helper_csrrw_i128(destl, tcg_env, csr, srcl, srch, maskl, maskh);
1068 tcg_gen_ld_i64(wide_desth, tcg_env, offsetof(CPURISCVState, retxh));
1069 tcg_gen_trunc_i64_tl(desth, wide_desth);
1070 gen_set_gpr128(ctx, rd, destl, desth);
1071 return do_csr_post(ctx);
1072 }
1073
1074 static bool trans_csrrw(DisasContext *ctx, arg_csrrw *a)
1075 {
1076 RISCVMXL xl = get_xl(ctx);
1077 if (xl < MXL_RV128) {
1078 TCGv src = get_gpr(ctx, a->rs1, EXT_NONE);
1079
1080 /*
1081 * If rd == 0, the insn shall not read the csr, nor cause any of the
1082 * side effects that might occur on a csr read.
1083 */
1084 if (a->rd == 0) {
1085 return do_csrw(ctx, a->csr, src);
1086 }
1087
1088 TCGv mask = tcg_constant_tl(xl == MXL_RV32 ? UINT32_MAX :
1089 (target_ulong)-1);
1090 return do_csrrw(ctx, a->rd, a->csr, src, mask);
1091 } else {
1092 TCGv srcl = get_gpr(ctx, a->rs1, EXT_NONE);
1093 TCGv srch = get_gprh(ctx, a->rs1);
1094
1095 /*
1096 * If rd == 0, the insn shall not read the csr, nor cause any of the
1097 * side effects that might occur on a csr read.
1098 */
1099 if (a->rd == 0) {
1100 return do_csrw_i128(ctx, a->csr, srcl, srch);
1101 }
1102
1103 TCGv mask = tcg_constant_tl(-1);
1104 return do_csrrw_i128(ctx, a->rd, a->csr, srcl, srch, mask, mask);
1105 }
1106 }
1107
1108 static bool trans_csrrs(DisasContext *ctx, arg_csrrs *a)
1109 {
1110 /*
1111 * If rs1 == 0, the insn shall not write to the csr at all, nor
1112 * cause any of the side effects that might occur on a csr write.
1113 * Note that if rs1 specifies a register other than x0, holding
1114 * a zero value, the instruction will still attempt to write the
1115 * unmodified value back to the csr and will cause side effects.
1116 */
1117 if (get_xl(ctx) < MXL_RV128) {
1118 if (a->rs1 == 0) {
1119 return do_csrr(ctx, a->rd, a->csr);
1120 }
1121
1122 TCGv ones = tcg_constant_tl(-1);
1123 TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
1124 return do_csrrw(ctx, a->rd, a->csr, ones, mask);
1125 } else {
1126 if (a->rs1 == 0) {
1127 return do_csrr_i128(ctx, a->rd, a->csr);
1128 }
1129
1130 TCGv ones = tcg_constant_tl(-1);
1131 TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
1132 TCGv maskh = get_gprh(ctx, a->rs1);
1133 return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, maskl, maskh);
1134 }
1135 }
1136
1137 static bool trans_csrrc(DisasContext *ctx, arg_csrrc *a)
1138 {
1139 /*
1140 * If rs1 == 0, the insn shall not write to the csr at all, nor
1141 * cause any of the side effects that might occur on a csr write.
1142 * Note that if rs1 specifies a register other than x0, holding
1143 * a zero value, the instruction will still attempt to write the
1144 * unmodified value back to the csr and will cause side effects.
1145 */
1146 if (get_xl(ctx) < MXL_RV128) {
1147 if (a->rs1 == 0) {
1148 return do_csrr(ctx, a->rd, a->csr);
1149 }
1150
1151 TCGv mask = get_gpr(ctx, a->rs1, EXT_ZERO);
1152 return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
1153 } else {
1154 if (a->rs1 == 0) {
1155 return do_csrr_i128(ctx, a->rd, a->csr);
1156 }
1157
1158 TCGv maskl = get_gpr(ctx, a->rs1, EXT_ZERO);
1159 TCGv maskh = get_gprh(ctx, a->rs1);
1160 return do_csrrw_i128(ctx, a->rd, a->csr,
1161 ctx->zero, ctx->zero, maskl, maskh);
1162 }
1163 }
1164
1165 static bool trans_csrrwi(DisasContext *ctx, arg_csrrwi *a)
1166 {
1167 RISCVMXL xl = get_xl(ctx);
1168 if (xl < MXL_RV128) {
1169 TCGv src = tcg_constant_tl(a->rs1);
1170
1171 /*
1172 * If rd == 0, the insn shall not read the csr, nor cause any of the
1173 * side effects that might occur on a csr read.
1174 */
1175 if (a->rd == 0) {
1176 return do_csrw(ctx, a->csr, src);
1177 }
1178
1179 TCGv mask = tcg_constant_tl(xl == MXL_RV32 ? UINT32_MAX :
1180 (target_ulong)-1);
1181 return do_csrrw(ctx, a->rd, a->csr, src, mask);
1182 } else {
1183 TCGv src = tcg_constant_tl(a->rs1);
1184
1185 /*
1186 * If rd == 0, the insn shall not read the csr, nor cause any of the
1187 * side effects that might occur on a csr read.
1188 */
1189 if (a->rd == 0) {
1190 return do_csrw_i128(ctx, a->csr, src, ctx->zero);
1191 }
1192
1193 TCGv mask = tcg_constant_tl(-1);
1194 return do_csrrw_i128(ctx, a->rd, a->csr, src, ctx->zero, mask, mask);
1195 }
1196 }
1197
1198 static bool trans_csrrsi(DisasContext *ctx, arg_csrrsi *a)
1199 {
1200 /*
1201 * If rs1 == 0, the insn shall not write to the csr at all, nor
1202 * cause any of the side effects that might occur on a csr write.
1203 * Note that if rs1 specifies a register other than x0, holding
1204 * a zero value, the instruction will still attempt to write the
1205 * unmodified value back to the csr and will cause side effects.
1206 */
1207 if (get_xl(ctx) < MXL_RV128) {
1208 if (a->rs1 == 0) {
1209 return do_csrr(ctx, a->rd, a->csr);
1210 }
1211
1212 TCGv ones = tcg_constant_tl(-1);
1213 TCGv mask = tcg_constant_tl(a->rs1);
1214 return do_csrrw(ctx, a->rd, a->csr, ones, mask);
1215 } else {
1216 if (a->rs1 == 0) {
1217 return do_csrr_i128(ctx, a->rd, a->csr);
1218 }
1219
1220 TCGv ones = tcg_constant_tl(-1);
1221 TCGv mask = tcg_constant_tl(a->rs1);
1222 return do_csrrw_i128(ctx, a->rd, a->csr, ones, ones, mask, ctx->zero);
1223 }
1224 }
1225
1226 static bool trans_csrrci(DisasContext *ctx, arg_csrrci * a)
1227 {
1228 /*
1229 * If rs1 == 0, the insn shall not write to the csr at all, nor
1230 * cause any of the side effects that might occur on a csr write.
1231 * Note that if rs1 specifies a register other than x0, holding
1232 * a zero value, the instruction will still attempt to write the
1233 * unmodified value back to the csr and will cause side effects.
1234 */
1235 if (get_xl(ctx) < MXL_RV128) {
1236 if (a->rs1 == 0) {
1237 return do_csrr(ctx, a->rd, a->csr);
1238 }
1239
1240 TCGv mask = tcg_constant_tl(a->rs1);
1241 return do_csrrw(ctx, a->rd, a->csr, ctx->zero, mask);
1242 } else {
1243 if (a->rs1 == 0) {
1244 return do_csrr_i128(ctx, a->rd, a->csr);
1245 }
1246
1247 TCGv mask = tcg_constant_tl(a->rs1);
1248 return do_csrrw_i128(ctx, a->rd, a->csr,
1249 ctx->zero, ctx->zero, mask, ctx->zero);
1250 }
1251 }