mirror of https://github.com/xemu-project/xemu.git
Merge branch 'qom-cpu-rest.v1' of git://github.com/afaerber/qemu-cpu
* 'qom-cpu-rest.v1' of git://github.com/afaerber/qemu-cpu: Makefile: Simplify compilation of target-*/cpu.c target-mips: Start QOM'ifying CPU init target-mips: QOM'ify CPU target-m68k: Add QOM CPU subclasses target-m68k: Start QOM'ifying CPU init target-m68k: QOM'ify CPU reset target-m68k: QOM'ify CPU target-sh4: Start QOM'ifying CPU init target-sh4: QOM'ify CPU reset target-sh4: QOM'ify CPU MAINTAINERS: Downgrade target-mips and target-sh4 to Odd Fixes MAINTAINERS: Downgrade target-m68k to Odd Fixes
This commit is contained in:
commit
61d25e1548
|
@ -78,7 +78,7 @@ F: target-lm32/
|
|||
|
||||
M68K
|
||||
M: Paul Brook <paul@codesourcery.com>
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
F: target-m68k/
|
||||
|
||||
MicroBlaze
|
||||
|
@ -88,7 +88,7 @@ F: target-microblaze/
|
|||
|
||||
MIPS
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
F: target-mips/
|
||||
|
||||
PowerPC
|
||||
|
@ -104,7 +104,7 @@ F: target-s390x/
|
|||
|
||||
SH4
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
S: Maintained
|
||||
S: Odd Fixes
|
||||
F: target-sh4/
|
||||
|
||||
SPARC
|
||||
|
|
|
@ -87,27 +87,18 @@ libobj-y += op_helper.o
|
|||
endif
|
||||
endif
|
||||
libobj-y += helper.o
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
ifneq ($(TARGET_BASE_ARCH), ppc)
|
||||
libobj-y += cpu.o
|
||||
endif
|
||||
libobj-$(TARGET_SPARC64) += vis_helper.o
|
||||
libobj-$(CONFIG_NEED_MMU) += mmu.o
|
||||
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
|
||||
libobj-$(TARGET_ARM) += cpu.o
|
||||
libobj-$(TARGET_CRIS) += cpu.o
|
||||
libobj-$(TARGET_LM32) += cpu.o
|
||||
libobj-$(TARGET_MICROBLAZE) += cpu.o
|
||||
libobj-$(TARGET_S390X) += cpu.o
|
||||
ifeq ($(TARGET_BASE_ARCH), sparc)
|
||||
libobj-y += fop_helper.o cc_helper.o win_helper.o mmu_helper.o ldst_helper.o
|
||||
libobj-y += cpu.o
|
||||
endif
|
||||
libobj-$(TARGET_SPARC) += int32_helper.o
|
||||
libobj-$(TARGET_SPARC64) += int64_helper.o
|
||||
libobj-$(TARGET_UNICORE32) += cpu.o
|
||||
libobj-$(TARGET_XTENSA) += cpu.o
|
||||
libobj-$(TARGET_ALPHA) += int_helper.o fpu_helper.o sys_helper.o mem_helper.o
|
||||
libobj-$(TARGET_ALPHA) += cpu.o
|
||||
|
||||
libobj-y += disas.o
|
||||
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* QEMU Motorola 68k 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_M68K_CPU_QOM_H
|
||||
#define QEMU_M68K_CPU_QOM_H
|
||||
|
||||
#include "qemu/cpu.h"
|
||||
|
||||
#define TYPE_M68K_CPU "m68k-cpu"
|
||||
|
||||
#define M68K_CPU_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(M68kCPUClass, (klass), TYPE_M68K_CPU)
|
||||
#define M68K_CPU(obj) \
|
||||
OBJECT_CHECK(M68kCPU, (obj), TYPE_M68K_CPU)
|
||||
#define M68K_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(M68kCPUClass, (obj), TYPE_M68K_CPU)
|
||||
|
||||
/**
|
||||
* M68kCPUClass:
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A Motorola 68k CPU model.
|
||||
*/
|
||||
typedef struct M68kCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} M68kCPUClass;
|
||||
|
||||
/**
|
||||
* M68kCPU:
|
||||
* @env: #CPUM68KState
|
||||
*
|
||||
* A Motorola 68k CPU.
|
||||
*/
|
||||
typedef struct M68kCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUM68KState env;
|
||||
} M68kCPU;
|
||||
|
||||
static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env)
|
||||
{
|
||||
return M68K_CPU(container_of(env, M68kCPU, env));
|
||||
}
|
||||
|
||||
#define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e))
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
* QEMU Motorola 68k 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>
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#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)
|
||||
{
|
||||
M68kCPU *cpu = M68K_CPU(s);
|
||||
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
||||
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
||||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
mcc->parent_reset(s);
|
||||
|
||||
memset(env, 0, offsetof(CPUM68KState, breakpoints));
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
env->sr = 0x2700;
|
||||
#endif
|
||||
m68k_switch_sp(env);
|
||||
/* ??? FP regs should be initialized to NaN. */
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
/* TODO: We should set PC from the interrupt vector. */
|
||||
env->pc = 0;
|
||||
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);
|
||||
CPUM68KState *env = &cpu->env;
|
||||
|
||||
cpu_exec_init(env);
|
||||
}
|
||||
|
||||
static void m68k_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
M68kCPUClass *mcc = M68K_CPU_CLASS(c);
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
|
||||
mcc->parent_reset = cc->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 = {
|
||||
.name = TYPE_M68K_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(M68kCPU),
|
||||
.instance_init = m68k_cpu_initfn,
|
||||
.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)
|
|
@ -116,10 +116,11 @@ typedef struct CPUM68KState {
|
|||
uint32_t features;
|
||||
} CPUM68KState;
|
||||
|
||||
#include "cpu-qom.h"
|
||||
|
||||
void m68k_tcg_init(void);
|
||||
CPUM68KState *cpu_m68k_init(const char *cpu_model);
|
||||
int cpu_m68k_exec(CPUM68KState *s);
|
||||
void cpu_m68k_close(CPUM68KState *s);
|
||||
void do_interrupt(CPUM68KState *env1);
|
||||
void do_interrupt_m68k_hardirq(CPUM68KState *env1);
|
||||
/* you can call this signal handler from your SIGBUS and SIGSEGV
|
||||
|
|
|
@ -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 M68kCPUListState {
|
||||
fprintf_function cpu_fprintf;
|
||||
FILE *file;
|
||||
} M68kCPUListState;
|
||||
|
||||
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 {
|
||||
const char * name;
|
||||
enum m68k_cpuid id;
|
||||
};
|
||||
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 m68k_def_t m68k_cpu_defs[] = {
|
||||
{"m5206", M68K_CPUID_M5206},
|
||||
{"m5208", M68K_CPUID_M5208},
|
||||
{"cfv4e", M68K_CPUID_CFV4E},
|
||||
{"any", M68K_CPUID_ANY},
|
||||
{NULL, 0},
|
||||
};
|
||||
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)
|
||||
|
@ -83,92 +98,23 @@ 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)
|
||||
{
|
||||
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
||||
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
||||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
memset(env, 0, offsetof(CPUM68KState, breakpoints));
|
||||
#if !defined (CONFIG_USER_ONLY)
|
||||
env->sr = 0x2700;
|
||||
#endif
|
||||
m68k_switch_sp(env);
|
||||
/* ??? FP regs should be initialized to NaN. */
|
||||
env->cc_op = CC_OP_FLAGS;
|
||||
/* TODO: We should set PC from the interrupt vector. */
|
||||
env->pc = 0;
|
||||
tlb_flush(env, 1);
|
||||
cpu_reset(ENV_GET_CPU(env));
|
||||
}
|
||||
|
||||
CPUM68KState *cpu_m68k_init(const char *cpu_model)
|
||||
{
|
||||
M68kCPU *cpu;
|
||||
CPUM68KState *env;
|
||||
static int inited;
|
||||
|
||||
env = g_malloc0(sizeof(CPUM68KState));
|
||||
cpu_exec_init(env);
|
||||
if (object_class_by_name(cpu_model) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cpu = M68K_CPU(object_new(cpu_model));
|
||||
env = &cpu->env;
|
||||
|
||||
if (!inited) {
|
||||
inited = 1;
|
||||
m68k_tcg_init();
|
||||
|
@ -176,21 +122,18 @@ CPUM68KState *cpu_m68k_init(const char *cpu_model)
|
|||
|
||||
env->cpu_model_str = cpu_model;
|
||||
|
||||
if (cpu_m68k_set_model(env, cpu_model) < 0) {
|
||||
cpu_m68k_close(env);
|
||||
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_state_reset(env);
|
||||
cpu_reset(ENV_GET_CPU(env));
|
||||
qemu_init_vcpu(env);
|
||||
return env;
|
||||
}
|
||||
|
||||
void cpu_m68k_close(CPUM68KState *env)
|
||||
{
|
||||
g_free(env);
|
||||
}
|
||||
|
||||
void cpu_m68k_flush_flags(CPUM68KState *env, int cc_op)
|
||||
{
|
||||
int flags;
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* QEMU MIPS 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_MIPS_CPU_QOM_H
|
||||
#define QEMU_MIPS_CPU_QOM_H
|
||||
|
||||
#include "qemu/cpu.h"
|
||||
|
||||
#ifdef TARGET_MIPS64
|
||||
#define TYPE_MIPS_CPU "mips64-cpu"
|
||||
#else
|
||||
#define TYPE_MIPS_CPU "mips-cpu"
|
||||
#endif
|
||||
|
||||
#define MIPS_CPU_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(MIPSCPUClass, (klass), TYPE_MIPS_CPU)
|
||||
#define MIPS_CPU(obj) \
|
||||
OBJECT_CHECK(MIPSCPU, (obj), TYPE_MIPS_CPU)
|
||||
#define MIPS_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(MIPSCPUClass, (obj), TYPE_MIPS_CPU)
|
||||
|
||||
/**
|
||||
* MIPSCPUClass:
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A MIPS CPU model.
|
||||
*/
|
||||
typedef struct MIPSCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} MIPSCPUClass;
|
||||
|
||||
/**
|
||||
* MIPSCPU:
|
||||
* @env: #CPUMIPSState
|
||||
*
|
||||
* A MIPS CPU.
|
||||
*/
|
||||
typedef struct MIPSCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUMIPSState env;
|
||||
} MIPSCPU;
|
||||
|
||||
static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env)
|
||||
{
|
||||
return MIPS_CPU(container_of(env, MIPSCPU, env));
|
||||
}
|
||||
|
||||
#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e))
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* QEMU MIPS 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>
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
||||
/* CPUClass::reset() */
|
||||
static void mips_cpu_reset(CPUState *s)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(s);
|
||||
MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
mcc->parent_reset(s);
|
||||
|
||||
cpu_state_reset(env);
|
||||
}
|
||||
|
||||
static void mips_cpu_initfn(Object *obj)
|
||||
{
|
||||
MIPSCPU *cpu = MIPS_CPU(obj);
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
cpu_exec_init(env);
|
||||
}
|
||||
|
||||
static void mips_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
MIPSCPUClass *mcc = MIPS_CPU_CLASS(c);
|
||||
CPUClass *cc = CPU_CLASS(c);
|
||||
|
||||
mcc->parent_reset = cc->reset;
|
||||
cc->reset = mips_cpu_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo mips_cpu_type_info = {
|
||||
.name = TYPE_MIPS_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(MIPSCPU),
|
||||
.instance_init = mips_cpu_initfn,
|
||||
.abstract = false,
|
||||
.class_size = sizeof(MIPSCPUClass),
|
||||
.class_init = mips_cpu_class_init,
|
||||
};
|
||||
|
||||
static void mips_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&mips_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(mips_cpu_register_types)
|
|
@ -476,6 +476,8 @@ struct CPUMIPSState {
|
|||
struct QEMUTimer *timer; /* Internal timer */
|
||||
};
|
||||
|
||||
#include "cpu-qom.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
int no_mmu_map_address (CPUMIPSState *env, target_phys_addr_t *physical, int *prot,
|
||||
target_ulong address, int rw, int access_type);
|
||||
|
|
|
@ -12691,17 +12691,18 @@ static void mips_tcg_init(void)
|
|||
|
||||
CPUMIPSState *cpu_mips_init (const char *cpu_model)
|
||||
{
|
||||
MIPSCPU *cpu;
|
||||
CPUMIPSState *env;
|
||||
const mips_def_t *def;
|
||||
|
||||
def = cpu_mips_find_by_name(cpu_model);
|
||||
if (!def)
|
||||
return NULL;
|
||||
env = g_malloc0(sizeof(CPUMIPSState));
|
||||
cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
|
||||
env = &cpu->env;
|
||||
env->cpu_model = def;
|
||||
env->cpu_model_str = cpu_model;
|
||||
|
||||
cpu_exec_init(env);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
mmu_init(env, def);
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* QEMU SuperH 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_SUPERH_CPU_QOM_H
|
||||
#define QEMU_SUPERH_CPU_QOM_H
|
||||
|
||||
#include "qemu/cpu.h"
|
||||
|
||||
#define TYPE_SUPERH_CPU "superh-cpu"
|
||||
|
||||
#define SUPERH_CPU_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(SuperHCPUClass, (klass), TYPE_SUPERH_CPU)
|
||||
#define SUPERH_CPU(obj) \
|
||||
OBJECT_CHECK(SuperHCPU, (obj), TYPE_SUPERH_CPU)
|
||||
#define SUPERH_CPU_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(SuperHCPUClass, (obj), TYPE_SUPERH_CPU)
|
||||
|
||||
/**
|
||||
* SuperHCPUClass:
|
||||
* @parent_reset: The parent class' reset handler.
|
||||
*
|
||||
* A SuperH CPU model.
|
||||
*/
|
||||
typedef struct SuperHCPUClass {
|
||||
/*< private >*/
|
||||
CPUClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
void (*parent_reset)(CPUState *cpu);
|
||||
} SuperHCPUClass;
|
||||
|
||||
/**
|
||||
* SuperHCPU:
|
||||
* @env: #CPUSH4State
|
||||
*
|
||||
* A SuperH CPU.
|
||||
*/
|
||||
typedef struct SuperHCPU {
|
||||
/*< private >*/
|
||||
CPUState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
CPUSH4State env;
|
||||
} SuperHCPU;
|
||||
|
||||
static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env)
|
||||
{
|
||||
return SUPERH_CPU(container_of(env, SuperHCPU, env));
|
||||
}
|
||||
|
||||
#define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e))
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* QEMU SuperH CPU
|
||||
*
|
||||
* Copyright (c) 2005 Samuel Tardieu
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
||||
/* CPUClass::reset() */
|
||||
static void superh_cpu_reset(CPUState *s)
|
||||
{
|
||||
SuperHCPU *cpu = SUPERH_CPU(s);
|
||||
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu);
|
||||
CPUSH4State *env = &cpu->env;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
||||
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
||||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
scc->parent_reset(s);
|
||||
|
||||
memset(env, 0, offsetof(CPUSH4State, breakpoints));
|
||||
tlb_flush(env, 1);
|
||||
|
||||
env->pc = 0xA0000000;
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
|
||||
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
|
||||
#else
|
||||
env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
|
||||
env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
|
||||
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
|
||||
set_flush_to_zero(1, &env->fp_status);
|
||||
#endif
|
||||
set_default_nan_mode(1, &env->fp_status);
|
||||
}
|
||||
|
||||
static void superh_cpu_initfn(Object *obj)
|
||||
{
|
||||
SuperHCPU *cpu = SUPERH_CPU(obj);
|
||||
CPUSH4State *env = &cpu->env;
|
||||
|
||||
cpu_exec_init(env);
|
||||
|
||||
env->movcal_backup_tail = &(env->movcal_backup);
|
||||
}
|
||||
|
||||
static void superh_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
CPUClass *cc = CPU_CLASS(oc);
|
||||
SuperHCPUClass *scc = SUPERH_CPU_CLASS(oc);
|
||||
|
||||
scc->parent_reset = cc->reset;
|
||||
cc->reset = superh_cpu_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo superh_cpu_type_info = {
|
||||
.name = TYPE_SUPERH_CPU,
|
||||
.parent = TYPE_CPU,
|
||||
.instance_size = sizeof(SuperHCPU),
|
||||
.instance_init = superh_cpu_initfn,
|
||||
.abstract = false,
|
||||
.class_size = sizeof(SuperHCPUClass),
|
||||
.class_init = superh_cpu_class_init,
|
||||
};
|
||||
|
||||
static void superh_cpu_register_types(void)
|
||||
{
|
||||
type_register_static(&superh_cpu_type_info);
|
||||
}
|
||||
|
||||
type_init(superh_cpu_register_types)
|
|
@ -189,6 +189,8 @@ typedef struct CPUSH4State {
|
|||
memory_content **movcal_backup_tail;
|
||||
} CPUSH4State;
|
||||
|
||||
#include "cpu-qom.h"
|
||||
|
||||
CPUSH4State *cpu_sh4_init(const char *cpu_model);
|
||||
int cpu_sh4_exec(CPUSH4State * s);
|
||||
int cpu_sh4_signal_handler(int host_signum, void *pinfo,
|
||||
|
|
|
@ -180,25 +180,7 @@ void cpu_dump_state(CPUSH4State * env, FILE * f,
|
|||
|
||||
void cpu_state_reset(CPUSH4State *env)
|
||||
{
|
||||
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
|
||||
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
|
||||
log_cpu_state(env, 0);
|
||||
}
|
||||
|
||||
memset(env, 0, offsetof(CPUSH4State, breakpoints));
|
||||
tlb_flush(env, 1);
|
||||
|
||||
env->pc = 0xA0000000;
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
|
||||
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
|
||||
#else
|
||||
env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
|
||||
env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
|
||||
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
|
||||
set_flush_to_zero(1, &env->fp_status);
|
||||
#endif
|
||||
set_default_nan_mode(1, &env->fp_status);
|
||||
cpu_reset(ENV_GET_CPU(env));
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -267,19 +249,19 @@ static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
|
|||
|
||||
CPUSH4State *cpu_sh4_init(const char *cpu_model)
|
||||
{
|
||||
SuperHCPU *cpu;
|
||||
CPUSH4State *env;
|
||||
const sh4_def_t *def;
|
||||
|
||||
def = cpu_sh4_find_by_name(cpu_model);
|
||||
if (!def)
|
||||
return NULL;
|
||||
env = g_malloc0(sizeof(CPUSH4State));
|
||||
cpu = SUPERH_CPU(object_new(TYPE_SUPERH_CPU));
|
||||
env = &cpu->env;
|
||||
env->features = def->features;
|
||||
cpu_exec_init(env);
|
||||
env->movcal_backup_tail = &(env->movcal_backup);
|
||||
sh4_translate_init();
|
||||
env->cpu_model_str = cpu_model;
|
||||
cpu_state_reset(env);
|
||||
cpu_reset(CPU(cpu));
|
||||
cpu_register(env, def);
|
||||
qemu_init_vcpu(env);
|
||||
return env;
|
||||
|
|
Loading…
Reference in New Issue