summaryrefslogtreecommitdiff
path: root/target-arm/cpu.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2012-06-20 11:57:06 +0000
committerPeter Maydell <peter.maydell@linaro.org>2012-06-20 12:01:02 +0000
commit4b6a83fb0c34a6fcc7bb1058284e3c3674e54421 (patch)
tree96993a63c6c6e60f7936467c1f57658a52c73466 /target-arm/cpu.c
parent200bf596b96820186883953de9bda26cac8e6bd7 (diff)
downloadqemu-4b6a83fb0c34a6fcc7bb1058284e3c3674e54421.tar.gz
target-arm: initial coprocessor register framework
Initial infrastructure for data-driven registration of coprocessor register implementations. We still fall back to the old-style switch statements pending complete conversion of all existing registers. Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm/cpu.c')
-rw-r--r--target-arm/cpu.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 934894bf93..6456a3dfa8 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -24,6 +24,37 @@
#include "hw/loader.h"
#endif
+static void cp_reg_reset(gpointer key, gpointer value, gpointer opaque)
+{
+ /* Reset a single ARMCPRegInfo register */
+ ARMCPRegInfo *ri = value;
+ ARMCPU *cpu = opaque;
+
+ if (ri->type & ARM_CP_SPECIAL) {
+ return;
+ }
+
+ if (ri->resetfn) {
+ ri->resetfn(&cpu->env, ri);
+ return;
+ }
+
+ /* A zero offset is never possible as it would be regs[0]
+ * so we use it to indicate that reset is being handled elsewhere.
+ * This is basically only used for fields in non-core coprocessors
+ * (like the pxa2xx ones).
+ */
+ if (!ri->fieldoffset) {
+ return;
+ }
+
+ if (ri->type & ARM_CP_64BIT) {
+ CPREG_FIELD64(&cpu->env, ri) = ri->resetvalue;
+ } else {
+ CPREG_FIELD32(&cpu->env, ri) = ri->resetvalue;
+ }
+}
+
/* CPUClass::reset() */
static void arm_cpu_reset(CPUState *s)
{
@@ -39,6 +70,7 @@ static void arm_cpu_reset(CPUState *s)
acc->parent_reset(s);
memset(env, 0, offsetof(CPUARMState, breakpoints));
+ g_hash_table_foreach(cpu->cp_regs, cp_reg_reset, cpu);
env->cp15.c15_config_base_address = cpu->reset_cbar;
env->cp15.c0_cpuid = cpu->midr;
env->vfp.xregs[ARM_VFP_FPSID] = cpu->reset_fpsid;
@@ -130,6 +162,14 @@ static void arm_cpu_initfn(Object *obj)
ARMCPU *cpu = ARM_CPU(obj);
cpu_exec_init(&cpu->env);
+ cpu->cp_regs = g_hash_table_new_full(g_int_hash, g_int_equal,
+ g_free, g_free);
+}
+
+static void arm_cpu_finalizefn(Object *obj)
+{
+ ARMCPU *cpu = ARM_CPU(obj);
+ g_hash_table_destroy(cpu->cp_regs);
}
void arm_cpu_realize(ARMCPU *cpu)
@@ -657,6 +697,7 @@ static const TypeInfo arm_cpu_type_info = {
.parent = TYPE_CPU,
.instance_size = sizeof(ARMCPU),
.instance_init = arm_cpu_initfn,
+ .instance_finalize = arm_cpu_finalizefn,
.abstract = true,
.class_size = sizeof(ARMCPUClass),
.class_init = arm_cpu_class_init,