diff options
Diffstat (limited to 'target/riscv/translate.c')
-rw-r--r-- | target/riscv/translate.c | 689 |
1 files changed, 147 insertions, 542 deletions
diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6983be5..e356fc6 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -39,15 +39,25 @@ static TCGv load_val; #include "exec/gen-icount.h" +/* + * If an operation is being performed on less than TARGET_LONG_BITS, + * it may require the inputs to be sign- or zero-extended; which will + * depend on the exact operation being performed. + */ +typedef enum { + EXT_NONE, + EXT_SIGN, + EXT_ZERO, +} DisasExtend; + typedef struct DisasContext { DisasContextBase base; /* pc_succ_insn points to the instruction following base.pc_next */ target_ulong pc_succ_insn; target_ulong priv_ver; - bool virt_enabled; + target_ulong misa; uint32_t opcode; uint32_t mstatus_fs; - target_ulong misa; uint32_t mem_idx; /* Remember the rounding mode encoded in the previous fp instruction, which we have already installed into env->fp_status. Or -1 for @@ -55,6 +65,8 @@ typedef struct DisasContext { to any system register, which includes CSR_FRM, so we do not have to reset this known value. */ int frm; + bool w; + bool virt_enabled; bool ext_ifencei; bool hlsx; /* vector extension */ @@ -64,7 +76,11 @@ typedef struct DisasContext { uint16_t vlen; uint16_t mlen; bool vl_eq_vlmax; + uint8_t ntemp; CPUState *cs; + TCGv zero; + /* Space for 3 operands plus 1 extra for address computation. */ + TCGv temp[4]; } DisasContext; static inline bool has_ext(DisasContext *ctx, uint32_t ext) @@ -83,6 +99,13 @@ static inline bool is_32bit(DisasContext *ctx) } #endif +/* The word size for this operation. */ +static inline int oper_len(DisasContext *ctx) +{ + return ctx->w ? 32 : TARGET_LONG_BITS; +} + + /* * RISC-V requires NaN-boxing of narrower width floating point values. * This applies when a 32-bit value is assigned to a 64-bit FP register. @@ -104,20 +127,16 @@ static void gen_nanbox_s(TCGv_i64 out, TCGv_i64 in) */ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in) { - TCGv_i64 t_max = tcg_const_i64(0xffffffff00000000ull); - TCGv_i64 t_nan = tcg_const_i64(0xffffffff7fc00000ull); + TCGv_i64 t_max = tcg_constant_i64(0xffffffff00000000ull); + TCGv_i64 t_nan = tcg_constant_i64(0xffffffff7fc00000ull); tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan); - tcg_temp_free_i64(t_max); - tcg_temp_free_i64(t_nan); } static void generate_exception(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); - TCGv_i32 helper_tmp = tcg_const_i32(excp); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } @@ -125,17 +144,13 @@ static void generate_exception_mtval(DisasContext *ctx, int excp) { tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next); tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr)); - TCGv_i32 helper_tmp = tcg_const_i32(excp); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp)); ctx->base.is_jmp = DISAS_NORETURN; } static void gen_exception_debug(void) { - TCGv_i32 helper_tmp = tcg_const_i32(EXCP_DEBUG); - gen_helper_raise_exception(cpu_env, helper_tmp); - tcg_temp_free_i32(helper_tmp); + gen_helper_raise_exception(cpu_env, tcg_constant_i32(EXCP_DEBUG)); } /* Wrapper around tcg_gen_exit_tb that handles single stepping */ @@ -180,151 +195,60 @@ static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) } } -/* Wrapper for getting reg values - need to check of reg is zero since - * cpu_gpr[0] is not actually allocated - */ -static inline void gen_get_gpr(TCGv t, int reg_num) -{ - if (reg_num == 0) { - tcg_gen_movi_tl(t, 0); - } else { - tcg_gen_mov_tl(t, cpu_gpr[reg_num]); - } -} - -/* Wrapper for setting reg values - need to check of reg is zero since - * cpu_gpr[0] is not actually allocated. this is more for safety purposes, - * since we usually avoid calling the OP_TYPE_gen function if we see a write to - * $zero +/* + * Wrappers for getting reg values. + * + * The $zero register does not have cpu_gpr[0] allocated -- we supply the + * constant zero as a source, and an uninitialized sink as destination. + * + * Further, we may provide an extension for word operations. */ -static inline void gen_set_gpr(int reg_num_dst, TCGv t) +static TCGv temp_new(DisasContext *ctx) { - if (reg_num_dst != 0) { - tcg_gen_mov_tl(cpu_gpr[reg_num_dst], t); - } + assert(ctx->ntemp < ARRAY_SIZE(ctx->temp)); + return ctx->temp[ctx->ntemp++] = tcg_temp_new(); } -static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) +static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) { - TCGv rl = tcg_temp_new(); - TCGv rh = tcg_temp_new(); - - tcg_gen_mulu2_tl(rl, rh, arg1, arg2); - /* fix up for one negative */ - tcg_gen_sari_tl(rl, arg1, TARGET_LONG_BITS - 1); - tcg_gen_and_tl(rl, rl, arg2); - tcg_gen_sub_tl(ret, rh, rl); + TCGv t; - tcg_temp_free(rl); - tcg_temp_free(rh); -} - -static void gen_div(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv cond1, cond2, zeroreg, resultopt1; - /* - * Handle by altering args to tcg_gen_div to produce req'd results: - * For overflow: want source1 in source1 and 1 in source2 - * For div by zero: want -1 in source1 and 1 in source2 -> -1 result - */ - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)(~0L)); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - ((target_ulong)1) << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond1, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, 0); /* cond2 = div 0 */ - /* if div by zero, set source1 to -1, otherwise don't change */ - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond2, zeroreg, source1, - resultopt1); - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond1, cond1, cond2); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_div_tl(ret, source1, source2); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); -} + if (reg_num == 0) { + return ctx->zero; + } -static void gen_divu(TCGv ret, TCGv source1, TCGv source2) -{ - TCGv cond1, zeroreg, resultopt1; - cond1 = tcg_temp_new(); - - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movi_tl(resultopt1, (target_ulong)-1); - tcg_gen_movcond_tl(TCG_COND_EQ, source1, cond1, zeroreg, source1, - resultopt1); - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_divu_tl(ret, source1, source2); - - tcg_temp_free(cond1); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); + switch (ctx->w ? ext : EXT_NONE) { + case EXT_NONE: + return cpu_gpr[reg_num]; + case EXT_SIGN: + t = temp_new(ctx); + tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); + return t; + case EXT_ZERO: + t = temp_new(ctx); + tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); + return t; + } + g_assert_not_reached(); } -static void gen_rem(TCGv ret, TCGv source1, TCGv source2) +static TCGv dest_gpr(DisasContext *ctx, int reg_num) { - TCGv cond1, cond2, zeroreg, resultopt1; - - cond1 = tcg_temp_new(); - cond2 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, 1L); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond2, source2, (target_ulong)-1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source1, - (target_ulong)1 << (TARGET_LONG_BITS - 1)); - tcg_gen_and_tl(cond2, cond1, cond2); /* cond1 = overflow */ - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); /* cond2 = div 0 */ - /* if overflow or div by zero, set source2 to 1, else don't change */ - tcg_gen_or_tl(cond2, cond1, cond2); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond2, zeroreg, source2, - resultopt1); - tcg_gen_rem_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(cond2); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); + if (reg_num == 0 || ctx->w) { + return temp_new(ctx); + } + return cpu_gpr[reg_num]; } -static void gen_remu(TCGv ret, TCGv source1, TCGv source2) +static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) { - TCGv cond1, zeroreg, resultopt1; - cond1 = tcg_temp_new(); - zeroreg = tcg_const_tl(0); - resultopt1 = tcg_temp_new(); - - tcg_gen_movi_tl(resultopt1, (target_ulong)1); - tcg_gen_setcondi_tl(TCG_COND_EQ, cond1, source2, 0); - tcg_gen_movcond_tl(TCG_COND_EQ, source2, cond1, zeroreg, source2, - resultopt1); - tcg_gen_remu_tl(resultopt1, source1, source2); - /* if div by zero, just return the original dividend */ - tcg_gen_movcond_tl(TCG_COND_EQ, ret, cond1, zeroreg, resultopt1, - source1); - - tcg_temp_free(cond1); - tcg_temp_free(zeroreg); - tcg_temp_free(resultopt1); + if (reg_num != 0) { + if (ctx->w) { + tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); + } else { + tcg_gen_mov_tl(cpu_gpr[reg_num], t); + } + } } static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) @@ -384,15 +308,11 @@ static inline void mark_fs_dirty(DisasContext *ctx) { } static void gen_set_rm(DisasContext *ctx, int rm) { - TCGv_i32 t0; - if (ctx->frm == rm) { return; } ctx->frm = rm; - t0 = tcg_const_i32(rm); - gen_helper_set_rounding_mode(cpu_env, t0); - tcg_temp_free_i32(t0); + gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm)); } static int ex_plus_1(DisasContext *ctx, int nf) @@ -437,355 +357,108 @@ static int ex_rvc_shifti(DisasContext *ctx, int imm) /* Include the auto-generated decoder for 32 bit insn */ #include "decode-insn32.c.inc" -static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, +static bool gen_arith_imm_fn(DisasContext *ctx, arg_i *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { - TCGv source1; - source1 = tcg_temp_new(); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); - gen_get_gpr(source1, a->rs1); + func(dest, src1, a->imm); - (*func)(source1, source1, a->imm); - - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); + gen_set_gpr(ctx, a->rd, dest); return true; } -static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, +static bool gen_arith_imm_tl(DisasContext *ctx, arg_i *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - tcg_gen_movi_tl(source2, a->imm); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = tcg_constant_tl(a->imm); - (*func)(source1, source1, source2); + func(dest, src1, src2); - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -static void gen_addw(TCGv ret, TCGv arg1, TCGv arg2) +static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - tcg_gen_add_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, ext); -static void gen_subw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_sub_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} - -static void gen_mulw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_mul_tl(ret, arg1, arg2); - tcg_gen_ext32s_tl(ret, ret); -} + func(dest, src1, src2); -static bool gen_arith_div_w(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); - tcg_gen_ext32s_tl(source1, source1); - tcg_gen_ext32s_tl(source2, source2); - - (*func)(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static bool gen_arith_div_uw(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); - tcg_gen_ext32u_tl(source1, source1); - tcg_gen_ext32u_tl(source2, source2); - - (*func)(source1, source1, source2); - - tcg_gen_ext32s_tl(source1, source1); - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } -static void gen_pack(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_deposit_tl(ret, arg1, arg2, - TARGET_LONG_BITS / 2, - TARGET_LONG_BITS / 2); -} - -static void gen_packu(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_shri_tl(t, arg1, TARGET_LONG_BITS / 2); - tcg_gen_deposit_tl(ret, arg2, t, 0, TARGET_LONG_BITS / 2); - tcg_temp_free(t); -} - -static void gen_packh(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_ext8u_tl(t, arg2); - tcg_gen_deposit_tl(ret, arg1, t, 8, TARGET_LONG_BITS - 8); - tcg_temp_free(t); -} - -static void gen_sbop_mask(TCGv ret, TCGv shamt) -{ - tcg_gen_movi_tl(ret, 1); - tcg_gen_shl_tl(ret, ret, shamt); -} - -static void gen_bset(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_or_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_bclr(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_andc_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_binv(TCGv ret, TCGv arg1, TCGv shamt) -{ - TCGv t = tcg_temp_new(); - - gen_sbop_mask(t, shamt); - tcg_gen_xor_tl(ret, arg1, t); - - tcg_temp_free(t); -} - -static void gen_bext(TCGv ret, TCGv arg1, TCGv shamt) -{ - tcg_gen_shr_tl(ret, arg1, shamt); - tcg_gen_andi_tl(ret, ret, 1); -} - -static void gen_slo(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_not_tl(ret, arg1); - tcg_gen_shl_tl(ret, ret, arg2); - tcg_gen_not_tl(ret, ret); -} - -static void gen_sro(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_not_tl(ret, arg1); - tcg_gen_shr_tl(ret, ret, arg2); - tcg_gen_not_tl(ret, ret); -} - -static bool gen_grevi(DisasContext *ctx, arg_grevi *a) +static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, + void (*func)(TCGv, TCGv, target_long)) { - TCGv source1 = tcg_temp_new(); - TCGv source2; + TCGv dest, src1; + int max_len = oper_len(ctx); - gen_get_gpr(source1, a->rs1); - - if (a->shamt == (TARGET_LONG_BITS - 8)) { - /* rev8, byte swaps */ - tcg_gen_bswap_tl(source1, source1); - } else { - source2 = tcg_temp_new(); - tcg_gen_movi_tl(source2, a->shamt); - gen_helper_grev(source1, source1, source2); - tcg_temp_free(source2); + if (a->shamt >= max_len) { + return false; } - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - return true; -} - -#define GEN_SHADD(SHAMT) \ -static void gen_sh##SHAMT##add(TCGv ret, TCGv arg1, TCGv arg2) \ -{ \ - TCGv t = tcg_temp_new(); \ - \ - tcg_gen_shli_tl(t, arg1, SHAMT); \ - tcg_gen_add_tl(ret, t, arg2); \ - \ - tcg_temp_free(t); \ -} - -GEN_SHADD(1) -GEN_SHADD(2) -GEN_SHADD(3) - -static void gen_ctzw(TCGv ret, TCGv arg1) -{ - tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); - tcg_gen_ctzi_tl(ret, ret, 64); -} - -static void gen_clzw(TCGv ret, TCGv arg1) -{ - tcg_gen_ext32u_tl(ret, arg1); - tcg_gen_clzi_tl(ret, ret, 64); - tcg_gen_subi_tl(ret, ret, 32); -} - -static void gen_cpopw(TCGv ret, TCGv arg1) -{ - tcg_gen_ext32u_tl(arg1, arg1); - tcg_gen_ctpop_tl(ret, arg1); -} - -static void gen_packw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_ext16s_tl(t, arg2); - tcg_gen_deposit_tl(ret, arg1, t, 16, 48); - tcg_temp_free(t); -} - -static void gen_packuw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv t = tcg_temp_new(); - tcg_gen_shri_tl(t, arg1, 16); - tcg_gen_deposit_tl(ret, arg2, t, 0, 16); - tcg_gen_ext32s_tl(ret, ret); - tcg_temp_free(t); -} - -static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); - - tcg_gen_rotr_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); -} - -static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); + dest = dest_gpr(ctx, a->rd); + src1 = get_gpr(ctx, a->rs1, ext); - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); + func(dest, src1, a->shamt); - tcg_gen_rotl_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); + gen_set_gpr(ctx, a->rd, dest); + return true; } -static void gen_grevw(TCGv ret, TCGv arg1, TCGv arg2) +static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_grev(ret, arg1, arg2); -} + TCGv dest, src1, src2; + int max_len = oper_len(ctx); -static void gen_gorcw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - gen_helper_gorcw(ret, arg1, arg2); -} + if (a->shamt >= max_len) { + return false; + } -#define GEN_SHADD_UW(SHAMT) \ -static void gen_sh##SHAMT##add_uw(TCGv ret, TCGv arg1, TCGv arg2) \ -{ \ - TCGv t = tcg_temp_new(); \ - \ - tcg_gen_ext32u_tl(t, arg1); \ - \ - tcg_gen_shli_tl(t, t, SHAMT); \ - tcg_gen_add_tl(ret, t, arg2); \ - \ - tcg_temp_free(t); \ -} + dest = dest_gpr(ctx, a->rd); + src1 = get_gpr(ctx, a->rs1, ext); + src2 = tcg_constant_tl(a->shamt); -GEN_SHADD_UW(1) -GEN_SHADD_UW(2) -GEN_SHADD_UW(3) + func(dest, src1, src2); -static void gen_add_uw(TCGv ret, TCGv arg1, TCGv arg2) -{ - tcg_gen_ext32u_tl(arg1, arg1); - tcg_gen_add_tl(ret, arg1, arg2); + gen_set_gpr(ctx, a->rd, dest); + return true; } -static bool gen_arith(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*func)(TCGv, TCGv, TCGv)) { - TCGv source1, source2; - source1 = tcg_temp_new(); - source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + TCGv ext2 = tcg_temp_new(); - (*func)(source1, source1, source2); + tcg_gen_andi_tl(ext2, src2, oper_len(ctx) - 1); + func(dest, src1, ext2); - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); + tcg_temp_free(ext2); return true; } -static bool gen_shift(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) +static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*func)(TCGv, TCGv)) { - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1 = get_gpr(ctx, a->rs1, ext); - tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); - (*func)(source1, source1, source2); + func(dest, src1); - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); + gen_set_gpr(ctx, a->rd, dest); return true; } @@ -798,88 +471,6 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) return cpu_ldl_code(env, pc); } -static bool gen_shifti(DisasContext *ctx, arg_shift *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - if (a->shamt >= TARGET_LONG_BITS) { - return false; - } - - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - - tcg_gen_movi_tl(source2, a->shamt); - (*func)(source1, source1, source2); - - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static bool gen_shiftw(DisasContext *ctx, arg_r *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - gen_get_gpr(source2, a->rs2); - - tcg_gen_andi_tl(source2, source2, 31); - (*func)(source1, source1, source2); - tcg_gen_ext32s_tl(source1, source1); - - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static bool gen_shiftiw(DisasContext *ctx, arg_shift *a, - void(*func)(TCGv, TCGv, TCGv)) -{ - TCGv source1 = tcg_temp_new(); - TCGv source2 = tcg_temp_new(); - - gen_get_gpr(source1, a->rs1); - tcg_gen_movi_tl(source2, a->shamt); - - (*func)(source1, source1, source2); - tcg_gen_ext32s_tl(source1, source1); - - gen_set_gpr(a->rd, source1); - tcg_temp_free(source1); - tcg_temp_free(source2); - return true; -} - -static void gen_ctz(TCGv ret, TCGv arg1) -{ - tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); -} - -static void gen_clz(TCGv ret, TCGv arg1) -{ - tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); -} - -static bool gen_unary(DisasContext *ctx, arg_r2 *a, - void(*func)(TCGv, TCGv)) -{ - TCGv source = tcg_temp_new(); - - gen_get_gpr(source, a->rs1); - - (*func)(source, source); - - gen_set_gpr(a->rd, source); - tcg_temp_free(source); - return true; -} - /* Include insn module translation function */ #include "insn_trans/trans_rvi.c.inc" #include "insn_trans/trans_rvm.c.inc" @@ -948,6 +539,11 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); ctx->cs = cs; + ctx->w = false; + ctx->ntemp = 0; + memset(ctx->temp, 0, sizeof(ctx->temp)); + + ctx->zero = tcg_constant_tl(0); } static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu) @@ -969,6 +565,13 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) decode_opc(env, ctx, opcode16); ctx->base.pc_next = ctx->pc_succ_insn; + ctx->w = false; + + for (int i = ctx->ntemp - 1; i >= 0; --i) { + tcg_temp_free(ctx->temp[i]); + ctx->temp[i] = NULL; + } + ctx->ntemp = 0; if (ctx->base.is_jmp == DISAS_NEXT) { target_ulong page_start; @@ -1029,9 +632,11 @@ void riscv_translate_init(void) { int i; - /* cpu_gpr[0] is a placeholder for the zero register. Do not use it. */ - /* Use the gen_set_gpr and gen_get_gpr helper functions when accessing */ - /* registers, unless you specifically block reads/writes to reg 0 */ + /* + * cpu_gpr[0] is a placeholder for the zero register. Do not use it. + * Use the gen_set_gpr and get_gpr helper functions when accessing regs, + * unless you specifically block reads/writes to reg 0. + */ cpu_gpr[0] = NULL; for (i = 1; i < 32; i++) { |