提交 61d25e15 编写于 作者: B Blue Swirl

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
......@@ -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
......
/*
* 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
/*
* 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,37 +25,52 @@
#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;
void m68k_cpu_list(FILE *f, fprintf_function cpu_fprintf)
/* Sort alphabetically, except for "any". */
static gint m68k_cpu_list_compare(gconstpointer a, gconstpointer b)
{
unsigned int i;
ObjectClass *class_a = (ObjectClass *)a;
ObjectClass *class_b = (ObjectClass *)b;
const char *name_a, *name_b;
for (i = 0; m68k_cpu_defs[i].name; i++) {
(*cpu_fprintf)(f, "%s\n", m68k_cpu_defs[i].name);
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)
{
M68kCPUListState s = {
.file = f,
.cpu_fprintf = cpu_fprintf,
};
GSList *list;
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)
{
if (n < 8) {
......@@ -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;
......
/*
* 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
/*
* 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
......
/*
* 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
/*
* 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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册