Skip to content

Commit

Permalink
target-alpha: Turn CPU definitions into subclasses
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
afaerber committed Dec 19, 2012
1 parent c924585 commit 0c28246
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 58 deletions.
178 changes: 177 additions & 1 deletion target-alpha/cpu.c
Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -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)
2 changes: 2 additions & 0 deletions target-alpha/cpu.h
Expand Up @@ -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)
Expand Down
58 changes: 1 addition & 57 deletions target-alpha/translate.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand Down

0 comments on commit 0c28246

Please sign in to comment.