diff options
Diffstat (limited to 'target/riscv/translate.c')
| -rw-r--r-- | target/riscv/translate.c | 174 |
1 files changed, 130 insertions, 44 deletions
diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6d7fbca1fa..d38f87d718 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -55,7 +55,8 @@ typedef struct DisasContext { /* pc_succ_insn points to the instruction following base.pc_next */ target_ulong pc_succ_insn; target_ulong priv_ver; - target_ulong misa; + RISCVMXL xl; + uint32_t misa_ext; uint32_t opcode; uint32_t mstatus_fs; uint32_t mstatus_hs_fs; @@ -66,7 +67,7 @@ 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; + RISCVMXL ol; bool virt_enabled; bool ext_ifencei; bool hlsx; @@ -86,27 +87,35 @@ typedef struct DisasContext { static inline bool has_ext(DisasContext *ctx, uint32_t ext) { - return ctx->misa & ext; + return ctx->misa_ext & ext; } #ifdef TARGET_RISCV32 -# define is_32bit(ctx) true +#define get_xl(ctx) MXL_RV32 #elif defined(CONFIG_USER_ONLY) -# define is_32bit(ctx) false +#define get_xl(ctx) MXL_RV64 #else -static inline bool is_32bit(DisasContext *ctx) +#define get_xl(ctx) ((ctx)->xl) +#endif + +/* The word size for this machine mode. */ +static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) { - return (ctx->misa & RV32) == RV32; + return 16 << get_xl(ctx); } + +/* The operation length, as opposed to the xlen. */ +#ifdef TARGET_RISCV32 +#define get_ol(ctx) MXL_RV32 +#else +#define get_ol(ctx) ((ctx)->ol) #endif -/* The word size for this operation. */ -static inline int oper_len(DisasContext *ctx) +static inline int get_olen(DisasContext *ctx) { - return ctx->w ? 32 : TARGET_LONG_BITS; + return 16 << get_ol(ctx); } - /* * 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. @@ -193,24 +202,34 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) return ctx->zero; } - 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; + switch (get_ol(ctx)) { + case MXL_RV32: + switch (ext) { + case EXT_NONE: + break; + 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; + default: + g_assert_not_reached(); + } + break; + case MXL_RV64: + break; + default: + g_assert_not_reached(); } - g_assert_not_reached(); + return cpu_gpr[reg_num]; } static TCGv dest_gpr(DisasContext *ctx, int reg_num) { - if (reg_num == 0 || ctx->w) { + if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) { return temp_new(ctx); } return cpu_gpr[reg_num]; @@ -219,10 +238,15 @@ static TCGv dest_gpr(DisasContext *ctx, int reg_num) static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) { if (reg_num != 0) { - if (ctx->w) { + switch (get_ol(ctx)) { + case MXL_RV32: tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); - } else { + break; + case MXL_RV64: tcg_gen_mov_tl(cpu_gpr[reg_num], t); + break; + default: + g_assert_not_reached(); } } } @@ -256,7 +280,6 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) static void mark_fs_dirty(DisasContext *ctx) { TCGv tmp; - target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD; if (ctx->mstatus_fs != MSTATUS_FS) { /* Remember the state change for the rest of the TB. */ @@ -264,7 +287,7 @@ static void mark_fs_dirty(DisasContext *ctx) tmp = tcg_temp_new(); tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); - tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd); + tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); tcg_temp_free(tmp); } @@ -275,7 +298,7 @@ static void mark_fs_dirty(DisasContext *ctx) tmp = tcg_temp_new(); tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs)); - tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd); + tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs)); tcg_temp_free(tmp); } @@ -315,16 +338,16 @@ EX_SH(12) } \ } while (0) -#define REQUIRE_32BIT(ctx) do { \ - if (!is_32bit(ctx)) { \ - return false; \ - } \ +#define REQUIRE_32BIT(ctx) do { \ + if (get_xl(ctx) != MXL_RV32) { \ + return false; \ + } \ } while (0) -#define REQUIRE_64BIT(ctx) do { \ - if (is_32bit(ctx)) { \ - return false; \ - } \ +#define REQUIRE_64BIT(ctx) do { \ + if (get_xl(ctx) < MXL_RV64) { \ + return false; \ + } \ } while (0) static int ex_rvc_register(DisasContext *ctx, int reg) @@ -379,11 +402,27 @@ static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, return true; } +static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv, TCGv), + void (*f_32)(TCGv, TCGv, TCGv)) +{ + int olen = get_olen(ctx); + + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_arith(ctx, a, ext, f_tl); +} + static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { TCGv dest, src1; - int max_len = oper_len(ctx); + int max_len = get_olen(ctx); if (a->shamt >= max_len) { return false; @@ -398,11 +437,27 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, return true; } +static bool 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)) +{ + int olen = get_olen(ctx); + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_shift_imm_fn(ctx, a, ext, f_tl); +} + static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { TCGv dest, src1, src2; - int max_len = oper_len(ctx); + int max_len = get_olen(ctx); if (a->shamt >= max_len) { return false; @@ -426,7 +481,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); TCGv ext2 = tcg_temp_new(); - tcg_gen_andi_tl(ext2, src2, oper_len(ctx) - 1); + tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1); func(dest, src1, ext2); gen_set_gpr(ctx, a->rd, dest); @@ -434,6 +489,21 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, return true; } +static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv, TCGv), + void (*f_32)(TCGv, TCGv, TCGv)) +{ + int olen = get_olen(ctx); + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_shift(ctx, a, ext, f_tl); +} + static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, void (*func)(TCGv, TCGv)) { @@ -446,6 +516,22 @@ static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, return true; } +static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv), + void (*f_32)(TCGv, TCGv)) +{ + int olen = get_olen(ctx); + + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_unary(ctx, a, ext, f_tl); +} + static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) { DisasContext *ctx = container_of(dcbase, DisasContext, base); @@ -501,7 +587,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) uint32_t tb_flags = ctx->base.tb->flags; ctx->pc_succ_insn = ctx->base.pc_first; - ctx->mem_idx = tb_flags & TB_FLAGS_MMU_MASK; + ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX); ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS; ctx->priv_ver = env->priv_ver; #if !defined(CONFIG_USER_ONLY) @@ -513,7 +599,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #else ctx->virt_enabled = false; #endif - ctx->misa = env->misa; + ctx->misa_ext = env->misa_ext; ctx->frm = -1; /* unknown rounding mode */ ctx->ext_ifencei = cpu->cfg.ext_ifencei; ctx->vlen = cpu->cfg.vlen; @@ -524,8 +610,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL); ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); + ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->cs = cs; - ctx->w = false; ctx->ntemp = 0; memset(ctx->temp, 0, sizeof(ctx->temp)); @@ -549,9 +635,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPURISCVState *env = cpu->env_ptr; uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next); + ctx->ol = ctx->xl; 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]); |