109 changes: 50 additions & 59 deletions target/riscv/translate.c
Expand Up @@ -64,22 +64,22 @@ typedef struct DisasContext {
RISCVMXL xl;
uint32_t misa_ext;
uint32_t opcode;
uint32_t mstatus_fs;
uint32_t mstatus_vs;
uint32_t mstatus_hs_fs;
uint32_t mstatus_hs_vs;
RISCVExtStatus mstatus_fs;
RISCVExtStatus mstatus_vs;
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
no previous fp instruction. Note that we exit the TB when writing
to any system register, which includes CSR_FRM, so we do not have
to reset this known value. */
uint32_t priv;
/*
* Remember the rounding mode encoded in the previous fp instruction,
* which we have already installed into env->fp_status. Or -1 for
* no previous fp instruction. Note that we exit the TB when writing
* to any system register, which includes CSR_FRM, so we do not have
* to reset this known value.
*/
int frm;
RISCVMXL ol;
bool virt_inst_excp;
bool virt_enabled;
const RISCVCPUConfig *cfg_ptr;
bool hlsx;
/* vector extension */
bool vill;
/*
Expand All @@ -99,7 +99,7 @@ typedef struct DisasContext {
uint8_t vta;
uint8_t vma;
bool cfg_vta_all_1s;
target_ulong vstart;
bool vstart_eq_zero;
bool vl_eq_vlmax;
CPUState *cs;
TCGv zero;
Expand Down Expand Up @@ -491,7 +491,7 @@ static TCGv_i64 dest_fpr(DisasContext *ctx, int reg_num)
}
}

/* assume t is nanboxing (for normal) or sign-extended (for zfinx) */
/* assume it is nanboxing (for normal) or sign-extended (for zfinx) */
static void gen_set_fpr_hs(DisasContext *ctx, int reg_num, TCGv_i64 t)
{
if (!ctx->cfg_ptr->ext_zfinx) {
Expand Down Expand Up @@ -549,7 +549,7 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm)

/* check misaligned: */
next_pc = ctx->base.pc_next + imm;
if (!has_ext(ctx, RVC)) {
if (!ctx->cfg_ptr->ext_zca) {
if ((next_pc & 0x3) != 0) {
gen_exception_inst_addr_mis(ctx);
return;
Expand Down Expand Up @@ -598,8 +598,7 @@ static TCGv get_address_indexed(DisasContext *ctx, int rs1, TCGv offs)
}

#ifndef CONFIG_USER_ONLY
/* The states of mstatus_fs are:
* 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
/*
* We will have already diagnosed disabled state,
* and need to turn initial/clean into dirty.
*/
Expand All @@ -611,58 +610,49 @@ static void mark_fs_dirty(DisasContext *ctx)
return;
}

if (ctx->mstatus_fs != MSTATUS_FS) {
if (ctx->mstatus_fs != EXT_STATUS_DIRTY) {
/* Remember the state change for the rest of the TB. */
ctx->mstatus_fs = MSTATUS_FS;
ctx->mstatus_fs = EXT_STATUS_DIRTY;

tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
}

if (ctx->virt_enabled && ctx->mstatus_hs_fs != MSTATUS_FS) {
/* Remember the stage change for the rest of the TB. */
ctx->mstatus_hs_fs = MSTATUS_FS;

tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
if (ctx->virt_enabled) {
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
}
}
}
#else
static inline void mark_fs_dirty(DisasContext *ctx) { }
#endif

#ifndef CONFIG_USER_ONLY
/* The states of mstatus_vs are:
* 0 = disabled, 1 = initial, 2 = clean, 3 = dirty
/*
* We will have already diagnosed disabled state,
* and need to turn initial/clean into dirty.
*/
static void mark_vs_dirty(DisasContext *ctx)
{
TCGv tmp;

if (ctx->mstatus_vs != MSTATUS_VS) {
if (ctx->mstatus_vs != EXT_STATUS_DIRTY) {
/* Remember the state change for the rest of the TB. */
ctx->mstatus_vs = MSTATUS_VS;
ctx->mstatus_vs = EXT_STATUS_DIRTY;

tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus));
}

if (ctx->virt_enabled && ctx->mstatus_hs_vs != MSTATUS_VS) {
/* Remember the stage change for the rest of the TB. */
ctx->mstatus_hs_vs = MSTATUS_VS;

tmp = tcg_temp_new();
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
if (ctx->virt_enabled) {
tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
tcg_gen_ori_tl(tmp, tmp, MSTATUS_VS);
tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs));
}
}
}
#else
Expand Down Expand Up @@ -746,8 +736,8 @@ EX_SH(12)
} while (0)

#define REQUIRE_EITHER_EXT(ctx, A, B) do { \
if (!ctx->cfg_ptr->ext_##A && \
!ctx->cfg_ptr->ext_##B) { \
if (!ctx->cfg_ptr->ext_##A && \
!ctx->cfg_ptr->ext_##B) { \
return false; \
} \
} while (0)
Expand All @@ -757,6 +747,11 @@ static int ex_rvc_register(DisasContext *ctx, int reg)
return 8 + reg;
}

