[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH] MIPS instruction set configuration
From: |
Dirk Behme |
Subject: |
Re: [Qemu-devel] [PATCH] MIPS instruction set configuration |
Date: |
Sat, 08 Jul 2006 08:15:59 +0200 |
User-agent: |
Mozilla Thunderbird 1.0.7 (X11/20050923) |
Fabrice Bellard wrote:
Dirk Behme wrote:
Fabrice Bellard wrote:
Each machine can add specific support for that (for example a -cpu
option). It is likely to come at least for the PC machines.
I add suggest one more parameter to cpu_mips_set_model() to specify
optional features. A function converting a CPU "string id" into an id
+ features would be interesting too.
Fabrice, do you will accept the patch if I remove the
MIPS_FEATURE_ISAx options and convert MIPS_FEATURE_NEC_EXT to
MIPS_FEATURE_NEC_VR5400 as described in my previous mail?
Yes. Even without I can accept it as it is better than what we
previously had.
Please find as promised in attachment the updated version of
this patch. It removes MIPS_FEATURE_ISAx for the moment and
renames MIPS_FEATURE_NEC_EXT to MIPS_FEATURE_NEC_VR5400.
Best regards
Dirk
--- ./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);