34 changes: 11 additions & 23 deletions target/riscv/cpu.h
Expand Up @@ -81,17 +81,6 @@
#define RVH RV('H')
#define RVJ RV('J')

/* S extension denotes that Supervisor mode exists, however it is possible
to have a core that support S mode but does not have an MMU and there
is currently no bit in misa to indicate whether an MMU exists or not
so a cpu features bitfield is required, likewise for optional PMP support */
enum {
RISCV_FEATURE_MMU,
RISCV_FEATURE_PMP,
RISCV_FEATURE_EPMP,
RISCV_FEATURE_MISA,
RISCV_FEATURE_DEBUG
};

/* Privileged specification version */
enum {
Expand Down Expand Up @@ -186,8 +175,6 @@ struct CPUArchState {
/* 128-bit helpers upper part return value */
target_ulong retxh;

uint32_t features;

#ifdef CONFIG_USER_ONLY
uint32_t elf_flags;
#endif
Expand Down Expand Up @@ -447,9 +434,11 @@ struct RISCVCPUConfig {
bool ext_zkt;
bool ext_ifencei;
bool ext_icsr;
bool ext_zicond;
bool ext_zihintpause;
bool ext_smstateen;
bool ext_sstc;
bool ext_svadu;
bool ext_svinval;
bool ext_svnapot;
bool ext_svpbmt;
Expand All @@ -462,7 +451,10 @@ struct RISCVCPUConfig {
bool ext_zhinxmin;
bool ext_zve32f;
bool ext_zve64f;
bool ext_zve64d;
bool ext_zmmul;
bool ext_zvfh;
bool ext_zvfhmin;
bool ext_smaia;
bool ext_ssaia;
bool ext_sscofpmf;
Expand Down Expand Up @@ -498,6 +490,7 @@ struct RISCVCPUConfig {
bool pmp;
bool epmp;
bool debug;
bool misa_w;

bool short_isa_string;
};
Expand Down Expand Up @@ -535,16 +528,6 @@ static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
return (env->misa_ext & ext) != 0;
}

static inline bool riscv_feature(CPURISCVState *env, int feature)
{
return env->features & (1ULL << feature);
}

static inline void riscv_set_feature(CPURISCVState *env, int feature)
{
env->features |= (1ULL << feature);
}

#include "cpu_user.h"

extern const char * const riscv_int_regnames[];
Expand Down Expand Up @@ -654,6 +637,11 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
#endif
#define riscv_cpu_mxl_bits(env) (1UL << (4 + riscv_cpu_mxl(env)))

static inline const RISCVCPUConfig *riscv_cpu_cfg(CPURISCVState *env)
{
return &env_archcpu(env)->cfg;
}

#if defined(TARGET_RISCV32)
#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
#else
Expand Down
4 changes: 4 additions & 0 deletions target/riscv/cpu_bits.h
Expand Up @@ -747,10 +747,12 @@ typedef enum RISCVException {
#define MENVCFG_CBIE (3UL << 4)
#define MENVCFG_CBCFE BIT(6)
#define MENVCFG_CBZE BIT(7)
#define MENVCFG_HADE (1ULL << 61)
#define MENVCFG_PBMTE (1ULL << 62)
#define MENVCFG_STCE (1ULL << 63)

/* For RV32 */
#define MENVCFGH_HADE BIT(29)
#define MENVCFGH_PBMTE BIT(30)
#define MENVCFGH_STCE BIT(31)

Expand All @@ -763,10 +765,12 @@ typedef enum RISCVException {
#define HENVCFG_CBIE MENVCFG_CBIE
#define HENVCFG_CBCFE MENVCFG_CBCFE
#define HENVCFG_CBZE MENVCFG_CBZE
#define HENVCFG_HADE MENVCFG_HADE
#define HENVCFG_PBMTE MENVCFG_PBMTE
#define HENVCFG_STCE MENVCFG_STCE

/* For RV32 */
#define HENVCFGH_HADE MENVCFGH_HADE
#define HENVCFGH_PBMTE MENVCFGH_PBMTE
#define HENVCFGH_STCE MENVCFGH_STCE

Expand Down
24 changes: 18 additions & 6 deletions target/riscv/cpu_helper.c
Expand Up @@ -51,7 +51,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
*pc = env->xl == MXL_RV32 ? env->pc & UINT32_MAX : env->pc;
*cs_base = 0;

if (riscv_has_ext(env, RVV) || cpu->cfg.ext_zve32f || cpu->cfg.ext_zve64f) {
if (cpu->cfg.ext_zve32f) {
/*
* If env->vl equals to VLMAX, we can use generic vector operation
* expanders (GVEC) to accerlate the vector operations.
Expand Down Expand Up @@ -105,7 +105,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_VS,
get_field(env->mstatus_hs, MSTATUS_VS));
}
if (riscv_feature(env, RISCV_FEATURE_DEBUG) && !icount_enabled()) {
if (cpu->cfg.debug && !icount_enabled()) {
flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
}
#endif
Expand Down Expand Up @@ -706,7 +706,7 @@ static int get_physical_address_pmp(CPURISCVState *env, int *prot,
pmp_priv_t pmp_priv;
int pmp_index = -1;

if (!riscv_feature(env, RISCV_FEATURE_PMP)) {
if (!riscv_cpu_cfg(env)->pmp) {
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return TRANSLATE_SUCCESS;
}
Expand Down Expand Up @@ -796,7 +796,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
mode = PRV_U;
}

if (mode == PRV_M || !riscv_feature(env, RISCV_FEATURE_MMU)) {
if (mode == PRV_M || !riscv_cpu_cfg(env)->mmu) {
*physical = addr;
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return TRANSLATE_SUCCESS;
Expand Down Expand Up @@ -936,9 +936,17 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
return TRANSLATE_FAIL;
}

bool pbmte = env->menvcfg & MENVCFG_PBMTE;
bool hade = env->menvcfg & MENVCFG_HADE;

if (first_stage && two_stage && riscv_cpu_virt_enabled(env)) {
pbmte = pbmte && (env->henvcfg & HENVCFG_PBMTE);
hade = hade && (env->henvcfg & HENVCFG_HADE);
}

if (riscv_cpu_sxl(env) == MXL_RV32) {
ppn = pte >> PTE_PPN_SHIFT;
} else if (cpu->cfg.ext_svpbmt || cpu->cfg.ext_svnapot) {
} else if (pbmte || cpu->cfg.ext_svnapot) {
ppn = (pte & (target_ulong)PTE_PPN_MASK) >> PTE_PPN_SHIFT;
} else {
ppn = pte >> PTE_PPN_SHIFT;
Expand All @@ -950,7 +958,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
if (!(pte & PTE_V)) {
/* Invalid PTE */
return TRANSLATE_FAIL;
} else if (!cpu->cfg.ext_svpbmt && (pte & PTE_PBMT)) {
} else if (!pbmte && (pte & PTE_PBMT)) {
return TRANSLATE_FAIL;
} else if (!(pte & (PTE_R | PTE_W | PTE_X))) {
/* Inner PTE, continue walking */
Expand Down Expand Up @@ -992,6 +1000,10 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,

/* Page table updates need to be atomic with MTTCG enabled */
if (updated_pte != pte) {
if (!hade) {
return TRANSLATE_FAIL;
}

/*
* - if accessed or dirty bits need updating, and the PTE is
* in RAM, then we do so atomically with a compare and swap.
Expand Down
354 changes: 186 additions & 168 deletions target/riscv/csr.c

Large diffs are not rendered by default.

100 changes: 20 additions & 80 deletions target/riscv/gdbstub.c
Expand Up @@ -127,40 +127,6 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}

/*
* Convert register index number passed by GDB to the correspond
* vector CSR number. Vector CSRs are defined after vector registers
* in dynamic generated riscv-vector.xml, thus the starting register index
* of vector CSRs is 32.
* Return 0 if register index number is out of range.
*/
static int riscv_gdb_vector_csrno(int num_regs)
{
/*
* The order of vector CSRs in the switch case
* should match with the order defined in csr_ops[].
*/
switch (num_regs) {
case 32:
return CSR_VSTART;
case 33:
return CSR_VXSAT;
case 34:
return CSR_VXRM;
case 35:
return CSR_VCSR;
case 36:
return CSR_VL;
case 37:
return CSR_VTYPE;
case 38:
return CSR_VLENB;
default:
/* Unknown register. */
return 0;
}
}

static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
{
uint16_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
Expand All @@ -174,19 +140,6 @@ static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n)
return cnt;
}

int csrno = riscv_gdb_vector_csrno(n);

if (!csrno) {
return 0;
}

target_ulong val = 0;
int result = riscv_csrrw_debug(env, csrno, &val, 0, 0);

if (result == RISCV_EXCP_NONE) {
return gdb_get_regl(buf, val);
}

return 0;
}

Expand All @@ -201,19 +154,6 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n)
return vlenb;
}

int csrno = riscv_gdb_vector_csrno(n);

if (!csrno) {
return 0;
}

target_ulong val = ldtul_p(mem_buf);
int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);

if (result == RISCV_EXCP_NONE) {
return sizeof(target_ulong);
}

return 0;
}

Expand Down Expand Up @@ -280,6 +220,10 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
int bitsize = 16 << env->misa_mxl_max;
int i;

#if !defined(CONFIG_USER_ONLY)
env->debugger = true;
#endif

/* Until gdb knows about 128-bit registers */
if (bitsize > 64) {
bitsize = 64;
Expand All @@ -290,6 +234,9 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
g_string_append_printf(s, "<feature name=\"org.gnu.gdb.riscv.csr\">");

for (i = 0; i < CSR_TABLE_SIZE; i++) {
if (env->priv_ver < csr_ops[i].min_priv_ver) {
continue;
}
predicate = csr_ops[i].predicate;
if (predicate && (predicate(env, i) == RISCV_EXCP_NONE)) {
if (csr_ops[i].name) {
Expand All @@ -305,6 +252,11 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg)
g_string_append_printf(s, "</feature>");

cpu->dyn_csr_xml = g_string_free(s, false);

#if !defined(CONFIG_USER_ONLY)
env->debugger = false;
#endif

return CSR_TABLE_SIZE;
}

Expand Down Expand Up @@ -349,21 +301,6 @@ static int ricsv_gen_dynamic_vector_xml(CPUState *cs, int base_reg)
num_regs++;
}

/* Define vector CSRs */
const char *vector_csrs[7] = {
"vstart", "vxsat", "vxrm", "vcsr",
"vl", "vtype", "vlenb"
};

for (i = 0; i < 7; i++) {
g_string_append_printf(s,
"<reg name=\"%s\" bitsize=\"%d\""
" regnum=\"%d\" group=\"vector\""
" type=\"int\"/>",
vector_csrs[i], TARGET_LONG_BITS, base_reg++);
num_regs++;
}

g_string_append_printf(s, "</feature>");

cpu->dyn_vreg_xml = g_string_free(s, false);
Expand All @@ -382,9 +319,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
32, "riscv-32bit-fpu.xml", 0);
}
if (env->misa_ext & RVV) {
int base_reg = cs->gdb_num_regs;
gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector,
ricsv_gen_dynamic_vector_xml(cs,
cs->gdb_num_regs),
ricsv_gen_dynamic_vector_xml(cs, base_reg),
"riscv-vector.xml", 0);
}
switch (env->misa_mxl_max) {
Expand All @@ -403,7 +340,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
g_assert_not_reached();
}

gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs),
"riscv-csr.xml", 0);
if (cpu->cfg.ext_icsr) {
int base_reg = cs->gdb_num_regs;
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
riscv_gen_dynamic_csr_xml(cs, base_reg),
"riscv-csr.xml", 0);
}
}
4 changes: 4 additions & 0 deletions target/riscv/insn32.decode
Expand Up @@ -890,3 +890,7 @@ sm3p1 00 01000 01001 ..... 001 ..... 0010011 @r2
# *** RV32 Zksed Standard Extension ***
sm4ed .. 11000 ..... ..... 000 ..... 0110011 @k_aes
sm4ks .. 11010 ..... ..... 000 ..... 0110011 @k_aes

# *** RV32 Zicond Standard Extension ***
czero_eqz 0000111 ..... ..... 101 ..... 0110011 @r
czero_nez 0000111 ..... ..... 111 ..... 0110011 @r
184 changes: 58 additions & 126 deletions target/riscv/insn_trans/trans_rvv.c.inc

Large diffs are not rendered by default.

25 changes: 12 additions & 13 deletions target/riscv/insn_trans/trans_rvzfh.c.inc
Expand Up @@ -28,15 +28,14 @@
} \
} while (0)

#define REQUIRE_ZFH_OR_ZFHMIN(ctx) do { \
if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin)) { \
#define REQUIRE_ZFHMIN(ctx) do { \
if (!ctx->cfg_ptr->ext_zfhmin) { \
return false; \
} \
} while (0)