static int ex_sreg_register(DisasContext *ctx, int reg)
{
return reg < 2 ? reg + 8 : reg + 16;
}

static int ex_rvc_shiftli(DisasContext *ctx, int imm)
{
/* For RV128 a shamt of 0 means a shift by 64. */
Expand Down Expand Up @@ -1091,6 +1086,8 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)

/* Include the auto-generated decoder for 16 bit insn */
#include "decode-insn16.c.inc"
#include "insn_trans/trans_rvzce.c.inc"

/* Include decoders for factored-out extensions */
#include "decode-XVentanaCondOps.c.inc"

Expand Down Expand Up @@ -1122,7 +1119,11 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
if (insn_len(opcode) == 2) {
ctx->opcode = opcode;
ctx->pc_succ_insn = ctx->base.pc_next + 2;
if (has_ext(ctx, RVC) && decode_insn16(ctx, opcode)) {
/*
* The Zca extension is added as way to refer to instructions in the C
* extension that do not include the floating-point loads and stores
*/
if (ctx->cfg_ptr->ext_zca && decode_insn16(ctx, opcode)) {
return;
}
} else {
Expand Down Expand Up @@ -1152,32 +1153,22 @@ 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->priv = FIELD_EX32(tb_flags, TB_FLAGS, PRIV);
ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX);
ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS;
ctx->mstatus_vs = tb_flags & TB_FLAGS_MSTATUS_VS;
ctx->mstatus_fs = FIELD_EX32(tb_flags, TB_FLAGS, FS);
ctx->mstatus_vs = FIELD_EX32(tb_flags, TB_FLAGS, VS);
ctx->priv_ver = env->priv_ver;
#if !defined(CONFIG_USER_ONLY)
if (riscv_has_ext(env, RVH)) {
ctx->virt_enabled = riscv_cpu_virt_enabled(env);
} else {
ctx->virt_enabled = false;
}
#else
ctx->virt_enabled = false;
#endif
ctx->virt_enabled = FIELD_EX32(tb_flags, TB_FLAGS, VIRT_ENABLED);
ctx->misa_ext = env->misa_ext;
ctx->frm = -1; /* unknown rounding mode */
ctx->cfg_ptr = &(cpu->cfg);
ctx->mstatus_hs_fs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_FS);
ctx->mstatus_hs_vs = FIELD_EX32(tb_flags, TB_FLAGS, MSTATUS_HS_VS);
ctx->hlsx = FIELD_EX32(tb_flags, TB_FLAGS, HLSX);
ctx->vill = FIELD_EX32(tb_flags, TB_FLAGS, VILL);
ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW);
ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3);
ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s;
ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s;
ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s;
ctx->vstart = env->vstart;
ctx->vstart_eq_zero = FIELD_EX32(tb_flags, TB_FLAGS, VSTART_EQ_ZERO);
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
ctx->misa_mxl_max = env->misa_mxl_max;
ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL);
Expand Down Expand Up @@ -1255,8 +1246,8 @@ static void riscv_tr_disas_log(const DisasContextBase *dcbase,

fprintf(logfile, "IN: %s\n", lookup_symbol(dcbase->pc_first));
#ifndef CONFIG_USER_ONLY
fprintf(logfile, "Priv: "TARGET_FMT_ld"; Virt: "TARGET_FMT_ld"\n",
env->priv, env->virt);
fprintf(logfile, "Priv: "TARGET_FMT_ld"; Virt: %d\n",
env->priv, env->virt_enabled);
#endif
target_disas(logfile, cpu, dcbase->pc_first, dcbase->tb->size);
}
Expand Down
317 changes: 180 additions & 137 deletions target/riscv/vector_helper.c

Large diffs are not rendered by default.

55 changes: 55 additions & 0 deletions target/riscv/zce_helper.c
@@ -0,0 +1,55 @@
/*
* RISC-V Zcmt Extension Helper for QEMU.
*
* Copyright (c) 2021-2022 PLCT Lab
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "exec/cpu_ldst.h"

target_ulong HELPER(cm_jalt)(CPURISCVState *env, uint32_t index)
{

#if !defined(CONFIG_USER_ONLY)
RISCVException ret = smstateen_acc_ok(env, 0, SMSTATEEN0_JVT);
if (ret != RISCV_EXCP_NONE) {
riscv_raise_exception(env, ret, 0);
}
#endif

target_ulong target;
target_ulong val = env->jvt;
int xlen = riscv_cpu_xlen(env);
uint8_t mode = get_field(val, JVT_MODE);
target_ulong base = val & JVT_BASE;
target_ulong t0;

if (mode != 0) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, 0);
}

if (xlen == 32) {
t0 = base + (index << 2);
target = cpu_ldl_code(env, t0);
} else {
t0 = base + (index << 3);
target = cpu_ldq_code(env, t0);
}

return target & ~0x1;
}