]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/translate.c
target/riscv: Introduce DisasExtend and new helpers
[mirror_qemu.git] / target / riscv / translate.c
CommitLineData
55c2a12c
MC
1/*
2 * RISC-V emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2 or later, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include "qemu/osdep.h"
20#include "qemu/log.h"
21#include "cpu.h"
dcb32f1d 22#include "tcg/tcg-op.h"
55c2a12c
MC
23#include "disas/disas.h"
24#include "exec/cpu_ldst.h"
25#include "exec/exec-all.h"
26#include "exec/helper-proto.h"
27#include "exec/helper-gen.h"
28
b2e32021 29#include "exec/translator.h"
55c2a12c
MC
30#include "exec/log.h"
31
32#include "instmap.h"
33
34/* global register indices */
ad9e5aa2 35static TCGv cpu_gpr[32], cpu_pc, cpu_vl;
55c2a12c
MC
36static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
37static TCGv load_res;
38static TCGv load_val;
39
40#include "exec/gen-icount.h"
41
ecda15d1
RH
42/*
43 * If an operation is being performed on less than TARGET_LONG_BITS,
44 * it may require the inputs to be sign- or zero-extended; which will
45 * depend on the exact operation being performed.
46 */
47typedef enum {
48 EXT_NONE,
49 EXT_SIGN,
50 EXT_ZERO,
51} DisasExtend;
52
55c2a12c 53typedef struct DisasContext {
0114db1c
EC
54 DisasContextBase base;
55 /* pc_succ_insn points to the instruction following base.pc_next */
56 target_ulong pc_succ_insn;
d75377bf 57 target_ulong priv_ver;
ecda15d1 58 target_ulong misa;
45b4dc8b 59 uint32_t opcode;
83a71719 60 uint32_t mstatus_fs;
55c2a12c 61 uint32_t mem_idx;
55c2a12c
MC
62 /* Remember the rounding mode encoded in the previous fp instruction,
63 which we have already installed into env->fp_status. Or -1 for
64 no previous fp instruction. Note that we exit the TB when writing
65 to any system register, which includes CSR_FRM, so we do not have
66 to reset this known value. */
67 int frm;
ecda15d1
RH
68 bool w;
69 bool virt_enabled;
50fba816 70 bool ext_ifencei;
743077b3 71 bool hlsx;
2b7168fc
LZ
72 /* vector extension */
73 bool vill;
74 uint8_t lmul;
75 uint8_t sew;
76 uint16_t vlen;
751538d5 77 uint16_t mlen;
2b7168fc 78 bool vl_eq_vlmax;
ecda15d1 79 uint8_t ntemp;
a10b9d93 80 CPUState *cs;
ecda15d1
RH
81 TCGv zero;
82 /* Space for 3 operands plus 1 extra for address computation. */
83 TCGv temp[4];
55c2a12c
MC
84} DisasContext;
85
db9f3fd6
MC
86static inline bool has_ext(DisasContext *ctx, uint32_t ext)
87{
88 return ctx->misa & ext;
d36a86d0
RH
89}
90
4fd7455b
AF
91#ifdef TARGET_RISCV32
92# define is_32bit(ctx) true
93#elif defined(CONFIG_USER_ONLY)
94# define is_32bit(ctx) false
95#else
96static inline bool is_32bit(DisasContext *ctx)
97{
98 return (ctx->misa & RV32) == RV32;
99}
100#endif
101
d36a86d0
RH
102/*
103 * RISC-V requires NaN-boxing of narrower width floating point values.
104 * This applies when a 32-bit value is assigned to a 64-bit FP register.
105 * For consistency and simplicity, we nanbox results even when the RVD
106 * extension is not present.
107 */
108static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
109{
110 tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
ffe70e4d
RH
111}
112
113/*
114 * A narrow n-bit operation, where n < FLEN, checks that input operands
115 * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
116 * If so, the least-significant bits of the input are used, otherwise the
117 * input value is treated as an n-bit canonical NaN (v2.2 section 9.2).
118 *
119 * Here, the result is always nan-boxed, even the canonical nan.
120 */
121static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
122{
05b80ed0
RH
123 TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull);
124 TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull);
ffe70e4d
RH
125
126 tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
db9f3fd6
MC
127}
128
55c2a12c
MC
129static void generate_exception(DisasContext *ctx, int excp)
130{
0114db1c 131 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
05b80ed0 132 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
0114db1c 133 ctx->base.is_jmp = DISAS_NORETURN;
55c2a12c
MC
134}
135
ac12b601 136static void generate_exception_mtval(DisasContext *ctx, int excp)
55c2a12c 137{
0114db1c 138 tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
55c2a12c 139 tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
05b80ed0 140 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
0114db1c 141 ctx->base.is_jmp = DISAS_NORETURN;
55c2a12c
MC
142}
143
144static void gen_exception_debug(void)
145{
05b80ed0 146 gen_helper_raise_exception(cpu_env, tcg_constant_i32(EXCP_DEBUG));
55c2a12c
MC
147}
148
6e2716d8
FC
149/* Wrapper around tcg_gen_exit_tb that handles single stepping */
150static void exit_tb(DisasContext *ctx)
151{
152 if (ctx->base.singlestep_enabled) {
153 gen_exception_debug();
154 } else {
155 tcg_gen_exit_tb(NULL, 0);
156 }
157}
158
159/* Wrapper around tcg_gen_lookup_and_goto_ptr that handles single stepping */
160static void lookup_and_goto_ptr(DisasContext *ctx)
161{
162 if (ctx->base.singlestep_enabled) {
163 gen_exception_debug();
164 } else {
165 tcg_gen_lookup_and_goto_ptr();
166 }
167}
168
55c2a12c
MC
169static void gen_exception_illegal(DisasContext *ctx)
170{
171 generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
172}
173
174static void gen_exception_inst_addr_mis(DisasContext *ctx)
175{
ac12b601 176 generate_exception_mtval(ctx, RISCV_EXCP_INST_ADDR_MIS);
55c2a12c
MC
177}
178
55c2a12c
MC
179static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
180{
c54d50c1 181 if (translator_use_goto_tb(&ctx->base, dest)) {
55c2a12c
MC
182 tcg_gen_goto_tb(n);
183 tcg_gen_movi_tl(cpu_pc, dest);
07ea28b4 184 tcg_gen_exit_tb(ctx->base.tb, n);
55c2a12c
MC
185 } else {
186 tcg_gen_movi_tl(cpu_pc, dest);
6e2716d8 187 lookup_and_goto_ptr(ctx);
55c2a12c
MC
188 }
189}
190
ecda15d1
RH
191/*
192 * Wrappers for getting reg values.
193 *
194 * The $zero register does not have cpu_gpr[0] allocated -- we supply the
195 * constant zero as a source, and an uninitialized sink as destination.
196 *
197 * Further, we may provide an extension for word operations.
55c2a12c 198 */
ecda15d1
RH
199static TCGv temp_new(DisasContext *ctx)
200{
201 assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
202 return ctx->temp[ctx->ntemp++] = tcg_temp_new();
203}
204
205static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
55c2a12c 206{
ecda15d1
RH
207 TCGv t;
208
55c2a12c 209 if (reg_num == 0) {
ecda15d1 210 return ctx->zero;
55c2a12c 211 }
ecda15d1
RH
212
213 switch (ctx->w ? ext : EXT_NONE) {
214 case EXT_NONE:
215 return cpu_gpr[reg_num];
216 case EXT_SIGN:
217 t = temp_new(ctx);
218 tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
219 return t;
220 case EXT_ZERO:
221 t = temp_new(ctx);
222 tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
223 return t;
224 }
225 g_assert_not_reached();
55c2a12c
MC
226}
227
ecda15d1
RH
228static void gen_get_gpr(DisasContext *ctx, TCGv t, int reg_num)
229{
230 tcg_gen_mov_tl(t, get_gpr(ctx, reg_num, EXT_NONE));
231}
232
233static TCGv __attribute__((unused)) dest_gpr(DisasContext *ctx, int reg_num)
234{
235 if (reg_num == 0 || ctx->w) {
236 return temp_new(ctx);
237 }
238 return cpu_gpr[reg_num];
239}
240
241static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
55c2a12c 242{
ecda15d1
RH
243 if (reg_num != 0) {
244 if (ctx->w) {
245 tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
246 } else {
247 tcg_gen_mov_tl(cpu_gpr[reg_num], t);
248 }
55c2a12c
MC
249 }
250}
251
252static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2)
253{
254 TCGv rl = tcg_temp_new();
255 TCGv rh = tcg_temp_new();
256
257 tcg_gen_mulu2_tl(rl, rh, arg1, arg2);
258 /* fix up for one negative */
259 tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1);
260 tcg_gen_and_tl(rl, rl, arg2);
261 tcg_gen_sub_tl(ret, rh, rl);
262
263 tcg_temp_free(rl);
264 tcg_temp_free(rh);
265}
266
12887016 267static void gen_div(TCGv ret, TCGv source1, TCGv source2)
55c2a12c 268{
4a083b56
RH
269 TCGv temp1, temp2, zero, one, mone, min;
270
271 temp1 = tcg_temp_new();
272 temp2 = tcg_temp_new();
273 zero = tcg_constant_tl(0);
274 one = tcg_constant_tl(1);
275 mone = tcg_constant_tl(-1);
276 min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1));
277
278 /*
279 * If overflow, set temp2 to 1, else source2.
280 * This produces the required result of min.
281 */
282 tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min);
283 tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone);
284 tcg_gen_and_tl(temp1, temp1, temp2);
285 tcg_gen_movcond_tl(TCG_COND_NE, temp2, temp1, zero, one, source2);
286
12887016 287 /*
4a083b56
RH
288 * If div by zero, set temp1 to -1 and temp2 to 1 to
289 * produce the required result of -1.
12887016 290 */
4a083b56
RH
291 tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, mone, source1);
292 tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, temp2);
293
294 tcg_gen_div_tl(ret, temp1, temp2);
295
296 tcg_temp_free(temp1);
297 tcg_temp_free(temp2);
12887016 298}
55c2a12c 299
12887016
BK
300static void gen_divu(TCGv ret, TCGv source1, TCGv source2)
301{
4a083b56
RH
302 TCGv temp1, temp2, zero, one, max;
303
304 temp1 = tcg_temp_new();
305 temp2 = tcg_temp_new();
306 zero = tcg_constant_tl(0);
307 one = tcg_constant_tl(1);
308 max = tcg_constant_tl(~0);
309
310 /*
311 * If div by zero, set temp1 to max and temp2 to 1 to
312 * produce the required result of max.
313 */
314 tcg_gen_movcond_tl(TCG_COND_EQ, temp1, source2, zero, max, source1);
315 tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2);
316 tcg_gen_divu_tl(ret, temp1, temp2);
317
318 tcg_temp_free(temp1);
319 tcg_temp_free(temp2);
12887016 320}
55c2a12c 321
12887016
BK
322static void gen_rem(TCGv ret, TCGv source1, TCGv source2)
323{
4a083b56
RH
324 TCGv temp1, temp2, zero, one, mone, min;
325
326 temp1 = tcg_temp_new();
327 temp2 = tcg_temp_new();
328 zero = tcg_constant_tl(0);
329 one = tcg_constant_tl(1);
330 mone = tcg_constant_tl(-1);
331 min = tcg_constant_tl(1ull << (TARGET_LONG_BITS - 1));
332
333 /*
334 * If overflow, set temp1 to 0, else source1.
335 * This avoids a possible host trap, and produces the required result of 0.
336 */
337 tcg_gen_setcond_tl(TCG_COND_EQ, temp1, source1, min);
338 tcg_gen_setcond_tl(TCG_COND_EQ, temp2, source2, mone);
339 tcg_gen_and_tl(temp1, temp1, temp2);
340 tcg_gen_movcond_tl(TCG_COND_NE, temp1, temp1, zero, zero, source1);
341
342 /*
343 * If div by zero, set temp2 to 1, else source2.
344 * This avoids a possible host trap, but produces an incorrect result.
345 */
346 tcg_gen_movcond_tl(TCG_COND_EQ, temp2, source2, zero, one, source2);
347
348 tcg_gen_rem_tl(temp1, temp1, temp2);
349
350 /* If div by zero, the required result is the original dividend. */
351 tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp1);
352
353 tcg_temp_free(temp1);
354 tcg_temp_free(temp2);
12887016 355}
55c2a12c 356
12887016
BK
357static void gen_remu(TCGv ret, TCGv source1, TCGv source2)
358{
4a083b56
RH
359 TCGv temp, zero, one;
360
361 temp = tcg_temp_new();
362 zero = tcg_constant_tl(0);
363 one = tcg_constant_tl(1);
364
365 /*
366 * If div by zero, set temp to 1, else source2.
367 * This avoids a possible host trap, but produces an incorrect result.
368 */
369 tcg_gen_movcond_tl(TCG_COND_EQ, temp, source2, zero, one, source2);
370
371 tcg_gen_remu_tl(temp, source1, temp);
372
373 /* If div by zero, the required result is the original dividend. */
374 tcg_gen_movcond_tl(TCG_COND_EQ, ret, source2, zero, source1, temp);
375
376 tcg_temp_free(temp);
55c2a12c
MC
377}
378
db9f3fd6 379static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
55c2a12c
MC
380{
381 target_ulong next_pc;
382
383 /* check misaligned: */
0114db1c 384 next_pc = ctx->base.pc_next + imm;
db9f3fd6 385 if (!has_ext(ctx, RVC)) {
55c2a12c
MC
386 if ((next_pc & 0x3) != 0) {
387 gen_exception_inst_addr_mis(ctx);
388 return;
389 }
390 }
391 if (rd != 0) {
0114db1c 392 tcg_gen_movi_tl(cpu_gpr[rd], ctx->pc_succ_insn);
55c2a12c
MC
393 }
394
0114db1c
EC
395 gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */
396 ctx->base.is_jmp = DISAS_NORETURN;
55c2a12c
MC
397}
398
533b8f88
RH
399#ifndef CONFIG_USER_ONLY
400/* The states of mstatus_fs are:
401 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
402 * We will have already diagnosed disabled state,
403 * and need to turn initial/clean into dirty.
404 */
405static void mark_fs_dirty(DisasContext *ctx)
406{
407 TCGv tmp;
4fd7455b
AF
408 target_ulong sd;
409
533b8f88
RH
410 if (ctx->mstatus_fs == MSTATUS_FS) {
411 return;
412 }
413 /* Remember the state change for the rest of the TB. */
414 ctx->mstatus_fs = MSTATUS_FS;
415
416 tmp = tcg_temp_new();
4fd7455b
AF
417 sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD;
418
533b8f88 419 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
4fd7455b 420 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
533b8f88 421 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
45b4dc8b
AF
422
423 if (ctx->virt_enabled) {
424 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
4fd7455b 425 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd);
45b4dc8b
AF
426 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
427 }
533b8f88
RH
428 tcg_temp_free(tmp);
429}
430#else
431static inline void mark_fs_dirty(DisasContext *ctx) { }
432#endif
433
55c2a12c
MC
434static void gen_set_rm(DisasContext *ctx, int rm)
435{
55c2a12c
MC
436 if (ctx->frm == rm) {
437 return;
438 }
439 ctx->frm = rm;
05b80ed0 440 gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
55c2a12c
MC
441}
442
751538d5
LZ
443static int ex_plus_1(DisasContext *ctx, int nf)
444{
445 return nf + 1;
446}
447
2a53cff4 448#define EX_SH(amount) \
451e4ffd 449 static int ex_shift_##amount(DisasContext *ctx, int imm) \
2a53cff4
BK
450 { \
451 return imm << amount; \
452 }
3cca75a6 453EX_SH(1)
e98d9140
BK
454EX_SH(2)
455EX_SH(3)
07b001c6 456EX_SH(4)
2a53cff4
BK
457EX_SH(12)
458
d2e2c1e4
BK
459#define REQUIRE_EXT(ctx, ext) do { \
460 if (!has_ext(ctx, ext)) { \
461 return false; \
462 } \
463} while (0)
464
daf866b6
AF
465#define REQUIRE_64BIT(ctx) do { \
466 if (is_32bit(ctx)) { \
467 return false; \
468 } \
469} while (0)
470
451e4ffd 471static int ex_rvc_register(DisasContext *ctx, int reg)
e98d9140
BK
472{
473 return 8 + reg;
474}
475
6cafec92
RH
476static int ex_rvc_shifti(DisasContext *ctx, int imm)
477{
478 /* For RV128 a shamt of 0 means a shift by 64. */
479 return imm ? imm : 64;
480}
481
2a53cff4 482/* Include the auto-generated decoder for 32 bit insn */
abff1abf 483#include "decode-insn32.c.inc"
7a50d3e2 484
598aa116
RH
485static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a,
486 void (*func)(TCGv, TCGv, target_long))
487{
488 TCGv source1;
489 source1 = tcg_temp_new();
490
867c8196 491 gen_get_gpr(ctx, source1, a->rs1);
598aa116
RH
492
493 (*func)(source1, source1, a->imm);
494
867c8196 495 gen_set_gpr(ctx, a->rd, source1);
598aa116
RH
496 tcg_temp_free(source1);
497 return true;
498}
499
500static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a,
501 void (*func)(TCGv, TCGv, TCGv))
7a50d3e2
BK
502{
503 TCGv source1, source2;
504 source1 = tcg_temp_new();
505 source2 = tcg_temp_new();
506
867c8196 507 gen_get_gpr(ctx, source1, a->rs1);
7a50d3e2
BK
508 tcg_gen_movi_tl(source2, a->imm);
509
510 (*func)(source1, source1, source2);
511
867c8196 512 gen_set_gpr(ctx, a->rd, source1);
7a50d3e2
BK
513 tcg_temp_free(source1);
514 tcg_temp_free(source2);
515 return true;
516}
517
7a50d3e2
BK
518static void gen_addw(TCGv ret, TCGv arg1, TCGv arg2)
519{
520 tcg_gen_add_tl(ret, arg1, arg2);
521 tcg_gen_ext32s_tl(ret, ret);
522}
f2ab1728
BK
523
524static void gen_subw(TCGv ret, TCGv arg1, TCGv arg2)
525{
526 tcg_gen_sub_tl(ret, arg1, arg2);
527 tcg_gen_ext32s_tl(ret, ret);
528}
529
12887016
BK
530static void gen_mulw(TCGv ret, TCGv arg1, TCGv arg2)
531{
532 tcg_gen_mul_tl(ret, arg1, arg2);
533 tcg_gen_ext32s_tl(ret, ret);
534}
535
536static bool gen_arith_div_w(DisasContext *ctx, arg_r *a,
537 void(*func)(TCGv, TCGv, TCGv))
538{
539 TCGv source1, source2;
540 source1 = tcg_temp_new();
541 source2 = tcg_temp_new();
542
867c8196
RH
543 gen_get_gpr(ctx, source1, a->rs1);
544 gen_get_gpr(ctx, source2, a->rs2);
12887016
BK
545 tcg_gen_ext32s_tl(source1, source1);
546 tcg_gen_ext32s_tl(source2, source2);
547
548 (*func)(source1, source1, source2);
549
550 tcg_gen_ext32s_tl(source1, source1);
867c8196 551 gen_set_gpr(ctx, a->rd, source1);
12887016
BK
552 tcg_temp_free(source1);
553 tcg_temp_free(source2);
554 return true;
555}
556
f17e02cd
PD
557static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a,
558 void(*func)(TCGv, TCGv, TCGv))
559{
560 TCGv source1, source2;
561 source1 = tcg_temp_new();
562 source2 = tcg_temp_new();
563
867c8196
RH
564 gen_get_gpr(ctx, source1, a->rs1);
565 gen_get_gpr(ctx, source2, a->rs2);
f17e02cd
PD
566 tcg_gen_ext32u_tl(source1, source1);
567 tcg_gen_ext32u_tl(source2, source2);
568
569 (*func)(source1, source1, source2);
570
571 tcg_gen_ext32s_tl(source1, source1);
867c8196 572 gen_set_gpr(ctx, a->rd, source1);
f17e02cd
PD
573 tcg_temp_free(source1);
574 tcg_temp_free(source2);
575 return true;
576}
577
6ef58431
KC
578static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2)
579{
580 tcg_gen_deposit_tl(ret, arg1, arg2,
581 TARGET_LONG_BITS / 2,
582 TARGET_LONG_BITS / 2);
583}
584
585static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2)
586{
587 TCGv t = tcg_temp_new();
588 tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2);
589 tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2);
590 tcg_temp_free(t);
591}
592
593static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2)
594{
595 TCGv t = tcg_temp_new();
596 tcg_gen_ext8u_tl(t, arg2);
597 tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8);
598 tcg_temp_free(t);
599}
600
23cd1777
FC
601static void gen_sbop_mask(TCGv ret, TCGv shamt)
602{
603 tcg_gen_movi_tl(ret, 1);
604 tcg_gen_shl_tl(ret, ret, shamt);
605}
606
607static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt)
608{
609 TCGv t = tcg_temp_new();
610
611 gen_sbop_mask(t, shamt);
612 tcg_gen_or_tl(ret, arg1, t);
613
614 tcg_temp_free(t);
615}
616
617static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt)
618{
619 TCGv t = tcg_temp_new();
620
621 gen_sbop_mask(t, shamt);
622 tcg_gen_andc_tl(ret, arg1, t);
623
624 tcg_temp_free(t);
625}
626
627static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt)
628{
629 TCGv t = tcg_temp_new();
630
631 gen_sbop_mask(t, shamt);
632 tcg_gen_xor_tl(ret, arg1, t);
633
634 tcg_temp_free(t);
635}
636
637static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt)
638{
639 tcg_gen_shr_tl(ret, arg1, shamt);
640 tcg_gen_andi_tl(ret, ret, 1);
641}
642
91d8fc67
KC
643static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2)
644{
645 tcg_gen_not_tl(ret, arg1);
646 tcg_gen_shl_tl(ret, ret, arg2);
647 tcg_gen_not_tl(ret, ret);
648}
649
650static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2)
651{
652 tcg_gen_not_tl(ret, arg1);
653 tcg_gen_shr_tl(ret, ret, arg2);
654 tcg_gen_not_tl(ret, ret);
655}
656
831ec7f3
FC
657static bool gen_grevi(DisasContext *ctx, arg_grevi *a)
658{
659 TCGv source1 = tcg_temp_new();
660 TCGv source2;
661
867c8196 662 gen_get_gpr(ctx, source1, a->rs1);
831ec7f3
FC
663
664 if (a->shamt == (TARGET_LONG_BITS - 8)) {
665 /* rev8, byte swaps */
666 tcg_gen_bswap_tl(source1, source1);
667 } else {
668 source2 = tcg_temp_new();
669 tcg_gen_movi_tl(source2, a->shamt);
670 gen_helper_grev(source1, source1, source2);
671 tcg_temp_free(source2);
672 }
673
867c8196 674 gen_set_gpr(ctx, a->rd, source1);
831ec7f3
FC
675 tcg_temp_free(source1);
676 return true;
677}
678
920a1f99
KC
679#define GEN_SHADD(SHAMT) \
680static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \
681{ \
682 TCGv t = tcg_temp_new(); \
683 \
684 tcg_gen_shli_tl(t, arg1, SHAMT); \
685 tcg_gen_add_tl(ret, t, arg2); \
686 \
687 tcg_temp_free(t); \
688}
689
690GEN_SHADD(1)
691GEN_SHADD(2)
692GEN_SHADD(3)
693
43824018
KC
694static void gen_ctzw(TCGv ret, TCGv arg1)
695{
696 tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32));
697 tcg_gen_ctzi_tl(ret, ret, 64);
698}
699
700static void gen_clzw(TCGv ret, TCGv arg1)
701{
702 tcg_gen_ext32u_tl(ret, arg1);
703 tcg_gen_clzi_tl(ret, ret, 64);
704 tcg_gen_subi_tl(ret, ret, 32);
705}
706
1e16310c
FC
707static void gen_cpopw(TCGv ret, TCGv arg1)
708{
709 tcg_gen_ext32u_tl(arg1, arg1);
710 tcg_gen_ctpop_tl(ret, arg1);
711}
712
6ef58431
KC
713static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2)
714{
715 TCGv t = tcg_temp_new();
716 tcg_gen_ext16s_tl(t, arg2);
717 tcg_gen_deposit_tl(ret, arg1, t, 16, 48);
718 tcg_temp_free(t);
719}
720
721static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2)
722{
723 TCGv t = tcg_temp_new();
724 tcg_gen_shri_tl(t, arg1, 16);
725 tcg_gen_deposit_tl(ret, arg2, t, 0, 16);
726 tcg_gen_ext32s_tl(ret, ret);
727 tcg_temp_free(t);
728}
729
e58529a8
KC
730static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2)
731{
732 TCGv_i32 t1 = tcg_temp_new_i32();
733 TCGv_i32 t2 = tcg_temp_new_i32();
734
735 /* truncate to 32-bits */
736 tcg_gen_trunc_tl_i32(t1, arg1);
737 tcg_gen_trunc_tl_i32(t2, arg2);
738
739 tcg_gen_rotr_i32(t1, t1, t2);
740
741 /* sign-extend 64-bits */
742 tcg_gen_ext_i32_tl(ret, t1);
743
744 tcg_temp_free_i32(t1);
745 tcg_temp_free_i32(t2);
746}
747
748static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2)
749{
750 TCGv_i32 t1 = tcg_temp_new_i32();
751 TCGv_i32 t2 = tcg_temp_new_i32();
752
753 /* truncate to 32-bits */
754 tcg_gen_trunc_tl_i32(t1, arg1);
755 tcg_gen_trunc_tl_i32(t2, arg2);
756
757 tcg_gen_rotl_i32(t1, t1, t2);
758
759 /* sign-extend 64-bits */
760 tcg_gen_ext_i32_tl(ret, t1);
761
762 tcg_temp_free_i32(t1);
763 tcg_temp_free_i32(t2);
764}
765
831ec7f3
FC
766static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2)
767{
768 tcg_gen_ext32u_tl(arg1, arg1);
769 gen_helper_grev(ret, arg1, arg2);
770}
771
c24f0422
FC
772static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2)
773{
774 tcg_gen_ext32u_tl(arg1, arg1);
775 gen_helper_gorcw(ret, arg1, arg2);
776}
777
920a1f99
KC
778#define GEN_SHADD_UW(SHAMT) \
779static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \
780{ \
781 TCGv t = tcg_temp_new(); \
782 \
783 tcg_gen_ext32u_tl(t, arg1); \
784 \
785 tcg_gen_shli_tl(t, t, SHAMT); \
786 tcg_gen_add_tl(ret, t, arg2); \
787 \
788 tcg_temp_free(t); \
789}
790
791GEN_SHADD_UW(1)
792GEN_SHADD_UW(2)
793GEN_SHADD_UW(3)
794
3a4a43e4
KC
795static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2)
796{
797 tcg_gen_ext32u_tl(arg1, arg1);
798 tcg_gen_add_tl(ret, arg1, arg2);
799}
800
8dc9e8a8
BK
801static bool gen_arith(DisasContext *ctx, arg_r *a,
802 void(*func)(TCGv, TCGv, TCGv))
f2ab1728
BK
803{
804 TCGv source1, source2;
805 source1 = tcg_temp_new();
806 source2 = tcg_temp_new();
807
867c8196
RH
808 gen_get_gpr(ctx, source1, a->rs1);
809 gen_get_gpr(ctx, source2, a->rs2);
f2ab1728
BK
810
811 (*func)(source1, source1, source2);
812
867c8196 813 gen_set_gpr(ctx, a->rd, source1);
f2ab1728
BK
814 tcg_temp_free(source1);
815 tcg_temp_free(source2);
816 return true;
817}
818
34446e84
BK
819static bool gen_shift(DisasContext *ctx, arg_r *a,
820 void(*func)(TCGv, TCGv, TCGv))
821{
822 TCGv source1 = tcg_temp_new();
823 TCGv source2 = tcg_temp_new();
824
867c8196
RH
825 gen_get_gpr(ctx, source1, a->rs1);
826 gen_get_gpr(ctx, source2, a->rs2);
34446e84
BK
827
828 tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
829 (*func)(source1, source1, source2);
830
867c8196 831 gen_set_gpr(ctx, a->rd, source1);
34446e84
BK
832 tcg_temp_free(source1);
833 tcg_temp_free(source2);
834 return true;
835}
836
a10b9d93
KP
837static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
838{
839 DisasContext *ctx = container_of(dcbase, DisasContext, base);
840 CPUState *cpu = ctx->cs;
841 CPURISCVState *env = cpu->env_ptr;
842
843 return cpu_ldl_code(env, pc);
844}
845
981d3568
FC
846static bool gen_shifti(DisasContext *ctx, arg_shift *a,
847 void(*func)(TCGv, TCGv, TCGv))
848{
849 if (a->shamt >= TARGET_LONG_BITS) {
850 return false;
851 }
852
853 TCGv source1 = tcg_temp_new();
854 TCGv source2 = tcg_temp_new();
855
867c8196 856 gen_get_gpr(ctx, source1, a->rs1);
981d3568
FC
857
858 tcg_gen_movi_tl(source2, a->shamt);
859 (*func)(source1, source1, source2);
860
867c8196 861 gen_set_gpr(ctx, a->rd, source1);
981d3568
FC
862 tcg_temp_free(source1);
863 tcg_temp_free(source2);
864 return true;
865}
866
23cd1777
FC
867static bool gen_shiftw(DisasContext *ctx, arg_r *a,
868 void(*func)(TCGv, TCGv, TCGv))
869{
870 TCGv source1 = tcg_temp_new();
871 TCGv source2 = tcg_temp_new();
872
867c8196
RH
873 gen_get_gpr(ctx, source1, a->rs1);
874 gen_get_gpr(ctx, source2, a->rs2);
23cd1777
FC
875
876 tcg_gen_andi_tl(source2, source2, 31);
877 (*func)(source1, source1, source2);
878 tcg_gen_ext32s_tl(source1, source1);
879
867c8196 880 gen_set_gpr(ctx, a->rd, source1);
23cd1777
FC
881 tcg_temp_free(source1);
882 tcg_temp_free(source2);
883 return true;
884}
885
981d3568
FC
886static bool gen_shiftiw(DisasContext *ctx, arg_shift *a,
887 void(*func)(TCGv, TCGv, TCGv))
888{
889 TCGv source1 = tcg_temp_new();
890 TCGv source2 = tcg_temp_new();
891
867c8196 892 gen_get_gpr(ctx, source1, a->rs1);
981d3568
FC
893 tcg_gen_movi_tl(source2, a->shamt);
894
895 (*func)(source1, source1, source2);
896 tcg_gen_ext32s_tl(source1, source1);
897
867c8196 898 gen_set_gpr(ctx, a->rd, source1);
981d3568
FC
899 tcg_temp_free(source1);
900 tcg_temp_free(source2);
901 return true;
902}
903
43824018
KC
904static void gen_ctz(TCGv ret, TCGv arg1)
905{
906 tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS);
907}
908
909static void gen_clz(TCGv ret, TCGv arg1)
910{
911 tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS);
912}
913
914static bool gen_unary(DisasContext *ctx, arg_r2 *a,
915 void(*func)(TCGv, TCGv))
916{
917 TCGv source = tcg_temp_new();
918
867c8196 919 gen_get_gpr(ctx, source, a->rs1);
43824018
KC
920
921 (*func)(source, source);
922
867c8196 923 gen_set_gpr(ctx, a->rd, source);
43824018
KC
924 tcg_temp_free(source);
925 return true;
926}
927
2a53cff4 928/* Include insn module translation function */
139c1837
PB
929#include "insn_trans/trans_rvi.c.inc"
930#include "insn_trans/trans_rvm.c.inc"
931#include "insn_trans/trans_rva.c.inc"
932#include "insn_trans/trans_rvf.c.inc"
933#include "insn_trans/trans_rvd.c.inc"
934#include "insn_trans/trans_rvh.c.inc"
935#include "insn_trans/trans_rvv.c.inc"
43824018 936#include "insn_trans/trans_rvb.c.inc"
139c1837 937#include "insn_trans/trans_privileged.c.inc"
2a53cff4 938
59a3a1c0 939/* Include the auto-generated decoder for 16 bit insn */
abff1abf 940#include "decode-insn16.c.inc"
e98d9140 941
25139bf7 942static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
55c2a12c
MC
943{
944 /* check for compressed insn */
25139bf7 945 if (extract16(opcode, 0, 2) != 3) {
db9f3fd6 946 if (!has_ext(ctx, RVC)) {
55c2a12c
MC
947 gen_exception_illegal(ctx);
948 } else {
0114db1c 949 ctx->pc_succ_insn = ctx->base.pc_next + 2;
25139bf7 950 if (!decode_insn16(ctx, opcode)) {
9a27f69b 951 gen_exception_illegal(ctx);
e98d9140 952 }
55c2a12c
MC
953 }
954 } else {
25139bf7
AB
955 uint32_t opcode32 = opcode;
956 opcode32 = deposit32(opcode32, 16, 16,
957 translator_lduw(env, ctx->base.pc_next + 2));
0114db1c 958 ctx->pc_succ_insn = ctx->base.pc_next + 4;
25139bf7 959 if (!decode_insn32(ctx, opcode32)) {
25e6ca30 960 gen_exception_illegal(ctx);
2a53cff4 961 }
55c2a12c
MC
962 }
963}
964
5b4f1d2d 965static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
55c2a12c 966{
5b4f1d2d 967 DisasContext *ctx = container_of(dcbase, DisasContext, base);
d75377bf 968 CPURISCVState *env = cs->env_ptr;
50fba816 969 RISCVCPU *cpu = RISCV_CPU(cs);
2b7168fc 970 uint32_t tb_flags = ctx->base.tb->flags;
55c2a12c 971
5b4f1d2d 972 ctx->pc_succ_insn = ctx->base.pc_first;
2b7168fc
LZ
973 ctx->mem_idx = tb_flags & TB_FLAGS_MMU_MASK;
974 ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
d75377bf 975 ctx->priv_ver = env->priv_ver;
45b4dc8b 976#if !defined(CONFIG_USER_ONLY)
ae84dd0a
AF
977 if (riscv_has_ext(env, RVH)) {
978 ctx->virt_enabled = riscv_cpu_virt_enabled(env);
ae84dd0a
AF
979 } else {
980 ctx->virt_enabled = false;
981 }
45b4dc8b
AF
982#else
983 ctx->virt_enabled = false;
984#endif
db9f3fd6 985 ctx->misa = env->misa;
5b4f1d2d 986 ctx->frm = -1; /* unknown rounding mode */
50fba816 987 ctx->ext_ifencei = cpu->cfg.ext_ifencei;
2b7168fc 988 ctx->vlen = cpu->cfg.vlen;
743077b3 989 ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
2b7168fc
LZ
990 ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
991 ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
992 ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
751538d5 993 ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul);
2b7168fc 994 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
a10b9d93 995 ctx->cs = cs;
ecda15d1
RH
996 ctx->w = false;
997 ctx->ntemp = 0;
998 memset(ctx->temp, 0, sizeof(ctx->temp));
999
1000 ctx->zero = tcg_constant_tl(0);
5b4f1d2d 1001}
55c2a12c 1002
5b4f1d2d
EC
1003static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1004{
1005}
55c2a12c 1006
5b4f1d2d
EC
1007static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1008{
1009 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1010
1011 tcg_gen_insn_start(ctx->base.pc_next);
1012}
1013
5b4f1d2d
EC
1014static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
1015{
1016 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1017 CPURISCVState *env = cpu->env_ptr;
25139bf7 1018 uint16_t opcode16 = translator_lduw(env, ctx->base.pc_next);
55c2a12c 1019
25139bf7 1020 decode_opc(env, ctx, opcode16);
5b4f1d2d 1021 ctx->base.pc_next = ctx->pc_succ_insn;
ecda15d1
RH
1022 ctx->w = false;
1023
1024 for (int i = ctx->ntemp - 1; i >= 0; --i) {
1025 tcg_temp_free(ctx->temp[i]);
1026 ctx->temp[i] = NULL;
1027 }
1028 ctx->ntemp = 0;
5b4f1d2d
EC
1029
1030 if (ctx->base.is_jmp == DISAS_NEXT) {
1031 target_ulong page_start;
1032
1033 page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
1034 if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
1035 ctx->base.is_jmp = DISAS_TOO_MANY;
55c2a12c 1036 }
55c2a12c 1037 }
5b4f1d2d
EC
1038}
1039
1040static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1041{
1042 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1043
1044 switch (ctx->base.is_jmp) {
b2e32021 1045 case DISAS_TOO_MANY:
ccf08e40 1046 gen_goto_tb(ctx, 0, ctx->base.pc_next);
55c2a12c 1047 break;
b2e32021 1048 case DISAS_NORETURN:
55c2a12c 1049 break;
b2e32021
EC
1050 default:
1051 g_assert_not_reached();
55c2a12c 1052 }
5b4f1d2d
EC
1053}
1054
1055static void riscv_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
1056{
35f69039
AF
1057#ifndef CONFIG_USER_ONLY
1058 RISCVCPU *rvcpu = RISCV_CPU(cpu);
1059 CPURISCVState *env = &rvcpu->env;
1060#endif
1061
5b4f1d2d 1062 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
35f69039
AF
1063#ifndef CONFIG_USER_ONLY
1064 qemu_log("Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n", env->priv, env->virt);
1065#endif
5b4f1d2d
EC
1066 log_target_disas(cpu, dcbase->pc_first, dcbase->tb->size);
1067}
1068
1069static const TranslatorOps riscv_tr_ops = {
1070 .init_disas_context = riscv_tr_init_disas_context,
1071 .tb_start = riscv_tr_tb_start,
1072 .insn_start = riscv_tr_insn_start,
5b4f1d2d
EC
1073 .translate_insn = riscv_tr_translate_insn,
1074 .tb_stop = riscv_tr_tb_stop,
1075 .disas_log = riscv_tr_disas_log,
1076};
1077
8b86d6d2 1078void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
5b4f1d2d
EC
1079{
1080 DisasContext ctx;
1081
8b86d6d2 1082 translator_loop(&riscv_tr_ops, &ctx.base, cs, tb, max_insns);
55c2a12c
MC
1083}
1084
1085void riscv_translate_init(void)
1086{
1087 int i;
1088
1089 /* cpu_gpr[0] is a placeholder for the zero register. Do not use it. */
1090 /* Use the gen_set_gpr and gen_get_gpr helper functions when accessing */
1091 /* registers, unless you specifically block reads/writes to reg 0 */
1092 cpu_gpr[0] = NULL;
1093
1094 for (i = 1; i < 32; i++) {
1095 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
1096 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
1097 }
1098
1099 for (i = 0; i < 32; i++) {
1100 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
1101 offsetof(CPURISCVState, fpr[i]), riscv_fpr_regnames[i]);
1102 }
1103
1104 cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc");
ad9e5aa2 1105 cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl");
55c2a12c
MC
1106 load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res),
1107 "load_res");
1108 load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val),
1109 "load_val");
1110}