aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/csr.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/csr.c')
-rw-r--r--target/riscv/csr.c54
1 files changed, 53 insertions, 1 deletions
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index e2bd374..e72fcf1 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -332,6 +332,58 @@ static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
return 0;
}
+static int write_misa(CPURISCVState *env, int csrno, target_ulong val)
+{
+ if (!riscv_feature(env, RISCV_FEATURE_MISA)) {
+ /* drop write to misa */
+ return 0;
+ }
+
+ /* 'I' or 'E' must be present */
+ if (!(val & (RVI | RVE))) {
+ /* It is not, drop write to misa */
+ return 0;
+ }
+
+ /* 'E' excludes all other extensions */
+ if (val & RVE) {
+ /* when we support 'E' we can do "val = RVE;" however
+ * for now we just drop writes if 'E' is present.
+ */
+ return 0;
+ }
+
+ /* Mask extensions that are not supported by this hart */
+ val &= env->misa_mask;
+
+ /* Mask extensions that are not supported by QEMU */
+ val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+
+ /* 'D' depends on 'F', so clear 'D' if 'F' is not present */
+ if ((val & RVD) && !(val & RVF)) {
+ val &= ~RVD;
+ }
+
+ /* Suppress 'C' if next instruction is not aligned
+ * TODO: this should check next_pc
+ */
+ if ((val & RVC) && (GETPC() & ~3) != 0) {
+ val &= ~RVC;
+ }
+
+ /* misa.MXL writes are not supported by QEMU */
+ val = (env->misa & MISA_MXL) | (val & ~MISA_MXL);
+
+ /* flush translation cache */
+ if (val != env->misa) {
+ tb_flush(CPU(riscv_env_get_cpu(env)));
+ }
+
+ env->misa = val;
+
+ return 0;
+}
+
static int read_medeleg(CPURISCVState *env, int csrno, target_ulong *val)
{
*val = env->medeleg;
@@ -810,7 +862,7 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
/* Machine Trap Setup */
[CSR_MSTATUS] = { any, read_mstatus, write_mstatus },
- [CSR_MISA] = { any, read_misa },
+ [CSR_MISA] = { any, read_misa, write_misa },
[CSR_MIDELEG] = { any, read_mideleg, write_mideleg },
[CSR_MEDELEG] = { any, read_medeleg, write_medeleg },
[CSR_MIE] = { any, read_mie, write_mie },