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:
parent
c92458538f
commit
0c28246fcd
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
Loading…
Reference in New Issue
Block a user