#define REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx) do { \
if (!(ctx->cfg_ptr->ext_zfh || ctx->cfg_ptr->ext_zfhmin || \
ctx->cfg_ptr->ext_zhinx || ctx->cfg_ptr->ext_zhinxmin)) { \
#define REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx) do { \
if (!(ctx->cfg_ptr->ext_zfhmin || ctx->cfg_ptr->ext_zhinxmin)) { \
return false; \
} \
} while (0)
Expand All @@ -47,7 +46,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a)
TCGv t0;

REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN(ctx);
REQUIRE_ZFHMIN(ctx);

decode_save_opc(ctx);
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
Expand All @@ -70,7 +69,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a)
TCGv t0;

REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN(ctx);
REQUIRE_ZFHMIN(ctx);

decode_save_opc(ctx);
t0 = get_gpr(ctx, a->rs1, EXT_NONE);
Expand Down Expand Up @@ -401,7 +400,7 @@ static bool trans_fmax_h(DisasContext *ctx, arg_fmax_h *a)
static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);

TCGv_i64 dest = dest_fpr(ctx, a->rd);
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
Expand All @@ -418,7 +417,7 @@ static bool trans_fcvt_s_h(DisasContext *ctx, arg_fcvt_s_h *a)
static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
REQUIRE_ZDINX_OR_D(ctx);

