|
@@ -31,11 +31,17 @@
|
|
#include "hw/core/accel-cpu.h"
|
|
#include "hw/core/accel-cpu.h"
|
|
#include "hw/core/tcg-cpu-ops.h"
|
|
#include "hw/core/tcg-cpu-ops.h"
|
|
#include "tcg/tcg.h"
|
|
#include "tcg/tcg.h"
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+#include "hw/boards.h"
|
|
|
|
+#endif
|
|
|
|
|
|
/* Hash that stores user set extensions */
|
|
/* Hash that stores user set extensions */
|
|
static GHashTable *multi_ext_user_opts;
|
|
static GHashTable *multi_ext_user_opts;
|
|
static GHashTable *misa_ext_user_opts;
|
|
static GHashTable *misa_ext_user_opts;
|
|
|
|
|
|
|
|
+static GHashTable *multi_ext_implied_rules;
|
|
|
|
+static GHashTable *misa_ext_implied_rules;
|
|
|
|
+
|
|
static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
|
|
static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
|
|
{
|
|
{
|
|
return g_hash_table_contains(multi_ext_user_opts,
|
|
return g_hash_table_contains(multi_ext_user_opts,
|
|
@@ -76,16 +82,11 @@ static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit,
|
|
|
|
|
|
static const char *cpu_priv_ver_to_str(int priv_ver)
|
|
static const char *cpu_priv_ver_to_str(int priv_ver)
|
|
{
|
|
{
|
|
- switch (priv_ver) {
|
|
|
|
- case PRIV_VERSION_1_10_0:
|
|
|
|
- return "v1.10.0";
|
|
|
|
- case PRIV_VERSION_1_11_0:
|
|
|
|
- return "v1.11.0";
|
|
|
|
- case PRIV_VERSION_1_12_0:
|
|
|
|
- return "v1.12.0";
|
|
|
|
- }
|
|
|
|
|
|
+ const char *priv_spec_str = priv_spec_to_str(priv_ver);
|
|
|
|
|
|
- g_assert_not_reached();
|
|
|
|
|
|
+ g_assert(priv_spec_str);
|
|
|
|
+
|
|
|
|
+ return priv_spec_str;
|
|
}
|
|
}
|
|
|
|
|
|
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
|
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
|
@@ -323,6 +324,10 @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu)
|
|
cpu->cfg.has_priv_1_12 = true;
|
|
cpu->cfg.has_priv_1_12 = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (cpu->env.priv_ver >= PRIV_VERSION_1_13_0) {
|
|
|
|
+ cpu->cfg.has_priv_1_13 = true;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* zic64b is 1.12 or later */
|
|
/* zic64b is 1.12 or later */
|
|
cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 &&
|
|
cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 &&
|
|
cpu->cfg.cbop_blocksize == 64 &&
|
|
cpu->cfg.cbop_blocksize == 64 &&
|
|
@@ -466,10 +471,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (cpu->cfg.ext_zfh) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
|
|
if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) {
|
|
error_setg(errp, "Zfh/Zfhmin extensions require F extension");
|
|
error_setg(errp, "Zfh/Zfhmin extensions require F extension");
|
|
return;
|
|
return;
|
|
@@ -491,9 +492,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
error_propagate(errp, local_err);
|
|
error_propagate(errp, local_err);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
-
|
|
|
|
- /* The V vector extension depends on the Zve64d extension */
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* The Zve64d extension depends on the Zve64f extension */
|
|
/* The Zve64d extension depends on the Zve64f extension */
|
|
@@ -502,18 +500,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
error_setg(errp, "Zve64d/V extensions require D extension");
|
|
error_setg(errp, "Zve64d/V extensions require D extension");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* The Zve64f extension depends on the Zve64x and Zve32f extensions */
|
|
|
|
- if (cpu->cfg.ext_zve64f) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64x), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* The Zve64x extension depends on the Zve32x extension */
|
|
|
|
- if (cpu->cfg.ext_zve64x) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/* The Zve32f extension depends on the Zve32x extension */
|
|
/* The Zve32f extension depends on the Zve32x extension */
|
|
@@ -522,11 +508,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
error_setg(errp, "Zve32f/Zve64f extensions require F extension");
|
|
error_setg(errp, "Zve32f/Zve64f extensions require F extension");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32x), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvfh) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
|
|
if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
|
|
@@ -549,11 +530,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Set the ISA extensions, checks should have happened above */
|
|
|
|
- if (cpu->cfg.ext_zhinx) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
|
|
if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) {
|
|
error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
|
|
error_setg(errp, "Zdinx/Zhinx/Zhinxmin extensions require Zfinx");
|
|
return;
|
|
return;
|
|
@@ -571,27 +547,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- if (cpu->cfg.ext_zce) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
|
|
|
|
- if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* zca, zcd and zcf has a PRIV 1.12.0 restriction */
|
|
|
|
- if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
|
|
|
|
- if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
|
|
|
|
- }
|
|
|
|
- if (riscv_has_ext(env, RVD)) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
|
|
if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
|
|
error_setg(errp, "Zcf extension is only relevant to RV32");
|
|
error_setg(errp, "Zcf extension is only relevant to RV32");
|
|
return;
|
|
return;
|
|
@@ -625,48 +580,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /*
|
|
|
|
- * Shorthand vector crypto extensions
|
|
|
|
- */
|
|
|
|
- if (cpu->cfg.ext_zvknc) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkn), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvkng) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkn), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkg), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvkn) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkned), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvknhb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkt), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvksc) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvks), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvksg) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvks), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkg), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvks) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvksed), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvksh), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkt), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zvkt) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
|
|
if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg ||
|
|
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
|
|
cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed ||
|
|
cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32x) {
|
|
cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32x) {
|
|
@@ -682,29 +595,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (cpu->cfg.ext_zk) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zkn) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (cpu->cfg.ext_zks) {
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true);
|
|
|
|
- cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (cpu->cfg.ext_zicntr && !cpu->cfg.ext_zicsr) {
|
|
if (cpu->cfg.ext_zicntr && !cpu->cfg.ext_zicsr) {
|
|
if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicntr))) {
|
|
if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicntr))) {
|
|
error_setg(errp, "zicntr requires zicsr");
|
|
error_setg(errp, "zicntr requires zicsr");
|
|
@@ -833,11 +723,151 @@ static void riscv_cpu_validate_profiles(RISCVCPU *cpu)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void riscv_cpu_init_implied_exts_rules(void)
|
|
|
|
+{
|
|
|
|
+ RISCVCPUImpliedExtsRule *rule;
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ MachineState *ms = MACHINE(qdev_get_machine());
|
|
|
|
+#endif
|
|
|
|
+ static bool initialized;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Implied rules only need to be initialized once. */
|
|
|
|
+ if (initialized) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; (rule = riscv_misa_ext_implied_rules[i]); i++) {
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ rule->enabled = bitmap_new(ms->smp.cpus);
|
|
|
|
+#endif
|
|
|
|
+ g_hash_table_insert(misa_ext_implied_rules,
|
|
|
|
+ GUINT_TO_POINTER(rule->ext), (gpointer)rule);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (i = 0; (rule = riscv_multi_ext_implied_rules[i]); i++) {
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ rule->enabled = bitmap_new(ms->smp.cpus);
|
|
|
|
+#endif
|
|
|
|
+ g_hash_table_insert(multi_ext_implied_rules,
|
|
|
|
+ GUINT_TO_POINTER(rule->ext), (gpointer)rule);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ initialized = true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cpu_enable_implied_rule(RISCVCPU *cpu,
|
|
|
|
+ RISCVCPUImpliedExtsRule *rule)
|
|
|
|
+{
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+ RISCVCPUImpliedExtsRule *ir;
|
|
|
|
+ bool enabled = false;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ enabled = test_bit(cpu->env.mhartid, rule->enabled);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+ if (!enabled) {
|
|
|
|
+ /* Enable the implied MISAs. */
|
|
|
|
+ if (rule->implied_misa_exts) {
|
|
|
|
+ riscv_cpu_set_misa_ext(env,
|
|
|
|
+ env->misa_ext | rule->implied_misa_exts);
|
|
|
|
+
|
|
|
|
+ for (i = 0; misa_bits[i] != 0; i++) {
|
|
|
|
+ if (rule->implied_misa_exts & misa_bits[i]) {
|
|
|
|
+ ir = g_hash_table_lookup(misa_ext_implied_rules,
|
|
|
|
+ GUINT_TO_POINTER(misa_bits[i]));
|
|
|
|
+
|
|
|
|
+ if (ir) {
|
|
|
|
+ cpu_enable_implied_rule(cpu, ir);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Enable the implied extensions. */
|
|
|
|
+ for (i = 0;
|
|
|
|
+ rule->implied_multi_exts[i] != RISCV_IMPLIED_EXTS_RULE_END; i++) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, rule->implied_multi_exts[i], true);
|
|
|
|
+
|
|
|
|
+ ir = g_hash_table_lookup(multi_ext_implied_rules,
|
|
|
|
+ GUINT_TO_POINTER(
|
|
|
|
+ rule->implied_multi_exts[i]));
|
|
|
|
+
|
|
|
|
+ if (ir) {
|
|
|
|
+ cpu_enable_implied_rule(cpu, ir);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ bitmap_set(rule->enabled, cpu->env.mhartid, 1);
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* Zc extension has special implied rules that need to be handled separately. */
|
|
|
|
+static void cpu_enable_zc_implied_rules(RISCVCPU *cpu)
|
|
|
|
+{
|
|
|
|
+ RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+
|
|
|
|
+ if (cpu->cfg.ext_zce) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true);
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true);
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true);
|
|
|
|
+
|
|
|
|
+ if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Zca, Zcd and Zcf has a PRIV 1.12.0 restriction */
|
|
|
|
+ if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true);
|
|
|
|
+
|
|
|
|
+ if (riscv_has_ext(env, RVF) && mcc->misa_mxl_max == MXL_RV32) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (riscv_has_ext(env, RVD)) {
|
|
|
|
+ cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void riscv_cpu_enable_implied_rules(RISCVCPU *cpu)
|
|
|
|
+{
|
|
|
|
+ RISCVCPUImpliedExtsRule *rule;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Enable the implied extensions for Zc. */
|
|
|
|
+ cpu_enable_zc_implied_rules(cpu);
|
|
|
|
+
|
|
|
|
+ /* Enable the implied MISAs. */
|
|
|
|
+ for (i = 0; (rule = riscv_misa_ext_implied_rules[i]); i++) {
|
|
|
|
+ if (riscv_has_ext(&cpu->env, rule->ext)) {
|
|
|
|
+ cpu_enable_implied_rule(cpu, rule);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Enable the implied extensions. */
|
|
|
|
+ for (i = 0; (rule = riscv_multi_ext_implied_rules[i]); i++) {
|
|
|
|
+ if (isa_ext_is_enabled(cpu, rule->ext)) {
|
|
|
|
+ cpu_enable_implied_rule(cpu, rule);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
|
|
void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
|
|
{
|
|
{
|
|
CPURISCVState *env = &cpu->env;
|
|
CPURISCVState *env = &cpu->env;
|
|
Error *local_err = NULL;
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
+ riscv_cpu_init_implied_exts_rules();
|
|
|
|
+ riscv_cpu_enable_implied_rules(cpu);
|
|
|
|
+
|
|
riscv_cpu_validate_misa_priv(env, &local_err);
|
|
riscv_cpu_validate_misa_priv(env, &local_err);
|
|
if (local_err != NULL) {
|
|
if (local_err != NULL) {
|
|
error_propagate(errp, local_err);
|
|
error_propagate(errp, local_err);
|
|
@@ -1343,6 +1373,15 @@ static void riscv_tcg_cpu_instance_init(CPUState *cs)
|
|
|
|
|
|
misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
|
|
misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
|
|
multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
|
|
multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
|
|
|
|
+
|
|
|
|
+ if (!misa_ext_implied_rules) {
|
|
|
|
+ misa_ext_implied_rules = g_hash_table_new(NULL, g_direct_equal);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!multi_ext_implied_rules) {
|
|
|
|
+ multi_ext_implied_rules = g_hash_table_new(NULL, g_direct_equal);
|
|
|
|
+ }
|
|
|
|
+
|
|
riscv_cpu_add_user_properties(obj);
|
|
riscv_cpu_add_user_properties(obj);
|
|
|
|
|
|
if (riscv_cpu_has_max_extensions(obj)) {
|
|
if (riscv_cpu_has_max_extensions(obj)) {
|