mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-03 17:05:47 +00:00
target/riscv: Merge m/vsstatus and m/vsstatush into one uint64_t unit
mstatus/mstatush and vsstatus/vsstatush are two halved for RISCV32. This patch expands mstatus and vsstatus to uint64_t instead of target_ulong so that it can be saved as one unit and reduce some ifdefs in the code. Backports 284d697c74ef3f4210cbccc5cd6b4894740e4ab3
This commit is contained in:
parent
281d851303
commit
9d47840784
|
@ -148,7 +148,11 @@ struct CPURISCVState {
|
|||
target_ulong resetvec;
|
||||
|
||||
target_ulong mhartid;
|
||||
target_ulong mstatus;
|
||||
/*
|
||||
* For RV32 this is 32-bit mstatus and 32-bit mstatush.
|
||||
* For RV64 this is a 64-bit mstatus.
|
||||
*/
|
||||
uint64_t mstatus;
|
||||
|
||||
/*
|
||||
* CAUTION! Unlike the rest of this struct, mip is accessed asynchonously
|
||||
|
@ -161,10 +165,6 @@ struct CPURISCVState {
|
|||
*/
|
||||
target_ulong mip;
|
||||
|
||||
#ifdef TARGET_RISCV32
|
||||
target_ulong mstatush;
|
||||
#endif
|
||||
|
||||
uint32_t miclaim;
|
||||
|
||||
target_ulong mie;
|
||||
|
@ -196,16 +196,17 @@ struct CPURISCVState {
|
|||
uint64_t htimedelta;
|
||||
|
||||
/* Virtual CSRs */
|
||||
target_ulong vsstatus;
|
||||
/*
|
||||
* For RV32 this is 32-bit vsstatus and 32-bit vsstatush.
|
||||
* For RV64 this is a 64-bit vsstatus.
|
||||
*/
|
||||
uint64_t vsstatus;
|
||||
target_ulong vstvec;
|
||||
target_ulong vsscratch;
|
||||
target_ulong vsepc;
|
||||
target_ulong vscause;
|
||||
target_ulong vstval;
|
||||
target_ulong vsatp;
|
||||
#ifdef TARGET_RISCV32
|
||||
target_ulong vsstatush;
|
||||
#endif
|
||||
|
||||
target_ulong mtval2;
|
||||
target_ulong mtinst;
|
||||
|
@ -217,10 +218,7 @@ struct CPURISCVState {
|
|||
target_ulong scause_hs;
|
||||
target_ulong stval_hs;
|
||||
target_ulong satp_hs;
|
||||
target_ulong mstatus_hs;
|
||||
#ifdef TARGET_RISCV32
|
||||
target_ulong mstatush_hs;
|
||||
#endif
|
||||
uint64_t mstatus_hs;
|
||||
|
||||
target_ulong scounteren;
|
||||
target_ulong mcounteren;
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
#define TARGET_RISCV_CPU_BITS_H
|
||||
|
||||
#define get_field(reg, mask) (((reg) & \
|
||||
(target_ulong)(mask)) / ((mask) & ~((mask) << 1)))
|
||||
#define set_field(reg, mask, val) (((reg) & ~(target_ulong)(mask)) | \
|
||||
(((target_ulong)(val) * ((mask) & ~((mask) << 1))) & \
|
||||
(target_ulong)(mask)))
|
||||
(uint64_t)(mask)) / ((mask) & ~((mask) << 1)))
|
||||
#define set_field(reg, mask, val) (((reg) & ~(uint64_t)(mask)) | \
|
||||
(((uint64_t)(val) * ((mask) & ~((mask) << 1))) & \
|
||||
(uint64_t)(mask)))
|
||||
|
||||
/* Floating point round mode */
|
||||
#define FSR_RD_SHIFT 5
|
||||
|
@ -381,19 +381,8 @@
|
|||
#define MSTATUS_TVM 0x00100000 /* since: priv-1.10 */
|
||||
#define MSTATUS_TW 0x20000000 /* since: priv-1.10 */
|
||||
#define MSTATUS_TSR 0x40000000 /* since: priv-1.10 */
|
||||
#if defined(TARGET_RISCV64)
|
||||
#define MSTATUS_GVA 0x4000000000ULL
|
||||
#define MSTATUS_MPV 0x8000000000ULL
|
||||
#elif defined(TARGET_RISCV32)
|
||||
#define MSTATUS_GVA 0x00000040
|
||||
#define MSTATUS_MPV 0x00000080
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_RISCV32
|
||||
# define MSTATUS_MPV_ISSET(env) get_field(env->mstatush, MSTATUS_MPV)
|
||||
#else
|
||||
# define MSTATUS_MPV_ISSET(env) get_field(env->mstatus, MSTATUS_MPV)
|
||||
#endif
|
||||
|
||||
#define MSTATUS64_UXL 0x0000000300000000ULL
|
||||
#define MSTATUS64_SXL 0x0000000C00000000ULL
|
||||
|
|
|
@ -110,27 +110,19 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
|
|||
|
||||
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
|
||||
{
|
||||
target_ulong mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
|
||||
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE;
|
||||
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
|
||||
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
|
||||
MSTATUS64_UXL;
|
||||
bool current_virt = riscv_cpu_virt_enabled(env);
|
||||
|
||||
g_assert(riscv_has_ext(env, RVH));
|
||||
|
||||
#if defined(TARGET_RISCV64)
|
||||
mstatus_mask |= MSTATUS64_UXL;
|
||||
#endif
|
||||
|
||||
if (current_virt) {
|
||||
/* Current V=1 and we are about to change to V=0 */
|
||||
env->vsstatus = env->mstatus & mstatus_mask;
|
||||
env->mstatus &= ~mstatus_mask;
|
||||
env->mstatus |= env->mstatus_hs;
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
env->vsstatush = env->mstatush;
|
||||
env->mstatush |= env->mstatush_hs;
|
||||
#endif
|
||||
|
||||
env->vstvec = env->stvec;
|
||||
env->stvec = env->stvec_hs;
|
||||
|
||||
|
@ -154,11 +146,6 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
|
|||
env->mstatus &= ~mstatus_mask;
|
||||
env->mstatus |= env->vsstatus;
|
||||
|
||||
#if defined(TARGET_RISCV32)
|
||||
env->mstatush_hs = env->mstatush;
|
||||
env->mstatush |= env->vsstatush;
|
||||
#endif
|
||||
|
||||
env->stvec_hs = env->stvec;
|
||||
env->stvec = env->vstvec;
|
||||
|
||||
|
@ -718,7 +705,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
|
||||
access_type != MMU_INST_FETCH &&
|
||||
get_field(env->mstatus, MSTATUS_MPRV) &&
|
||||
MSTATUS_MPV_ISSET(env)) {
|
||||
get_field(env->mstatus, MSTATUS_MPV)) {
|
||||
riscv_cpu_set_two_stage_lookup(env, true);
|
||||
}
|
||||
|
||||
|
@ -790,7 +777,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||
if (riscv_has_ext(env, RVH) && env->priv == PRV_M &&
|
||||
access_type != MMU_INST_FETCH &&
|
||||
get_field(env->mstatus, MSTATUS_MPRV) &&
|
||||
MSTATUS_MPV_ISSET(env)) {
|
||||
get_field(env->mstatus, MSTATUS_MPV)) {
|
||||
riscv_cpu_set_two_stage_lookup(env, false);
|
||||
}
|
||||
|
||||
|
@ -850,7 +837,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
RISCVCPU *cpu = RISCV_CPU(cs->uc, cs);
|
||||
CPURISCVState *env = &cpu->env;
|
||||
bool force_hs_execp = riscv_cpu_force_hs_excep_enabled(env);
|
||||
target_ulong s;
|
||||
uint64_t s;
|
||||
|
||||
/* cs->exception is 32-bits wide unlike mcause which is XLEN-bits wide
|
||||
* so we mask off the MSB and separate into trap type and cause.
|
||||
|
@ -982,19 +969,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||
if (riscv_cpu_virt_enabled(env)) {
|
||||
riscv_cpu_swap_hypervisor_regs(env);
|
||||
}
|
||||
#ifdef TARGET_RISCV32
|
||||
env->mstatush = set_field(env->mstatush, MSTATUS_MPV,
|
||||
riscv_cpu_virt_enabled(env));
|
||||
if (riscv_cpu_virt_enabled(env) && tval) {
|
||||
env->mstatush = set_field(env->mstatush, MSTATUS_GVA, 1);
|
||||
}
|
||||
#else
|
||||
|
||||
env->mstatus = set_field(env->mstatus, MSTATUS_MPV,
|
||||
riscv_cpu_virt_enabled(env));
|
||||
riscv_cpu_virt_enabled(env));
|
||||
if (riscv_cpu_virt_enabled(env) && tval) {
|
||||
env->mstatus = set_field(env->mstatus, MSTATUS_GVA, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
mtval2 = env->guest_phys_fault_addr;
|
||||
|
||||
|
|
|
@ -391,8 +391,8 @@ static int validate_vm(CPURISCVState *env, target_ulong vm)
|
|||
|
||||
static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
target_ulong mstatus = env->mstatus;
|
||||
target_ulong mask = 0;
|
||||
uint64_t mstatus = env->mstatus;
|
||||
uint64_t mask = 0;
|
||||
|
||||
/* flush tlb on mstatus fields that affect VM */
|
||||
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
|
||||
|
@ -425,19 +425,20 @@ static int write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
|
|||
#ifdef TARGET_RISCV32
|
||||
static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
*val = env->mstatush;
|
||||
*val = env->mstatus >> 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
if ((val ^ env->mstatush) & (MSTATUS_MPV)) {
|
||||
uint64_t valh = (uint64_t)val << 32;
|
||||
uint64_t mask = MSTATUS_MPV | MSTATUS_GVA;
|
||||
|
||||
if ((valh ^ env->mstatus) & (MSTATUS_MPV)) {
|
||||
tlb_flush(env_cpu(env));
|
||||
}
|
||||
|
||||
val &= MSTATUS_MPV | MSTATUS_GVA;
|
||||
|
||||
env->mstatush = val;
|
||||
env->mstatus = (env->mstatus & ~mask) | (valh & mask);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1053,7 +1054,8 @@ static int read_vsstatus(CPURISCVState *env, int csrno, target_ulong *val)
|
|||
|
||||
static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
env->vsstatus = val;
|
||||
uint64_t mask = (target_ulong)-1;
|
||||
env->vsstatus = (env->vsstatus & ~mask) | (uint64_t)val;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,8 @@ target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
|
|||
|
||||
target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
||||
{
|
||||
target_ulong prev_priv, prev_virt, mstatus;
|
||||
uint64_t mstatus;
|
||||
target_ulong prev_priv, prev_virt;
|
||||
|
||||
if (!(env->priv >= PRV_S)) {
|
||||
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
|
||||
|
@ -147,18 +148,14 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb)
|
|||
riscv_raise_exception(env, RISCV_EXCP_INST_ADDR_MIS, GETPC());
|
||||
}
|
||||
|
||||
target_ulong mstatus = env->mstatus;
|
||||
uint64_t mstatus = env->mstatus;
|
||||
target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
|
||||
target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
|
||||
target_ulong prev_virt = get_field(env->mstatus, MSTATUS_MPV);
|
||||
mstatus = set_field(mstatus, MSTATUS_MIE,
|
||||
get_field(mstatus, MSTATUS_MPIE));
|
||||
mstatus = set_field(mstatus, MSTATUS_MPIE, 1);
|
||||
mstatus = set_field(mstatus, MSTATUS_MPP, PRV_U);
|
||||
#ifdef TARGET_RISCV32
|
||||
env->mstatush = set_field(env->mstatush, MSTATUS_MPV, 0);
|
||||
#else
|
||||
mstatus = set_field(mstatus, MSTATUS_MPV, 0);
|
||||
#endif
|
||||
env->mstatus = mstatus;
|
||||
riscv_cpu_set_mode(env, prev_priv);
|
||||
|
||||
|
|
Loading…
Reference in a new issue