Commit 0c28246f authored by Andreas Färber's avatar Andreas Färber
Browse files

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: default avatarAndreas Färber <afaerber@suse.de>
Acked-by: default avatarRichard Henderson <rth@twiddle.net>
parent c9245853
Loading
Loading
Loading
Loading
+177 −1
Original line number Diff line number Diff line
@@ -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)
+2 −0
Original line number Diff line number Diff line
@@ -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)
+1 −57
Original line number Diff line number Diff line
@@ -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];