Signed-off-by: LIU Zhiwei <zhiwei_...@c-sky.com> --- target/riscv/csr.c | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-)
diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9a4ed18ac5..dc9807c0ff 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -297,7 +297,7 @@ static RISCVException read_vxrm(CPURISCVState *env, int csrno, static RISCVException write_vxrm(CPURISCVState *env, int csrno, target_ulong val) { - env->vxrm = val; + env->vxrm = riscv_cpu_is_uxl32(env) ? val & UINT32_MAX : val; return RISCV_EXCP_NONE; } @@ -311,7 +311,7 @@ static RISCVException read_vxsat(CPURISCVState *env, int csrno, static RISCVException write_vxsat(CPURISCVState *env, int csrno, target_ulong val) { - env->vxsat = val; + env->vxsat = riscv_cpu_is_uxl32(env) ? val & UINT32_MAX : val; return RISCV_EXCP_NONE; } @@ -325,7 +325,7 @@ static RISCVException read_vstart(CPURISCVState *env, int csrno, static RISCVException write_vstart(CPURISCVState *env, int csrno, target_ulong val) { - env->vstart = val; + env->vstart = riscv_cpu_is_uxl32(env) ? val & UINT32_MAX : val; return RISCV_EXCP_NONE; } @@ -493,6 +493,36 @@ static int validate_vm(CPURISCVState *env, target_ulong vm) } } +static void uxl32_switch(CPURISCVState *env, target_ulong val) +{ + uint32_t old = get_field(env->mstatus, MSTATUS64_UXL); + uint32_t new = get_field(val, MSTATUS64_UXL); + + if (old == new) { + return; + } + + /* + * For the read-only bits of the previous-width CSR, the bits at the + * same positions in the temporary register are set to zeros. + */ + if (env->misa & RVV) { + env->vl = 0; + env->vtype = 0; + } + + /* + * If the new width W is narrower than the previous width, the + * least-significant W bits of the temporary register are retained and + * the more-significant bits are discarded. + */ + if ((old == 2) && (new == 1)) { + if (env->misa & RVV) { + env->vtype &= UINT32_MAX; + } + } +} + static RISCVException write_mstatus(CPURISCVState *env, int csrno, target_ulong val) { @@ -502,13 +532,13 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, /* flush tlb on mstatus fields that affect VM */ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | - MSTATUS_MPRV | MSTATUS_SUM)) { + MSTATUS_MPRV | MSTATUS_SUM | MSTATUS64_UXL)) { tlb_flush(env_cpu(env)); } mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_SPP | MSTATUS_FS | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | - MSTATUS_TW; + MSTATUS_TW | MSTATUS64_UXL; if (!riscv_cpu_is_32bit(env)) { /* @@ -518,6 +548,8 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mask |= MSTATUS_MPV | MSTATUS_GVA; } + uxl32_switch(env, val); + mstatus = (mstatus & ~mask) | (val & mask); dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | -- 2.17.1