TCGv_i64 dest = dest_fpr(ctx, a->rd);
Expand All @@ -436,7 +435,7 @@ static bool trans_fcvt_d_h(DisasContext *ctx, arg_fcvt_d_h *a)
static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);

TCGv_i64 dest = dest_fpr(ctx, a->rd);
TCGv_i64 src1 = get_fpr_hs(ctx, a->rs1);
Expand All @@ -452,7 +451,7 @@ static bool trans_fcvt_h_s(DisasContext *ctx, arg_fcvt_h_s *a)
static bool trans_fcvt_h_d(DisasContext *ctx, arg_fcvt_h_d *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN_OR_ZHINX_OR_ZHINXMIN(ctx);
REQUIRE_ZFHMIN_OR_ZHINXMIN(ctx);
REQUIRE_ZDINX_OR_D(ctx);

TCGv_i64 dest = dest_fpr(ctx, a->rd);
Expand Down Expand Up @@ -585,7 +584,7 @@ static bool trans_fcvt_h_wu(DisasContext *ctx, arg_fcvt_h_wu *a)
static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN(ctx);
REQUIRE_ZFHMIN(ctx);

TCGv dest = dest_gpr(ctx, a->rd);

Expand All @@ -605,7 +604,7 @@ static bool trans_fmv_x_h(DisasContext *ctx, arg_fmv_x_h *a)
static bool trans_fmv_h_x(DisasContext *ctx, arg_fmv_h_x *a)
{
REQUIRE_FPU;
REQUIRE_ZFH_OR_ZFHMIN(ctx);
REQUIRE_ZFHMIN(ctx);

TCGv t0 = get_gpr(ctx, a->rs1, EXT_ZERO);

Expand Down
49 changes: 49 additions & 0 deletions target/riscv/insn_trans/trans_rvzicond.c.inc
@@ -0,0 +1,49 @@
/*
* RISC-V translation routines for the Zicond Standard Extension.
*
* Copyright (c) 2020-2023 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/>.
*/

#define REQUIRE_ZICOND(ctx) do { \
if (!ctx->cfg_ptr->ext_zicond) { \
return false; \
} \
} while (0)

static bool trans_czero_eqz(DisasContext *ctx, arg_czero_eqz *a)
{
REQUIRE_ZICOND(ctx);

TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);

tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, ctx->zero, ctx->zero, src1);
gen_set_gpr(ctx, a->rd, dest);
return true;
}

