diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2012-06-20 11:57:06 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2012-06-20 12:01:02 +0000 |
commit | 4b6a83fb0c34a6fcc7bb1058284e3c3674e54421 (patch) | |
tree | 96993a63c6c6e60f7936467c1f57658a52c73466 /target-arm/cpu.c | |
parent | 200bf596b96820186883953de9bda26cac8e6bd7 (diff) | |
download | qemu-4b6a83fb0c34a6fcc7bb1058284e3c3674e54421.zip qemu-4b6a83fb0c34a6fcc7bb1058284e3c3674e54421.tar.gz qemu-4b6a83fb0c34a6fcc7bb1058284e3c3674e54421.tar.bz2 |
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.c | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 934894b..6456a3d 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, |