Skip to content

Commit

Permalink
target-m68k: Add QOM CPU subclasses
Browse files Browse the repository at this point in the history
Move code from cpu_m68k_set_model() into model-specific initfns
and inline the remaining parts into cpu_m68k_init().

Let m68k_cpu_list() print CPU classes alphabetically except for "any".

Signed-off-by: Andreas Färber <afaerber@suse.de>
  • Loading branch information
afaerber committed Apr 15, 2012
1 parent 15c0a35 commit 2f69f48
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 90 deletions.
89 changes: 88 additions & 1 deletion target-m68k/cpu.c
Expand Up @@ -22,6 +22,11 @@
#include "qemu-common.h"


static void m68k_set_feature(CPUM68KState *env, int feature)
{
env->features |= (1u << feature);
}

/* CPUClass::reset() */
static void m68k_cpu_reset(CPUState *s)
{
Expand All @@ -48,6 +53,72 @@ static void m68k_cpu_reset(CPUState *s)
tlb_flush(env, 1);
}

/* CPU models */

static void m5206_cpu_initfn(Object *obj)
{
M68kCPU *cpu = M68K_CPU(obj);
CPUM68KState *env = &cpu->env;

m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
}

static void m5208_cpu_initfn(Object *obj)
{
M68kCPU *cpu = M68K_CPU(obj);
CPUM68KState *env = &cpu->env;

m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_USP);
}

static void cfv4e_cpu_initfn(Object *obj)
{
M68kCPU *cpu = M68K_CPU(obj);
CPUM68KState *env = &cpu->env;

m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_USP);
}

static void any_cpu_initfn(Object *obj)
{
M68kCPU *cpu = M68K_CPU(obj);
CPUM68KState *env = &cpu->env;

m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
/* MAC and EMAC are mututally exclusive, so pick EMAC.
It's mostly backwards compatible. */
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
m68k_set_feature(env, M68K_FEATURE_USP);
m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
}

typedef struct M68kCPUInfo {
const char *name;
void (*instance_init)(Object *obj);
} M68kCPUInfo;

static const M68kCPUInfo m68k_cpus[] = {
{ .name = "m5206", .instance_init = m5206_cpu_initfn },
{ .name = "m5208", .instance_init = m5208_cpu_initfn },
{ .name = "cfv4e", .instance_init = cfv4e_cpu_initfn },
{ .name = "any", .instance_init = any_cpu_initfn },
};

static void m68k_cpu_initfn(Object *obj)
{
M68kCPU *cpu = M68K_CPU(obj);
Expand All @@ -65,19 +136,35 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
cc->reset = m68k_cpu_reset;
}

static void register_cpu_type(const M68kCPUInfo *info)
{
TypeInfo type_info = {
.name = info->name,
.parent = TYPE_M68K_CPU,
.instance_init = info->instance_init,
};

type_register_static(&type_info);
}

static const TypeInfo m68k_cpu_type_info = {
.name = TYPE_M68K_CPU,
.parent = TYPE_CPU,
.instance_size = sizeof(M68kCPU),
.instance_init = m68k_cpu_initfn,
.abstract = false,
.abstract = true,
.class_size = sizeof(M68kCPUClass),
.class_init = m68k_cpu_class_init,
};

static void m68k_cpu_register_types(void)
{
int i;

type_register_static(&m68k_cpu_type_info);
for (i = 0; i < ARRAY_SIZE(m68k_cpus); i++) {
register_cpu_type(&m68k_cpus[i]);
}
}

type_init(m68k_cpu_register_types)
138 changes: 49 additions & 89 deletions target-m68k/helper.c
Expand Up @@ -25,35 +25,50 @@

#define SIGNBIT (1u << 31)

enum m68k_cpuid {
M68K_CPUID_M5206,
M68K_CPUID_M5208,
M68K_CPUID_CFV4E,
M68K_CPUID_ANY,
};

typedef struct m68k_def_t m68k_def_t;

struct m68k_def_t {
const char * name;
enum m68k_cpuid id;
};

