xref: /openbmc/qemu/target/riscv/translate.c (revision 92ec7805190313c9e628f8fc4eb4f932c15247bd)
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