aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/cpu.h
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/cpu.h')
-rw-r--r--target/riscv/cpu.h31
1 files changed, 31 insertions, 0 deletions
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 03552f4aaa..7657e22a56 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -146,6 +146,7 @@ struct CPURISCVState {
uint32_t misa_mxl_max; /* max mxl for this cpu */
uint32_t misa_ext; /* current extensions */
uint32_t misa_ext_mask; /* max ext for this cpu */
+ uint32_t xl; /* current xlen */
/* 128-bit helpers upper part return value */
target_ulong retxh;
@@ -456,6 +457,36 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
}
#endif
+#if defined(TARGET_RISCV32)
+#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
+#else
+static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
+{
+ RISCVMXL xl = env->misa_mxl;
+#if !defined(CONFIG_USER_ONLY)
+ /*
+ * When emulating a 32-bit-only cpu, use RV32.
+ * When emulating a 64-bit cpu, and MXL has been reduced to RV32,
+ * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
+ * back to RV64 for lower privs.
+ */
+ if (xl != MXL_RV32) {
+ switch (env->priv) {
+ case PRV_M:
+ break;
+ case PRV_U:
+ xl = get_field(env->mstatus, MSTATUS64_UXL);
+ break;
+ default: /* PRV_S | PRV_H */
+ xl = get_field(env->mstatus, MSTATUS64_SXL);
+ break;
+ }
+ }
+#endif
+ return xl;
+}
+#endif
+
/*
* Encode LMUL to lmul as follows:
* LMUL vlmul lmul