155c2a12cSMichael Clark /*
255c2a12cSMichael Clark * RISC-V emulation for qemu: main translation routines.
355c2a12cSMichael Clark *
455c2a12cSMichael Clark * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
555c2a12cSMichael Clark *
655c2a12cSMichael Clark * This program is free software; you can redistribute it and/or modify it
755c2a12cSMichael Clark * under the terms and conditions of the GNU General Public License,
855c2a12cSMichael Clark * version 2 or later, as published by the Free Software Foundation.
955c2a12cSMichael Clark *
1055c2a12cSMichael Clark * This program is distributed in the hope it will be useful, but WITHOUT
1155c2a12cSMichael Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1255c2a12cSMichael Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1355c2a12cSMichael Clark * more details.
1455c2a12cSMichael Clark *
1555c2a12cSMichael Clark * You should have received a copy of the GNU General Public License along with
1655c2a12cSMichael Clark * this program. If not, see <http://www.gnu.org/licenses/>.
1755c2a12cSMichael Clark */
1855c2a12cSMichael Clark
1955c2a12cSMichael Clark #include "qemu/osdep.h"
2055c2a12cSMichael Clark #include "qemu/log.h"
2155c2a12cSMichael Clark #include "cpu.h"
22dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
2355c2a12cSMichael Clark #include "exec/exec-all.h"
2455c2a12cSMichael Clark #include "exec/helper-proto.h"
2555c2a12cSMichael Clark #include "exec/helper-gen.h"
2655c2a12cSMichael Clark
27b2e32021SEmilio G. Cota #include "exec/translator.h"
2855c2a12cSMichael Clark #include "exec/log.h"
297d7fb116SPeter Maydell #include "semihosting/semihost.h"
3055c2a12cSMichael Clark
3175804f71SFrank Chang #include "internals.h"
3255c2a12cSMichael Clark
33d53106c9SRichard Henderson #define HELPER_H "helper.h"
34d53106c9SRichard Henderson #include "exec/helper-info.c.inc"
35d53106c9SRichard Henderson #undef HELPER_H
36d53106c9SRichard Henderson
378c8a7cd6SHuang Tao #include "tcg/tcg-cpu.h"
388c8a7cd6SHuang Tao
3955c2a12cSMichael Clark /* global register indices */
402b547084SFrédéric Pétrot static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc, cpu_vl, cpu_vstart;
4155c2a12cSMichael Clark static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */
4255c2a12cSMichael Clark static TCGv load_res;
4355c2a12cSMichael Clark static TCGv load_val;
440774a7a1SAnatoly Parshintsev /* globals for PM CSRs */
450cff460dSLIU Zhiwei static TCGv pm_mask;
460cff460dSLIU Zhiwei static TCGv pm_base;
4755c2a12cSMichael Clark
48ecda15d1SRichard Henderson /*
49ecda15d1SRichard Henderson * If an operation is being performed on less than TARGET_LONG_BITS,
50ecda15d1SRichard Henderson * it may require the inputs to be sign- or zero-extended; which will
51ecda15d1SRichard Henderson * depend on the exact operation being performed.
52ecda15d1SRichard Henderson */
53ecda15d1SRichard Henderson typedef enum {
54ecda15d1SRichard Henderson EXT_NONE,
55ecda15d1SRichard Henderson EXT_SIGN,
56ecda15d1SRichard Henderson EXT_ZERO,
57ecda15d1SRichard Henderson } DisasExtend;
58ecda15d1SRichard Henderson
5955c2a12cSMichael Clark typedef struct DisasContext {
600114db1cSEmilio G. Cota DisasContextBase base;
618ef23a32SWeiwei Li target_ulong cur_insn_len;
62356c13f9SWeiwei Li target_ulong pc_save;
63d75377bfSAlistair Francis target_ulong priv_ver;
64a2f827ffSFrédéric Pétrot RISCVMXL misa_mxl_max;
65e91a7227SRichard Henderson RISCVMXL xl;
663a610f54SWeiwei Li RISCVMXL address_xl;
67e91a7227SRichard Henderson uint32_t misa_ext;
6845b4dc8bSAlistair Francis uint32_t opcode;
69ebd47648SLIU Zhiwei RISCVExtStatus mstatus_fs;
70ebd47648SLIU Zhiwei RISCVExtStatus mstatus_vs;
7155c2a12cSMichael Clark uint32_t mem_idx;
7247debc72SFei Wu uint32_t priv;
733b57254dSWeiwei Li /*
743b57254dSWeiwei Li * Remember the rounding mode encoded in the previous fp instruction,
753b57254dSWeiwei Li * which we have already installed into env->fp_status. Or -1 for
763b57254dSWeiwei Li * no previous fp instruction. Note that we exit the TB when writing
773b57254dSWeiwei Li * to any system register, which includes CSR_FRM, so we do not have
783b57254dSWeiwei Li * to reset this known value.
793b57254dSWeiwei Li */
8055c2a12cSMichael Clark int frm;
817667cafdSRichard Henderson RISCVMXL ol;
82fb3f3730SMayuresh Chitale bool virt_inst_excp;
83ecda15d1SRichard Henderson bool virt_enabled;
843b91323eSPhilipp Tomsich const RISCVCPUConfig *cfg_ptr;
852b7168fcSLIU Zhiwei /* vector extension */
862b7168fcSLIU Zhiwei bool vill;
8733f1beafSFrank Chang /*
8833f1beafSFrank Chang * Encode LMUL to lmul as follows:
8933f1beafSFrank Chang * LMUL vlmul lmul
9033f1beafSFrank Chang * 1 000 0
9133f1beafSFrank Chang * 2 001 1
9233f1beafSFrank Chang * 4 010 2
9333f1beafSFrank Chang * 8 011 3
9433f1beafSFrank Chang * - 100 -
9533f1beafSFrank Chang * 1/8 101 -3
9633f1beafSFrank Chang * 1/4 110 -2
9733f1beafSFrank Chang * 1/2 111 -1
9833f1beafSFrank Chang */
9933f1beafSFrank Chang int8_t lmul;
1002b7168fcSLIU Zhiwei uint8_t sew;
101f1eed927SeopXD uint8_t vta;
102355d5584SYueh-Ting (eop) Chen uint8_t vma;
103752614caSeopXD bool cfg_vta_all_1s;
1044acaa133SLIU Zhiwei bool vstart_eq_zero;
1052b7168fcSLIU Zhiwei bool vl_eq_vlmax;
106a10b9d93SKeith Packard CPUState *cs;
107ecda15d1SRichard Henderson TCGv zero;
1080774a7a1SAnatoly Parshintsev /* PointerMasking extension */
1094208dc7eSLIU Zhiwei bool pm_mask_enabled;
1104208dc7eSLIU Zhiwei bool pm_base_enabled;
11109c4e887SPalmer Dabbelt /* Ztso */
11209c4e887SPalmer Dabbelt bool ztso;
1132c9d7471SLIU Zhiwei /* Use icount trigger for native debug */
1142c9d7471SLIU Zhiwei bool itrigger;
1153ceeb19aSRichard Henderson /* FRM is known to contain a valid value. */
1163ceeb19aSRichard Henderson bool frm_valid;
117401aa608SRichard Henderson bool insn_start_updated;
1188c8a7cd6SHuang Tao const GPtrArray *decoders;
119b039c961SDeepak Gupta /* zicfilp extension. fcfi_enabled, lp expected or not */
120b039c961SDeepak Gupta bool fcfi_enabled;
121b039c961SDeepak Gupta bool fcfi_lp_expected;
122f9fdf907SDeepak Gupta /* zicfiss extension, if shadow stack was enabled during TB gen */
123f9fdf907SDeepak Gupta bool bcfi_enabled;
12455c2a12cSMichael Clark } DisasContext;
12555c2a12cSMichael Clark
has_ext(DisasContext * ctx,uint32_t ext)126db9f3fd6SMichael Clark static inline bool has_ext(DisasContext *ctx, uint32_t ext)
127db9f3fd6SMichael Clark {
128e91a7227SRichard Henderson return ctx->misa_ext & ext;
129db9f3fd6SMichael Clark }
130db9f3fd6SMichael Clark
1314fd7455bSAlistair Francis #ifdef TARGET_RISCV32
132905b9fcdSRichard Henderson #define get_xl(ctx) MXL_RV32
1334fd7455bSAlistair Francis #elif defined(CONFIG_USER_ONLY)
134905b9fcdSRichard Henderson #define get_xl(ctx) MXL_RV64
1354fd7455bSAlistair Francis #else
136905b9fcdSRichard Henderson #define get_xl(ctx) ((ctx)->xl)
1374fd7455bSAlistair Francis #endif
1384fd7455bSAlistair Francis
1393a610f54SWeiwei Li #ifdef TARGET_RISCV32
1403a610f54SWeiwei Li #define get_address_xl(ctx) MXL_RV32
1413a610f54SWeiwei Li #elif defined(CONFIG_USER_ONLY)
1423a610f54SWeiwei Li #define get_address_xl(ctx) MXL_RV64
1433a610f54SWeiwei Li #else
1443a610f54SWeiwei Li #define get_address_xl(ctx) ((ctx)->address_xl)
1453a610f54SWeiwei Li #endif
1463a610f54SWeiwei Li
147*f06bfe3dSDeepak Gupta #define mxl_memop(ctx) ((get_xl(ctx) + 1) | MO_TE)
148*f06bfe3dSDeepak Gupta
149905b9fcdSRichard Henderson /* The word size for this machine mode. */
get_xlen(DisasContext * ctx)150905b9fcdSRichard Henderson static inline int __attribute__((unused)) get_xlen(DisasContext *ctx)
151905b9fcdSRichard Henderson {
152905b9fcdSRichard Henderson return 16 << get_xl(ctx);
153905b9fcdSRichard Henderson }
154905b9fcdSRichard Henderson
1557667cafdSRichard Henderson /* The operation length, as opposed to the xlen. */
1567667cafdSRichard Henderson #ifdef TARGET_RISCV32
1577667cafdSRichard Henderson #define get_ol(ctx) MXL_RV32
1587667cafdSRichard Henderson #else
1597667cafdSRichard Henderson #define get_ol(ctx) ((ctx)->ol)
1607667cafdSRichard Henderson #endif
16189c88309SRichard Henderson
get_olen(DisasContext * ctx)1627667cafdSRichard Henderson static inline int get_olen(DisasContext *ctx)
1637667cafdSRichard Henderson {
1647667cafdSRichard Henderson return 16 << get_ol(ctx);
1657667cafdSRichard Henderson }
16689c88309SRichard Henderson
167a2f827ffSFrédéric Pétrot /* The maximum register length */
168a2f827ffSFrédéric Pétrot #ifdef TARGET_RISCV32
169a2f827ffSFrédéric Pétrot #define get_xl_max(ctx) MXL_RV32
170a2f827ffSFrédéric Pétrot #else
171a2f827ffSFrédéric Pétrot #define get_xl_max(ctx) ((ctx)->misa_mxl_max)
172a2f827ffSFrédéric Pétrot #endif
173a2f827ffSFrédéric Pétrot
174d36a86d0SRichard Henderson /*
175d36a86d0SRichard Henderson * RISC-V requires NaN-boxing of narrower width floating point values.
176d36a86d0SRichard Henderson * This applies when a 32-bit value is assigned to a 64-bit FP register.
177d36a86d0SRichard Henderson * For consistency and simplicity, we nanbox results even when the RVD
178d36a86d0SRichard Henderson * extension is not present.
179d36a86d0SRichard Henderson */
gen_nanbox_s(TCGv_i64 out,TCGv_i64 in)180d36a86d0SRichard Henderson static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in)
181d36a86d0SRichard Henderson {
182d36a86d0SRichard Henderson tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(32, 32));
183d36a86d0SRichard Henderson }
184d36a86d0SRichard Henderson
gen_nanbox_h(TCGv_i64 out,TCGv_i64 in)185915f77b2SKito Cheng static void gen_nanbox_h(TCGv_i64 out, TCGv_i64 in)
186915f77b2SKito Cheng {
187915f77b2SKito Cheng tcg_gen_ori_i64(out, in, MAKE_64BIT_MASK(16, 48));
188915f77b2SKito Cheng }
189915f77b2SKito Cheng
190ffe70e4dSRichard Henderson /*
191ffe70e4dSRichard Henderson * A narrow n-bit operation, where n < FLEN, checks that input operands
192ffe70e4dSRichard Henderson * are correctly Nan-boxed, i.e., all upper FLEN - n bits are 1.
193ffe70e4dSRichard Henderson * If so, the least-significant bits of the input are used, otherwise the
194ffe70e4dSRichard Henderson * input value is treated as an n-bit canonical NaN (v2.2 section 9.2).
195ffe70e4dSRichard Henderson *
196ffe70e4dSRichard Henderson * Here, the result is always nan-boxed, even the canonical nan.
197ffe70e4dSRichard Henderson */
gen_check_nanbox_h(TCGv_i64 out,TCGv_i64 in)1987b03c8e5SKito Cheng static void gen_check_nanbox_h(TCGv_i64 out, TCGv_i64 in)
1997b03c8e5SKito Cheng {
2002f668fabSRichard Henderson TCGv_i64 t_max = tcg_constant_i64(0xffffffffffff0000ull);
2012f668fabSRichard Henderson TCGv_i64 t_nan = tcg_constant_i64(0xffffffffffff7e00ull);
2027b03c8e5SKito Cheng
2037b03c8e5SKito Cheng tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
2047b03c8e5SKito Cheng }
2057b03c8e5SKito Cheng
gen_check_nanbox_s(TCGv_i64 out,TCGv_i64 in)206ffe70e4dSRichard Henderson static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
207ffe70e4dSRichard Henderson {
20805b80ed0SRichard Henderson TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull);
20905b80ed0SRichard Henderson TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull);
210ffe70e4dSRichard Henderson
211ffe70e4dSRichard Henderson tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
212ffe70e4dSRichard Henderson }
213ffe70e4dSRichard Henderson
decode_save_opc(DisasContext * ctx,target_ulong excp_uw2)214f21b36a0SDeepak Gupta static void decode_save_opc(DisasContext *ctx, target_ulong excp_uw2)
215a9814e3eSRichard Henderson {
216401aa608SRichard Henderson assert(!ctx->insn_start_updated);
217401aa608SRichard Henderson ctx->insn_start_updated = true;
218401aa608SRichard Henderson tcg_set_insn_start_param(ctx->base.insn_start, 1, ctx->opcode);
219f21b36a0SDeepak Gupta tcg_set_insn_start_param(ctx->base.insn_start, 2, excp_uw2);
220a9814e3eSRichard Henderson }
221a9814e3eSRichard Henderson
gen_pc_plus_diff(TCGv target,DisasContext * ctx,target_long diff)222bfc4f9e3SWeiwei Li static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
223227fb82fSWeiwei Li target_long diff)
22440f0c204SLIU Zhiwei {
225227fb82fSWeiwei Li target_ulong dest = ctx->base.pc_next + diff;
226227fb82fSWeiwei Li
227356c13f9SWeiwei Li assert(ctx->pc_save != -1);
228356c13f9SWeiwei Li if (tb_cflags(ctx->base.tb) & CF_PCREL) {
229356c13f9SWeiwei Li tcg_gen_addi_tl(target, cpu_pc, dest - ctx->pc_save);
230356c13f9SWeiwei Li if (get_xl(ctx) == MXL_RV32) {
231356c13f9SWeiwei Li tcg_gen_ext32s_tl(target, target);
232356c13f9SWeiwei Li }
233356c13f9SWeiwei Li } else {
23440f0c204SLIU Zhiwei if (get_xl(ctx) == MXL_RV32) {
23540f0c204SLIU Zhiwei dest = (int32_t)dest;
23640f0c204SLIU Zhiwei }
237bfc4f9e3SWeiwei Li tcg_gen_movi_tl(target, dest);
23840f0c204SLIU Zhiwei }
239356c13f9SWeiwei Li }
24040f0c204SLIU Zhiwei
gen_update_pc(DisasContext * ctx,target_long diff)241022c7550SWeiwei Li static void gen_update_pc(DisasContext *ctx, target_long diff)
24240f0c204SLIU Zhiwei {
243227fb82fSWeiwei Li gen_pc_plus_diff(cpu_pc, ctx, diff);
244356c13f9SWeiwei Li ctx->pc_save = ctx->base.pc_next + diff;
24540f0c204SLIU Zhiwei }
24640f0c204SLIU Zhiwei
generate_exception(DisasContext * ctx,int excp)24755c2a12cSMichael Clark static void generate_exception(DisasContext *ctx, int excp)
24855c2a12cSMichael Clark {
249022c7550SWeiwei Li gen_update_pc(ctx, 0);
250ad75a51eSRichard Henderson gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
2510114db1cSEmilio G. Cota ctx->base.is_jmp = DISAS_NORETURN;
25255c2a12cSMichael Clark }
25355c2a12cSMichael Clark
gen_exception_illegal(DisasContext * ctx)25455c2a12cSMichael Clark static void gen_exception_illegal(DisasContext *ctx)
25555c2a12cSMichael Clark {
256ad75a51eSRichard Henderson tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), tcg_env,
257b97028b8SRichard Henderson offsetof(CPURISCVState, bins));
258fb3f3730SMayuresh Chitale if (ctx->virt_inst_excp) {
259fb3f3730SMayuresh Chitale generate_exception(ctx, RISCV_EXCP_VIRT_INSTRUCTION_FAULT);
260fb3f3730SMayuresh Chitale } else {
26155c2a12cSMichael Clark generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
26255c2a12cSMichael Clark }
263fb3f3730SMayuresh Chitale }
26455c2a12cSMichael Clark
gen_exception_inst_addr_mis(DisasContext * ctx,TCGv target)265bfc4f9e3SWeiwei Li static void gen_exception_inst_addr_mis(DisasContext *ctx, TCGv target)
26655c2a12cSMichael Clark {
267ad75a51eSRichard Henderson tcg_gen_st_tl(target, tcg_env, offsetof(CPURISCVState, badaddr));
2685dacdbaeSRichard Henderson generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
26955c2a12cSMichael Clark }
27055c2a12cSMichael Clark
lookup_and_goto_ptr(DisasContext * ctx)2712c9d7471SLIU Zhiwei static void lookup_and_goto_ptr(DisasContext *ctx)
2722c9d7471SLIU Zhiwei {
2732c9d7471SLIU Zhiwei #ifndef CONFIG_USER_ONLY
2742c9d7471SLIU Zhiwei if (ctx->itrigger) {
275ad75a51eSRichard Henderson gen_helper_itrigger_match(tcg_env);
2762c9d7471SLIU Zhiwei }
2772c9d7471SLIU Zhiwei #endif
2782c9d7471SLIU Zhiwei tcg_gen_lookup_and_goto_ptr();
2792c9d7471SLIU Zhiwei }
2802c9d7471SLIU Zhiwei
exit_tb(DisasContext * ctx)2812c9d7471SLIU Zhiwei static void exit_tb(DisasContext *ctx)
2822c9d7471SLIU Zhiwei {
2832c9d7471SLIU Zhiwei #ifndef CONFIG_USER_ONLY
2842c9d7471SLIU Zhiwei if (ctx->itrigger) {
285ad75a51eSRichard Henderson gen_helper_itrigger_match(tcg_env);
2862c9d7471SLIU Zhiwei }
2872c9d7471SLIU Zhiwei #endif
2882c9d7471SLIU Zhiwei tcg_gen_exit_tb(NULL, 0);
2892c9d7471SLIU Zhiwei }
2902c9d7471SLIU Zhiwei
gen_goto_tb(DisasContext * ctx,int n,target_long diff)2911df8497bSWeiwei Li static void gen_goto_tb(DisasContext *ctx, int n, target_long diff)
29255c2a12cSMichael Clark {
2931df8497bSWeiwei Li target_ulong dest = ctx->base.pc_next + diff;
2941df8497bSWeiwei Li
2952c9d7471SLIU Zhiwei /*
2962c9d7471SLIU Zhiwei * Under itrigger, instruction executes one by one like singlestep,
2972c9d7471SLIU Zhiwei * direct block chain benefits will be small.
2982c9d7471SLIU Zhiwei */
2992c9d7471SLIU Zhiwei if (translator_use_goto_tb(&ctx->base, dest) && !ctx->itrigger) {
300356c13f9SWeiwei Li /*
301356c13f9SWeiwei Li * For pcrel, the pc must always be up-to-date on entry to
302356c13f9SWeiwei Li * the linked TB, so that it can use simple additions for all
303356c13f9SWeiwei Li * further adjustments. For !pcrel, the linked TB is compiled
304356c13f9SWeiwei Li * to know its full virtual address, so we can delay the
305356c13f9SWeiwei Li * update to pc to the unlinked path. A long chain of links
306356c13f9SWeiwei Li * can thus avoid many updates to the PC.
307356c13f9SWeiwei Li */
308356c13f9SWeiwei Li if (tb_cflags(ctx->base.tb) & CF_PCREL) {
309356c13f9SWeiwei Li gen_update_pc(ctx, diff);
310356c13f9SWeiwei Li tcg_gen_goto_tb(n);
311356c13f9SWeiwei Li } else {
31255c2a12cSMichael Clark tcg_gen_goto_tb(n);
313022c7550SWeiwei Li gen_update_pc(ctx, diff);
314356c13f9SWeiwei Li }
31507ea28b4SRichard Henderson tcg_gen_exit_tb(ctx->base.tb, n);
31655c2a12cSMichael Clark } else {
317022c7550SWeiwei Li gen_update_pc(ctx, diff);
3182c9d7471SLIU Zhiwei lookup_and_goto_ptr(ctx);
31955c2a12cSMichael Clark }
32055c2a12cSMichael Clark }
32155c2a12cSMichael Clark
322ecda15d1SRichard Henderson /*
323ecda15d1SRichard Henderson * Wrappers for getting reg values.
324ecda15d1SRichard Henderson *
325ecda15d1SRichard Henderson * The $zero register does not have cpu_gpr[0] allocated -- we supply the
326ecda15d1SRichard Henderson * constant zero as a source, and an uninitialized sink as destination.
327ecda15d1SRichard Henderson *
328ecda15d1SRichard Henderson * Further, we may provide an extension for word operations.
32955c2a12cSMichael Clark */
get_gpr(DisasContext * ctx,int reg_num,DisasExtend ext)330ecda15d1SRichard Henderson static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext)
33155c2a12cSMichael Clark {
332ecda15d1SRichard Henderson TCGv t;
333ecda15d1SRichard Henderson
334ecda15d1SRichard Henderson if (reg_num == 0) {
335ecda15d1SRichard Henderson return ctx->zero;
336ecda15d1SRichard Henderson }
337ecda15d1SRichard Henderson
3387667cafdSRichard Henderson switch (get_ol(ctx)) {
3397667cafdSRichard Henderson case MXL_RV32:
3407667cafdSRichard Henderson switch (ext) {
341ecda15d1SRichard Henderson case EXT_NONE:
3427667cafdSRichard Henderson break;
343ecda15d1SRichard Henderson case EXT_SIGN:
344574f3116SRichard Henderson t = tcg_temp_new();
345ecda15d1SRichard Henderson tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]);
346ecda15d1SRichard Henderson return t;
347ecda15d1SRichard Henderson case EXT_ZERO:
348574f3116SRichard Henderson t = tcg_temp_new();
349ecda15d1SRichard Henderson tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]);
350ecda15d1SRichard Henderson return t;
3517667cafdSRichard Henderson default:
352ecda15d1SRichard Henderson g_assert_not_reached();
353ecda15d1SRichard Henderson }
3547667cafdSRichard Henderson break;
3557667cafdSRichard Henderson case MXL_RV64:
356a2f827ffSFrédéric Pétrot case MXL_RV128:
3577667cafdSRichard Henderson break;
3587667cafdSRichard Henderson default:
3597667cafdSRichard Henderson g_assert_not_reached();
3607667cafdSRichard Henderson }
3617667cafdSRichard Henderson return cpu_gpr[reg_num];
3627667cafdSRichard Henderson }
363ecda15d1SRichard Henderson
get_gprh(DisasContext * ctx,int reg_num)364a2f827ffSFrédéric Pétrot static TCGv get_gprh(DisasContext *ctx, int reg_num)
365a2f827ffSFrédéric Pétrot {
366a2f827ffSFrédéric Pétrot assert(get_xl(ctx) == MXL_RV128);
367a2f827ffSFrédéric Pétrot if (reg_num == 0) {
368a2f827ffSFrédéric Pétrot return ctx->zero;
369a2f827ffSFrédéric Pétrot }
370a2f827ffSFrédéric Pétrot return cpu_gprh[reg_num];
371a2f827ffSFrédéric Pétrot }
372a2f827ffSFrédéric Pétrot
dest_gpr(DisasContext * ctx,int reg_num)373191d1dafSRichard Henderson static TCGv dest_gpr(DisasContext *ctx, int reg_num)
374ecda15d1SRichard Henderson {
3757667cafdSRichard Henderson if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) {
376574f3116SRichard Henderson return tcg_temp_new();
377ecda15d1SRichard Henderson }
378ecda15d1SRichard Henderson return cpu_gpr[reg_num];
379ecda15d1SRichard Henderson }
380ecda15d1SRichard Henderson
dest_gprh(DisasContext * ctx,int reg_num)381a2f827ffSFrédéric Pétrot static TCGv dest_gprh(DisasContext *ctx, int reg_num)
382a2f827ffSFrédéric Pétrot {
383a2f827ffSFrédéric Pétrot if (reg_num == 0) {
384574f3116SRichard Henderson return tcg_temp_new();
385a2f827ffSFrédéric Pétrot }
386a2f827ffSFrédéric Pétrot return cpu_gprh[reg_num];
387a2f827ffSFrédéric Pétrot }
388a2f827ffSFrédéric Pétrot
gen_set_gpr(DisasContext * ctx,int reg_num,TCGv t)389ecda15d1SRichard Henderson static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t)
390ecda15d1SRichard Henderson {
391ecda15d1SRichard Henderson if (reg_num != 0) {
3927667cafdSRichard Henderson switch (get_ol(ctx)) {
3937667cafdSRichard Henderson case MXL_RV32:
394ecda15d1SRichard Henderson tcg_gen_ext32s_tl(cpu_gpr[reg_num], t);
3957667cafdSRichard Henderson break;
3967667cafdSRichard Henderson case MXL_RV64:
397a2f827ffSFrédéric Pétrot case MXL_RV128:
398ecda15d1SRichard Henderson tcg_gen_mov_tl(cpu_gpr[reg_num], t);
3997667cafdSRichard Henderson break;
4007667cafdSRichard Henderson default:
4017667cafdSRichard Henderson g_assert_not_reached();
402ecda15d1SRichard Henderson }
403a2f827ffSFrédéric Pétrot
404a2f827ffSFrédéric Pétrot if (get_xl_max(ctx) == MXL_RV128) {
405a2f827ffSFrédéric Pétrot tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63);
406a2f827ffSFrédéric Pétrot }
407a2f827ffSFrédéric Pétrot }
408a2f827ffSFrédéric Pétrot }
409a2f827ffSFrédéric Pétrot
gen_set_gpri(DisasContext * ctx,int reg_num,target_long imm)41057c108b8SFrédéric Pétrot static void gen_set_gpri(DisasContext *ctx, int reg_num, target_long imm)
41157c108b8SFrédéric Pétrot {
41257c108b8SFrédéric Pétrot if (reg_num != 0) {
41357c108b8SFrédéric Pétrot switch (get_ol(ctx)) {
41457c108b8SFrédéric Pétrot case MXL_RV32:
41557c108b8SFrédéric Pétrot tcg_gen_movi_tl(cpu_gpr[reg_num], (int32_t)imm);
41657c108b8SFrédéric Pétrot break;
41757c108b8SFrédéric Pétrot case MXL_RV64:
41857c108b8SFrédéric Pétrot case MXL_RV128:
41957c108b8SFrédéric Pétrot tcg_gen_movi_tl(cpu_gpr[reg_num], imm);
42057c108b8SFrédéric Pétrot break;
42157c108b8SFrédéric Pétrot default:
42257c108b8SFrédéric Pétrot g_assert_not_reached();
42357c108b8SFrédéric Pétrot }
42457c108b8SFrédéric Pétrot
42557c108b8SFrédéric Pétrot if (get_xl_max(ctx) == MXL_RV128) {
42657c108b8SFrédéric Pétrot tcg_gen_movi_tl(cpu_gprh[reg_num], -(imm < 0));
42757c108b8SFrédéric Pétrot }
42857c108b8SFrédéric Pétrot }
42957c108b8SFrédéric Pétrot }
43057c108b8SFrédéric Pétrot
gen_set_gpr128(DisasContext * ctx,int reg_num,TCGv rl,TCGv rh)431a2f827ffSFrédéric Pétrot static void gen_set_gpr128(DisasContext *ctx, int reg_num, TCGv rl, TCGv rh)
432a2f827ffSFrédéric Pétrot {
433a2f827ffSFrédéric Pétrot assert(get_ol(ctx) == MXL_RV128);
434a2f827ffSFrédéric Pétrot if (reg_num != 0) {
435a2f827ffSFrédéric Pétrot tcg_gen_mov_tl(cpu_gpr[reg_num], rl);
436a2f827ffSFrédéric Pétrot tcg_gen_mov_tl(cpu_gprh[reg_num], rh);
43755c2a12cSMichael Clark }
43855c2a12cSMichael Clark }
43955c2a12cSMichael Clark
get_fpr_hs(DisasContext * ctx,int reg_num)440e1a29bbdSWeiwei Li static TCGv_i64 get_fpr_hs(DisasContext *ctx, int reg_num)
441e1a29bbdSWeiwei Li {
442e1a29bbdSWeiwei Li if (!ctx->cfg_ptr->ext_zfinx) {
443e1a29bbdSWeiwei Li return cpu_fpr[reg_num];
444e1a29bbdSWeiwei Li }
445e1a29bbdSWeiwei Li
446e1a29bbdSWeiwei Li if (reg_num == 0) {
447e1a29bbdSWeiwei Li return tcg_constant_i64(0);
448e1a29bbdSWeiwei Li }
449e1a29bbdSWeiwei Li switch (get_xl(ctx)) {
450e1a29bbdSWeiwei Li case MXL_RV32:
451e1a29bbdSWeiwei Li #ifdef TARGET_RISCV32
452e1a29bbdSWeiwei Li {
4535d509451SRichard Henderson TCGv_i64 t = tcg_temp_new_i64();
454e1a29bbdSWeiwei Li tcg_gen_ext_i32_i64(t, cpu_gpr[reg_num]);
455e1a29bbdSWeiwei Li return t;
456e1a29bbdSWeiwei Li }
457e1a29bbdSWeiwei Li #else
458e1a29bbdSWeiwei Li /* fall through */
459e1a29bbdSWeiwei Li case MXL_RV64:
460e1a29bbdSWeiwei Li return cpu_gpr[reg_num];
461e1a29bbdSWeiwei Li #endif
462e1a29bbdSWeiwei Li default:
463e1a29bbdSWeiwei Li g_assert_not_reached();
464e1a29bbdSWeiwei Li }
465e1a29bbdSWeiwei Li }
466e1a29bbdSWeiwei Li
get_fpr_d(DisasContext * ctx,int reg_num)467026e73faSWeiwei Li static TCGv_i64 get_fpr_d(DisasContext *ctx, int reg_num)
468026e73faSWeiwei Li {
469026e73faSWeiwei Li if (!ctx->cfg_ptr->ext_zfinx) {
470026e73faSWeiwei Li return cpu_fpr[reg_num];
471026e73faSWeiwei Li }
472026e73faSWeiwei Li
473026e73faSWeiwei Li if (reg_num == 0) {
474026e73faSWeiwei Li return tcg_constant_i64(0);
475026e73faSWeiwei Li }
476026e73faSWeiwei Li switch (get_xl(ctx)) {
477026e73faSWeiwei Li case MXL_RV32:
478026e73faSWeiwei Li {
4795d509451SRichard Henderson TCGv_i64 t = tcg_temp_new_i64();
480026e73faSWeiwei Li tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]);
481026e73faSWeiwei Li return t;
482026e73faSWeiwei Li }
483026e73faSWeiwei Li #ifdef TARGET_RISCV64
484026e73faSWeiwei Li case MXL_RV64:
485026e73faSWeiwei Li return cpu_gpr[reg_num];
486026e73faSWeiwei Li #endif
487026e73faSWeiwei Li default:
488026e73faSWeiwei Li g_assert_not_reached();
489026e73faSWeiwei Li }
490026e73faSWeiwei Li }
491026e73faSWeiwei Li
dest_fpr(DisasContext * ctx,int reg_num)492e1a29bbdSWeiwei Li static TCGv_i64 dest_fpr(DisasContext *ctx, int reg_num)
493e1a29bbdSWeiwei Li {
494e1a29bbdSWeiwei Li if (!ctx->cfg_ptr->ext_zfinx) {
495e1a29bbdSWeiwei Li return cpu_fpr[reg_num];
496e1a29bbdSWeiwei Li }
497e1a29bbdSWeiwei Li
498e1a29bbdSWeiwei Li if (reg_num == 0) {
4995d509451SRichard Henderson return tcg_temp_new_i64();
500e1a29bbdSWeiwei Li }
501e1a29bbdSWeiwei Li
502e1a29bbdSWeiwei Li switch (get_xl(ctx)) {
503e1a29bbdSWeiwei Li case MXL_RV32:
5045d509451SRichard Henderson return tcg_temp_new_i64();
505e1a29bbdSWeiwei Li #ifdef TARGET_RISCV64
506e1a29bbdSWeiwei Li case MXL_RV64:
507e1a29bbdSWeiwei Li return cpu_gpr[reg_num];
508e1a29bbdSWeiwei Li #endif
509e1a29bbdSWeiwei Li default:
510e1a29bbdSWeiwei Li g_assert_not_reached();
511e1a29bbdSWeiwei Li }
512e1a29bbdSWeiwei Li }
513e1a29bbdSWeiwei Li
5143b57254dSWeiwei Li /* assume it is nanboxing (for normal) or sign-extended (for zfinx) */
gen_set_fpr_hs(DisasContext * ctx,int reg_num,TCGv_i64 t)515e1a29bbdSWeiwei Li static void gen_set_fpr_hs(DisasContext *ctx, int reg_num, TCGv_i64 t)
516e1a29bbdSWeiwei Li {
517e1a29bbdSWeiwei Li if (!ctx->cfg_ptr->ext_zfinx) {
518e1a29bbdSWeiwei Li tcg_gen_mov_i64(cpu_fpr[reg_num], t);
519e1a29bbdSWeiwei Li return;
520e1a29bbdSWeiwei Li }
521e1a29bbdSWeiwei Li if (reg_num != 0) {
522e1a29bbdSWeiwei Li switch (get_xl(ctx)) {
523e1a29bbdSWeiwei Li case MXL_RV32:
524e1a29bbdSWeiwei Li #ifdef TARGET_RISCV32
525e1a29bbdSWeiwei Li tcg_gen_extrl_i64_i32(cpu_gpr[reg_num], t);
526e1a29bbdSWeiwei Li break;
527e1a29bbdSWeiwei Li #else
528e1a29bbdSWeiwei Li /* fall through */
529e1a29bbdSWeiwei Li case MXL_RV64:
530e1a29bbdSWeiwei Li tcg_gen_mov_i64(cpu_gpr[reg_num], t);
531e1a29bbdSWeiwei Li break;
532e1a29bbdSWeiwei Li #endif
533e1a29bbdSWeiwei Li default:
534e1a29bbdSWeiwei Li g_assert_not_reached();
535e1a29bbdSWeiwei Li }
536e1a29bbdSWeiwei Li }
537e1a29bbdSWeiwei Li }
538e1a29bbdSWeiwei Li
gen_set_fpr_d(DisasContext * ctx,int reg_num,TCGv_i64 t)539026e73faSWeiwei Li static void gen_set_fpr_d(DisasContext *ctx, int reg_num, TCGv_i64 t)
540026e73faSWeiwei Li {
541026e73faSWeiwei Li if (!ctx->cfg_ptr->ext_zfinx) {
542026e73faSWeiwei Li tcg_gen_mov_i64(cpu_fpr[reg_num], t);
543026e73faSWeiwei Li return;
544026e73faSWeiwei Li }
545026e73faSWeiwei Li
546026e73faSWeiwei Li if (reg_num != 0) {
547026e73faSWeiwei Li switch (get_xl(ctx)) {
548026e73faSWeiwei Li case MXL_RV32:
549026e73faSWeiwei Li #ifdef TARGET_RISCV32
550026e73faSWeiwei Li tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t);
551026e73faSWeiwei Li break;
552026e73faSWeiwei Li #else
553026e73faSWeiwei Li tcg_gen_ext32s_i64(cpu_gpr[reg_num], t);
554026e73faSWeiwei Li tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32);
555026e73faSWeiwei Li break;
556026e73faSWeiwei Li case MXL_RV64:
557026e73faSWeiwei Li tcg_gen_mov_i64(cpu_gpr[reg_num], t);
558026e73faSWeiwei Li break;
559026e73faSWeiwei Li #endif
560026e73faSWeiwei Li default:
561026e73faSWeiwei Li g_assert_not_reached();
562026e73faSWeiwei Li }
563026e73faSWeiwei Li }
564026e73faSWeiwei Li }
565026e73faSWeiwei Li
gen_jal(DisasContext * ctx,int rd,target_ulong imm)566db9f3fd6SMichael Clark static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)
56755c2a12cSMichael Clark {
568356c13f9SWeiwei Li TCGv succ_pc = dest_gpr(ctx, rd);
569356c13f9SWeiwei Li
57055c2a12cSMichael Clark /* check misaligned: */
571d33e39f9SWeiwei Li if (!has_ext(ctx, RVC) && !ctx->cfg_ptr->ext_zca) {
572227fb82fSWeiwei Li if ((imm & 0x3) != 0) {
573bfc4f9e3SWeiwei Li TCGv target_pc = tcg_temp_new();
574227fb82fSWeiwei Li gen_pc_plus_diff(target_pc, ctx, imm);
575bfc4f9e3SWeiwei Li gen_exception_inst_addr_mis(ctx, target_pc);
57655c2a12cSMichael Clark return;
57755c2a12cSMichael Clark }
57855c2a12cSMichael Clark }
57955c2a12cSMichael Clark
580356c13f9SWeiwei Li gen_pc_plus_diff(succ_pc, ctx, ctx->cur_insn_len);
581356c13f9SWeiwei Li gen_set_gpr(ctx, rd, succ_pc);
582356c13f9SWeiwei Li
5831df8497bSWeiwei Li gen_goto_tb(ctx, 0, imm); /* must use this for safety */
5840114db1cSEmilio G. Cota ctx->base.is_jmp = DISAS_NORETURN;
58555c2a12cSMichael Clark }
58655c2a12cSMichael Clark
5874302bef9SLIU Zhiwei /* Compute a canonical address from a register plus offset. */
get_address(DisasContext * ctx,int rs1,int imm)5884302bef9SLIU Zhiwei static TCGv get_address(DisasContext *ctx, int rs1, int imm)
589c655df7fSAlexey Baturo {
590574f3116SRichard Henderson TCGv addr = tcg_temp_new();
5914302bef9SLIU Zhiwei TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
5924302bef9SLIU Zhiwei
5934302bef9SLIU Zhiwei tcg_gen_addi_tl(addr, src1, imm);
5944208dc7eSLIU Zhiwei if (ctx->pm_mask_enabled) {
595dec19f68SAlexey Baturo tcg_gen_andc_tl(addr, addr, pm_mask);
5963a610f54SWeiwei Li } else if (get_address_xl(ctx) == MXL_RV32) {
5974302bef9SLIU Zhiwei tcg_gen_ext32u_tl(addr, addr);
5980774a7a1SAnatoly Parshintsev }
5994208dc7eSLIU Zhiwei if (ctx->pm_base_enabled) {
6004208dc7eSLIU Zhiwei tcg_gen_or_tl(addr, addr, pm_base);
6014208dc7eSLIU Zhiwei }
6023a610f54SWeiwei Li
6034302bef9SLIU Zhiwei return addr;
604c655df7fSAlexey Baturo }
605c655df7fSAlexey Baturo
60645f9df86SChristoph Müllner /* Compute a canonical address from a register plus reg offset. */
get_address_indexed(DisasContext * ctx,int rs1,TCGv offs)60745f9df86SChristoph Müllner static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
60845f9df86SChristoph Müllner {
609574f3116SRichard Henderson TCGv addr = tcg_temp_new();
61045f9df86SChristoph Müllner TCGv src1 = get_gpr(ctx, rs1, EXT_NONE);
61145f9df86SChristoph Müllner
61245f9df86SChristoph Müllner tcg_gen_add_tl(addr, src1, offs);
61345f9df86SChristoph Müllner if (ctx->pm_mask_enabled) {
61445f9df86SChristoph Müllner tcg_gen_andc_tl(addr, addr, pm_mask);
61545f9df86SChristoph Müllner } else if (get_xl(ctx) == MXL_RV32) {
61645f9df86SChristoph Müllner tcg_gen_ext32u_tl(addr, addr);
61745f9df86SChristoph Müllner }
61845f9df86SChristoph Müllner if (ctx->pm_base_enabled) {
61945f9df86SChristoph Müllner tcg_gen_or_tl(addr, addr, pm_base);
62045f9df86SChristoph Müllner }
62145f9df86SChristoph Müllner return addr;
62245f9df86SChristoph Müllner }
62345f9df86SChristoph Müllner
624533b8f88SRichard Henderson #ifndef CONFIG_USER_ONLY
6253b57254dSWeiwei Li /*
626533b8f88SRichard Henderson * We will have already diagnosed disabled state,
627533b8f88SRichard Henderson * and need to turn initial/clean into dirty.
628533b8f88SRichard Henderson */
mark_fs_dirty(DisasContext * ctx)629533b8f88SRichard Henderson static void mark_fs_dirty(DisasContext *ctx)
630533b8f88SRichard Henderson {
631533b8f88SRichard Henderson TCGv tmp;
6324fd7455bSAlistair Francis
633c163b3baSWeiwei Li if (!has_ext(ctx, RVF)) {
634c163b3baSWeiwei Li return;
635c163b3baSWeiwei Li }
636c163b3baSWeiwei Li
637ebd47648SLIU Zhiwei if (ctx->mstatus_fs != EXT_STATUS_DIRTY) {
638533b8f88SRichard Henderson /* Remember the state change for the rest of the TB. */
639ebd47648SLIU Zhiwei ctx->mstatus_fs = EXT_STATUS_DIRTY;
640533b8f88SRichard Henderson
641533b8f88SRichard Henderson tmp = tcg_temp_new();
642ad75a51eSRichard Henderson tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus));
643b550f894SRichard Henderson tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
644ad75a51eSRichard Henderson tcg_gen_st_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus));
64545b4dc8bSAlistair Francis
64625f3ddffSRichard Henderson if (ctx->virt_enabled) {
647ad75a51eSRichard Henderson tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus_hs));
648b550f894SRichard Henderson tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
649ad75a51eSRichard Henderson tcg_gen_st_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus_hs));
650533b8f88SRichard Henderson }
651a88f0402SFrank Chang }
65225f3ddffSRichard Henderson }
653533b8f88SRichard Henderson #else
mark_fs_dirty(DisasContext * ctx)654533b8f88SRichard Henderson static inline void mark_fs_dirty(DisasContext *ctx) { }
655533b8f88SRichard Henderson #endif
656533b8f88SRichard Henderson
6578e1ee1fbSFrank Chang #ifndef CONFIG_USER_ONLY
6583b57254dSWeiwei Li /*
6598e1ee1fbSFrank Chang * We will have already diagnosed disabled state,
6608e1ee1fbSFrank Chang * and need to turn initial/clean into dirty.
6618e1ee1fbSFrank Chang */
mark_vs_dirty(DisasContext * ctx)6628e1ee1fbSFrank Chang static void mark_vs_dirty(DisasContext *ctx)
6638e1ee1fbSFrank Chang {
6648e1ee1fbSFrank Chang TCGv tmp;
6658e1ee1fbSFrank Chang
666ebd47648SLIU Zhiwei if (ctx->mstatus_vs != EXT_STATUS_DIRTY) {
6678e1ee1fbSFrank Chang /* Remember the state change for the rest of the TB. */
668ebd47648SLIU Zhiwei ctx->mstatus_vs = EXT_STATUS_DIRTY;
6698e1ee1fbSFrank Chang
6708e1ee1fbSFrank Chang tmp = tcg_temp_new();
671ad75a51eSRichard Henderson tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus));
6728e1ee1fbSFrank Chang tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
673ad75a51eSRichard Henderson tcg_gen_st_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus));
6748e1ee1fbSFrank Chang
67525f3ddffSRichard Henderson if (ctx->virt_enabled) {
676ad75a51eSRichard Henderson tcg_gen_ld_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus_hs));
6778e1ee1fbSFrank Chang tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
678ad75a51eSRichard Henderson tcg_gen_st_tl(tmp, tcg_env, offsetof(CPURISCVState, mstatus_hs));
6798e1ee1fbSFrank Chang }
6808e1ee1fbSFrank Chang }
68125f3ddffSRichard Henderson }
6828e1ee1fbSFrank Chang #else
mark_vs_dirty(DisasContext * ctx)6838e1ee1fbSFrank Chang static inline void mark_vs_dirty(DisasContext *ctx) { }
6848e1ee1fbSFrank Chang #endif
6858e1ee1fbSFrank Chang
finalize_rvv_inst(DisasContext * ctx)686bac802adSIvan Klokov static void finalize_rvv_inst(DisasContext *ctx)
687bac802adSIvan Klokov {
688bac802adSIvan Klokov mark_vs_dirty(ctx);
689bac802adSIvan Klokov ctx->vstart_eq_zero = true;
690bac802adSIvan Klokov }
691bac802adSIvan Klokov
gen_set_rm(DisasContext * ctx,int rm)69255c2a12cSMichael Clark static void gen_set_rm(DisasContext *ctx, int rm)
69355c2a12cSMichael Clark {
69455c2a12cSMichael Clark if (ctx->frm == rm) {
69555c2a12cSMichael Clark return;
69655c2a12cSMichael Clark }
69755c2a12cSMichael Clark ctx->frm = rm;
69875804f71SFrank Chang
6993ceeb19aSRichard Henderson if (rm == RISCV_FRM_DYN) {
7003ceeb19aSRichard Henderson /* The helper will return only if frm valid. */
7013ceeb19aSRichard Henderson ctx->frm_valid = true;
7023ceeb19aSRichard Henderson }
70375804f71SFrank Chang
704a9814e3eSRichard Henderson /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
705f21b36a0SDeepak Gupta decode_save_opc(ctx, 0);
706ad75a51eSRichard Henderson gen_helper_set_rounding_mode(tcg_env, tcg_constant_i32(rm));
70755c2a12cSMichael Clark }
70855c2a12cSMichael Clark
gen_set_rm_chkfrm(DisasContext * ctx,int rm)7093ceeb19aSRichard Henderson static void gen_set_rm_chkfrm(DisasContext *ctx, int rm)
7103ceeb19aSRichard Henderson {
7113ceeb19aSRichard Henderson if (ctx->frm == rm && ctx->frm_valid) {
7123ceeb19aSRichard Henderson return;
7133ceeb19aSRichard Henderson }
7143ceeb19aSRichard Henderson ctx->frm = rm;
7153ceeb19aSRichard Henderson ctx->frm_valid = true;
7163ceeb19aSRichard Henderson
7173ceeb19aSRichard Henderson /* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
718f21b36a0SDeepak Gupta decode_save_opc(ctx, 0);
719ad75a51eSRichard Henderson gen_helper_set_rounding_mode_chkfrm(tcg_env, tcg_constant_i32(rm));
7203ceeb19aSRichard Henderson }
7213ceeb19aSRichard Henderson
ex_plus_1(DisasContext * ctx,int nf)722751538d5SLIU Zhiwei static int ex_plus_1(DisasContext *ctx, int nf)
723751538d5SLIU Zhiwei {
724751538d5SLIU Zhiwei return nf + 1;
725751538d5SLIU Zhiwei }
726751538d5SLIU Zhiwei
7272a53cff4SBastian Koppelmann #define EX_SH(amount) \
728451e4ffdSRichard Henderson static int ex_shift_##amount(DisasContext *ctx, int imm) \
7292a53cff4SBastian Koppelmann { \
7302a53cff4SBastian Koppelmann return imm << amount; \
7312a53cff4SBastian Koppelmann }
7323cca75a6SBastian Koppelmann EX_SH(1)
733e98d9140SBastian Koppelmann EX_SH(2)
734e98d9140SBastian Koppelmann EX_SH(3)
73507b001c6SBastian Koppelmann EX_SH(4)
7362a53cff4SBastian Koppelmann EX_SH(12)
7372a53cff4SBastian Koppelmann
738d2e2c1e4SBastian Koppelmann #define REQUIRE_EXT(ctx, ext) do { \
739d2e2c1e4SBastian Koppelmann if (!has_ext(ctx, ext)) { \
740d2e2c1e4SBastian Koppelmann return false; \
741d2e2c1e4SBastian Koppelmann } \
742d2e2c1e4SBastian Koppelmann } while (0)
743d2e2c1e4SBastian Koppelmann
7447e68e6c7SPhilipp Tomsich #define REQUIRE_32BIT(ctx) do { \
745905b9fcdSRichard Henderson if (get_xl(ctx) != MXL_RV32) { \
7467e68e6c7SPhilipp Tomsich return false; \
7477e68e6c7SPhilipp Tomsich } \
7487e68e6c7SPhilipp Tomsich } while (0)
7497e68e6c7SPhilipp Tomsich
750daf866b6SAlistair Francis #define REQUIRE_64BIT(ctx) do { \
751344b4a82SFrédéric Pétrot if (get_xl(ctx) != MXL_RV64) { \
752344b4a82SFrédéric Pétrot return false; \
753344b4a82SFrédéric Pétrot } \
754344b4a82SFrédéric Pétrot } while (0)
755344b4a82SFrédéric Pétrot
756344b4a82SFrédéric Pétrot #define REQUIRE_128BIT(ctx) do { \
757344b4a82SFrédéric Pétrot if (get_xl(ctx) != MXL_RV128) { \
758344b4a82SFrédéric Pétrot return false; \
759344b4a82SFrédéric Pétrot } \
760344b4a82SFrédéric Pétrot } while (0)
761344b4a82SFrédéric Pétrot
762344b4a82SFrédéric Pétrot #define REQUIRE_64_OR_128BIT(ctx) do { \
763344b4a82SFrédéric Pétrot if (get_xl(ctx) == MXL_RV32) { \
764daf866b6SAlistair Francis return false; \
765daf866b6SAlistair Francis } \
766daf866b6SAlistair Francis } while (0)
767daf866b6SAlistair Francis
768d8e81e3cSWeiwei Li #define REQUIRE_EITHER_EXT(ctx, A, B) do { \
769d8e81e3cSWeiwei Li if (!ctx->cfg_ptr->ext_##A && \
770d8e81e3cSWeiwei Li !ctx->cfg_ptr->ext_##B) { \
771d8e81e3cSWeiwei Li return false; \
772d8e81e3cSWeiwei Li } \
773d8e81e3cSWeiwei Li } while (0)
774d8e81e3cSWeiwei Li
ex_rvc_register(DisasContext * ctx,int reg)775451e4ffdSRichard Henderson static int ex_rvc_register(DisasContext *ctx, int reg)
776e98d9140SBastian Koppelmann {
777e98d9140SBastian Koppelmann return 8 + reg;
778e98d9140SBastian Koppelmann }
779e98d9140SBastian Koppelmann
ex_sreg_register(DisasContext * ctx,int reg)780193eb522SWeiwei Li static int ex_sreg_register(DisasContext *ctx, int reg)
781193eb522SWeiwei Li {
782193eb522SWeiwei Li return reg < 2 ? reg + 8 : reg + 16;
783193eb522SWeiwei Li }
784193eb522SWeiwei Li
ex_rvc_shiftli(DisasContext * ctx,int imm)78533632775SFrédéric Pétrot static int ex_rvc_shiftli(DisasContext *ctx, int imm)
7866cafec92SRichard Henderson {
7876cafec92SRichard Henderson /* For RV128 a shamt of 0 means a shift by 64. */
78833632775SFrédéric Pétrot if (get_ol(ctx) == MXL_RV128) {
78933632775SFrédéric Pétrot imm = imm ? imm : 64;
79033632775SFrédéric Pétrot }
79133632775SFrédéric Pétrot return imm;
79233632775SFrédéric Pétrot }
79333632775SFrédéric Pétrot
ex_rvc_shiftri(DisasContext * ctx,int imm)79433632775SFrédéric Pétrot static int ex_rvc_shiftri(DisasContext *ctx, int imm)
79533632775SFrédéric Pétrot {
79633632775SFrédéric Pétrot /*
79733632775SFrédéric Pétrot * For RV128 a shamt of 0 means a shift by 64, furthermore, for right
79833632775SFrédéric Pétrot * shifts, the shamt is sign-extended.
79933632775SFrédéric Pétrot */
80033632775SFrédéric Pétrot if (get_ol(ctx) == MXL_RV128) {
80133632775SFrédéric Pétrot imm = imm | (imm & 32) << 1;
80233632775SFrédéric Pétrot imm = imm ? imm : 64;
80333632775SFrédéric Pétrot }
80433632775SFrédéric Pétrot return imm;
8056cafec92SRichard Henderson }
8066cafec92SRichard Henderson
8072a53cff4SBastian Koppelmann /* Include the auto-generated decoder for 32 bit insn */
808abff1abfSPaolo Bonzini #include "decode-insn32.c.inc"
8097a50d3e2SBastian Koppelmann
gen_logic_imm_fn(DisasContext * ctx,arg_i * a,void (* func)(TCGv,TCGv,target_long))810a1a3aac4SFrédéric Pétrot static bool gen_logic_imm_fn(DisasContext *ctx, arg_i *a,
811a1a3aac4SFrédéric Pétrot void (*func)(TCGv, TCGv, target_long))
812a1a3aac4SFrédéric Pétrot {
813a1a3aac4SFrédéric Pétrot TCGv dest = dest_gpr(ctx, a->rd);
814a1a3aac4SFrédéric Pétrot TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
815a1a3aac4SFrédéric Pétrot
816a1a3aac4SFrédéric Pétrot func(dest, src1, a->imm);
817a1a3aac4SFrédéric Pétrot
818568f247fSFrédéric Pétrot if (get_xl(ctx) == MXL_RV128) {
819568f247fSFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
820568f247fSFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
821568f247fSFrédéric Pétrot
822568f247fSFrédéric Pétrot func(desth, src1h, -(a->imm < 0));
823568f247fSFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
824568f247fSFrédéric Pétrot } else {
825a1a3aac4SFrédéric Pétrot gen_set_gpr(ctx, a->rd, dest);
826568f247fSFrédéric Pétrot }
827a1a3aac4SFrédéric Pétrot
828a1a3aac4SFrédéric Pétrot return true;
829a1a3aac4SFrédéric Pétrot }
830a1a3aac4SFrédéric Pétrot
gen_logic(DisasContext * ctx,arg_r * a,void (* func)(TCGv,TCGv,TCGv))831a1a3aac4SFrédéric Pétrot static bool gen_logic(DisasContext *ctx, arg_r *a,
832a1a3aac4SFrédéric Pétrot void (*func)(TCGv, TCGv, TCGv))
833a1a3aac4SFrédéric Pétrot {
834a1a3aac4SFrédéric Pétrot TCGv dest = dest_gpr(ctx, a->rd);
835a1a3aac4SFrédéric Pétrot TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
836a1a3aac4SFrédéric Pétrot TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
837a1a3aac4SFrédéric Pétrot
838a1a3aac4SFrédéric Pétrot func(dest, src1, src2);
839a1a3aac4SFrédéric Pétrot
840568f247fSFrédéric Pétrot if (get_xl(ctx) == MXL_RV128) {
841568f247fSFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
842568f247fSFrédéric Pétrot TCGv src2h = get_gprh(ctx, a->rs2);
843568f247fSFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
844568f247fSFrédéric Pétrot
845568f247fSFrédéric Pétrot func(desth, src1h, src2h);
846568f247fSFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
847568f247fSFrédéric Pétrot } else {
848a1a3aac4SFrédéric Pétrot gen_set_gpr(ctx, a->rd, dest);
849568f247fSFrédéric Pétrot }
850a1a3aac4SFrédéric Pétrot
851a1a3aac4SFrédéric Pétrot return true;
852a1a3aac4SFrédéric Pétrot }
853a1a3aac4SFrédéric Pétrot
gen_arith_imm_fn(DisasContext * ctx,arg_i * a,DisasExtend ext,void (* func)(TCGv,TCGv,target_long),void (* f128)(TCGv,TCGv,TCGv,TCGv,target_long))854191d1dafSRichard Henderson static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext,
8557fd40f86SFrédéric Pétrot void (*func)(TCGv, TCGv, target_long),
8567fd40f86SFrédéric Pétrot void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
857598aa116SRichard Henderson {
858191d1dafSRichard Henderson TCGv dest = dest_gpr(ctx, a->rd);
859191d1dafSRichard Henderson TCGv src1 = get_gpr(ctx, a->rs1, ext);
860598aa116SRichard Henderson
8617fd40f86SFrédéric Pétrot if (get_ol(ctx) < MXL_RV128) {
862191d1dafSRichard Henderson func(dest, src1, a->imm);
863191d1dafSRichard Henderson gen_set_gpr(ctx, a->rd, dest);
8647fd40f86SFrédéric Pétrot } else {
8657fd40f86SFrédéric Pétrot if (f128 == NULL) {
8667fd40f86SFrédéric Pétrot return false;
8677fd40f86SFrédéric Pétrot }
8687fd40f86SFrédéric Pétrot
8697fd40f86SFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
8707fd40f86SFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
8717fd40f86SFrédéric Pétrot
8727fd40f86SFrédéric Pétrot f128(dest, desth, src1, src1h, a->imm);
8737fd40f86SFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
8747fd40f86SFrédéric Pétrot }
875598aa116SRichard Henderson return true;
876598aa116SRichard Henderson }
877598aa116SRichard Henderson
gen_arith_imm_tl(DisasContext * ctx,arg_i * a,DisasExtend ext,void (* func)(TCGv,TCGv,TCGv),void (* f128)(TCGv,TCGv,TCGv,TCGv,TCGv,TCGv))878191d1dafSRichard Henderson static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext,
8797fd40f86SFrédéric Pétrot void (*func)(TCGv, TCGv, TCGv),
8807fd40f86SFrédéric Pétrot void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
8817a50d3e2SBastian Koppelmann {
882191d1dafSRichard Henderson TCGv dest = dest_gpr(ctx, a->rd);
883191d1dafSRichard Henderson TCGv src1 = get_gpr(ctx, a->rs1, ext);
884191d1dafSRichard Henderson TCGv src2 = tcg_constant_tl(a->imm);
8857a50d3e2SBastian Koppelmann
8867fd40f86SFrédéric Pétrot if (get_ol(ctx) < MXL_RV128) {
887191d1dafSRichard Henderson func(dest, src1, src2);
888191d1dafSRichard Henderson gen_set_gpr(ctx, a->rd, dest);
8897fd40f86SFrédéric Pétrot } else {
8907fd40f86SFrédéric Pétrot if (f128 == NULL) {
8917fd40f86SFrédéric Pétrot return false;
8927fd40f86SFrédéric Pétrot }
8937fd40f86SFrédéric Pétrot
8947fd40f86SFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
8957fd40f86SFrédéric Pétrot TCGv src2h = tcg_constant_tl(-(a->imm < 0));
8967fd40f86SFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
8977fd40f86SFrédéric Pétrot
8987fd40f86SFrédéric Pétrot f128(dest, desth, src1, src1h, src2, src2h);
8997fd40f86SFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
9007fd40f86SFrédéric Pétrot }
9017a50d3e2SBastian Koppelmann return true;
9027a50d3e2SBastian Koppelmann }
9037a50d3e2SBastian Koppelmann
gen_arith(DisasContext * ctx,arg_r * a,DisasExtend ext,void (* func)(TCGv,TCGv,TCGv),void (* f128)(TCGv,TCGv,TCGv,TCGv,TCGv,TCGv))904191d1dafSRichard Henderson static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext,
9057fd40f86SFrédéric Pétrot void (*func)(TCGv, TCGv, TCGv),
9067fd40f86SFrédéric Pétrot void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
907f2ab1728SBastian Koppelmann {
908191d1dafSRichard Henderson TCGv dest = dest_gpr(ctx, a->rd);
909191d1dafSRichard Henderson TCGv src1 = get_gpr(ctx, a->rs1, ext);
910191d1dafSRichard Henderson TCGv src2 = get_gpr(ctx, a->rs2, ext);
911f2ab1728SBastian Koppelmann
9127fd40f86SFrédéric Pétrot if (get_ol(ctx) < MXL_RV128) {
913191d1dafSRichard Henderson func(dest, src1, src2);
914191d1dafSRichard Henderson gen_set_gpr(ctx, a->rd, dest);
9157fd40f86SFrédéric Pétrot } else {
9167fd40f86SFrédéric Pétrot if (f128 == NULL) {
9177fd40f86SFrédéric Pétrot return false;
9187fd40f86SFrédéric Pétrot }
9197fd40f86SFrédéric Pétrot
9207fd40f86SFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
9217fd40f86SFrédéric Pétrot TCGv src2h = get_gprh(ctx, a->rs2);
9227fd40f86SFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
9237fd40f86SFrédéric Pétrot
9247fd40f86SFrédéric Pétrot f128(dest, desth, src1, src1h, src2, src2h);
9257fd40f86SFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
9267fd40f86SFrédéric Pétrot }
927f2ab1728SBastian Koppelmann return true;
928f2ab1728SBastian Koppelmann }
929f2ab1728SBastian Koppelmann
gen_arith_per_ol(DisasContext * ctx,arg_r * a,DisasExtend ext,void (* f_tl)(TCGv,TCGv,TCGv),void (* f_32)(TCGv,TCGv,TCGv),void (* f_128)(TCGv,TCGv,TCGv,TCGv,TCGv,TCGv))93080347ae9SRichard Henderson static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
93180347ae9SRichard Henderson void (*f_tl)(TCGv, TCGv, TCGv),
9327fd40f86SFrédéric Pétrot void (*f_32)(TCGv, TCGv, TCGv),
9337fd40f86SFrédéric Pétrot void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv, TCGv))
93480347ae9SRichard Henderson {
93580347ae9SRichard Henderson int olen = get_olen(ctx);
93680347ae9SRichard Henderson
93780347ae9SRichard Henderson if (olen != TARGET_LONG_BITS) {
93880347ae9SRichard Henderson if (olen == 32) {
93980347ae9SRichard Henderson f_tl = f_32;
9407fd40f86SFrédéric Pétrot } else if (olen != 128) {
94180347ae9SRichard Henderson g_assert_not_reached();
94280347ae9SRichard Henderson }
94380347ae9SRichard Henderson }
9447fd40f86SFrédéric Pétrot return gen_arith(ctx, a, ext, f_tl, f_128);
94580347ae9SRichard Henderson }
94680347ae9SRichard Henderson
gen_shift_imm_fn(DisasContext * ctx,arg_shift * a,DisasExtend ext,void (* func)(TCGv,TCGv,target_long),void (* f128)(TCGv,TCGv,TCGv,TCGv,target_long))94789c88309SRichard Henderson static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext,
9486bf4bbedSFrédéric Pétrot void (*func)(TCGv, TCGv, target_long),
9496bf4bbedSFrédéric Pétrot void (*f128)(TCGv, TCGv, TCGv, TCGv, target_long))
95034446e84SBastian Koppelmann {
95189c88309SRichard Henderson TCGv dest, src1;
9527667cafdSRichard Henderson int max_len = get_olen(ctx);
95334446e84SBastian Koppelmann
95489c88309SRichard Henderson if (a->shamt >= max_len) {
955981d3568SFrank Chang return false;
956981d3568SFrank Chang }
957981d3568SFrank Chang
95889c88309SRichard Henderson dest = dest_gpr(ctx, a->rd);
95989c88309SRichard Henderson src1 = get_gpr(ctx, a->rs1, ext);
960981d3568SFrank Chang
9616bf4bbedSFrédéric Pétrot if (max_len < 128) {
96289c88309SRichard Henderson func(dest, src1, a->shamt);
96389c88309SRichard Henderson gen_set_gpr(ctx, a->rd, dest);
9646bf4bbedSFrédéric Pétrot } else {
9656bf4bbedSFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
9666bf4bbedSFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
9676bf4bbedSFrédéric Pétrot
9686bf4bbedSFrédéric Pétrot if (f128 == NULL) {
9696bf4bbedSFrédéric Pétrot return false;
9706bf4bbedSFrédéric Pétrot }
9716bf4bbedSFrédéric Pétrot f128(dest, desth, src1, src1h, a->shamt);
9726bf4bbedSFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
9736bf4bbedSFrédéric Pétrot }
974981d3568SFrank Chang return true;
975981d3568SFrank Chang }
976981d3568SFrank Chang
gen_shift_imm_fn_per_ol(DisasContext * ctx,arg_shift * a,DisasExtend ext,void (* f_tl)(TCGv,TCGv,target_long),void (* f_32)(TCGv,TCGv,target_long),void (* f_128)(TCGv,TCGv,TCGv,TCGv,target_long))977a0245d91SRichard Henderson static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a,
978a0245d91SRichard Henderson DisasExtend ext,
979a0245d91SRichard Henderson void (*f_tl)(TCGv, TCGv, target_long),
9806bf4bbedSFrédéric Pétrot void (*f_32)(TCGv, TCGv, target_long),
9816bf4bbedSFrédéric Pétrot void (*f_128)(TCGv, TCGv, TCGv, TCGv,
9826bf4bbedSFrédéric Pétrot target_long))
983a0245d91SRichard Henderson {
984a0245d91SRichard Henderson int olen = get_olen(ctx);
985a0245d91SRichard Henderson if (olen != TARGET_LONG_BITS) {
986a0245d91SRichard Henderson if (olen == 32) {
987a0245d91SRichard Henderson f_tl = f_32;
9886bf4bbedSFrédéric Pétrot } else if (olen != 128) {
989a0245d91SRichard Henderson g_assert_not_reached();
990a0245d91SRichard Henderson }
991a0245d91SRichard Henderson }
9926bf4bbedSFrédéric Pétrot return gen_shift_imm_fn(ctx, a, ext, f_tl, f_128);
993a0245d91SRichard Henderson }
994a0245d91SRichard Henderson
gen_shift_imm_tl(DisasContext * ctx,arg_shift * a,DisasExtend ext,void (* func)(TCGv,TCGv,TCGv))99589c88309SRichard Henderson static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext,
99623cd1777SFrank Chang void (*func)(TCGv, TCGv, TCGv))
99723cd1777SFrank Chang {
99889c88309SRichard Henderson TCGv dest, src1, src2;
9997667cafdSRichard Henderson int max_len = get_olen(ctx);
100023cd1777SFrank Chang
100189c88309SRichard Henderson if (a->shamt >= max_len) {
100289c88309SRichard Henderson return false;
100389c88309SRichard Henderson }
100423cd1777SFrank Chang
100589c88309SRichard Henderson dest = dest_gpr(ctx, a->rd);
100689c88309SRichard Henderson src1 = get_gpr(ctx, a->rs1, ext);
100789c88309SRichard Henderson src2 = tcg_constant_tl(a->shamt);
100823cd1777SFrank Chang
100989c88309SRichard Henderson func(dest, src1, src2);
101089c88309SRichard Henderson
101189c88309SRichard Henderson gen_set_gpr(ctx, a->rd, dest);
101223cd1777SFrank Chang return true;
101323cd1777SFrank Chang }
101423cd1777SFrank Chang
gen_shift(DisasContext * ctx,arg_r * a,DisasExtend ext,void (* func)(TCGv,TCGv,TCGv),void (* f128)(TCGv,TCGv,TCGv,TCGv,TCGv))101589c88309SRichard Henderson static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext,
10166bf4bbedSFrédéric Pétrot void (*func)(TCGv, TCGv, TCGv),
10176bf4bbedSFrédéric Pétrot void (*f128)(TCGv, TCGv, TCGv, TCGv, TCGv))
1018981d3568SFrank Chang {
101989c88309SRichard Henderson TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
102089c88309SRichard Henderson TCGv ext2 = tcg_temp_new();
10216bf4bbedSFrédéric Pétrot int max_len = get_olen(ctx);
1022981d3568SFrank Chang
10236bf4bbedSFrédéric Pétrot tcg_gen_andi_tl(ext2, src2, max_len - 1);
10246bf4bbedSFrédéric Pétrot
10256bf4bbedSFrédéric Pétrot TCGv dest = dest_gpr(ctx, a->rd);
10266bf4bbedSFrédéric Pétrot TCGv src1 = get_gpr(ctx, a->rs1, ext);
10276bf4bbedSFrédéric Pétrot
10286bf4bbedSFrédéric Pétrot if (max_len < 128) {
102989c88309SRichard Henderson func(dest, src1, ext2);
103089c88309SRichard Henderson gen_set_gpr(ctx, a->rd, dest);
10316bf4bbedSFrédéric Pétrot } else {
10326bf4bbedSFrédéric Pétrot TCGv src1h = get_gprh(ctx, a->rs1);
10336bf4bbedSFrédéric Pétrot TCGv desth = dest_gprh(ctx, a->rd);
10346bf4bbedSFrédéric Pétrot
10356bf4bbedSFrédéric Pétrot if (f128 == NULL) {
10366bf4bbedSFrédéric Pétrot return false;
10376bf4bbedSFrédéric Pétrot }
10386bf4bbedSFrédéric Pétrot f128(dest, desth, src1, src1h, ext2);
10396bf4bbedSFrédéric Pétrot gen_set_gpr128(ctx, a->rd, dest, desth);
10406bf4bbedSFrédéric Pétrot }
1041981d3568SFrank Chang return true;
1042981d3568SFrank Chang }
1043981d3568SFrank Chang
gen_shift_per_ol(DisasContext * ctx,arg_r * a,DisasExtend ext,void (* f_tl)(TCGv,TCGv,TCGv),void (* f_32)(TCGv,TCGv,TCGv),void (* f_128)(TCGv,TCGv,TCGv,TCGv,TCGv))1044a0245d91SRichard Henderson static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext,
1045a0245d91SRichard Henderson void (*f_tl)(TCGv, TCGv, TCGv),
10466bf4bbedSFrédéric Pétrot void (*f_32)(TCGv, TCGv, TCGv),
10476bf4bbedSFrédéric Pétrot void (*f_128)(TCGv, TCGv, TCGv, TCGv, TCGv))
1048a0245d91SRichard Henderson {
1049a0245d91SRichard Henderson int olen = get_olen(ctx);
1050a0245d91SRichard Henderson if (olen != TARGET_LONG_BITS) {
1051a0245d91SRichard Henderson if (olen == 32) {
1052a0245d91SRichard Henderson f_tl = f_32;
10536bf4bbedSFrédéric Pétrot } else if (olen != 128) {
1054a0245d91SRichard Henderson g_assert_not_reached();
1055a0245d91SRichard Henderson }
1056a0245d91SRichard Henderson }
10576bf4bbedSFrédéric Pétrot return gen_shift(ctx, a, ext, f_tl, f_128);
1058a0245d91SRichard Henderson }
1059a0245d91SRichard Henderson
gen_unary(DisasContext * ctx,arg_r2 * a,DisasExtend ext,void (* func)(TCGv,TCGv))106060903915SRichard Henderson static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
106143824018SKito Cheng void (*func)(TCGv, TCGv))
106243824018SKito Cheng {
106360903915SRichard Henderson TCGv dest = dest_gpr(ctx, a->rd);
106460903915SRichard Henderson TCGv src1 = get_gpr(ctx, a->rs1, ext);
106543824018SKito Cheng
106660903915SRichard Henderson func(dest, src1);
106743824018SKito Cheng
106860903915SRichard Henderson gen_set_gpr(ctx, a->rd, dest);
106943824018SKito Cheng return true;
107043824018SKito Cheng }
107143824018SKito Cheng
gen_unary_per_ol(DisasContext * ctx,arg_r2 * a,DisasExtend ext,void (* f_tl)(TCGv,TCGv),void (* f_32)(TCGv,TCGv))1072fdab665fSRichard Henderson static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext,
1073fdab665fSRichard Henderson void (*f_tl)(TCGv, TCGv),
1074fdab665fSRichard Henderson void (*f_32)(TCGv, TCGv))
1075fdab665fSRichard Henderson {
1076fdab665fSRichard Henderson int olen = get_olen(ctx);
1077fdab665fSRichard Henderson
1078fdab665fSRichard Henderson if (olen != TARGET_LONG_BITS) {
1079fdab665fSRichard Henderson if (olen == 32) {
1080fdab665fSRichard Henderson f_tl = f_32;
1081fdab665fSRichard Henderson } else {
1082fdab665fSRichard Henderson g_assert_not_reached();
1083fdab665fSRichard Henderson }
1084fdab665fSRichard Henderson }
1085fdab665fSRichard Henderson return gen_unary(ctx, a, ext, f_tl);
1086fdab665fSRichard Henderson }
1087fdab665fSRichard Henderson
gen_amo(DisasContext * ctx,arg_atomic * a,void (* func)(TCGv,TCGv,TCGv,TCGArg,MemOp),MemOp mop)108824da9cbaSLIU Zhiwei static bool gen_amo(DisasContext *ctx, arg_atomic *a,
108924da9cbaSLIU Zhiwei void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
109024da9cbaSLIU Zhiwei MemOp mop)
109124da9cbaSLIU Zhiwei {
109224da9cbaSLIU Zhiwei TCGv dest = dest_gpr(ctx, a->rd);
109324da9cbaSLIU Zhiwei TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
1094be4a8db7SLIU Zhiwei MemOp size = mop & MO_SIZE;
109524da9cbaSLIU Zhiwei
1096be4a8db7SLIU Zhiwei if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) {
109724da9cbaSLIU Zhiwei mop |= MO_ATOM_WITHIN16;
109824da9cbaSLIU Zhiwei } else {
109924da9cbaSLIU Zhiwei mop |= MO_ALIGN;
110024da9cbaSLIU Zhiwei }
110124da9cbaSLIU Zhiwei
1102f21b36a0SDeepak Gupta decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
110324da9cbaSLIU Zhiwei src1 = get_address(ctx, a->rs1, 0);
110424da9cbaSLIU Zhiwei func(dest, src1, src2, ctx->mem_idx, mop);
110524da9cbaSLIU Zhiwei
110624da9cbaSLIU Zhiwei gen_set_gpr(ctx, a->rd, dest);
110724da9cbaSLIU Zhiwei return true;
110824da9cbaSLIU Zhiwei }
110924da9cbaSLIU Zhiwei
gen_cmpxchg(DisasContext * ctx,arg_atomic * a,MemOp mop)11108d07887bSLIU Zhiwei static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
11118d07887bSLIU Zhiwei {
11128d07887bSLIU Zhiwei TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
11138d07887bSLIU Zhiwei TCGv src1 = get_address(ctx, a->rs1, 0);
11148d07887bSLIU Zhiwei TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
11158d07887bSLIU Zhiwei
1116f21b36a0SDeepak Gupta decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO);
11178d07887bSLIU Zhiwei tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
11188d07887bSLIU Zhiwei
11198d07887bSLIU Zhiwei gen_set_gpr(ctx, a->rd, dest);
11208d07887bSLIU Zhiwei return true;
11218d07887bSLIU Zhiwei }
11228d07887bSLIU Zhiwei
opcode_at(DisasContextBase * dcbase,target_ulong pc)112389c88309SRichard Henderson static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
112489c88309SRichard Henderson {
112589c88309SRichard Henderson DisasContext *ctx = container_of(dcbase, DisasContext, base);
112689c88309SRichard Henderson CPUState *cpu = ctx->cs;
1127b77af26eSRichard Henderson CPURISCVState *env = cpu_env(cpu);
112889c88309SRichard Henderson
11291f9c4462SRichard Henderson return translator_ldl(env, &ctx->base, pc);
113089c88309SRichard Henderson }
113189c88309SRichard Henderson
1132*f06bfe3dSDeepak Gupta #define SS_MMU_INDEX(ctx) (ctx->mem_idx | MMU_IDX_SS_WRITE)
1133*f06bfe3dSDeepak Gupta
11342a53cff4SBastian Koppelmann /* Include insn module translation function */
1135139c1837SPaolo Bonzini #include "insn_trans/trans_rvi.c.inc"
1136139c1837SPaolo Bonzini #include "insn_trans/trans_rvm.c.inc"
1137139c1837SPaolo Bonzini #include "insn_trans/trans_rva.c.inc"
1138139c1837SPaolo Bonzini #include "insn_trans/trans_rvf.c.inc"
1139139c1837SPaolo Bonzini #include "insn_trans/trans_rvd.c.inc"
1140139c1837SPaolo Bonzini #include "insn_trans/trans_rvh.c.inc"
1141139c1837SPaolo Bonzini #include "insn_trans/trans_rvv.c.inc"
114243824018SKito Cheng #include "insn_trans/trans_rvb.c.inc"
1143b8e1f32cSWeiwei Li #include "insn_trans/trans_rvzicond.c.inc"
1144b52d49e9SWeiwei Li #include "insn_trans/trans_rvzacas.c.inc"
1145be4a8db7SLIU Zhiwei #include "insn_trans/trans_rvzabha.c.inc"
1146260b594dSChristoph Muellner #include "insn_trans/trans_rvzawrs.c.inc"
1147a939c500SChristoph Muellner #include "insn_trans/trans_rvzicbo.c.inc"
11486eab278dSLIU Zhiwei #include "insn_trans/trans_rvzimop.c.inc"
1149a47842d1SChristoph Müllner #include "insn_trans/trans_rvzfa.c.inc"
1150915f77b2SKito Cheng #include "insn_trans/trans_rvzfh.c.inc"
115168d19b58SWeiwei Li #include "insn_trans/trans_rvk.c.inc"
1152e13c7d3bSLawrence Hunter #include "insn_trans/trans_rvvk.c.inc"
1153139c1837SPaolo Bonzini #include "insn_trans/trans_privileged.c.inc"
1154c5d77dddSWeiwei Li #include "insn_trans/trans_svinval.c.inc"
11555d1270caSWeiwei Li #include "insn_trans/trans_rvbf16.c.inc"
115649a7f3aaSChristoph Müllner #include "decode-xthead.c.inc"
115749a7f3aaSChristoph Müllner #include "insn_trans/trans_xthead.c.inc"
11580d429bd2SPhilipp Tomsich #include "insn_trans/trans_xventanacondops.c.inc"
11592a53cff4SBastian Koppelmann
116059a3a1c0SRichard Henderson /* Include the auto-generated decoder for 16 bit insn */
1161abff1abfSPaolo Bonzini #include "decode-insn16.c.inc"
1162e0a3054fSWeiwei Li #include "insn_trans/trans_rvzce.c.inc"
1163197e4d29SLIU Zhiwei #include "insn_trans/trans_rvzcmop.c.inc"
1164*f06bfe3dSDeepak Gupta #include "insn_trans/trans_rvzicfiss.c.inc"
1165e0a3054fSWeiwei Li
11660d429bd2SPhilipp Tomsich /* Include decoders for factored-out extensions */
11670d429bd2SPhilipp Tomsich #include "decode-XVentanaCondOps.c.inc"
1168e98d9140SBastian Koppelmann
1169ef6e987bSRichard Henderson /* The specification allows for longer insns, but not supported by qemu. */
1170ef6e987bSRichard Henderson #define MAX_INSN_LEN 4
1171ef6e987bSRichard Henderson
insn_len(uint16_t first_word)1172ef6e987bSRichard Henderson static inline int insn_len(uint16_t first_word)
1173ef6e987bSRichard Henderson {
1174ef6e987bSRichard Henderson return (first_word & 3) == 3 ? 4 : 2;
1175ef6e987bSRichard Henderson }
1176ef6e987bSRichard Henderson
11778c8a7cd6SHuang Tao const RISCVDecoder decoder_table[] = {
11785e199b6bSPhilipp Tomsich { always_true_p, decode_insn32 },
117949a7f3aaSChristoph Müllner { has_xthead_p, decode_xthead},
11800d429bd2SPhilipp Tomsich { has_XVentanaCondOps_p, decode_XVentanaCodeOps},
11815e199b6bSPhilipp Tomsich };
11825e199b6bSPhilipp Tomsich
11838c8a7cd6SHuang Tao const size_t decoder_table_size = ARRAY_SIZE(decoder_table);
11848c8a7cd6SHuang Tao
decode_opc(CPURISCVState * env,DisasContext * ctx,uint16_t opcode)11858c8a7cd6SHuang Tao static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
11868c8a7cd6SHuang Tao {
1187fb3f3730SMayuresh Chitale ctx->virt_inst_excp = false;
11888ef23a32SWeiwei Li ctx->cur_insn_len = insn_len(opcode);
11895e199b6bSPhilipp Tomsich /* Check for compressed insn */
11908ef23a32SWeiwei Li if (ctx->cur_insn_len == 2) {
1191ea7b5d5aSAlistair Francis ctx->opcode = opcode;
1192b17dd74aSWeiwei Li /*
1193b17dd74aSWeiwei Li * The Zca extension is added as way to refer to instructions in the C
1194b17dd74aSWeiwei Li * extension that do not include the floating-point loads and stores
1195b17dd74aSWeiwei Li */
1196d33e39f9SWeiwei Li if ((has_ext(ctx, RVC) || ctx->cfg_ptr->ext_zca) &&
1197d33e39f9SWeiwei Li decode_insn16(ctx, opcode)) {
11985e199b6bSPhilipp Tomsich return;
119955c2a12cSMichael Clark }
120055c2a12cSMichael Clark } else {
120125139bf7SAlex Bennée uint32_t opcode32 = opcode;
120225139bf7SAlex Bennée opcode32 = deposit32(opcode32, 16, 16,
12034e116893SIlya Leoshkevich translator_lduw(env, &ctx->base,
12044e116893SIlya Leoshkevich ctx->base.pc_next + 2));
1205ea7b5d5aSAlistair Francis ctx->opcode = opcode32;
12065e199b6bSPhilipp Tomsich
12078c8a7cd6SHuang Tao for (guint i = 0; i < ctx->decoders->len; ++i) {
12088c8a7cd6SHuang Tao riscv_cpu_decode_fn func = g_ptr_array_index(ctx->decoders, i);
12098c8a7cd6SHuang Tao if (func(ctx, opcode32)) {
12105e199b6bSPhilipp Tomsich return;
12115e199b6bSPhilipp Tomsich }
12125e199b6bSPhilipp Tomsich }
12135e199b6bSPhilipp Tomsich }
12145e199b6bSPhilipp Tomsich
121525e6ca30SBastian Koppelmann gen_exception_illegal(ctx);
121655c2a12cSMichael Clark }
121755c2a12cSMichael Clark
riscv_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cs)12185b4f1d2dSEmilio G. Cota static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
121955c2a12cSMichael Clark {
12205b4f1d2dSEmilio G. Cota DisasContext *ctx = container_of(dcbase, DisasContext, base);
1221b77af26eSRichard Henderson CPURISCVState *env = cpu_env(cs);
1222742cc269SAkihiko Odaki RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cs);
122350fba816SPalmer Dabbelt RISCVCPU *cpu = RISCV_CPU(cs);
12242b7168fcSLIU Zhiwei uint32_t tb_flags = ctx->base.tb->flags;
122555c2a12cSMichael Clark
1226356c13f9SWeiwei Li ctx->pc_save = ctx->base.pc_first;
122747debc72SFei Wu ctx->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
122861d56494SFrank Chang ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
1229ebd47648SLIU Zhiwei ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
1230ebd47648SLIU Zhiwei ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
1231d75377bfSAlistair Francis ctx->priv_ver = env->priv_ver;
1232f1966390SLIU Zhiwei ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
1233e91a7227SRichard Henderson ctx->misa_ext = env->misa_ext;
12345b4f1d2dSEmilio G. Cota ctx->frm = -1; /* unknown rounding mode */
12353b91323eSPhilipp Tomsich ctx->cfg_ptr = &(cpu->cfg);
12362b7168fcSLIU Zhiwei ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
12372b7168fcSLIU Zhiwei ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
123833f1beafSFrank Chang ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
1239f1eed927SeopXD ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
1240355d5584SYueh-Ting (eop) Chen ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s;
1241752614caSeopXD ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
12424acaa133SLIU Zhiwei ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
12432b7168fcSLIU Zhiwei ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
1244742cc269SAkihiko Odaki ctx->misa_mxl_max = mcc->misa_mxl_max;
124592371bd9SRichard Henderson ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
12463a610f54SWeiwei Li ctx->address_xl = FIELD_EX32(tb_flags, TB_FLAGS, AXL);
1247a10b9d93SKeith Packard ctx->cs = cs;
12484208dc7eSLIU Zhiwei ctx->pm_mask_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_MASK_ENABLED);
12494208dc7eSLIU Zhiwei ctx->pm_base_enabled = FIELD_EX32(tb_flags, TB_FLAGS, PM_BASE_ENABLED);
125009c4e887SPalmer Dabbelt ctx->ztso = cpu->cfg.ext_ztso;
12512c9d7471SLIU Zhiwei ctx->itrigger = FIELD_EX32(tb_flags, TB_FLAGS, ITRIGGER);
1252f9fdf907SDeepak Gupta ctx->bcfi_enabled = FIELD_EX32(tb_flags, TB_FLAGS, BCFI_ENABLED);
1253b039c961SDeepak Gupta ctx->fcfi_lp_expected = FIELD_EX32(tb_flags, TB_FLAGS, FCFI_LP_EXPECTED);
1254b039c961SDeepak Gupta ctx->fcfi_enabled = FIELD_EX32(tb_flags, TB_FLAGS, FCFI_ENABLED);
1255ecda15d1SRichard Henderson ctx->zero = tcg_constant_tl(0);
1256506c6698SDeepak Gupta ctx->virt_inst_excp = false;
12578c8a7cd6SHuang Tao ctx->decoders = cpu->decoders;
125855c2a12cSMichael Clark }
12595b4f1d2dSEmilio G. Cota
riscv_tr_tb_start(DisasContextBase * db,CPUState * cpu)12605b4f1d2dSEmilio G. Cota static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
12615b4f1d2dSEmilio G. Cota {
126255c2a12cSMichael Clark }
126355c2a12cSMichael Clark
riscv_tr_insn_start(DisasContextBase * dcbase,CPUState * cpu)12645b4f1d2dSEmilio G. Cota static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
12655b4f1d2dSEmilio G. Cota {
12665b4f1d2dSEmilio G. Cota DisasContext *ctx = container_of(dcbase, DisasContext, base);
1267356c13f9SWeiwei Li target_ulong pc_next = ctx->base.pc_next;
126855c2a12cSMichael Clark
1269356c13f9SWeiwei Li if (tb_cflags(dcbase->tb) & CF_PCREL) {
1270356c13f9SWeiwei Li pc_next &= ~TARGET_PAGE_MASK;
1271356c13f9SWeiwei Li }
1272356c13f9SWeiwei Li
127398f21c30SDeepak Gupta tcg_gen_insn_start(pc_next, 0, 0);
1274401aa608SRichard Henderson ctx->insn_start_updated = false;
12755b4f1d2dSEmilio G. Cota }
12765b4f1d2dSEmilio G. Cota
riscv_tr_translate_insn(DisasContextBase * dcbase,CPUState * cpu)12775b4f1d2dSEmilio G. Cota static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12785b4f1d2dSEmilio G. Cota {
12795b4f1d2dSEmilio G. Cota DisasContext *ctx = container_of(dcbase, DisasContext, base);
1280b77af26eSRichard Henderson CPURISCVState *env = cpu_env(cpu);
12814e116893SIlya Leoshkevich uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next);
12825b4f1d2dSEmilio G. Cota
12837667cafdSRichard Henderson ctx->ol = ctx->xl;
128425139bf7SAlex Bennée decode_opc(env, ctx, opcode16);
128590b0aecaSWeiwei Li ctx->base.pc_next += ctx->cur_insn_len;
1286ecda15d1SRichard Henderson
1287b039c961SDeepak Gupta /*
1288b039c961SDeepak Gupta * If 'fcfi_lp_expected' is still true after processing the instruction,
1289b039c961SDeepak Gupta * then we did not see an 'lpad' instruction, and must raise an exception.
1290b039c961SDeepak Gupta * Insert code to raise the exception at the start of the insn; any other
1291b039c961SDeepak Gupta * code the insn may have emitted will be deleted as dead code following
1292b039c961SDeepak Gupta * the noreturn exception
1293b039c961SDeepak Gupta */
1294b039c961SDeepak Gupta if (ctx->fcfi_lp_expected) {
1295b039c961SDeepak Gupta /* Emit after insn_start, i.e. before the op following insn_start. */
1296b039c961SDeepak Gupta tcg_ctx->emit_before_op = QTAILQ_NEXT(ctx->base.insn_start, link);
1297b039c961SDeepak Gupta tcg_gen_st_tl(tcg_constant_tl(RISCV_EXCP_SW_CHECK_FCFI_TVAL),
1298b039c961SDeepak Gupta tcg_env, offsetof(CPURISCVState, sw_check_code));
1299b039c961SDeepak Gupta gen_helper_raise_exception(tcg_env,
1300b039c961SDeepak Gupta tcg_constant_i32(RISCV_EXCP_SW_CHECK));
1301b039c961SDeepak Gupta tcg_ctx->emit_before_op = NULL;
1302b039c961SDeepak Gupta ctx->base.is_jmp = DISAS_NORETURN;
1303b039c961SDeepak Gupta }
1304b039c961SDeepak Gupta
130500c07344SRichard Henderson /* Only the first insn within a TB is allowed to cross a page boundary. */
13065b4f1d2dSEmilio G. Cota if (ctx->base.is_jmp == DISAS_NEXT) {
13072c9d7471SLIU Zhiwei if (ctx->itrigger || !is_same_page(&ctx->base, ctx->base.pc_next)) {
13085b4f1d2dSEmilio G. Cota ctx->base.is_jmp = DISAS_TOO_MANY;
130900c07344SRichard Henderson } else {
131000c07344SRichard Henderson unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
131100c07344SRichard Henderson
131200c07344SRichard Henderson if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
13131f9c4462SRichard Henderson uint16_t next_insn =
13141f9c4462SRichard Henderson translator_lduw(env, &ctx->base, ctx->base.pc_next);
131500c07344SRichard Henderson int len = insn_len(next_insn);
131600c07344SRichard Henderson
1317ae9c326fSShaobo Song if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
131800c07344SRichard Henderson ctx->base.is_jmp = DISAS_TOO_MANY;
131900c07344SRichard Henderson }
132000c07344SRichard Henderson }
13215b4f1d2dSEmilio G. Cota }
13225b4f1d2dSEmilio G. Cota }
132355c2a12cSMichael Clark }
132455c2a12cSMichael Clark
riscv_tr_tb_stop(DisasContextBase * dcbase,CPUState * cpu)13255b4f1d2dSEmilio G. Cota static void riscv_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
13265b4f1d2dSEmilio G. Cota {
13275b4f1d2dSEmilio G. Cota DisasContext *ctx = container_of(dcbase, DisasContext, base);
132855c2a12cSMichael Clark
13295b4f1d2dSEmilio G. Cota switch (ctx->base.is_jmp) {
1330b2e32021SEmilio G. Cota case DISAS_TOO_MANY:
13311df8497bSWeiwei Li gen_goto_tb(ctx, 0, 0);
133255c2a12cSMichael Clark break;
1333b2e32021SEmilio G. Cota case DISAS_NORETURN:
133455c2a12cSMichael Clark break;
1335b2e32021SEmilio G. Cota default:
1336b2e32021SEmilio G. Cota g_assert_not_reached();
133755c2a12cSMichael Clark }
133855c2a12cSMichael Clark }
13395b4f1d2dSEmilio G. Cota
13405b4f1d2dSEmilio G. Cota static const TranslatorOps riscv_tr_ops = {
13415b4f1d2dSEmilio G. Cota .init_disas_context = riscv_tr_init_disas_context,
13425b4f1d2dSEmilio G. Cota .tb_start = riscv_tr_tb_start,
13435b4f1d2dSEmilio G. Cota .insn_start = riscv_tr_insn_start,
13445b4f1d2dSEmilio G. Cota .translate_insn = riscv_tr_translate_insn,
13455b4f1d2dSEmilio G. Cota .tb_stop = riscv_tr_tb_stop,
13465b4f1d2dSEmilio G. Cota };
13475b4f1d2dSEmilio G. Cota
gen_intermediate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)1348597f9b2dSRichard Henderson void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
134932f0c394SAnton Johansson vaddr pc, void *host_pc)
13505b4f1d2dSEmilio G. Cota {
13515b4f1d2dSEmilio G. Cota DisasContext ctx;
13525b4f1d2dSEmilio G. Cota
1353306c8721SRichard Henderson translator_loop(cs, tb, max_insns, pc, host_pc, &riscv_tr_ops, &ctx.base);
135455c2a12cSMichael Clark }
135555c2a12cSMichael Clark
riscv_translate_init(void)135655c2a12cSMichael Clark void riscv_translate_init(void)
135755c2a12cSMichael Clark {
135855c2a12cSMichael Clark int i;
135955c2a12cSMichael Clark
13608e034ae4SRichard Henderson /*
13618e034ae4SRichard Henderson * cpu_gpr[0] is a placeholder for the zero register. Do not use it.
13628e034ae4SRichard Henderson * Use the gen_set_gpr and get_gpr helper functions when accessing regs,
13638e034ae4SRichard Henderson * unless you specifically block reads/writes to reg 0.
13648e034ae4SRichard Henderson */
136555c2a12cSMichael Clark cpu_gpr[0] = NULL;
13662b547084SFrédéric Pétrot cpu_gprh[0] = NULL;
136755c2a12cSMichael Clark
136855c2a12cSMichael Clark for (i = 1; i < 32; i++) {
1369ad75a51eSRichard Henderson cpu_gpr[i] = tcg_global_mem_new(tcg_env,
137055c2a12cSMichael Clark offsetof(CPURISCVState, gpr[i]), riscv_int_regnames[i]);
1371ad75a51eSRichard Henderson cpu_gprh[i] = tcg_global_mem_new(tcg_env,
13722b547084SFrédéric Pétrot offsetof(CPURISCVState, gprh[i]), riscv_int_regnamesh[i]);
137355c2a12cSMichael Clark }
137455c2a12cSMichael Clark
137555c2a12cSMichael Clark for (i = 0; i < 32; i++) {
1376ad75a51eSRichard Henderson cpu_fpr[i] = tcg_global_mem_new_i64(tcg_env,
137755c2a12cSMichael Clark offsetof(CPURISCVState, fpr[i]), riscv_fpr_regnames[i]);
137855c2a12cSMichael Clark }
137955c2a12cSMichael Clark
1380ad75a51eSRichard Henderson cpu_pc = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, pc), "pc");
1381ad75a51eSRichard Henderson cpu_vl = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, vl), "vl");
1382ad75a51eSRichard Henderson cpu_vstart = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, vstart),
1383f714361eSFrank Chang "vstart");
1384ad75a51eSRichard Henderson load_res = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_res),
138555c2a12cSMichael Clark "load_res");
1386ad75a51eSRichard Henderson load_val = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, load_val),
138755c2a12cSMichael Clark "load_val");
13880774a7a1SAnatoly Parshintsev /* Assign PM CSRs to tcg globals */
1389ad75a51eSRichard Henderson pm_mask = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, cur_pmmask),
13900cff460dSLIU Zhiwei "pmmask");
1391ad75a51eSRichard Henderson pm_base = tcg_global_mem_new(tcg_env, offsetof(CPURISCVState, cur_pmbase),
13920cff460dSLIU Zhiwei "pmbase");
139355c2a12cSMichael Clark }
1394