static bool trans_czero_nez(DisasContext *ctx, arg_czero_nez *a)
{
REQUIRE_ZICOND(ctx);

TCGv dest = dest_gpr(ctx, a->rd);
TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);

tcg_gen_movcond_tl(TCG_COND_NE, dest, src2, ctx->zero, ctx->zero, src1);
gen_set_gpr(ctx, a->rd, dest);
return true;
}
4 changes: 0 additions & 4 deletions target/riscv/insn_trans/trans_xthead.c.inc
Expand Up @@ -980,10 +980,6 @@ static bool trans_th_lwud(DisasContext *ctx, arg_th_pair *a)
static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop,
int shamt)
{
if (a->rs == a->rd1 || a->rs == a->rd2 || a->rd1 == a->rd2) {
return false;
}

TCGv data1 = get_gpr(ctx, a->rd1, EXT_NONE);
TCGv data2 = get_gpr(ctx, a->rd2, EXT_NONE);
TCGv addr1 = tcg_temp_new();
Expand Down
11 changes: 4 additions & 7 deletions target/riscv/machine.c
Expand Up @@ -27,9 +27,8 @@
static bool pmp_needed(void *opaque)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;

return riscv_feature(env, RISCV_FEATURE_PMP);
return cpu->cfg.pmp;
}

static int pmp_post_load(void *opaque, int version_id)
Expand Down Expand Up @@ -226,9 +225,8 @@ static const VMStateDescription vmstate_kvmtimer = {
static bool debug_needed(void *opaque)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;

return riscv_feature(env, RISCV_FEATURE_DEBUG);
return cpu->cfg.debug;
}

static int debug_post_load(void *opaque, int version_id)
Expand Down Expand Up @@ -333,8 +331,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = {

const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 6,
.minimum_version_id = 6,
.version_id = 7,
.minimum_version_id = 7,
.post_load = riscv_cpu_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
Expand All @@ -353,7 +351,6 @@ const VMStateDescription vmstate_riscv_cpu = {
VMSTATE_UINT32(env.misa_ext, RISCVCPU),
VMSTATE_UINT32(env.misa_mxl_max, RISCVCPU),
VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
VMSTATE_UINT32(env.features, RISCVCPU),
VMSTATE_UINTTL(env.priv, RISCVCPU),
VMSTATE_UINTTL(env.virt, RISCVCPU),
VMSTATE_UINT64(env.resetvec, RISCVCPU),
Expand Down
2 changes: 1 addition & 1 deletion target/riscv/monitor.c
Expand Up @@ -218,7 +218,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict)
return;
}

if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
if (!riscv_cpu_cfg(env)->mmu) {
monitor_printf(mon, "S-mode MMU unavailable\n");
return;
}
Expand Down
2 changes: 1 addition & 1 deletion target/riscv/op_helper.c
Expand Up @@ -195,7 +195,7 @@ target_ulong helper_mret(CPURISCVState *env)
uint64_t mstatus = env->mstatus;
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);

