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.h63
1 files changed, 54 insertions, 9 deletions
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 302e085..0ad51c6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -21,6 +21,7 @@
#define RISCV_CPU_H
#include "hw/core/cpu.h"
+#include "hw/registerfields.h"
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
@@ -93,6 +94,12 @@ typedef struct CPURISCVState CPURISCVState;
#define RV_VLEN_MAX 512
+FIELD(VTYPE, VLMUL, 0, 2)
+FIELD(VTYPE, VSEW, 2, 3)
+FIELD(VTYPE, VEDIV, 5, 2)
+FIELD(VTYPE, RESERVED, 7, sizeof(target_ulong) * 8 - 9)
+FIELD(VTYPE, VILL, sizeof(target_ulong) * 8 - 2, 1)
+
struct CPURISCVState {
target_ulong gpr[32];
uint64_t fpr[32]; /* assume both F and D extensions */
@@ -352,19 +359,62 @@ void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
#define TB_FLAGS_MMU_MASK 3
#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
+typedef CPURISCVState CPUArchState;
+typedef RISCVCPU ArchCPU;
+#include "exec/cpu-all.h"
+
+FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1)
+FIELD(TB_FLAGS, LMUL, 3, 2)
+FIELD(TB_FLAGS, SEW, 5, 3)
+FIELD(TB_FLAGS, VILL, 8, 1)
+
+/*
+ * A simplification for VLMAX
+ * = (1 << LMUL) * VLEN / (8 * (1 << SEW))
+ * = (VLEN << LMUL) / (8 << SEW)
+ * = (VLEN << LMUL) >> (SEW + 3)
+ * = VLEN >> (SEW + 3 - LMUL)
+ */
+static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
+{
+ uint8_t sew, lmul;
+
+ sew = FIELD_EX64(vtype, VTYPE, VSEW);
+ lmul = FIELD_EX64(vtype, VTYPE, VLMUL);
+ return cpu->cfg.vlen >> (sew + 3 - lmul);
+}
+
static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
- target_ulong *cs_base, uint32_t *flags)
+ target_ulong *cs_base, uint32_t *pflags)
{
+ uint32_t flags = 0;
+
*pc = env->pc;
*cs_base = 0;
+
+ if (riscv_has_ext(env, RVV)) {
+ uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
+ bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
+ flags = FIELD_DP32(flags, TB_FLAGS, VILL,
+ FIELD_EX64(env->vtype, VTYPE, VILL));
+ flags = FIELD_DP32(flags, TB_FLAGS, SEW,
+ FIELD_EX64(env->vtype, VTYPE, VSEW));
+ flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
+ FIELD_EX64(env->vtype, VTYPE, VLMUL));
+ flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
+ } else {
+ flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
+ }
+
#ifdef CONFIG_USER_ONLY
- *flags = TB_FLAGS_MSTATUS_FS;
+ flags |= TB_FLAGS_MSTATUS_FS;
#else
- *flags = cpu_mmu_index(env, 0);
+ flags |= cpu_mmu_index(env, 0);
if (riscv_cpu_fp_enabled(env)) {
- *flags |= env->mstatus & MSTATUS_FS;
+ flags |= env->mstatus & MSTATUS_FS;
}
#endif
+ *pflags = flags;
}
int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
@@ -405,9 +455,4 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops);
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
-typedef CPURISCVState CPUArchState;
-typedef RISCVCPU ArchCPU;
-
-#include "exec/cpu-all.h"
-
#endif /* RISCV_CPU_H */