[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [RFC 06/12] target-ppc: QOM'ify CPU
From: |
Andreas Färber |
Subject: |
[Qemu-ppc] [RFC 06/12] target-ppc: QOM'ify CPU |
Date: |
Wed, 14 Mar 2012 18:53:30 +0100 |
Signed-off-by: Andreas Färber <address@hidden>
---
target-ppc/cpu-qom.h | 84 ++++++++++++++
target-ppc/cpu.h | 25 +----
target-ppc/helper.c | 72 ++----------
target-ppc/kvm.c | 29 +++--
target-ppc/kvm_ppc.h | 6 -
target-ppc/translate.c | 2 +-
target-ppc/translate_init.c | 264 ++++++++++++++++++++++++++++++++++++-------
7 files changed, 342 insertions(+), 140 deletions(-)
create mode 100644 target-ppc/cpu-qom.h
diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h
new file mode 100644
index 0000000..9236dcc
--- /dev/null
+++ b/target-ppc/cpu-qom.h
@@ -0,0 +1,84 @@
+/*
+ * QEMU PowerPC CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+#ifndef QEMU_PPC_CPU_QOM_H
+#define QEMU_PPC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#define TYPE_POWERPC_CPU "powerpc-cpu"
+
+#define POWERPC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(PowerPCCPUClass, (klass), TYPE_POWERPC_CPU)
+#define POWERPC_CPU(obj) \
+ OBJECT_CHECK(PowerPCCPU, (obj), TYPE_POWERPC_CPU)
+#define POWERPC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(PowerPCCPUClass, (obj), TYPE_POWERPC_CPU)
+
+/**
+ * PowerPCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A PowerPC CPU model.
+ */
+typedef struct PowerPCCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+
+ uint32_t pvr;
+ uint32_t svr;
+ uint64_t insns_flags;
+ uint64_t insns_flags2;
+ uint64_t msr_mask;
+ powerpc_mmu_t mmu_model;
+ powerpc_excp_t excp_model;
+ powerpc_input_t bus_model;
+ uint32_t flags;
+ int bfd_mach;
+ void (*init_proc)(CPUPPCState *env);
+ int (*check_pow)(CPUPPCState *env);
+} PowerPCCPUClass;
+
+/**
+ * PowerPCCPU:
+ * @env: Legacy CPU state.
+ *
+ * A PowerPC CPU.
+ */
+typedef struct PowerPCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUPPCState env;
+} PowerPCCPU;
+
+static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env)
+{
+ return POWERPC_CPU(container_of(env, PowerPCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ad09cbe..ff28843 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -305,7 +305,6 @@ enum powerpc_input_t {
#define PPC_INPUT(env) (env->bus_model)
/*****************************************************************************/
-typedef struct ppc_def_t ppc_def_t;
typedef struct opc_handler_t opc_handler_t;
/*****************************************************************************/
@@ -877,22 +876,6 @@ enum {
/* The whole PowerPC CPU context */
#define NB_MMU_MODES 3
-struct ppc_def_t {
- const char *name;
- uint32_t pvr;
- uint32_t svr;
- uint64_t insns_flags;
- uint64_t insns_flags2;
- uint64_t msr_mask;
- powerpc_mmu_t mmu_model;
- powerpc_excp_t excp_model;
- powerpc_input_t bus_model;
- uint32_t flags;
- int bfd_mach;
- void (*init_proc)(CPUPPCState *env);
- int (*check_pow)(CPUPPCState *env);
-};
-
struct CPUPPCState {
/* First are the most commonly used resources
* during translated code execution
@@ -1096,6 +1079,8 @@ struct mmu_ctx_t {
};
#endif
+#include "cpu-qom.h"
+
/*****************************************************************************/
CPUPPCState *cpu_ppc_init (const char *cpu_model);
void ppc_translate_init(void);
@@ -1142,9 +1127,9 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr);
-const ppc_def_t *cpu_ppc_find_by_name (const char *name);
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def);
+void ppc_cpu_initfn(Object *obj);
+const char *ppc_find_by_pvr(uint32_t pvr);
+PowerPCCPU *cpu_ppc_find_by_name(const char *name);
/* Time-base and decrementer management */
#ifndef NO_CPU_IO_DEFS
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index bd711b6..7d26cb5 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -3138,85 +3138,31 @@ void cpu_dump_rfi (target_ulong RA, target_ulong msr)
void cpu_state_reset(CPUPPCState *env)
{
- target_ulong msr;
-
- if (qemu_loglevel_mask(CPU_LOG_RESET)) {
- qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
- log_cpu_state(env, 0);
- }
-
- msr = (target_ulong)0;
- if (0) {
- /* XXX: find a suitable condition to enable the hypervisor mode */
- msr |= (target_ulong)MSR_HVB;
- }
- msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
- msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
- msr |= (target_ulong)1 << MSR_EP;
-#if defined (DO_SINGLE_STEP) && 0
- /* Single step trace mode */
- msr |= (target_ulong)1 << MSR_SE;
- msr |= (target_ulong)1 << MSR_BE;
-#endif
-#if defined(CONFIG_USER_ONLY)
- msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
- msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
- msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
- msr |= (target_ulong)1 << MSR_PR;
-#else
- env->excp_prefix = env->hreset_excp_prefix;
- env->nip = env->hreset_vector | env->excp_prefix;
- if (env->mmu_model != POWERPC_MMU_REAL)
- ppc_tlb_invalidate_all(env);
-#endif
- env->msr = msr & env->msr_mask;
-#if defined(TARGET_PPC64)
- if (env->mmu_model & POWERPC_MMU_64)
- env->msr |= (1ULL << MSR_SF);
-#endif
- hreg_compute_hflags(env);
- env->reserve_addr = (target_ulong)-1ULL;
- /* Be sure no exception or interrupt is pending */
- env->pending_interrupts = 0;
- env->exception_index = POWERPC_EXCP_NONE;
- env->error_code = 0;
- /* Flush all TLBs */
- tlb_flush(env, 1);
+ cpu_reset(ENV_GET_CPU(env));
}
-CPUPPCState *cpu_ppc_init (const char *cpu_model)
+CPUPPCState *cpu_ppc_init(const char *cpu_model)
{
+ PowerPCCPU *cpu;
CPUPPCState *env;
- const ppc_def_t *def;
- def = cpu_ppc_find_by_name(cpu_model);
- if (!def)
+ cpu = cpu_ppc_find_by_name(cpu_model);
+ if (cpu == NULL) {
return NULL;
+ }
+ env = &cpu->env;
- env = g_malloc0(sizeof(CPUPPCState));
- cpu_exec_init(env);
if (tcg_enabled()) {
ppc_translate_init();
}
- /* Adjust cpu index for SMT */
-#if !defined(CONFIG_USER_ONLY)
- if (kvm_enabled()) {
- int smt = kvmppc_smt_threads();
-
- env->cpu_index = (env->cpu_index / smp_threads)*smt
- + (env->cpu_index % smp_threads);
- }
-#endif /* !CONFIG_USER_ONLY */
- env->cpu_model_str = cpu_model;
- cpu_ppc_register_internal(env, def);
qemu_init_vcpu(env);
return env;
}
-void cpu_ppc_close (CPUPPCState *env)
+void cpu_ppc_close(CPUPPCState *env)
{
/* Should also remove all opcode tables... */
- g_free(env);
+ object_delete(OBJECT(ppc_env_get_cpu(env)));
}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index aeb3de9..2ee5bc0 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -902,19 +902,12 @@ static void alter_insns(uint64_t *word, uint64_t flags,
bool on)
}
}
-const ppc_def_t *kvmppc_host_cpu_def(void)
+static void kvmppc_host_cpu_class_init(ObjectClass *klass, void *data)
{
- uint32_t host_pvr = mfpvr();
- const ppc_def_t *base_spec;
- ppc_def_t *spec;
+ PowerPCCPUClass *spec = POWERPC_CPU_CLASS(klass);
uint32_t vmx = kvmppc_get_vmx();
uint32_t dfp = kvmppc_get_dfp();
- base_spec = ppc_find_by_pvr(host_pvr);
-
- spec = g_malloc0(sizeof(*spec));
- memcpy(spec, base_spec, sizeof(*spec));
-
/* Now fix up the spec with information we can query from the host */
if (vmx != -1) {
@@ -926,8 +919,6 @@ const ppc_def_t *kvmppc_host_cpu_def(void)
/* Only override when we know what the host supports */
alter_insns(&spec->insns_flags2, PPC2_DFP, dfp);
}
-
- return spec;
}
bool kvm_arch_stop_on_emulation_error(CPUPPCState *env)
@@ -944,3 +935,19 @@ int kvm_arch_on_sigbus(int code, void *addr)
{
return 1;
}
+
+static void kvmppc_register_types(void)
+{
+ TypeInfo type = {
+ .name = "host",
+ .instance_size = sizeof(PowerPCCPU),
+ .instance_init = ppc_cpu_initfn,
+ .class_size = sizeof(PowerPCCPUClass),
+ .class_init = kvmppc_host_cpu_class_init,
+ };
+ uint32_t host_pvr = mfpvr();
+ type.parent = ppc_find_by_pvr(host_pvr);
+ type_register_static(&type);
+}
+
+type_init(kvmppc_register_types)
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 8f1267c..ce5be6e 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -28,7 +28,6 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion
*sysmem);
void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
#endif /* !CONFIG_USER_ONLY */
-const ppc_def_t *kvmppc_host_cpu_def(void);
#else
@@ -90,11 +89,6 @@ static inline int kvmppc_remove_spapr_tce(void *table, int
pfd,
}
#endif /* !CONFIG_USER_ONLY */
-static inline const ppc_def_t *kvmppc_host_cpu_def(void)
-{
- return NULL;
-}
-
#endif
#ifndef CONFIG_KVM
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3ec59a7..e43160d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -9272,8 +9272,8 @@ GEN_SPEOP_LDST(evstwwe, 0x1C, 2),
GEN_SPEOP_LDST(evstwwo, 0x1E, 2),
};
-#include "translate_init.c"
#include "helper_regs.h"
+#include "translate_init.c"
/*****************************************************************************/
/* Misc PowerPC helpers */
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 1ec6f42..52264c8 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2003-2007 Jocelyn Mayer
* Copyright 2011 Freescale Semiconductor, Inc.
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,6 +28,7 @@
#include "gdbstub.h"
#include <kvm.h>
#include "kvm_ppc.h"
+#include "cpus.h"
//#define PPC_DUMP_CPU
//#define PPC_DEBUG_SPR
@@ -7583,6 +7585,51 @@ enum {
/*****************************************************************************/
/* PowerPC CPU definitions */
+
+typedef struct PowerPCCPUInfo PowerPCCPUInfo;
+
+struct PowerPCCPUInfo {
+ const char *name;
+ uint32_t pvr;
+ uint32_t svr;
+ uint64_t insns_flags;
+ uint64_t insns_flags2;
+ uint64_t msr_mask;
+ powerpc_mmu_t mmu_model;
+ powerpc_excp_t excp_model;
+ powerpc_input_t bus_model;
+ uint32_t flags;
+ int bfd_mach;
+ void (*init_proc)(CPUPPCState *env);
+ int (*check_pow)(CPUPPCState *env);
+};
+
+static void ppc_cpu_reset(CPUState *cpu);
+
+static void ppc_cpu_class_init(ObjectClass *klass, void *data)
+{
+ CPUClass *cpu_class = CPU_CLASS(klass);
+ PowerPCCPUClass *k = POWERPC_CPU_CLASS(klass);
+ const PowerPCCPUInfo *info = data;
+
+ k->parent_reset = cpu_class->reset;
+ cpu_class->reset = ppc_cpu_reset;
+
+ k->pvr = info->pvr;
+ k->svr = info->svr;
+ k->insns_flags = info->insns_flags;
+ k->insns_flags2 = info->insns_flags2;
+ k->msr_mask = info->msr_mask;
+ k->mmu_model = info->mmu_model;
+ k->excp_model = info->excp_model;
+ k->bus_model = info->bus_model;
+ k->flags = info->flags;
+ k->bfd_mach = info->bfd_mach;
+
+ k->init_proc = info->init_proc;
+ k->check_pow = info->check_pow;
+}
+
#define POWERPC_DEF_SVR(_name, _pvr, _svr, _type) \
{ \
.name = _name, \
@@ -7602,7 +7649,7 @@ enum {
#define POWERPC_DEF(_name, _pvr, _type) \
POWERPC_DEF_SVR(_name, _pvr, POWERPC_SVR_NONE, _type)
-static const ppc_def_t ppc_defs[] = {
+static const PowerPCCPUInfo ppc_cpus[] = {
/* Embedded PowerPC */
/* PowerPC 401 family */
/* Generic PowerPC 401 */
@@ -9280,7 +9327,7 @@ static const ppc_def_t ppc_defs[] = {
/*****************************************************************************/
/* Generic CPU instantiation routine */
-static void init_ppc_proc (CPUPPCState *env, const ppc_def_t *def)
+static void init_ppc_proc(CPUPPCState *env, PowerPCCPUClass *def)
{
#if !defined(CONFIG_USER_ONLY)
int i;
@@ -9672,7 +9719,7 @@ static void fix_opcode_tables (opc_handler_t
**ppc_opcodes)
}
/*****************************************************************************/
-static int create_ppc_opcodes (CPUPPCState *env, const ppc_def_t *def)
+static int create_ppc_opcodes(CPUPPCState *env, const PowerPCCPUClass *def)
{
opcode_t *opc;
@@ -9884,8 +9931,26 @@ static int gdb_set_spe_reg(CPUPPCState *env, uint8_t
*mem_buf, int n)
return 0;
}
-int cpu_ppc_register_internal (CPUPPCState *env, const ppc_def_t *def)
+void ppc_cpu_initfn(Object *obj)
{
+ PowerPCCPU *cpu = POWERPC_CPU(obj);
+ PowerPCCPUClass *def = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+
+ memset(env, 0, sizeof(*env));
+ cpu_exec_init(env);
+ env->cpu_model_str = object_get_typename(obj);
+
+ /* Adjust cpu index for SMT */
+#if !defined(CONFIG_USER_ONLY)
+ if (kvm_enabled()) {
+ int smt = kvmppc_smt_threads();
+
+ env->cpu_index = (env->cpu_index / smp_threads) * smt
+ + (env->cpu_index % smp_threads);
+ }
+#endif /* !CONFIG_USER_ONLY */
+
env->msr_mask = def->msr_mask;
env->mmu_model = def->mmu_model;
env->excp_model = def->excp_model;
@@ -9911,8 +9976,9 @@ int cpu_ppc_register_internal (CPUPPCState *env, const
ppc_def_t *def)
env->flags = def->flags;
env->bfd_mach = def->bfd_mach;
env->check_pow = def->check_pow;
- if (create_ppc_opcodes(env, def) < 0)
- return -1;
+ if (create_ppc_opcodes(env, def) < 0) {
+ abort();
+ }
init_ppc_proc(env, def);
if (def->insns_flags & PPC_FLOAT) {
@@ -10089,11 +10155,64 @@ int cpu_ppc_register_internal (CPUPPCState *env,
const ppc_def_t *def)
dump_ppc_sprs(env);
fflush(stdout);
#endif
+}
- return 0;
+static void ppc_cpu_reset(CPUState *c)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(c);
+ PowerPCCPUClass *klass = POWERPC_CPU_GET_CLASS(cpu);
+ CPUPPCState *env = &cpu->env;
+ target_ulong msr;
+
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
+ klass->parent_reset(c);
+
+ msr = (target_ulong)0;
+ if (0) {
+ /* XXX: find a suitable condition to enable the hypervisor mode */
+ msr |= (target_ulong)MSR_HVB;
+ }
+ msr |= (target_ulong)0 << MSR_AP; /* TO BE CHECKED */
+ msr |= (target_ulong)0 << MSR_SA; /* TO BE CHECKED */
+ msr |= (target_ulong)1 << MSR_EP;
+#if defined(DO_SINGLE_STEP) && 0
+ /* Single step trace mode */
+ msr |= (target_ulong)1 << MSR_SE;
+ msr |= (target_ulong)1 << MSR_BE;
+#endif
+#if defined(CONFIG_USER_ONLY)
+ msr |= (target_ulong)1 << MSR_FP; /* Allow floating point usage */
+ msr |= (target_ulong)1 << MSR_VR; /* Allow altivec usage */
+ msr |= (target_ulong)1 << MSR_SPE; /* Allow SPE usage */
+ msr |= (target_ulong)1 << MSR_PR;
+#else
+ env->excp_prefix = env->hreset_excp_prefix;
+ env->nip = env->hreset_vector | env->excp_prefix;
+ if (env->mmu_model != POWERPC_MMU_REAL) {
+ ppc_tlb_invalidate_all(env);
+ }
+#endif
+ env->msr = msr & env->msr_mask;
+#if defined(TARGET_PPC64)
+ if (env->mmu_model & POWERPC_MMU_64) {
+ env->msr |= (1ULL << MSR_SF);
+ }
+#endif
+ hreg_compute_hflags(env);
+ env->reserve_addr = (target_ulong)-1ULL;
+ /* Be sure no exception or interrupt is pending */
+ env->pending_interrupts = 0;
+ env->exception_index = POWERPC_EXCP_NONE;
+ env->error_code = 0;
+ /* Flush all TLBs */
+ tlb_flush(env, 1);
}
-static bool ppc_cpu_usable(const ppc_def_t *def)
+static bool ppc_cpu_usable(const PowerPCCPUInfo *def)
{
#if defined(TARGET_PPCEMB)
/* When using the ppcemb target, we only support 440 style cores */
@@ -10105,18 +10224,18 @@ static bool ppc_cpu_usable(const ppc_def_t *def)
return true;
}
-const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
+const char *ppc_find_by_pvr(uint32_t pvr)
{
int i;
- for (i = 0; i < ARRAY_SIZE(ppc_defs); i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
+ for (i = 0; i < ARRAY_SIZE(ppc_cpus); i++) {
+ if (!ppc_cpu_usable(&ppc_cpus[i])) {
continue;
}
/* If we have an exact match, we're done */
- if (pvr == ppc_defs[i].pvr) {
- return &ppc_defs[i];
+ if (pvr == ppc_cpus[i].pvr) {
+ return ppc_cpus[i].name;
}
}
@@ -10125,14 +10244,13 @@ const ppc_def_t *ppc_find_by_pvr(uint32_t pvr)
#include <ctype.h>
-const ppc_def_t *cpu_ppc_find_by_name (const char *name)
+PowerPCCPU *cpu_ppc_find_by_name(const char *name)
{
- const ppc_def_t *ret;
const char *p;
- int i, max, len;
+ int i, len;
- if (kvm_enabled() && (strcasecmp(name, "host") == 0)) {
- return kvmppc_host_cpu_def();
+ if (!kvm_enabled() && (strcasecmp(name, "host") == 0)) {
+ return NULL;
}
/* Check if the given name is a PVR */
@@ -10147,36 +10265,104 @@ const ppc_def_t *cpu_ppc_find_by_name (const char
*name)
if (!qemu_isxdigit(*p++))
break;
}
- if (i == 8)
- return ppc_find_by_pvr(strtoul(name, NULL, 16));
- }
- ret = NULL;
- max = ARRAY_SIZE(ppc_defs);
- for (i = 0; i < max; i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
- continue;
+ if (i == 8) {
+ name = ppc_find_by_pvr(strtoul(name, NULL, 16));
+ if (name == NULL) {
+ return NULL;
+ }
}
+ }
- if (strcasecmp(name, ppc_defs[i].name) == 0) {
- ret = &ppc_defs[i];
- break;
- }
+ if (object_class_by_name(name) == NULL) {
+ return NULL;
}
+ return POWERPC_CPU(object_new(name));
+}
- return ret;
+typedef struct PowerPCCPUListState {
+ FILE *file;
+ fprintf_function cpu_fprintf;
+} PowerPCCPUListState;
+
+/* Sort by PVR and alphabetically. */
+static gint ppc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+ PowerPCCPUClass *class_a = POWERPC_CPU_CLASS(a);
+ PowerPCCPUClass *class_b = POWERPC_CPU_CLASS(b);
+
+ if (class_a->pvr == class_b->pvr) {
+ return strcasecmp(object_class_get_name(OBJECT_CLASS(class_a)),
+ object_class_get_name(OBJECT_CLASS(class_b)));
+ } else if (class_a->pvr > class_b->pvr) {
+ return 1;
+ } else {
+ return -1;
+ }
+}
+
+static void ppc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+ ObjectClass *klass = data;
+ PowerPCCPUClass *k = POWERPC_CPU_CLASS(klass);
+ PowerPCCPUListState *s = user_data;
+ const char *name;
+
+ name = object_class_get_name(klass);
+ if (strcmp(name, "host") == 0) {
+ return;
+ }
+ (*s->cpu_fprintf)(s->file, "PowerPC %-16s PVR %08x\n",
+ name, k->pvr);
+}
+
+void ppc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
+{
+ PowerPCCPUListState s = {
+ .file = f,
+ .cpu_fprintf = cpu_fprintf,
+ };
+ GSList *list;
+
+ list = object_class_get_list(TYPE_POWERPC_CPU, false);
+ list = g_slist_sort(list, ppc_cpu_list_compare);
+ g_slist_foreach(list, ppc_cpu_list_entry, &s);
+ g_slist_free(list);
+}
+
+static void ppc_register_cpu(const PowerPCCPUInfo *info)
+{
+ TypeInfo type = {
+ .name = info->name,
+ .parent = TYPE_POWERPC_CPU,
+ .instance_size = sizeof(PowerPCCPU),
+ .instance_init = ppc_cpu_initfn,
+ .class_size = sizeof(PowerPCCPUClass),
+ .class_init = ppc_cpu_class_init,
+ .class_data = (void *)info,
+ };
+
+ type_register_static(&type);
}
-void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf)
+static TypeInfo ppc_cpu_type_info = {
+ .name = TYPE_POWERPC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(PowerPCCPU),
+ .abstract = true,
+ .class_size = sizeof(PowerPCCPUClass),
+};
+
+static void ppc_cpu_register_types(void)
{
- int i, max;
+ int i;
- max = ARRAY_SIZE(ppc_defs);
- for (i = 0; i < max; i++) {
- if (!ppc_cpu_usable(&ppc_defs[i])) {
+ type_register_static(&ppc_cpu_type_info);
+ for (i = 0; i < ARRAY_SIZE(ppc_cpus); i++) {
+ if (!ppc_cpu_usable(&ppc_cpus[i])) {
continue;
}
-
- (*cpu_fprintf)(f, "PowerPC %-16s PVR %08x\n",
- ppc_defs[i].name, ppc_defs[i].pvr);
+ ppc_register_cpu(&ppc_cpus[i]);
}
}
+
+type_init(ppc_cpu_register_types)
--
1.7.7