target-alpha: Turn CPU definitions into subclasses

Make TYPE_ALPHA_CPU abstract and add types <name>-alpha-cpu.
Use type inheritence, and turn "2*" models into aliases.

Move cpu_alpha_init() to cpu.c and split out CPU realization.
Default to creating type "ev67-alpha-cpu" as before.

Signed-off-by: Andreas Färber <afaerber@suse.de>
Acked-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Andreas Färber 2012-10-15 17:33:32 +02:00
parent c92458538f
commit 0c28246fcd
3 changed files with 180 additions and 58 deletions

View File

@ -21,8 +21,175 @@
#include "cpu.h"
#include "qemu-common.h"
#include "error.h"
static void alpha_cpu_realize(Object *obj, Error **errp)
{
#ifndef CONFIG_USER_ONLY
AlphaCPU *cpu = ALPHA_CPU(obj);
qemu_init_vcpu(&cpu->env);
#endif
}
/* Models */
#define TYPE(model) model "-" TYPE_ALPHA_CPU
typedef struct AlphaCPUAlias {
const char *alias;
const char *typename;
} AlphaCPUAlias;
static const AlphaCPUAlias alpha_cpu_aliases[] = {
{ "21064", TYPE("ev4") },
{ "21164", TYPE("ev5") },
{ "21164a", TYPE("ev56") },
{ "21164pc", TYPE("pca56") },
{ "21264", TYPE("ev6") },
{ "21264a", TYPE("ev67") },
};
static ObjectClass *alpha_cpu_class_by_name(const char *cpu_model)
{
ObjectClass *oc = NULL;
char *typename;
int i;
if (cpu_model == NULL) {
return NULL;
}
oc = object_class_by_name(cpu_model);
if (oc != NULL) {
return oc;
}
for (i = 0; i < ARRAY_SIZE(alpha_cpu_aliases); i++) {
if (strcmp(cpu_model, alpha_cpu_aliases[i].alias) == 0) {
oc = object_class_by_name(alpha_cpu_aliases[i].typename);
assert(oc != NULL);
return oc;
}
}
typename = g_strdup_printf("%s-" TYPE_ALPHA_CPU, cpu_model);
oc = object_class_by_name(typename);
g_free(typename);
return oc;
}
AlphaCPU *cpu_alpha_init(const char *cpu_model)
{
AlphaCPU *cpu;
CPUAlphaState *env;
ObjectClass *cpu_class;
cpu_class = alpha_cpu_class_by_name(cpu_model);
if (cpu_class == NULL) {
/* Default to ev67; no reason not to emulate insns by default. */
cpu_class = object_class_by_name(TYPE("ev67"));
}
cpu = ALPHA_CPU(object_new(object_class_get_name(cpu_class)));
env = &cpu->env;
env->cpu_model_str = cpu_model;
alpha_cpu_realize(OBJECT(cpu), NULL);
return cpu;
}
static void ev4_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->implver = IMPLVER_2106x;
}
static const TypeInfo ev4_cpu_type_info = {
.name = TYPE("ev4"),
.parent = TYPE_ALPHA_CPU,
.instance_init = ev4_cpu_initfn,
};
static void ev5_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->implver = IMPLVER_21164;
}
static const TypeInfo ev5_cpu_type_info = {
.name = TYPE("ev5"),
.parent = TYPE_ALPHA_CPU,
.instance_init = ev5_cpu_initfn,
};
static void ev56_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->amask |= AMASK_BWX;
}
static const TypeInfo ev56_cpu_type_info = {
.name = TYPE("ev56"),
.parent = TYPE("ev5"),
.instance_init = ev56_cpu_initfn,
};
static void pca56_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->amask |= AMASK_MVI;
}
static const TypeInfo pca56_cpu_type_info = {
.name = TYPE("pca56"),
.parent = TYPE("ev56"),
.instance_init = pca56_cpu_initfn,
};
static void ev6_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->implver = IMPLVER_21264;
env->amask = AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP;
}
static const TypeInfo ev6_cpu_type_info = {
.name = TYPE("ev6"),
.parent = TYPE_ALPHA_CPU,
.instance_init = ev6_cpu_initfn,
};
static void ev67_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
CPUAlphaState *env = &cpu->env;
env->amask |= AMASK_CIX | AMASK_PREFETCH;
}
static const TypeInfo ev67_cpu_type_info = {
.name = TYPE("ev67"),
.parent = TYPE("ev6"),
.instance_init = ev67_cpu_initfn,
};
static const TypeInfo ev68_cpu_type_info = {
.name = TYPE("ev68"),
.parent = TYPE("ev67"),
};
static void alpha_cpu_initfn(Object *obj)
{
AlphaCPU *cpu = ALPHA_CPU(obj);
@ -31,6 +198,8 @@ static void alpha_cpu_initfn(Object *obj)
cpu_exec_init(env);
tlb_flush(env, 1);
alpha_translate_init();
#if defined(CONFIG_USER_ONLY)
env->ps = PS_USER_MODE;
cpu_alpha_store_fpcr(env, (FPCR_INVD | FPCR_DZED | FPCR_OVFD
@ -46,13 +215,20 @@ static const TypeInfo alpha_cpu_type_info = {
.parent = TYPE_CPU,
.instance_size = sizeof(AlphaCPU),
.instance_init = alpha_cpu_initfn,
.abstract = false,
.abstract = true,
.class_size = sizeof(AlphaCPUClass),
};
static void alpha_cpu_register_types(void)
{
type_register_static(&alpha_cpu_type_info);
type_register_static(&ev4_cpu_type_info);
type_register_static(&ev5_cpu_type_info);
type_register_static(&ev56_cpu_type_info);
type_register_static(&pca56_cpu_type_info);
type_register_static(&ev6_cpu_type_info);
type_register_static(&ev67_cpu_type_info);
type_register_static(&ev68_cpu_type_info);
}
type_init(alpha_cpu_register_types)

View File

@ -425,6 +425,8 @@ enum {
IR_ZERO = 31,
};
void alpha_translate_init(void);
AlphaCPU *cpu_alpha_init(const char *cpu_model);
static inline CPUAlphaState *cpu_init(const char *cpu_model)

View File

@ -90,7 +90,7 @@ static char cpu_reg_names[10*4+21*5 + 10*5+21*6];
#include "gen-icount.h"
static void alpha_translate_init(void)
void alpha_translate_init(void)
{
int i;
char *p;
@ -3493,62 +3493,6 @@ void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb)
gen_intermediate_code_internal(env, tb, 1);
}
struct cpu_def_t {
const char *name;
int implver, amask;
};
static const struct cpu_def_t cpu_defs[] = {
{ "ev4", IMPLVER_2106x, 0 },
{ "ev5", IMPLVER_21164, 0 },
{ "ev56", IMPLVER_21164, AMASK_BWX },
{ "pca56", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
{ "ev6", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
{ "ev67", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
{ "ev68", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), },
{ "21064", IMPLVER_2106x, 0 },
{ "21164", IMPLVER_21164, 0 },
{ "21164a", IMPLVER_21164, AMASK_BWX },
{ "21164pc", IMPLVER_21164, AMASK_BWX | AMASK_MVI },
{ "21264", IMPLVER_21264, AMASK_BWX | AMASK_FIX | AMASK_MVI | AMASK_TRAP },
{ "21264a", IMPLVER_21264, (AMASK_BWX | AMASK_FIX | AMASK_CIX
| AMASK_MVI | AMASK_TRAP | AMASK_PREFETCH), }
};
AlphaCPU *cpu_alpha_init(const char *cpu_model)
{
AlphaCPU *cpu;
CPUAlphaState *env;
int implver, amask, i, max;
cpu = ALPHA_CPU(object_new(TYPE_ALPHA_CPU));
env = &cpu->env;
alpha_translate_init();
/* Default to ev67; no reason not to emulate insns by default. */
implver = IMPLVER_21264;
amask = (AMASK_BWX | AMASK_FIX | AMASK_CIX | AMASK_MVI
| AMASK_TRAP | AMASK_PREFETCH);
max = ARRAY_SIZE(cpu_defs);
for (i = 0; i < max; i++) {
if (strcmp (cpu_model, cpu_defs[i].name) == 0) {
implver = cpu_defs[i].implver;
amask = cpu_defs[i].amask;
break;
}
}
env->implver = implver;
env->amask = amask;
env->cpu_model_str = cpu_model;
qemu_init_vcpu(env);
return cpu;
}
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos)
{
env->pc = tcg_ctx.gen_opc_pc[pc_pos];