if (riscv_feature(env, RISCV_FEATURE_PMP) &&
if (riscv_cpu_cfg(env)->pmp &&
!pmp_get_num_rules(env) && (prev_priv != PRV_M)) {
riscv_raise_exception(env, RISCV_EXCP_INST_ACCESS_FAULT, GETPC());
}
Expand Down
8 changes: 4 additions & 4 deletions target/riscv/pmp.c
Expand Up @@ -88,7 +88,7 @@ static void pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val)
if (pmp_index < MAX_RISCV_PMPS) {
bool locked = true;

if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
if (riscv_cpu_cfg(env)->epmp) {
/* mseccfg.RLB is set */
if (MSECCFG_RLB_ISSET(env)) {
locked = false;
Expand Down Expand Up @@ -239,7 +239,7 @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
{
bool ret;

if (riscv_feature(env, RISCV_FEATURE_EPMP)) {
if (riscv_cpu_cfg(env)->epmp) {
if (MSECCFG_MMWP_ISSET(env)) {
/*
* The Machine Mode Whitelist Policy (mseccfg.MMWP) is set
Expand All @@ -265,7 +265,7 @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, target_ulong addr,
}
}

if ((!riscv_feature(env, RISCV_FEATURE_PMP)) || (mode == PRV_M)) {
if (!riscv_cpu_cfg(env)->pmp || (mode == PRV_M)) {
/*
* Privileged spec v1.10 states if HW doesn't implement any PMP entry
* or no PMP entry matches an M-Mode access, the access succeeds.
Expand Down Expand Up @@ -315,7 +315,7 @@ int pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
}

if (size == 0) {
if (riscv_feature(env, RISCV_FEATURE_MMU)) {
if (riscv_cpu_cfg(env)->mmu) {
/*
* If size is unknown (0), assume that all bytes
* from addr to the end of the page will be accessed.
Expand Down
3 changes: 2 additions & 1 deletion target/riscv/translate.c
Expand Up @@ -1103,6 +1103,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
#include "insn_trans/trans_rvh.c.inc"
#include "insn_trans/trans_rvv.c.inc"
#include "insn_trans/trans_rvb.c.inc"
#include "insn_trans/trans_rvzicond.c.inc"
#include "insn_trans/trans_rvzawrs.c.inc"
#include "insn_trans/trans_rvzfh.c.inc"
#include "insn_trans/trans_rvk.c.inc"
Expand Down Expand Up @@ -1261,7 +1262,7 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
int len = insn_len(next_insn);

if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
if (!is_same_page(&ctx->base, ctx->base.pc_next + len - 1)) {
ctx->base.is_jmp = DISAS_TOO_MANY;
}
}
Expand Down
104 changes: 39 additions & 65 deletions target/riscv/vector_helper.c
Expand Up @@ -267,6 +267,28 @@ GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)

static void vext_set_tail_elems_1s(CPURISCVState *env, target_ulong vl,
void *vd, uint32_t desc, uint32_t nf,
uint32_t esz, uint32_t max_elems)
{
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
uint32_t vta = vext_vta(desc);
uint32_t registers_used;
int k;

for (k = 0; k < nf; ++k) {
vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
(k * max_elems + max_elems) * esz);
}

if (nf * max_elems % total_elems != 0) {
registers_used = ((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
registers_used * vlenb);
}
}

/*
*** stride: access vector element from strided memory
*/
Expand All @@ -281,8 +303,6 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
uint32_t nf = vext_nf(desc);
uint32_t max_elems = vext_max_elems(desc, log2_esz);
uint32_t esz = 1 << log2_esz;
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
uint32_t vta = vext_vta(desc);
uint32_t vma = vext_vma(desc);

for (i = env->vstart; i < env->vl; i++, env->vstart++) {
Expand All @@ -301,18 +321,8 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
}
}
env->vstart = 0;
/* set tail elements to 1s */
for (k = 0; k < nf; ++k) {
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
(k * max_elems + max_elems) * esz);
}
if (nf * max_elems % total_elems != 0) {
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
uint32_t registers_used =
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
registers_used * vlenb);
}

vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
}

#define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN) \
Expand Down Expand Up @@ -359,8 +369,6 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
uint32_t nf = vext_nf(desc);
uint32_t max_elems = vext_max_elems(desc, log2_esz);
uint32_t esz = 1 << log2_esz;
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
uint32_t vta = vext_vta(desc);

/* load bytes from guest memory */
for (i = env->vstart; i < evl; i++, env->vstart++) {
Expand All @@ -372,18 +380,8 @@ vext_ldst_us(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
}
}
env->vstart = 0;
/* set tail elements to 1s */
for (k = 0; k < nf; ++k) {
vext_set_elems_1s(vd, vta, (k * max_elems + evl) * esz,
(k * max_elems + max_elems) * esz);
}
if (nf * max_elems % total_elems != 0) {
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
uint32_t registers_used =
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
registers_used * vlenb);
}

vext_set_tail_elems_1s(env, evl, vd, desc, nf, esz, max_elems);
}

/*
Expand Down Expand Up @@ -484,8 +482,6 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
uint32_t vm = vext_vm(desc);
uint32_t max_elems = vext_max_elems(desc, log2_esz);
uint32_t esz = 1 << log2_esz;
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
uint32_t vta = vext_vta(desc);
uint32_t vma = vext_vma(desc);

/* load bytes from guest memory */
Expand All @@ -505,18 +501,8 @@ vext_ldst_index(void *vd, void *v0, target_ulong base,
}
}
env->vstart = 0;
/* set tail elements to 1s */
for (k = 0; k < nf; ++k) {
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
(k * max_elems + max_elems) * esz);
}
if (nf * max_elems % total_elems != 0) {
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
uint32_t registers_used =
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
registers_used * vlenb);
}

vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
}

#define GEN_VEXT_LD_INDEX(NAME, ETYPE, INDEX_FN, LOAD_FN) \
Expand Down Expand Up @@ -585,8 +571,6 @@ vext_ldff(void *vd, void *v0, target_ulong base,
uint32_t vm = vext_vm(desc);
uint32_t max_elems = vext_max_elems(desc, log2_esz);
uint32_t esz = 1 << log2_esz;
uint32_t total_elems = vext_get_total_elems(env, desc, esz);
uint32_t vta = vext_vta(desc);
uint32_t vma = vext_vma(desc);
target_ulong addr, offset, remain;

Expand Down Expand Up @@ -647,18 +631,8 @@ vext_ldff(void *vd, void *v0, target_ulong base,
}
}
env->vstart = 0;
/* set tail elements to 1s */
for (k = 0; k < nf; ++k) {
vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
(k * max_elems + max_elems) * esz);
}
if (nf * max_elems % total_elems != 0) {
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
uint32_t registers_used =
((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
registers_used * vlenb);
}

vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
}

#define GEN_VEXT_LDFF(NAME, ETYPE, LOAD_FN) \
Expand Down Expand Up @@ -697,7 +671,7 @@ vext_ldst_whole(void *vd, target_ulong base, CPURISCVState *env, uint32_t desc,
{
uint32_t i, k, off, pos;
uint32_t nf = vext_nf(desc);
uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
uint32_t vlenb = riscv_cpu_cfg(env)->vlen >> 3;
uint32_t max_elems = vlenb >> log2_esz;

k = env->vstart / max_elems;
Expand Down Expand Up @@ -1167,7 +1141,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
{ \
uint32_t vl = env->vl; \
uint32_t vm = vext_vm(desc); \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t i; \
\
Expand Down Expand Up @@ -1203,7 +1177,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \
{ \
uint32_t vl = env->vl; \
uint32_t vm = vext_vm(desc); \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t i; \
\
Expand Down Expand Up @@ -1402,7 +1376,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
{ \
uint32_t vm = vext_vm(desc); \
uint32_t vl = env->vl; \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t vma = vext_vma(desc); \
uint32_t i; \
Expand Down Expand Up @@ -1465,7 +1439,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \
{ \
uint32_t vm = vext_vm(desc); \
uint32_t vl = env->vl; \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t vma = vext_vma(desc); \
uint32_t i; \
Expand Down Expand Up @@ -4178,7 +4152,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \
{ \
uint32_t vm = vext_vm(desc); \
uint32_t vl = env->vl; \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t vma = vext_vma(desc); \
uint32_t i; \
Expand Down Expand Up @@ -4216,7 +4190,7 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \
{ \
uint32_t vm = vext_vm(desc); \
uint32_t vl = env->vl; \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t vma = vext_vma(desc); \
uint32_t i; \
Expand Down Expand Up @@ -4747,7 +4721,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \
uint32_t desc) \
{ \
uint32_t vl = env->vl; \
uint32_t total_elems = env_archcpu(env)->cfg.vlen; \
uint32_t total_elems = riscv_cpu_cfg(env)->vlen; \
uint32_t vta_all_1s = vext_vta_all_1s(desc); \
uint32_t i; \
int a, b; \
Expand Down Expand Up @@ -4834,7 +4808,7 @@ static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env,
{
uint32_t vm = vext_vm(desc);
uint32_t vl = env->vl;
uint32_t total_elems = env_archcpu(env)->cfg.vlen;
uint32_t total_elems = riscv_cpu_cfg(env)->vlen;
uint32_t vta_all_1s = vext_vta_all_1s(desc);
uint32_t vma = vext_vma(desc);
int i;
Expand Down