qemu-devel
[Top][All Lists]
Advanced

[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);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]