--- ./hw/mips_r4k.c_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./hw/mips_r4k.c 2006-07-08 07:16:45.000000000 +0200 @@ -189,10 +189,10 @@ CPUReadMemoryFunc *io_read[] = { &io_readl, }; -void mips_r4k_init (int ram_size, int vga_ram_size, int boot_device, - DisplayState *ds, const char **fd_filename, int snapshot, - const char *kernel_filename, const char *kernel_cmdline, - const char *initrd_filename) +void mips_r4kc_init (int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) { char buf[1024]; int64_t entry = 0; @@ -203,6 +203,7 @@ void mips_r4k_init (int ram_size, int vg long kernel_size; env = cpu_init(); + cpu_mips_set_model(env, MIPS_R4Kc); register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); /* allocate RAM */ @@ -284,8 +285,8 @@ void mips_r4k_init (int ram_size, int vg } } -QEMUMachine mips_machine = { - "mips", - "mips r4k platform", - mips_r4k_init, +QEMUMachine mips_r4kc_machine = { + "r4kc", + "mips r4kc platform", + mips_r4kc_init, }; --- ./vl.h_orig 2006-07-08 07:16:51.000000000 +0200 +++ ./vl.h 2006-07-08 07:16:45.000000000 +0200 @@ -917,7 +917,7 @@ extern QEMUMachine core99_machine; extern QEMUMachine heathrow_machine; /* mips_r4k.c */ -extern QEMUMachine mips_machine; +extern QEMUMachine mips_r4kc_machine; /* shix.c */ extern QEMUMachine shix_machine; --- ./target-mips/cpu.h_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./target-mips/cpu.h 2006-07-08 07:23:52.000000000 +0200 @@ -210,6 +210,8 @@ struct CPUMIPSState { int bcond; /* Branch condition (if needed) */ int halted; /* TRUE if the CPU is in suspend state */ + + uint32_t features; /* Internal CPU feature flags */ CPU_COMMON }; @@ -275,5 +277,30 @@ enum { int cpu_mips_exec(CPUMIPSState *s); CPUMIPSState *cpu_mips_init(void); uint32_t cpu_mips_get_clock (void); +void cpu_mips_set_model(CPUMIPSState *env, uint32_t id); + +enum mips_features { + MIPS_FEATURE_R4K_EXT = 0x1, /* instruction set extension for MIPS R4K */ + MIPS_FEATURE_NEC_VR5400 = 0x2, /* instruction set extension for NEC VR5400 CPUs */ + MIPS_FEATURE_FPU = 0x4, /* floating point instruction set */ +}; + +#ifdef MIPS_USES_R4K_EXT +#define mips_uses_r4k_ext() (env->features & MIPS_FEATURE_R4K_EXT) +#else +#define mips_uses_r4k_ext() 0 +#endif + +#ifdef MIPS_USES_NEC_VR5400 +#define mips_uses_nec_vr5400() (env->features & MIPS_FEATURE_NEC_VR5400) +#else +#define mips_uses_nec_vr5400() 0 +#endif + +#ifdef MIPS_USES_FPU +#define mips_uses_fpu() (env->features & MIPS_FEATURE_FPU) +#else +#define mips_uses_fpu() 0 +#endif #endif /* !defined (__MIPS_CPU_H__) */ --- ./target-mips/translate.c_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./target-mips/translate.c 2006-07-08 07:22:48.000000000 +0200 @@ -1887,7 +1887,7 @@ static void gen_blikely(DisasContext *ct gen_set_label(l1); } -static void decode_opc (DisasContext *ctx) +static void decode_opc (CPUState *env, DisasContext *ctx) { int32_t offset; int rs, rt, rd, sa; @@ -1927,7 +1927,17 @@ static void decode_opc (DisasContext *ct gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt); break; case 0x18 ... 0x1B: /* MULT / DIV */ - gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt); + if(!sa) { + gen_muldiv(ctx, op1 | EXT_SPECIAL, rs, rt); + } else { + if(mips_uses_nec_vr5400()) { + op1 = ctx->opcode & 0x7FF; + /* tbd: call handler for special NEC instructions */ + } else { + MIPS_INVAL("NEC extension"); + generate_exception(ctx, EXCP_RI); + } + } break; case 0x08 ... 0x09: /* Jumps */ gen_compute_branch(ctx, op1 | EXT_SPECIAL, rs, rd, sa); @@ -1985,19 +1995,32 @@ static void decode_opc (DisasContext *ct case 0x1C: /* Special2 opcode */ op1 = ctx->opcode & 0x3F; switch (op1) { -#if defined (MIPS_USES_R4K_EXT) /* Those instructions are not part of MIPS32 core */ case 0x00 ... 0x01: /* Multiply and add/sub */ case 0x04 ... 0x05: - gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt); + if(mips_uses_r4k_ext()) { + gen_muldiv(ctx, op1 | EXT_SPECIAL2, rs, rt); + } else { + MIPS_INVAL("r4k extension"); + generate_exception(ctx, EXCP_RI); + } break; case 0x02: /* MUL */ - gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt); + if(mips_uses_r4k_ext()) { + gen_arith(ctx, op1 | EXT_SPECIAL2, rd, rs, rt); + } else { + MIPS_INVAL("r4k extension"); + generate_exception(ctx, EXCP_RI); + } break; case 0x20 ... 0x21: /* CLO / CLZ */ - gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs); + if(mips_uses_r4k_ext()) { + gen_cl(ctx, op1 | EXT_SPECIAL2, rd, rs); + } else { + MIPS_INVAL("r4k extension"); + generate_exception(ctx, EXCP_RI); + } break; -#endif case 0x3F: /* SDBBP */ /* XXX: not clear which exception should be raised * when in debug mode... @@ -2074,43 +2097,43 @@ static void decode_opc (DisasContext *ct case 0x35: /* LDC1 */ case 0x39: /* SWC1 */ case 0x3D: /* SDC1 */ -#if defined(MIPS_USES_FPU) - gen_op_cp1_enabled(); - gen_flt_ldst(ctx, op, rt, rs, imm); -#else - generate_exception_err(ctx, EXCP_CpU, 1); -#endif + if(mips_uses_fpu()) { + gen_op_cp1_enabled(); + gen_flt_ldst(ctx, op, rt, rs, imm); + } else { + generate_exception_err(ctx, EXCP_CpU, 1); + } break; case 0x11: /* CP1 opcode */ -#if defined(MIPS_USES_FPU) - gen_op_cp1_enabled(); - op1 = ((ctx->opcode >> 21) & 0x1F); - switch (op1) { - case 0x00: /* mfc1 */ - case 0x02: /* cfc1 */ - case 0x04: /* mtc1 */ - case 0x06: /* ctc1 */ - gen_cp1(ctx, op1 | EXT_CP1, rt, rd); - break; - case 0x08: /* bc */ - gen_compute_branch1(ctx, rt, imm << 2); - return; - case 0x10: /* 16: fmt=single fp */ - case 0x11: /* 17: fmt=double fp */ - case 0x14: /* 20: fmt=32bit fixed */ - case 0x15: /* 21: fmt=64bit fixed */ - gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f); - break; - default: - generate_exception_err(ctx, EXCP_RI, 1); + if(mips_uses_fpu()) { + gen_op_cp1_enabled(); + op1 = ((ctx->opcode >> 21) & 0x1F); + switch (op1) { + case 0x00: /* mfc1 */ + case 0x02: /* cfc1 */ + case 0x04: /* mtc1 */ + case 0x06: /* ctc1 */ + gen_cp1(ctx, op1 | EXT_CP1, rt, rd); + break; + case 0x08: /* bc */ + gen_compute_branch1(ctx, rt, imm << 2); + return; + case 0x10: /* 16: fmt=single fp */ + case 0x11: /* 17: fmt=double fp */ + case 0x14: /* 20: fmt=32bit fixed */ + case 0x15: /* 21: fmt=64bit fixed */ + gen_farith(ctx, op1, rt, rd, sa, ctx->opcode & 0x3f); + break; + default: + generate_exception_err(ctx, EXCP_RI, 1); + break; + } break; + } else { + generate_exception_err(ctx, EXCP_CpU, 1); } break; -#else - generate_exception_err(ctx, EXCP_CpU, 1); -#endif - break; /* COP2. */ case 0x32: /* LWC2 */ @@ -2262,7 +2285,7 @@ int gen_intermediate_code_internal (CPUS gen_opc_instr_start[lj] = 1; } ctx.opcode = ldl_code(ctx.pc); - decode_opc(&ctx); + decode_opc(env, &ctx); ctx.pc += 4; if (env->singlestep_enabled) @@ -2400,44 +2423,3 @@ void cpu_dump_state (CPUState *env, FILE fpu_dump_state(env, f, cpu_fprintf, flags); #endif } - -CPUMIPSState *cpu_mips_init (void) -{ - CPUMIPSState *env; - - env = qemu_mallocz(sizeof(CPUMIPSState)); - if (!env) - return NULL; - cpu_exec_init(env); - tlb_flush(env, 1); - /* Minimal init */ - env->PC = 0xBFC00000; -#if defined (MIPS_USES_R4K_TLB) - env->CP0_random = MIPS_TLB_NB - 1; -#endif - env->CP0_Wired = 0; - env->CP0_Config0 = MIPS_CONFIG0; -#if defined (MIPS_CONFIG1) - env->CP0_Config1 = MIPS_CONFIG1; -#endif -#if defined (MIPS_CONFIG2) - env->CP0_Config2 = MIPS_CONFIG2; -#endif -#if defined (MIPS_CONFIG3) - env->CP0_Config3 = MIPS_CONFIG3; -#endif - env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); - env->CP0_WatchLo = 0; - 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; - env->exception_index = EXCP_NONE; -#if defined(CONFIG_USER_ONLY) - env->hflags |= MIPS_HFLAG_UM; -#endif -#ifdef MIPS_USES_FPU - env->fcr0 = MIPS_FCR0; -#endif - return env; -} --- ./target-mips/helper.c_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./target-mips/helper.c 2006-07-08 07:22:04.000000000 +0200 @@ -430,3 +430,68 @@ void do_interrupt (CPUState *env) } env->exception_index = EXCP_NONE; } + +CPUMIPSState *cpu_mips_init (void) +{ + CPUMIPSState *env; + + env = qemu_mallocz(sizeof(CPUMIPSState)); + if (!env) + return NULL; + cpu_exec_init(env); + tlb_flush(env, 1); + /* Minimal init */ + env->PC = 0xBFC00000; +#if defined (MIPS_USES_R4K_TLB) + env->CP0_random = MIPS_TLB_NB - 1; +#endif + env->CP0_Wired = 0; + env->CP0_Config0 = MIPS_CONFIG0; +#if defined (MIPS_CONFIG1) + env->CP0_Config1 = MIPS_CONFIG1; +#endif +#if defined (MIPS_CONFIG2) + env->CP0_Config2 = MIPS_CONFIG2; +#endif +#if defined (MIPS_CONFIG3) + env->CP0_Config3 = MIPS_CONFIG3; +#endif + env->CP0_Status = (1 << CP0St_CU0) | (1 << CP0St_BEV); + env->CP0_WatchLo = 0; + env->hflags = MIPS_HFLAG_ERL; + /* Count register increments in debug mode, EJTAG version 1 */ + env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER); + env->exception_index = EXCP_NONE; +#if defined(CONFIG_USER_ONLY) + env->hflags |= MIPS_HFLAG_UM; +#endif + return env; +} + +static inline void set_feature(CPUMIPSState *env, int feature) +{ + env->features |= feature; +} + +void cpu_mips_set_model(CPUMIPSState *env, uint32_t id) +{ + env->CP0_PRid = id; + env->features = 0; + switch (id) { + case MIPS_R4Kc: + set_feature(env, MIPS_FEATURE_R4K_EXT); + set_feature(env, MIPS_FEATURE_FPU); + break; + default: + cpu_abort(env, "Bad CPU ID: %x\n", id); + break; + } + + if(mips_uses_fpu()) { + env->fcr0 = MIPS_FCR0; +#if defined (MIPS_CONFIG1) + env->CP0_Config1 |= (1 << CP0C1_FP); +#endif + } +} + --- ./target-mips/mips-defs.h_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./target-mips/mips-defs.h 2006-07-08 07:16:45.000000000 +0200 @@ -9,10 +9,6 @@ #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 */ #define TARGET_LONG_BITS 32 /* real pages are variable size... */ @@ -40,28 +36,13 @@ /* 16 TLBs, 64 sets Icache, 16 bytes Icache line, 2-way Icache, * 64 sets Dcache, 16 bytes Dcache line, 2-way Dcache, * no performance counters, watch registers present, no code compression, - * EJTAG present, FPU enable bit depending on MIPS_USES_FPU + * EJTAG present, FPU bit is set depending on runtime FPU selection */ #define MIPS_CONFIG1 \ ((15 << CP0C1_MMU) | \ (0x000 << CP0C1_IS) | (0x3 << CP0C1_IL) | (0x01 << CP0C1_IA) | \ (0x000 << CP0C1_DS) | (0x3 << CP0C1_DL) | (0x01 << CP0C1_DA) | \ (0 << CP0C1_PC) | (1 << CP0C1_WR) | (0 << CP0C1_CA) | \ - (1 << CP0C1_EP) | (MIPS_USES_FPU << CP0C1_FP)) -#elif (MIPS_CPU == MIPS_R4Kp) -/* 32 bits target */ -#define TARGET_LONG_BITS 32 -/* 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" -/* Remainder for other flags */ -//#define TARGET_MIPS64 -//#define MIPS_USES_FPU -#endif + (1 << CP0C1_EP)) #endif /* !defined (__QEMU_MIPS_DEFS_H__) */ --- ./vl.c_orig 2006-07-08 07:16:50.000000000 +0200 +++ ./vl.c 2006-07-08 07:16:45.000000000 +0200 @@ -5455,7 +5455,7 @@ void register_machines(void) qemu_register_machine(&core99_machine); qemu_register_machine(&prep_machine); #elif defined(TARGET_MIPS) - qemu_register_machine(&mips_machine); + qemu_register_machine(&mips_r4kc_machine); #elif defined(TARGET_SPARC) #ifdef TARGET_SPARC64 qemu_register_machine(&sun4u_machine);