diff --git a/Changelog b/Changelog index b0123e1d33..1ecf09b2de 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,7 @@ - Tap device emulation for Solaris (Sittichai Palanisong) - Monitor multiplexing to several I/O channels (Jason Wessel) - ds1225y nvram support (Herve Poussineau) + - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau) version 0.9.0: diff --git a/Makefile.target b/Makefile.target index 9f7a804a4f..c0a79f9699 100644 --- a/Makefile.target +++ b/Makefile.target @@ -551,6 +551,7 @@ endif ifeq ($(TARGET_ARCH), mips) op.o: op.c op_template.c fop_template.c op_mem.c op_helper.o: op_helper_mem.c +translate.o: translate.c translate_init.c endif loader.o: loader.c elf_ops.h diff --git a/hw/mips_malta.c b/hw/mips_malta.c index d137658fbd..b215cd58a8 100644 --- a/hw/mips_malta.c +++ b/hw/mips_malta.c @@ -626,8 +626,20 @@ void mips_malta_init (int ram_size, int vga_ram_size, int boot_device, /* fdctrl_t *floppy_controller; */ MaltaFPGAState *malta_fpga; int ret; + mips_def_t *def; + /* init CPUs */ + if (cpu_model == NULL) { +#ifdef MIPS_HAS_MIPS64 + cpu_model = "R4000"; +#else + cpu_model = "4KEc"; +#endif + } + if (mips_find_by_name(cpu_model, &def) != 0) + def = NULL; env = cpu_init(); + cpu_mips_register(env, def); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c index 2a3b15af68..7709418c00 100644 --- a/hw/mips_r4k.c +++ b/hw/mips_r4k.c @@ -138,8 +138,20 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, CPUState *env; RTCState *rtc_state; int i; + mips_def_t *def; + /* init CPUs */ + if (cpu_model == NULL) { +#ifdef MIPS_HAS_MIPS64 + cpu_model = "R4000"; +#else + cpu_model = "4KEc"; +#endif + } + if (mips_find_by_name(cpu_model, &def) != 0) + def = NULL; env = cpu_init(); + cpu_mips_register(env, def); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); qemu_register_reset(main_cpu_reset, env); @@ -148,7 +160,7 @@ void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, if (!mips_qemu_iomemtype) { mips_qemu_iomemtype = cpu_register_io_memory(0, mips_qemu_read, - mips_qemu_write, NULL); + mips_qemu_write, NULL); } cpu_register_physical_memory(0x1fbf0000, 0x10000, mips_qemu_iomemtype); diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 69335a0189..276910aaed 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -282,6 +282,11 @@ struct CPUMIPSState { struct QEMUTimer *timer; /* Internal timer */ }; +typedef struct mips_def_t mips_def_t; +int mips_find_by_name (const unsigned char *name, mips_def_t **def); +void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); +int cpu_mips_register (CPUMIPSState *env, mips_def_t *def); + #include "cpu-all.h" /* Memory access type : diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h index a78bef55ec..b0fc983969 100644 --- a/target-mips/mips-defs.h +++ b/target-mips/mips-defs.h @@ -6,26 +6,15 @@ /* If we want to use host float regs... */ //#define USE_HOST_FLOAT_REGS -#define MIPS_R4Kc 0x00018000 -#define MIPS_R4Kp 0x00018300 - -/* Emulate MIPS R4Kc for now */ -#define MIPS_CPU MIPS_R4Kc - -#if (MIPS_CPU == MIPS_R4Kc) /* 32 bits target */ #undef MIPS_HAS_MIPS64 //#define MIPS_HAS_MIPS64 1 /* real pages are variable size... */ #define TARGET_PAGE_BITS 12 -/* Uses MIPS R4Kx enhancements to MIPS32 architecture */ -#define MIPS_USES_R4K_EXT /* Uses MIPS R4Kc TLB model */ #define MIPS_USES_R4K_TLB #define MIPS_TLB_NB 16 #define MIPS_TLB_MAX 128 -/* basic FPU register support */ -#define MIPS_USES_FPU 1 /* Define a implementation number of 1. * Define a major version 1, minor version 0. */ @@ -63,21 +52,6 @@ ((0 << CP0C3_M) | (0 << CP0C3_DSPP) | (0 << CP0C3_LPA) | \ (0 << CP0C3_VEIC) | (0 << CP0C3_VInt) | (0 << CP0C3_SP) | \ (0 << CP0C3_MT) | (0 << CP0C3_SM) | (0 << CP0C3_TL)) -#elif (MIPS_CPU == MIPS_R4Kp) -/* 32 bits target */ -#undef MIPS_HAS_MIPS64 -/* real pages are variable size... */ -#define TARGET_PAGE_BITS 12 -/* Uses MIPS R4Kx enhancements to MIPS32 architecture */ -#define MIPS_USES_R4K_EXT -/* Uses MIPS R4Km FPM MMU model */ -#define MIPS_USES_R4K_FPM -#else -#error "MIPS CPU not defined" -/* Reminder for other flags */ -//#undef MIPS_HAS_MIPS64 -//#define MIPS_USES_FPU -#endif #ifdef MIPS_HAS_MIPS64 #define TARGET_LONG_BITS 64 diff --git a/target-mips/translate.c b/target-mips/translate.c index a9f7b75c46..75e30692a8 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -5283,12 +5283,6 @@ void cpu_reset (CPUMIPSState *env) env->CP0_Wired = 0; /* SMP not implemented */ env->CP0_EBase = 0x80000000; - env->CP0_Config0 = MIPS_CONFIG0; - env->CP0_Config1 = MIPS_CONFIG1; -#ifdef MIPS_USES_FPU - /* basic FPU register support */ - env->CP0_Config1 |= (1 << CP0C1_FP); -#endif env->CP0_Config2 = MIPS_CONFIG2; env->CP0_Config3 = MIPS_CONFIG3; env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL); @@ -5296,7 +5290,6 @@ void cpu_reset (CPUMIPSState *env) env->hflags = MIPS_HFLAG_ERL; /* Count register increments in debug mode, EJTAG version 1 */ env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); - env->CP0_PRid = MIPS_CPU; #endif env->exception_index = EXCP_NONE; #if defined(CONFIG_USER_ONLY) @@ -5308,3 +5301,5 @@ void cpu_reset (CPUMIPSState *env) env->SYNCI_Step = 16; env->CCRes = 2; } + +#include "translate_init.c" diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c new file mode 100644 index 0000000000..b7baff1871 --- /dev/null +++ b/target-mips/translate_init.c @@ -0,0 +1,97 @@ +/* + * MIPS emulation for qemu: CPU initialisation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2007 Herve Poussineau + * + * 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 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +struct mips_def_t { + const unsigned char *name; + int32_t CP0_PRid; + int32_t CP0_Config0; + int32_t CP0_Config1; +}; + +/*****************************************************************************/ +/* MIPS CPU definitions */ +static mips_def_t mips_defs[] = +{ +#ifndef MIPS_HAS_MIPS64 + { + .name = "4Kc", + .CP0_PRid = 0x00018000, + .CP0_Config0 = MIPS_CONFIG0, + .CP0_Config1 = MIPS_CONFIG1, + }, + { + .name = "4KEc", + .CP0_PRid = 0x00018400, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), + .CP0_Config1 = MIPS_CONFIG1, + }, + { + .name = "24Kf", + .CP0_PRid = 0x00019300, + .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), + }, +#else + { + .name = "R4000", + .CP0_PRid = 0x00000400, + .CP0_Config0 = MIPS_CONFIG0 | (0x2 << CP0C0_AT), + .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP), + }, +#endif +}; + +int mips_find_by_name (const unsigned char *name, mips_def_t **def) +{ + int i, ret; + + ret = -1; + *def = NULL; + for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) { + if (strcasecmp(name, mips_defs[i].name) == 0) { + *def = &mips_defs[i]; + ret = 0; + break; + } + } + + return ret; +} + +void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +{ + int i; + + for (i = 0; i < sizeof(mips_defs) / sizeof(mips_defs[0]); i++) { + (*cpu_fprintf)(f, "MIPS '%s'\n", + mips_defs[i].name); + } +} + +int cpu_mips_register (CPUMIPSState *env, mips_def_t *def) +{ + if (!def) + cpu_abort(env, "Unable to find MIPS CPU definition\n"); + env->CP0_PRid = def->CP0_PRid; + env->CP0_Config0 = def->CP0_Config0; + env->CP0_Config1 = def->CP0_Config1; + return 0; +} diff --git a/vl.c b/vl.c index cbf63167b2..fc0f8ff4c3 100644 --- a/vl.c +++ b/vl.c @@ -7009,6 +7009,8 @@ int main(int argc, char **argv) ppc_cpu_list(stdout, &fprintf); #elif defined(TARGET_ARM) arm_cpu_list(); +#elif defined(TARGET_MIPS) + mips_cpu_list(stdout, &fprintf); #endif exit(1); } else { diff --git a/vl.h b/vl.h index c7c7d73a0d..464bf899c0 100644 --- a/vl.h +++ b/vl.h @@ -713,6 +713,10 @@ typedef void IRQRequestFunc(void *opaque, int level); void ppc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); #endif +#if defined(TARGET_MIPS) +void mips_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); +#endif + /* ISA bus */ extern target_phys_addr_t isa_mem_base;