static m68k_def_t m68k_cpu_defs[] = {
{"m5206", M68K_CPUID_M5206},
{"m5208", M68K_CPUID_M5208},
{"cfv4e", M68K_CPUID_CFV4E},
{"any", M68K_CPUID_ANY},
{NULL, 0},
};
typedef struct M68kCPUListState {
fprintf_function cpu_fprintf;
FILE *file;
} M68kCPUListState;

/* Sort alphabetically, except for "any". */
static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
{
ObjectClass *class_a = (ObjectClass *)a;
ObjectClass *class_b = (ObjectClass *)b;
const char *name_a, *name_b;

name_a = object_class_get_name(class_a);
name_b = object_class_get_name(class_b);
if (strcmp(name_a, "any") == 0) {
return 1;
} else if (strcmp(name_b, "any") == 0) {
return -1;
} else {
return strcasecmp(name_a, name_b);
}
}

static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *c = data;
M68kCPUListState *s = user_data;

(*s->cpu_fprintf)(s->file, "%s\n",
object_class_get_name(c));
}

void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
{
unsigned int i;
M68kCPUListState s = {
.file = f,
.cpu_fprintf = cpu_fprintf,
};
GSList *list;

for (i = 0; m68k_cpu_defs[i].name; i++) {
(*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
}
list = object_class_get_list(TYPE_M68K_CPU, false);
list = g_slist_sort(list, m68k_cpu_list_compare);
g_slist_foreach(list, m68k_cpu_list_entry, &s);
g_slist_free(list);
}

static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
Expand Down Expand Up @@ -83,66 +98,6 @@ static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
return 0;
}

static void m68k_set_feature(CPUM68KState *env, int feature)
{
env->features |= (1u << feature);
}

static int cpu_m68k_set_model(CPUM68KState *env, const char *name)
{
m68k_def_t *def;

for (def = m68k_cpu_defs; def->name; def++) {
if (strcmp(def->name, name) == 0)
break;
}
if (!def->name)
return -1;

switch (def->id) {
case M68K_CPUID_M5206:
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
break;
case M68K_CPUID_M5208:
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_USP);
break;
case M68K_CPUID_CFV4E:
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_USP);
break;
case M68K_CPUID_ANY:
m68k_set_feature(env, M68K_FEATURE_CF_ISA_A);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_B);
m68k_set_feature(env, M68K_FEATURE_CF_ISA_APLUSC);
m68k_set_feature(env, M68K_FEATURE_BRAL);
m68k_set_feature(env, M68K_FEATURE_CF_FPU);
/* MAC and EMAC are mututally exclusive, so pick EMAC.
It's mostly backwards compatible. */
m68k_set_feature(env, M68K_FEATURE_CF_EMAC);
m68k_set_feature(env, M68K_FEATURE_CF_EMAC_B);
m68k_set_feature(env, M68K_FEATURE_USP);
m68k_set_feature(env, M68K_FEATURE_EXT_FULL);
m68k_set_feature(env, M68K_FEATURE_WORD_INDEX);
break;
}

register_m68k_insns(env);
if (m68k_feature (env, M68K_FEATURE_CF_FPU)) {
gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
11, "cf-fp.xml", 18);
}
/* TODO: Add [E]MAC registers. */
return 0;
}

void cpu_state_reset(CPUM68KState *env)
{
cpu_reset(ENV_GET_CPU(env));
Expand All @@ -154,7 +109,10 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)
CPUM68KState *env;
static int inited;

cpu = M68K_CPU(object_new(TYPE_M68K_CPU));
if (object_class_by_name(cpu_model) == NULL) {
return NULL;
}
cpu = M68K_CPU(object_new(cpu_model));
env = &cpu->env;

if (!inited) {
Expand All @@ -164,10 +122,12 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)

env->cpu_model_str = cpu_model;

if (cpu_m68k_set_model(env, cpu_model) < 0) {
object_delete(OBJECT(cpu));
return NULL;
register_m68k_insns(env);
if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
gdb_register_coprocessor(env, fpu_gdb_get_reg, fpu_gdb_set_reg,
11, "cf-fp.xml", 18);
}
/* TODO: Add [E]MAC registers. */

cpu_reset(ENV_GET_CPU(env));
qemu_init_vcpu(env);
Expand Down

0 comments on commit 2f69f48

Please sign in to comment.