]> git.proxmox.com Git - mirror_qemu.git/blame - target/riscv/translate.c
accel/tcg: Pass max_insn to gen_intermediate_code by pointer
[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 30#include "exec/log.h"
7d7fb116 31#include "semihosting/semihost.h"
55c2a12c
MC
32
33#include "instmap.h"
75804f71 34#include "internals.h"
55c2a12c
MC
35
36/* global register indices */
2b547084 37static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
55c2a12c
MC
38static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
39static TCGv load_res;
40static TCGv load_val;
0774a7a1 41/* globals for PM CSRs */
0cff460d
LZ
42static TCGv pm_mask;
43static TCGv pm_base;
55c2a12c
MC
44
45#include "exec/gen-icount.h"
46
ecda15d1
RH
47/*
48 * If an operation is being performed on less than TARGET_LONG_BITS,
49 * it may require the inputs to be sign- or zero-extended; which will
50 * depend on the exact operation being performed.
51 */
52typedef enum {
53 EXT_NONE,
54 EXT_SIGN,
55 EXT_ZERO,
56} DisasExtend;
57
55c2a12c 58typedef struct DisasContext {
0114db1c
EC
59 DisasContextBase base;
60 /* pc_succ_insn points to the instruction following base.pc_next */
61 target_ulong pc_succ_insn;
d75377bf 62 target_ulong priv_ver;
a2f827ff 63 RISCVMXL misa_mxl_max;
e91a7227
RH
64 RISCVMXL xl;
65 uint32_t misa_ext;
45b4dc8b 66 uint32_t opcode;
83a71719 67 uint32_t mstatus_fs;
8e1ee1fb 68 uint32_t mstatus_vs;
a88f0402 69 uint32_t mstatus_hs_fs;
8e1ee1fb 70 uint32_t mstatus_hs_vs;
55c2a12c 71 uint32_t mem_idx;
55c2a12c
MC
72 /* Remember the rounding mode encoded in the previous fp instruction,
73 which we have already installed into env->fp_status. Or -1 for
74 no previous fp instruction. Note that we exit the TB when writing
75 to any system register, which includes CSR_FRM, so we do not have
76 to reset this known value. */
77 int frm;
7667cafd 78 RISCVMXL ol;
fb3f3730 79 bool virt_inst_excp;
ecda15d1 80 bool virt_enabled;
3b91323e 81 const RISCVCPUConfig *cfg_ptr;
743077b3 82 bool hlsx;
2b7168fc
LZ
83 /* vector extension */
84 bool vill;
33f1beaf
FC
85 /*
86 * Encode LMUL to lmul as follows:
87 * LMUL vlmul lmul
88 * 1 000 0
89 * 2 001 1
90 * 4 010 2
91 * 8 011 3
92 * - 100 -
93 * 1/8 101 -3
94 * 1/4 110 -2
95 * 1/2 111 -1
96 */
97 int8_t lmul;
2b7168fc 98 uint8_t sew;
f1eed927 99 uint8_t vta;
355d5584 100 uint8_t vma;
752614ca 101 bool cfg_vta_all_1s;
f714361e 102 target_ulong vstart;
2b7168fc 103 bool vl_eq_vlmax;
ecda15d1 104 uint8_t ntemp;
a10b9d93 105 CPUState *cs;
ecda15d1
RH
106 TCGv zero;
107 /* Space for 3 operands plus 1 extra for address computation. */
108 TCGv temp[4];
e1a29bbd
WL
109 /* Space for 4 operands(1 dest and <=3 src) for float point computation */
110 TCGv_i64 ftemp[4];
111 uint8_t nftemp;
0774a7a1 112 /* PointerMasking extension */
4208dc7e
LZ
113 bool pm_mask_enabled;
114 bool pm_base_enabled;
2c9d7471
LZ
115 /* Use icount trigger for native debug */
116 bool itrigger;
3ceeb19a
RH
117 /* FRM is known to contain a valid value. */
118 bool frm_valid;
62cf0245
AP
119 /* TCG of the current insn_start */
120 TCGOp *insn_start;
55c2a12c
MC
121} DisasContext;
122
db9f3fd6
MC
123static inline bool has_ext(DisasContext *ctx, uint32_t ext)
124{
e91a7227 125 return ctx->misa_ext & ext;
d36a86d0
RH
126}
127
5e199b6b
PT
128static bool always_true_p(DisasContext *ctx __attribute__((__unused__)))
129{
130 return true;
131}
132
49a7f3aa
CM
133static bool has_xthead_p(DisasContext *ctx __attribute__((__unused__)))
134{
426c0491 135 return ctx->cfg_ptr->ext_xtheadba || ctx->cfg_ptr->ext_xtheadbb ||
fa134585 136 ctx->cfg_ptr->ext_xtheadbs || ctx->cfg_ptr->ext_xtheadcmo ||
d4d90115 137 ctx->cfg_ptr->ext_xtheadcondmov ||
578086ba
CM
138 ctx->cfg_ptr->ext_xtheadfmemidx || ctx->cfg_ptr->ext_xtheadfmv ||
139 ctx->cfg_ptr->ext_xtheadmac || ctx->cfg_ptr->ext_xtheadmemidx ||
140 ctx->cfg_ptr->ext_xtheadmempair || ctx->cfg_ptr->ext_xtheadsync;
49a7f3aa
CM
141}
142
0d429bd2
PT
143#define MATERIALISE_EXT_PREDICATE(ext) \
144 static bool has_ ## ext ## _p(DisasContext *ctx) \
145 { \
146 return ctx->cfg_ptr->ext_ ## ext ; \
147 }
148
149MATERIALISE_EXT_PREDICATE(XVentanaCondOps);
150
4fd7455b 151#ifdef TARGET_RISCV32
905b9fcd 152#define get_xl(ctx) MXL_RV32
4fd7455b 153#elif defined(CONFIG_USER_ONLY)
905b9fcd 154#define get_xl(ctx) MXL_RV64
4fd7455b 155#else
905b9fcd
RH
156#define get_xl(ctx) ((ctx)->xl)
157#endif
158
159/* The word size for this machine mode. */
160static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
4fd7455b 161{
905b9fcd 162 return 16 << get_xl(ctx);
4fd7455b 163}
4fd7455b 164
7667cafd
RH
165/* The operation length, as opposed to the xlen. */
166#ifdef TARGET_RISCV32
167#define get_ol(ctx) MXL_RV32
168#else
169#define get_ol(ctx) ((ctx)->ol)
170#endif
171
172static inline int get_olen(DisasContext *ctx)
89c88309 173{
7667cafd 174 return 16 << get_ol(ctx);
89c88309
RH
175}
176
a2f827ff
FP
177/* The maximum register length */
178#ifdef TARGET_RISCV32
179#define get_xl_max(ctx) MXL_RV32
180#else
181#define get_xl_max(ctx) ((ctx)->misa_mxl_max)
182#endif
183
d36a86d0
RH
184/*
185 * RISC-V requires NaN-boxing of narrower width floating point values.
186 * This applies when a 32-bit value is assigned to a 64-bit FP register.
187 * For consistency and simplicity, we nanbox results even when the RVD
188 * extension is not present.
189 */
190static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
191{
192 tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
ffe70e4d
RH
193}
194
915f77b2
KC
195static void gen_nanbox_h(TCGv_i64 out, TCGv_i64 in)
196{
197 tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(16, 48));
198}
199
ffe70e4d
RH
200/*
201 * A narrow n-bit operation, where n < FLEN, checks that input operands
202 * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
203 * If so, the least-significant bits of the input are used, otherwise the
204 * input value is treated as an n-bit canonical NaN (v2.2 section 9.2).
205 *
206 * Here, the result is always nan-boxed, even the canonical nan.
207 */
7b03c8e5
KC
208static void gen_check_nanbox_h(TCGv_i64 out, TCGv_i64 in)
209{
210 TCGv_i64 t_max = tcg_const_i64(0xffffffffffff0000ull);
211 TCGv_i64 t_nan = tcg_const_i64(0xffffffffffff7e00ull);
212
213 tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
214 tcg_temp_free_i64(t_max);
215 tcg_temp_free_i64(t_nan);
216}
217
ffe70e4d
RH
218static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
219{
05b80ed0
RH
220 TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull);
221 TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull);
ffe70e4d
RH
222
223 tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
db9f3fd6
MC
224}
225
a9814e3e
RH
226static void decode_save_opc(DisasContext *ctx)
227{
228 assert(ctx->insn_start != NULL);
229 tcg_set_insn_start_param(ctx->insn_start, 1, ctx->opcode);
230 ctx->insn_start = NULL;
231}
232
40f0c204
LZ
233static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
234{
235 if (get_xl(ctx) == MXL_RV32) {
236 dest = (int32_t)dest;
237 }
238 tcg_gen_movi_tl(cpu_pc, dest);
239}
240
241static void gen_set_pc(DisasContext *ctx, TCGv dest)
242{
243 if (get_xl(ctx) == MXL_RV32) {
244 tcg_gen_ext32s_tl(cpu_pc, dest);
245 } else {
246 tcg_gen_mov_tl(cpu_pc, dest);
247 }
248}
249
55c2a12c
MC
250static void generate_exception(DisasContext *ctx, int excp)
251{
40f0c204 252 gen_set_pc_imm(ctx, ctx->base.pc_next);
05b80ed0 253 gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
0114db1c 254 ctx->base.is_jmp = DISAS_NORETURN;
55c2a12c
MC
255}
256
55c2a12c
MC
257static void gen_exception_illegal(DisasContext *ctx)
258{
b97028b8
RH
259 tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
260 offsetof(CPURISCVState, bins));
fb3f3730
MC
261 if (ctx->virt_inst_excp) {
262 generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
263 } else {
264 generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
265 }
55c2a12c
MC
266}
267
268static void gen_exception_inst_addr_mis(DisasContext *ctx)
269{
5dacdbae
RH
270 tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
271 generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
55c2a12c
MC
272}
273
2c9d7471
LZ
274static void lookup_and_goto_ptr(DisasContext *ctx)
275{
276#ifndef CONFIG_USER_ONLY
277 if (ctx->itrigger) {
278 gen_helper_itrigger_match(cpu_env);
279 }
280#endif
281 tcg_gen_lookup_and_goto_ptr();
282}
283
284static void exit_tb(DisasContext *ctx)
285{
286#ifndef CONFIG_USER_ONLY
287 if (ctx->itrigger) {
288 gen_helper_itrigger_match(cpu_env);
289 }
290#endif
291 tcg_gen_exit_tb(NULL, 0);
292}
293
55c2a12c
MC
294static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
295{
2c9d7471
LZ
296 /*
297 * Under itrigger, instruction executes one by one like singlestep,
298 * direct block chain benefits will be small.
299 */
300 if (translator_use_goto_tb(&ctx->base, dest) && !ctx->itrigger) {
55c2a12c 301 tcg_gen_goto_tb(n);
40f0c204 302 gen_set_pc_imm(ctx, dest);
07ea28b4 303 tcg_gen_exit_tb(ctx->base.tb, n);
55c2a12c 304 } else {
40f0c204 305 gen_set_pc_imm(ctx, dest);
2c9d7471 306 lookup_and_goto_ptr(ctx);
55c2a12c
MC
307 }
308}
309
ecda15d1
RH
310/*
311 * Wrappers for getting reg values.
312 *
313 * The $zero register does not have cpu_gpr[0] allocated -- we supply the
314 * constant zero as a source, and an uninitialized sink as destination.
315 *
316 * Further, we may provide an extension for word operations.
55c2a12c 317 */
ecda15d1
RH
318static TCGv temp_new(DisasContext *ctx)
319{
320 assert(ctx->ntemp < ARRAY_SIZE(ctx->temp));
321 return ctx->temp[ctx->ntemp++] = tcg_temp_new();
322}
323
324static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
55c2a12c 325{
ecda15d1
RH
326 TCGv t;
327
55c2a12c 328 if (reg_num == 0) {
ecda15d1 329 return ctx->zero;
55c2a12c 330 }
ecda15d1 331
7667cafd
RH
332 switch (get_ol(ctx)) {
333 case MXL_RV32:
334 switch (ext) {
335 case EXT_NONE:
336 break;
337 case EXT_SIGN:
338 t = temp_new(ctx);
339 tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
340 return t;
341 case EXT_ZERO:
342 t = temp_new(ctx);
343 tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
344 return t;
345 default:
346 g_assert_not_reached();
347 }
348 break;
349 case MXL_RV64:
a2f827ff 350 case MXL_RV128:
7667cafd
RH
351 break;
352 default:
353 g_assert_not_reached();
ecda15d1 354 }
7667cafd 355 return cpu_gpr[reg_num];
55c2a12c
MC
356}
357
a2f827ff
FP
358static TCGv get_gprh(DisasContext *ctx, int reg_num)
359{
360 assert(get_xl(ctx) == MXL_RV128);
361 if (reg_num == 0) {
362 return ctx->zero;
363 }
364 return cpu_gprh[reg_num];
365}
366
191d1daf 367static TCGv dest_gpr(DisasContext *ctx, int reg_num)
ecda15d1 368{
7667cafd 369 if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) {
ecda15d1
RH
370 return temp_new(ctx);
371 }
372 return cpu_gpr[reg_num];
373}
374
a2f827ff
FP
375static TCGv dest_gprh(DisasContext *ctx, int reg_num)
376{
377 if (reg_num == 0) {
378 return temp_new(ctx);
379 }
380 return cpu_gprh[reg_num];
381}
382
ecda15d1 383static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
55c2a12c 384{
ecda15d1 385 if (reg_num != 0) {
7667cafd
RH
386 switch (get_ol(ctx)) {
387 case MXL_RV32:
ecda15d1 388 tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
7667cafd
RH
389 break;
390 case MXL_RV64:
a2f827ff 391 case MXL_RV128:
ecda15d1 392 tcg_gen_mov_tl(cpu_gpr[reg_num], t);
7667cafd
RH
393 break;
394 default:
395 g_assert_not_reached();
ecda15d1 396 }
a2f827ff
FP
397
398 if (get_xl_max(ctx) == MXL_RV128) {
399 tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
400 }
401 }
402}
403
57c108b8
FP
404static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
405{
406 if (reg_num != 0) {
407 switch (get_ol(ctx)) {
408 case MXL_RV32:
409 tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
410 break;
411 case MXL_RV64:
412 case MXL_RV128:
413 tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
414 break;
415 default:
416 g_assert_not_reached();
417 }
418
419 if (get_xl_max(ctx) == MXL_RV128) {
420 tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
421 }
422 }
423}
424
a2f827ff
FP
425static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
426{
427 assert(get_ol(ctx) == MXL_RV128);
428 if (reg_num != 0) {
429 tcg_gen_mov_tl(cpu_gpr[reg_num], rl);
430 tcg_gen_mov_tl(cpu_gprh[reg_num], rh);
55c2a12c
MC
431 }
432}
433
e1a29bbd
WL
434static TCGv_i64 ftemp_new(DisasContext *ctx)
435{
436 assert(ctx->nftemp < ARRAY_SIZE(ctx->ftemp));
437 return ctx->ftemp[ctx->nftemp++] = tcg_temp_new_i64();
438}
439
440static TCGv_i64 get_fpr_hs(DisasContext *ctx, int reg_num)
441{
442 if (!ctx->cfg_ptr->ext_zfinx) {
443 return cpu_fpr[reg_num];
444 }
445
446 if (reg_num == 0) {
447 return tcg_constant_i64(0);
448 }
449 switch (get_xl(ctx)) {
450 case MXL_RV32:
451#ifdef TARGET_RISCV32
452 {
453 TCGv_i64 t = ftemp_new(ctx);
454 tcg_gen_ext_i32_i64(t, cpu_gpr[reg_num]);
455 return t;
456 }
457#else
458 /* fall through */
459 case MXL_RV64:
460 return cpu_gpr[reg_num];
461#endif
462 default:
463 g_assert_not_reached();
464 }
465}
466
026e73fa
WL
467static TCGv_i64 get_fpr_d(DisasContext *ctx, int reg_num)
468{
469 if (!ctx->cfg_ptr->ext_zfinx) {
470 return cpu_fpr[reg_num];
471 }
472
473 if (reg_num == 0) {
474 return tcg_constant_i64(0);
475 }
476 switch (get_xl(ctx)) {
477 case MXL_RV32:
478 {
479 TCGv_i64 t = ftemp_new(ctx);
480 tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]);
481 return t;
482 }
483#ifdef TARGET_RISCV64
484 case MXL_RV64:
485 return cpu_gpr[reg_num];
486#endif
487 default:
488 g_assert_not_reached();
489 }
490}
491
e1a29bbd
WL
492static TCGv_i64 dest_fpr(DisasContext *ctx, int reg_num)
493{
494 if (!ctx->cfg_ptr->ext_zfinx) {
495 return cpu_fpr[reg_num];
496 }
497
498 if (reg_num == 0) {
499 return ftemp_new(ctx);
500 }
501
502 switch (get_xl(ctx)) {
503 case MXL_RV32:
504 return ftemp_new(ctx);
505#ifdef TARGET_RISCV64
506 case MXL_RV64:
507 return cpu_gpr[reg_num];
508#endif
509 default:
510 g_assert_not_reached();
511 }
512}
513
514/* assume t is nanboxing (for normal) or sign-extended (for zfinx) */
515static void gen_set_fpr_hs(DisasContext *ctx, int reg_num, TCGv_i64 t)
516{
517 if (!ctx->cfg_ptr->ext_zfinx) {
518 tcg_gen_mov_i64(cpu_fpr[reg_num], t);
519 return;
520 }
521 if (reg_num != 0) {
522 switch (get_xl(ctx)) {
523 case MXL_RV32:
524#ifdef TARGET_RISCV32
525 tcg_gen_extrl_i64_i32(cpu_gpr[reg_num], t);
526 break;
527#else
528 /* fall through */
529 case MXL_RV64:
530 tcg_gen_mov_i64(cpu_gpr[reg_num], t);
531 break;
532#endif
533 default:
534 g_assert_not_reached();
535 }
536 }
537}
538
026e73fa
WL
539static void gen_set_fpr_d(DisasContext *ctx, int reg_num, TCGv_i64 t)
540{
541 if (!ctx->cfg_ptr->ext_zfinx) {
542 tcg_gen_mov_i64(cpu_fpr[reg_num], t);
543 return;
544 }
545
546 if (reg_num != 0) {
547 switch (get_xl(ctx)) {
548 case MXL_RV32:
549#ifdef TARGET_RISCV32
550 tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t);
551 break;
552#else
553 tcg_gen_ext32s_i64(cpu_gpr[reg_num], t);
554 tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32);
555 break;
556 case MXL_RV64:
557 tcg_gen_mov_i64(cpu_gpr[reg_num], t);
558 break;
559#endif
560 default:
561 g_assert_not_reached();
562 }
563 }
564}
565
db9f3fd6 566static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
55c2a12c
MC
567{
568 target_ulong next_pc;
569
570 /* check misaligned: */
0114db1c 571 next_pc = ctx->base.pc_next + imm;
db9f3fd6 572 if (!has_ext(ctx, RVC)) {
55c2a12c
MC
573 if ((next_pc & 0x3) != 0) {
574 gen_exception_inst_addr_mis(ctx);
575 return;
576 }
577 }
55c2a12c 578
a14db52f 579 gen_set_gpri(ctx, rd, ctx->pc_succ_insn);
0114db1c
EC
580 gen_goto_tb(ctx, 0, ctx->base.pc_next + imm); /* must use this for safety */
581 ctx->base.is_jmp = DISAS_NORETURN;
55c2a12c
MC
582}
583
4302bef9
LZ
584/* Compute a canonical address from a register plus offset. */
585static TCGv get_address(DisasContext *ctx, int rs1, int imm)
c655df7f 586{
4302bef9
LZ
587 TCGv addr = temp_new(ctx);
588 TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
589
590 tcg_gen_addi_tl(addr, src1, imm);
4208dc7e 591 if (ctx->pm_mask_enabled) {
dec19f68 592 tcg_gen_andc_tl(addr, addr, pm_mask);
4302bef9
LZ
593 } else if (get_xl(ctx) == MXL_RV32) {
594 tcg_gen_ext32u_tl(addr, addr);
0774a7a1 595 }
4208dc7e
LZ
596 if (ctx->pm_base_enabled) {
597 tcg_gen_or_tl(addr, addr, pm_base);
598 }
4302bef9 599 return addr;
c655df7f
AB
600}
601
45f9df86
CM
602/* Compute a canonical address from a register plus reg offset. */
603static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
604{
605 TCGv addr = temp_new(ctx);
606 TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
607
608 tcg_gen_add_tl(addr, src1, offs);
609 if (ctx->pm_mask_enabled) {
610 tcg_gen_andc_tl(addr, addr, pm_mask);
611 } else if (get_xl(ctx) == MXL_RV32) {
612 tcg_gen_ext32u_tl(addr, addr);
613 }
614 if (ctx->pm_base_enabled) {
615 tcg_gen_or_tl(addr, addr, pm_base);
616 }
617 return addr;
618}
619
533b8f88
RH
620#ifndef CONFIG_USER_ONLY
621/* The states of mstatus_fs are:
622 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
623 * We will have already diagnosed disabled state,
624 * and need to turn initial/clean into dirty.
625 */
626static void mark_fs_dirty(DisasContext *ctx)
627{
628 TCGv tmp;
4fd7455b 629
c163b3ba
WL
630 if (!has_ext(ctx, RVF)) {
631 return;
632 }
633
a88f0402
FC
634 if (ctx->mstatus_fs != MSTATUS_FS) {
635 /* Remember the state change for the rest of the TB. */
636 ctx->mstatus_fs = MSTATUS_FS;
533b8f88 637
a88f0402
FC
638 tmp = tcg_temp_new();
639 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
b550f894 640 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
a88f0402
FC
641 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
642 tcg_temp_free(tmp);
643 }
4fd7455b 644
a88f0402
FC
645 if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
646 /* Remember the stage change for the rest of the TB. */
647 ctx->mstatus_hs_fs = MSTATUS_FS;
45b4dc8b 648
a88f0402 649 tmp = tcg_temp_new();
45b4dc8b 650 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
b550f894 651 tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
45b4dc8b 652 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
a88f0402 653 tcg_temp_free(tmp);
45b4dc8b 654 }
533b8f88
RH
655}
656#else
657static inline void mark_fs_dirty(DisasContext *ctx) { }
658#endif
659
8e1ee1fb
FC
660#ifndef CONFIG_USER_ONLY
661/* The states of mstatus_vs are:
662 * 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
663 * We will have already diagnosed disabled state,
664 * and need to turn initial/clean into dirty.
665 */
666static void mark_vs_dirty(DisasContext *ctx)
667{
668 TCGv tmp;
669
670 if (ctx->mstatus_vs != MSTATUS_VS) {
671 /* Remember the state change for the rest of the TB. */
672 ctx->mstatus_vs = MSTATUS_VS;
673
674 tmp = tcg_temp_new();
675 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
676 tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
677 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
678 tcg_temp_free(tmp);
679 }
680
681 if (ctx->virt_enabled && ctx->mstatus_hs_vs != MSTATUS_VS) {
682 /* Remember the stage change for the rest of the TB. */
683 ctx->mstatus_hs_vs = MSTATUS_VS;
684
685 tmp = tcg_temp_new();
686 tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
687 tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
688 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
689 tcg_temp_free(tmp);
690 }
691}
692#else
693static inline void mark_vs_dirty(DisasContext *ctx) { }
694#endif
695
55c2a12c
MC
696static void gen_set_rm(DisasContext *ctx, int rm)
697{
55c2a12c
MC
698 if (ctx->frm == rm) {
699 return;
700 }
701 ctx->frm = rm;
75804f71 702
3ceeb19a
RH
703 if (rm == RISCV_FRM_DYN) {
704 /* The helper will return only if frm valid. */
705 ctx->frm_valid = true;
706 }
75804f71 707
a9814e3e
RH
708 /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
709 decode_save_opc(ctx);
05b80ed0 710 gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
55c2a12c
MC
711}
712
3ceeb19a
RH
713static void gen_set_rm_chkfrm(DisasContext *ctx, int rm)
714{
715 if (ctx->frm == rm && ctx->frm_valid) {
716 return;
717 }
718 ctx->frm = rm;
719 ctx->frm_valid = true;
720
721 /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
722 decode_save_opc(ctx);
723 gen_helper_set_rounding_mode_chkfrm(cpu_env, tcg_constant_i32(rm));
724}
725
751538d5
LZ
726static int ex_plus_1(DisasContext *ctx, int nf)
727{
728 return nf + 1;
729}
730
2a53cff4 731#define EX_SH(amount) \
451e4ffd 732 static int ex_shift_##amount(DisasContext *ctx, int imm) \
2a53cff4
BK
733 { \
734 return imm << amount; \
735 }
3cca75a6 736EX_SH(1)
e98d9140
BK
737EX_SH(2)
738EX_SH(3)
07b001c6 739EX_SH(4)
2a53cff4
BK
740EX_SH(12)
741
d2e2c1e4
BK
742#define REQUIRE_EXT(ctx, ext) do { \
743 if (!has_ext(ctx, ext)) { \
744 return false; \
745 } \
746} while (0)
7e68e6c7 747
905b9fcd
RH
748#define REQUIRE_32BIT(ctx) do { \
749 if (get_xl(ctx) != MXL_RV32) { \
750 return false; \
751 } \
7e68e6c7 752} while (0)
d2e2c1e4 753
344b4a82
FP
754#define REQUIRE_64BIT(ctx) do { \
755 if (get_xl(ctx) != MXL_RV64) { \
756 return false; \
757 } \
758} while (0)
759
760#define REQUIRE_128BIT(ctx) do { \
761 if (get_xl(ctx) != MXL_RV128) { \
762 return false; \
763 } \
764} while (0)
765
766#define REQUIRE_64_OR_128BIT(ctx) do { \
767 if (get_xl(ctx) == MXL_RV32) { \
768 return false; \
769 } \
daf866b6
AF
770} while (0)
771
d8e81e3c
WL
772#define REQUIRE_EITHER_EXT(ctx, A, B) do { \
773 if (!ctx->cfg_ptr->ext_##A && \
774 !ctx->cfg_ptr->ext_##B) { \
775 return false; \
776 } \
777} while (0)
778
451e4ffd 779static int ex_rvc_register(DisasContext *ctx, int reg)
e98d9140
BK
780{
781 return 8 + reg;
782}
783
33632775 784static int ex_rvc_shiftli(DisasContext *ctx, int imm)
6cafec92
RH
785{
786 /* For RV128 a shamt of 0 means a shift by 64. */
33632775
FP
787 if (get_ol(ctx) == MXL_RV128) {
788 imm = imm ? imm : 64;
789 }
790 return imm;
791}
792
793static int ex_rvc_shiftri(DisasContext *ctx, int imm)
794{
795 /*
796 * For RV128 a shamt of 0 means a shift by 64, furthermore, for right
797 * shifts, the shamt is sign-extended.
798 */
799 if (get_ol(ctx) == MXL_RV128) {
800 imm = imm | (imm & 32) << 1;
801 imm = imm ? imm : 64;
802 }
803 return imm;
6cafec92
RH
804}
805
2a53cff4 806/* Include the auto-generated decoder for 32 bit insn */
abff1abf 807#include "decode-insn32.c.inc"
7a50d3e2 808
a1a3aac4
FP
809static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
810 void (*func)(TCGv, TCGv, target_long))
811{
812 TCGv dest = dest_gpr(ctx, a->rd);
813 TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
814
815 func(dest, src1, a->imm);
816
568f247f
FP
817 if (get_xl(ctx) == MXL_RV128) {
818 TCGv src1h = get_gprh(ctx, a->rs1);
819 TCGv desth = dest_gprh(ctx, a->rd);
820
821 func(desth, src1h, -(a->imm < 0));
822 gen_set_gpr128(ctx, a->rd, dest, desth);
823 } else {
824 gen_set_gpr(ctx, a->rd, dest);
825 }
a1a3aac4
FP
826
827 return true;
828}
829
830static bool gen_logic(DisasContext *ctx, arg_r *a,
831 void (*func)(TCGv, TCGv, TCGv))
832{
833 TCGv dest = dest_gpr(ctx, a->rd);
834 TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
835 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
836
837 func(dest, src1, src2);
838
568f247f
FP
839 if (get_xl(ctx) == MXL_RV128) {
840 TCGv src1h = get_gprh(ctx, a->rs1);
841 TCGv src2h = get_gprh(ctx, a->rs2);
842 TCGv desth = dest_gprh(ctx, a->rd);
843
844 func(desth, src1h, src2h);
845 gen_set_gpr128(ctx, a->rd, dest, desth);
846 } else {
847 gen_set_gpr(ctx, a->rd, dest);
848 }
a1a3aac4
FP
849
850 return true;
851}
852
191d1daf 853static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
7fd40f86
FP
854 void (*func)(TCGv, TCGv, target_long),
855 void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
598aa116 856{
191d1daf
RH
857 TCGv dest = dest_gpr(ctx, a->rd);
858 TCGv src1 = get_gpr(ctx, a->rs1, ext);
598aa116 859
7fd40f86
FP
860 if (get_ol(ctx) < MXL_RV128) {
861 func(dest, src1, a->imm);
862 gen_set_gpr(ctx, a->rd, dest);
863 } else {
864 if (f128 == NULL) {
865 return false;
866 }
867
868 TCGv src1h = get_gprh(ctx, a->rs1);
869 TCGv desth = dest_gprh(ctx, a->rd);
598aa116 870
7fd40f86
FP
871 f128(dest, desth, src1, src1h, a->imm);
872 gen_set_gpr128(ctx, a->rd, dest, desth);
873 }
598aa116
RH
874 return true;
875}
876
191d1daf 877static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
7fd40f86
FP
878 void (*func)(TCGv, TCGv, TCGv),
879 void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
7a50d3e2 880{
191d1daf
RH
881 TCGv dest = dest_gpr(ctx, a->rd);
882 TCGv src1 = get_gpr(ctx, a->rs1, ext);
883 TCGv src2 = tcg_constant_tl(a->imm);
7a50d3e2 884
7fd40f86
FP
885 if (get_ol(ctx) < MXL_RV128) {
886 func(dest, src1, src2);
887 gen_set_gpr(ctx, a->rd, dest);
888 } else {
889 if (f128 == NULL) {
890 return false;
891 }
7a50d3e2 892
7fd40f86
FP
893 TCGv src1h = get_gprh(ctx, a->rs1);
894 TCGv src2h = tcg_constant_tl(-(a->imm < 0));
895 TCGv desth = dest_gprh(ctx, a->rd);
896
897 f128(dest, desth, src1, src1h, src2, src2h);
898 gen_set_gpr128(ctx, a->rd, dest, desth);
899 }
7a50d3e2
BK
900 return true;
901}
902
191d1daf 903static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
7fd40f86
FP
904 void (*func)(TCGv, TCGv, TCGv),
905 void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
f2ab1728 906{
191d1daf
RH
907 TCGv dest = dest_gpr(ctx, a->rd);
908 TCGv src1 = get_gpr(ctx, a->rs1, ext);
909 TCGv src2 = get_gpr(ctx, a->rs2, ext);
f2ab1728 910
7fd40f86
FP
911 if (get_ol(ctx) < MXL_RV128) {
912 func(dest, src1, src2);
913 gen_set_gpr(ctx, a->rd, dest);
914 } else {
915 if (f128 == NULL) {
916 return false;
917 }
918
919 TCGv src1h = get_gprh(ctx, a->rs1);
920 TCGv src2h = get_gprh(ctx, a->rs2);
921 TCGv desth = dest_gprh(ctx, a->rd);
f2ab1728 922
7fd40f86
FP
923 f128(dest, desth, src1, src1h, src2, src2h);
924 gen_set_gpr128(ctx, a->rd, dest, desth);
925 }
f2ab1728
BK
926 return true;
927}
928
80347ae9
RH
929static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
930 void (*f_tl)(TCGv, TCGv, TCGv),
7fd40f86
FP
931 void (*f_32)(TCGv, TCGv, TCGv),
932 void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
80347ae9
RH
933{
934 int olen = get_olen(ctx);
935
936 if (olen != TARGET_LONG_BITS) {
937 if (olen == 32) {
938 f_tl = f_32;
7fd40f86 939 } else if (olen != 128) {
80347ae9
RH
940 g_assert_not_reached();
941 }
942 }
7fd40f86 943 return gen_arith(ctx, a, ext, f_tl, f_128);
80347ae9
RH
944}
945
89c88309 946static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
6bf4bbed
FP
947 void (*func)(TCGv, TCGv, target_long),
948 void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
a10b9d93 949{
89c88309 950 TCGv dest, src1;
7667cafd 951 int max_len = get_olen(ctx);
a10b9d93 952
89c88309 953 if (a->shamt >= max_len) {
981d3568
FC
954 return false;
955 }
956
89c88309
RH
957 dest = dest_gpr(ctx, a->rd);
958 src1 = get_gpr(ctx, a->rs1, ext);
981d3568 959
6bf4bbed
FP
960 if (max_len < 128) {
961 func(dest, src1, a->shamt);
962 gen_set_gpr(ctx, a->rd, dest);
963 } else {
964 TCGv src1h = get_gprh(ctx, a->rs1);
965 TCGv desth = dest_gprh(ctx, a->rd);
981d3568 966
6bf4bbed
FP
967 if (f128 == NULL) {
968 return false;
969 }
970 f128(dest, desth, src1, src1h, a->shamt);
971 gen_set_gpr128(ctx, a->rd, dest, desth);
972 }
981d3568
FC
973 return true;
974}
975
a0245d91
RH
976static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
977 DisasExtend ext,
978 void (*f_tl)(TCGv, TCGv, target_long),
6bf4bbed
FP
979 void (*f_32)(TCGv, TCGv, target_long),
980 void (*f_128)(TCGv, TCGv, TCGv, TCGv,
981 target_long))
a0245d91
RH
982{
983 int olen = get_olen(ctx);
984 if (olen != TARGET_LONG_BITS) {
985 if (olen == 32) {
986 f_tl = f_32;
6bf4bbed 987 } else if (olen != 128) {
a0245d91
RH
988 g_assert_not_reached();
989 }
990 }
6bf4bbed 991 return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
a0245d91
RH
992}
993
89c88309
RH
994static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
995 void (*func)(TCGv, TCGv, TCGv))
23cd1777 996{
89c88309 997 TCGv dest, src1, src2;
7667cafd 998 int max_len = get_olen(ctx);
89c88309
RH
999
1000 if (a->shamt >= max_len) {
1001 return false;
1002 }
23cd1777 1003
89c88309
RH
1004 dest = dest_gpr(ctx, a->rd);
1005 src1 = get_gpr(ctx, a->rs1, ext);
1006 src2 = tcg_constant_tl(a->shamt);
23cd1777 1007
89c88309 1008 func(dest, src1, src2);
23cd1777 1009
89c88309 1010 gen_set_gpr(ctx, a->rd, dest);
23cd1777
FC
1011 return true;
1012}
1013
89c88309 1014static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
6bf4bbed
FP
1015 void (*func)(TCGv, TCGv, TCGv),
1016 void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
981d3568 1017{
89c88309
RH
1018 TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
1019 TCGv ext2 = tcg_temp_new();
6bf4bbed 1020 int max_len = get_olen(ctx);
981d3568 1021
6bf4bbed 1022 tcg_gen_andi_tl(ext2, src2, max_len - 1);
981d3568 1023
6bf4bbed
FP
1024 TCGv dest = dest_gpr(ctx, a->rd);
1025 TCGv src1 = get_gpr(ctx, a->rs1, ext);
1026
1027 if (max_len < 128) {
1028 func(dest, src1, ext2);
1029 gen_set_gpr(ctx, a->rd, dest);
1030 } else {
1031 TCGv src1h = get_gprh(ctx, a->rs1);
1032 TCGv desth = dest_gprh(ctx, a->rd);
1033
1034 if (f128 == NULL) {
1035 return false;
1036 }
1037 f128(dest, desth, src1, src1h, ext2);
1038 gen_set_gpr128(ctx, a->rd, dest, desth);
1039 }
89c88309 1040 tcg_temp_free(ext2);
981d3568
FC
1041 return true;
1042}
1043
a0245d91
RH
1044static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
1045 void (*f_tl)(TCGv, TCGv, TCGv),
6bf4bbed
FP
1046 void (*f_32)(TCGv, TCGv, TCGv),
1047 void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv))
a0245d91
RH
1048{
1049 int olen = get_olen(ctx);
1050 if (olen != TARGET_LONG_BITS) {
1051 if (olen == 32) {
1052 f_tl = f_32;
6bf4bbed 1053 } else if (olen != 128) {
a0245d91
RH
1054 g_assert_not_reached();
1055 }
1056 }
6bf4bbed 1057 return gen_shift(ctx, a, ext, f_tl, f_128);
a0245d91
RH
1058}
1059
60903915
RH
1060static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
1061 void (*func)(TCGv, TCGv))
43824018 1062{
60903915
RH
1063 TCGv dest = dest_gpr(ctx, a->rd);
1064 TCGv src1 = get_gpr(ctx, a->rs1, ext);
43824018 1065
60903915 1066 func(dest, src1);
43824018 1067
60903915 1068 gen_set_gpr(ctx, a->rd, dest);
43824018
KC
1069 return true;
1070}
1071
fdab665f
RH
1072static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
1073 void (*f_tl)(TCGv, TCGv),
1074 void (*f_32)(TCGv, TCGv))
1075{
1076 int olen = get_olen(ctx);
1077
1078 if (olen != TARGET_LONG_BITS) {
1079 if (olen == 32) {
1080 f_tl = f_32;
1081 } else {
1082 g_assert_not_reached();
1083 }
1084 }
1085 return gen_unary(ctx, a, ext, f_tl);
1086}
1087
89c88309
RH
1088static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
1089{
1090 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1091 CPUState *cpu = ctx->cs;
1092 CPURISCVState *env = cpu->env_ptr;
1093
1094 return cpu_ldl_code(env, pc);
1095}
1096
2a53cff4 1097/* Include insn module translation function */
139c1837
PB
1098#include "insn_trans/trans_rvi.c.inc"
1099#include "insn_trans/trans_rvm.c.inc"
1100#include "insn_trans/trans_rva.c.inc"
1101#include "insn_trans/trans_rvf.c.inc"
1102#include "insn_trans/trans_rvd.c.inc"
1103#include "insn_trans/trans_rvh.c.inc"
1104#include "insn_trans/trans_rvv.c.inc"
43824018 1105#include "insn_trans/trans_rvb.c.inc"
260b594d 1106#include "insn_trans/trans_rvzawrs.c.inc"
915f77b2 1107#include "insn_trans/trans_rvzfh.c.inc"
68d19b58 1108#include "insn_trans/trans_rvk.c.inc"
139c1837 1109#include "insn_trans/trans_privileged.c.inc"
c5d77ddd 1110#include "insn_trans/trans_svinval.c.inc"
49a7f3aa
CM
1111#include "decode-xthead.c.inc"
1112#include "insn_trans/trans_xthead.c.inc"
0d429bd2 1113#include "insn_trans/trans_xventanacondops.c.inc"
2a53cff4 1114
59a3a1c0 1115/* Include the auto-generated decoder for 16 bit insn */
abff1abf 1116#include "decode-insn16.c.inc"
0d429bd2
PT
1117/* Include decoders for factored-out extensions */
1118#include "decode-XVentanaCondOps.c.inc"
e98d9140 1119
ef6e987b
RH
1120/* The specification allows for longer insns, but not supported by qemu. */
1121#define MAX_INSN_LEN 4
1122
1123static inline int insn_len(uint16_t first_word)
1124{
1125 return (first_word & 3) == 3 ? 4 : 2;
1126}
1127
25139bf7 1128static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
55c2a12c 1129{
5e199b6b
PT
1130 /*
1131 * A table with predicate (i.e., guard) functions and decoder functions
1132 * that are tested in-order until a decoder matches onto the opcode.
1133 */
1134 static const struct {
1135 bool (*guard_func)(DisasContext *);
1136 bool (*decode_func)(DisasContext *, uint32_t);
1137 } decoders[] = {
1138 { always_true_p, decode_insn32 },
49a7f3aa 1139 { has_xthead_p, decode_xthead },
0d429bd2 1140 { has_XVentanaCondOps_p, decode_XVentanaCodeOps },
5e199b6b
PT
1141 };
1142
fb3f3730 1143 ctx->virt_inst_excp = false;
5e199b6b 1144 /* Check for compressed insn */
ef6e987b 1145 if (insn_len(opcode) == 2) {
ec2918b4
RH
1146 ctx->opcode = opcode;
1147 ctx->pc_succ_insn = ctx->base.pc_next + 2;
1148 if (has_ext(ctx, RVC) && decode_insn16(ctx, opcode)) {
1149 return;
55c2a12c
MC
1150 }
1151 } else {
25139bf7
AB
1152 uint32_t opcode32 = opcode;
1153 opcode32 = deposit32(opcode32, 16, 16,
4e116893
IL
1154 translator_lduw(env, &ctx->base,
1155 ctx->base.pc_next + 2));
ea7b5d5a 1156 ctx->opcode = opcode32;
0114db1c 1157 ctx->pc_succ_insn = ctx->base.pc_next + 4;
5e199b6b
PT
1158
1159 for (size_t i = 0; i < ARRAY_SIZE(decoders); ++i) {
1160 if (decoders[i].guard_func(ctx) &&
1161 decoders[i].decode_func(ctx, opcode32)) {
1162 return;
1163 }
2a53cff4 1164 }
55c2a12c 1165 }
5e199b6b
PT
1166
1167 gen_exception_illegal(ctx);
55c2a12c
MC
1168}
1169
5b4f1d2d 1170static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
55c2a12c 1171{
5b4f1d2d 1172 DisasContext *ctx = container_of(dcbase, DisasContext, base);
d75377bf 1173 CPURISCVState *env = cs->env_ptr;
50fba816 1174 RISCVCPU *cpu = RISCV_CPU(cs);
2b7168fc 1175 uint32_t tb_flags = ctx->base.tb->flags;
55c2a12c 1176
5b4f1d2d 1177 ctx->pc_succ_insn = ctx->base.pc_first;
61d56494 1178 ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
2b7168fc 1179 ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
8e1ee1fb 1180 ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
d75377bf 1181 ctx->priv_ver = env->priv_ver;
45b4dc8b 1182#if !defined(CONFIG_USER_ONLY)
ae84dd0a
AF
1183 if (riscv_has_ext(env, RVH)) {
1184 ctx->virt_enabled = riscv_cpu_virt_enabled(env);
ae84dd0a
AF
1185 } else {
1186 ctx->virt_enabled = false;
1187 }
45b4dc8b
AF
1188#else
1189 ctx->virt_enabled = false;
1190#endif
e91a7227 1191 ctx->misa_ext = env->misa_ext;
5b4f1d2d 1192 ctx->frm = -1; /* unknown rounding mode */
3b91323e 1193 ctx->cfg_ptr = &(cpu->cfg);
a88f0402 1194 ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
8e1ee1fb 1195 ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
743077b3 1196 ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
2b7168fc
LZ
1197 ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
1198 ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
33f1beaf 1199 ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
f1eed927 1200 ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
355d5584 1201 ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s;
752614ca 1202 ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
f714361e 1203 ctx->vstart = env->vstart;
2b7168fc 1204 ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
a2f827ff 1205 ctx->misa_mxl_max = env->misa_mxl_max;
92371bd9 1206 ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
a10b9d93 1207 ctx->cs = cs;
ecda15d1
RH
1208 ctx->ntemp = 0;
1209 memset(ctx->temp, 0, sizeof(ctx->temp));
e1a29bbd
WL
1210 ctx->nftemp = 0;
1211 memset(ctx->ftemp, 0, sizeof(ctx->ftemp));
4208dc7e
LZ
1212 ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
1213 ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
2c9d7471 1214 ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
ecda15d1 1215 ctx->zero = tcg_constant_tl(0);
506c6698 1216 ctx->virt_inst_excp = false;
5b4f1d2d 1217}
55c2a12c 1218
5b4f1d2d
EC
1219static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
1220{
1221}
55c2a12c 1222
5b4f1d2d
EC
1223static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
1224{
1225 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1226
62cf0245
AP
1227 tcg_gen_insn_start(ctx->base.pc_next, 0);
1228 ctx->insn_start = tcg_last_op();
5b4f1d2d
EC
1229}
1230
5b4f1d2d
EC
1231static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
1232{
1233 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1234 CPURISCVState *env = cpu->env_ptr;
4e116893 1235 uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
e1a29bbd 1236 int i;
55c2a12c 1237
7667cafd 1238 ctx->ol = ctx->xl;
25139bf7 1239 decode_opc(env, ctx, opcode16);
5b4f1d2d 1240 ctx->base.pc_next = ctx->pc_succ_insn;
ecda15d1 1241
e1a29bbd 1242 for (i = ctx->ntemp - 1; i >= 0; --i) {
ecda15d1
RH
1243 tcg_temp_free(ctx->temp[i]);
1244 ctx->temp[i] = NULL;
1245 }
1246 ctx->ntemp = 0;
e1a29bbd
WL
1247 for (i = ctx->nftemp - 1; i >= 0; --i) {
1248 tcg_temp_free_i64(ctx->ftemp[i]);
1249 ctx->ftemp[i] = NULL;
1250 }
1251 ctx->nftemp = 0;
5b4f1d2d 1252
00c07344 1253 /* Only the first insn within a TB is allowed to cross a page boundary. */
5b4f1d2d 1254 if (ctx->base.is_jmp == DISAS_NEXT) {
2c9d7471 1255 if (ctx->itrigger || !is_same_page(&ctx->base, ctx->base.pc_next)) {
5b4f1d2d 1256 ctx->base.is_jmp = DISAS_TOO_MANY;
00c07344
RH
1257 } else {
1258 unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
1259
1260 if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
1261 uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
1262 int len = insn_len(next_insn);
1263
1264 if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
1265 ctx->base.is_jmp = DISAS_TOO_MANY;
1266 }
1267 }
55c2a12c 1268 }
55c2a12c 1269 }
5b4f1d2d
EC
1270}
1271
1272static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1273{
1274 DisasContext *ctx = container_of(dcbase, DisasContext, base);
1275
1276 switch (ctx->base.is_jmp) {
b2e32021 1277 case DISAS_TOO_MANY:
ccf08e40 1278 gen_goto_tb(ctx, 0, ctx->base.pc_next);
55c2a12c 1279 break;
b2e32021 1280 case DISAS_NORETURN:
55c2a12c 1281 break;
b2e32021
EC
1282 default:
1283 g_assert_not_reached();
55c2a12c 1284 }
5b4f1d2d
EC
1285}
1286
8eb806a7
RH
1287static void riscv_tr_disas_log(const DisasContextBase *dcbase,
1288 CPUState *cpu, FILE *logfile)
5b4f1d2d 1289{
35f69039
AF
1290#ifndef CONFIG_USER_ONLY
1291 RISCVCPU *rvcpu = RISCV_CPU(cpu);
1292 CPURISCVState *env = &rvcpu->env;
1293#endif
1294
8eb806a7 1295 fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
35f69039 1296#ifndef CONFIG_USER_ONLY
8eb806a7
RH
1297 fprintf(logfile, "Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n",
1298 env->priv, env->virt);
35f69039 1299#endif
8eb806a7 1300 target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
5b4f1d2d
EC
1301}
1302
1303static const TranslatorOps riscv_tr_ops = {
1304 .init_disas_context = riscv_tr_init_disas_context,
1305 .tb_start = riscv_tr_tb_start,
1306 .insn_start = riscv_tr_insn_start,
5b4f1d2d
EC
1307 .translate_insn = riscv_tr_translate_insn,
1308 .tb_stop = riscv_tr_tb_stop,
1309 .disas_log = riscv_tr_disas_log,
1310};
1311
597f9b2d 1312void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
306c8721 1313 target_ulong pc, void *host_pc)
5b4f1d2d
EC
1314{
1315 DisasContext ctx;
1316
306c8721 1317 translator_loop(cs, tb, max_insns, pc, host_pc, &riscv_tr_ops, &ctx.base);
55c2a12c
MC
1318}
1319
1320void riscv_translate_init(void)
1321{
1322 int i;
1323
8e034ae4
RH
1324 /*
1325 * cpu_gpr[0] is a placeholder for the zero register. Do not use it.
1326 * Use the gen_set_gpr and get_gpr helper functions when accessing regs,
1327 * unless you specifically block reads/writes to reg 0.
1328 */
55c2a12c 1329 cpu_gpr[0] = NULL;
2b547084 1330 cpu_gprh[0] = NULL;
55c2a12c
MC
1331
1332 for (i = 1; i < 32; i++) {
1333 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
1334 offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
2b547084
FP
1335 cpu_gprh[i] = tcg_global_mem_new(cpu_env,
1336 offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
55c2a12c
MC
1337 }
1338
1339 for (i = 0; i < 32; i++) {
1340 cpu_fpr[i] = tcg_global_mem_new_i64(cpu_env,
1341 offsetof(CPURISCVState, fpr[i]), riscv_fpr_regnames[i]);
1342 }
1343
1344 cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc");
ad9e5aa2 1345 cpu_vl = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vl), "vl");
f714361e
FC
1346 cpu_vstart = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, vstart),
1347 "vstart");
55c2a12c
MC
1348 load_res = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_res),
1349 "load_res");
1350 load_val = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, load_val),
1351 "load_val");
0774a7a1 1352 /* Assign PM CSRs to tcg globals */
0cff460d
LZ
1353 pm_mask = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmmask),
1354 "pmmask");
1355 pm_base = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, cur_pmbase),
1356 "pmbase");
55c2a12c 1357}