target-m68k: Add QOM CPU subclasses
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> Reviewed-by: Laurent Vivier <Laurent@Vivier.EU> Tested-by: Laurent Vivier <Laurent@Vivier.EU>
This commit is contained in:
parent
9b7060396e
commit
11150915fc
@ -22,6 +22,11 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void m68k_set_feature(CPUM68KState *env, int feature)
|
||||||
|
{
|
||||||
|
env->features |= (1u << feature);
|
||||||
|
}
|
||||||
|
|
||||||
/* CPUClass::reset() */
|
/* CPUClass::reset() */
|
||||||
static void m68k_cpu_reset(CPUState *s)
|
static void m68k_cpu_reset(CPUState *s)
|
||||||
{
|
{
|
||||||
@ -48,6 +53,72 @@ static void m68k_cpu_reset(CPUState *s)
|
|||||||
tlb_flush(env, 1);
|
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)
|
static void m68k_cpu_initfn(Object *obj)
|
||||||
{
|
{
|
||||||
M68kCPU *cpu = M68K_CPU(obj);
|
M68kCPU *cpu = M68K_CPU(obj);
|
||||||
@ -65,19 +136,35 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data)
|
|||||||
cc->reset = m68k_cpu_reset;
|
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 = {
|
static const TypeInfo m68k_cpu_type_info = {
|
||||||
.name = TYPE_M68K_CPU,
|
.name = TYPE_M68K_CPU,
|
||||||
.parent = TYPE_CPU,
|
.parent = TYPE_CPU,
|
||||||
.instance_size = sizeof(M68kCPU),
|
.instance_size = sizeof(M68kCPU),
|
||||||
.instance_init = m68k_cpu_initfn,
|
.instance_init = m68k_cpu_initfn,
|
||||||
.abstract = false,
|
.abstract = true,
|
||||||
.class_size = sizeof(M68kCPUClass),
|
.class_size = sizeof(M68kCPUClass),
|
||||||
.class_init = m68k_cpu_class_init,
|
.class_init = m68k_cpu_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void m68k_cpu_register_types(void)
|
static void m68k_cpu_register_types(void)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
type_register_static(&m68k_cpu_type_info);
|
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)
|
type_init(m68k_cpu_register_types)
|
||||||
|
@ -25,35 +25,50 @@
|
|||||||
|
|
||||||
#define SIGNBIT (1u << 31)
|
#define SIGNBIT (1u << 31)
|
||||||
|
|
||||||
enum m68k_cpuid {
|
typedef struct M68kCPUListState {
|
||||||
M68K_CPUID_M5206,
|
fprintf_function cpu_fprintf;
|
||||||
M68K_CPUID_M5208,
|
FILE *file;
|
||||||
M68K_CPUID_CFV4E,
|
} M68kCPUListState;
|
||||||
M68K_CPUID_ANY,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct m68k_def_t m68k_def_t;
|
/* 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;
|
||||||
|
|
||||||
struct m68k_def_t {
|
name_a = object_class_get_name(class_a);
|
||||||
const char * name;
|
name_b = object_class_get_name(class_b);
|
||||||
enum m68k_cpuid id;
|
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 m68k_def_t m68k_cpu_defs[] = {
|
static void m68k_cpu_list_entry(gpointer data, gpointer user_data)
|
||||||
{"m5206", M68K_CPUID_M5206},
|
{
|
||||||
{"m5208", M68K_CPUID_M5208},
|
ObjectClass *c = data;
|
||||||
{"cfv4e", M68K_CPUID_CFV4E},
|
M68kCPUListState *s = user_data;
|
||||||
{"any", M68K_CPUID_ANY},
|
|
||||||
{NULL, 0},
|
(*s->cpu_fprintf)(s->file, "%s\n",
|
||||||
};
|
object_class_get_name(c));
|
||||||
|
}
|
||||||
|
|
||||||
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
|
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++) {
|
list = object_class_get_list(TYPE_M68K_CPU, false);
|
||||||
(*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
|
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)
|
static int fpu_gdb_get_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
|
||||||
@ -83,66 +98,6 @@ static int fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n)
|
|||||||
return 0;
|
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)
|
void cpu_state_reset(CPUM68KState *env)
|
||||||
{
|
{
|
||||||
cpu_reset(ENV_GET_CPU(env));
|
cpu_reset(ENV_GET_CPU(env));
|
||||||
@ -154,7 +109,10 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)
|
|||||||
CPUM68KState *env;
|
CPUM68KState *env;
|
||||||
static int inited;
|
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;
|
env = &cpu->env;
|
||||||
|
|
||||||
if (!inited) {
|
if (!inited) {
|
||||||
@ -164,10 +122,12 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)
|
|||||||
|
|
||||||
env->cpu_model_str = cpu_model;
|
env->cpu_model_str = cpu_model;
|
||||||
|
|
||||||
if (cpu_m68k_set_model(env, cpu_model) < 0) {
|
register_m68k_insns(env);
|
||||||
object_delete(OBJECT(cpu));
|
if (m68k_feature(env, M68K_FEATURE_CF_FPU)) {
|
||||||
return NULL;
|
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));
|
cpu_reset(ENV_GET_CPU(env));
|
||||||
qemu_init_vcpu(env);
|
qemu_init_vcpu(env);
|
||||||
|
Loading…
Reference in New Issue
Block a user