qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH][MIPS] Per-CPU instruction decoding implementation


From: Aurelien Jarno
Subject: [Qemu-devel] [PATCH][MIPS] Per-CPU instruction decoding implementation
Date: Wed, 19 Sep 2007 23:47:57 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

Hi all,

The patch below implements per-cpu decoding on the MIPS target. The 
supported instruction set is defined by a set of flags. It assumes that
MIPS2 instructions are always supported. It also removes the check for 
CP0C0_AT when setting MIPS_HFLAG_64 as it is now obsolete.

Cheers,
Aurelien

Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.43
diff -u -d -p -r1.43 cpu.h
--- target-mips/cpu.h   6 Sep 2007 00:18:14 -0000       1.43
+++ target-mips/cpu.h   19 Sep 2007 21:39:58 -0000
@@ -441,6 +441,7 @@ struct CPUMIPSState {
     int CCRes; /* Cycle count resolution/divisor */
     uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
     uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
+    int insn_flags; /* Supported instruction set */
 
 #ifdef CONFIG_USER_ONLY
     target_ulong tls_value;
Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.48
diff -u -d -p -r1.48 helper.c
--- target-mips/helper.c        17 Sep 2007 08:09:53 -0000      1.48
+++ target-mips/helper.c        19 Sep 2007 21:39:58 -0000
@@ -369,8 +369,7 @@ void do_interrupt (CPUState *env)
         }
     enter_debug_mode:
         env->hflags |= MIPS_HFLAG_DM;
-        if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-            env->hflags |= MIPS_HFLAG_64;
+        env->hflags |= MIPS_HFLAG_64;
         env->hflags &= ~MIPS_HFLAG_UM;
         /* EJTAG probe trap enable is not implemented... */
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
@@ -396,8 +395,7 @@ void do_interrupt (CPUState *env)
             env->CP0_ErrorEPC = env->PC[env->current_tc];
         }
         env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
-        if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-            env->hflags |= MIPS_HFLAG_64;
+        env->hflags |= MIPS_HFLAG_64;
         env->hflags &= ~MIPS_HFLAG_UM;
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -499,8 +497,7 @@ void do_interrupt (CPUState *env)
                 env->CP0_Cause &= ~(1 << CP0Ca_BD);
             }
             env->CP0_Status |= (1 << CP0St_EXL);
-            if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
-                env->hflags |= MIPS_HFLAG_64;
+            env->hflags |= MIPS_HFLAG_64;
             env->hflags &= ~MIPS_HFLAG_UM;
         }
         env->hflags &= ~MIPS_HFLAG_BMASK;
Index: target-mips/mips-defs.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/mips-defs.h,v
retrieving revision 1.15
diff -u -d -p -r1.15 mips-defs.h
--- target-mips/mips-defs.h     13 May 2007 13:49:43 -0000      1.15
+++ target-mips/mips-defs.h     19 Sep 2007 21:39:58 -0000
@@ -14,6 +14,35 @@
 #define TARGET_LONG_BITS 32
 #endif
 
+/* Masks used to mark instructions to indicate which ISA level they
+   were introduced in. */
+#define                INSN_MIPS3      0x00000001
+#define                INSN_MIPS4      0x00000002
+#define                INSN_MIPS5      0x00000004
+#define                INSN_MIPS32     0x00000008
+#define                INSN_MIPS32R2   0x00000010
+#define                INSN_MIPS64     0x00000020
+#define                INSN_MIPS64R2   0x00000040
+
+/* MIPS ASE */
+#define                INSN_MIPS16     0x00000100
+#define                INSN_MIPS3D     0x00000200
+#define                INSN_MDMX       0x00000400
+
+/* Chip specific instructions.   */
+/* Currently void */
+
+/* MIPS CPU defines.  */
+#define                CPU_MIPS3       (INSN_MIPS3)
+#define                CPU_MIPS4       (CPU_MIPS3 | INSN_MIPS4)
+#define                CPU_MIPS5       (CPU_MIPS4 | INSN_MIPS5)
+
+#define                CPU_MIPS32      (INSN_MIPS32)
+#define                CPU_MIPS64      (CPU_MIPS5 | CPU_MIPS32 | INSN_MIPS64)
+
+#define                CPU_MIPS32R2    (CPU_MIPS32 | INSN_MIPS32R2)
+#define                CPU_MIPS64R2    (CPU_MIPS64 | CPU_MIPS32R2 | 
INSN_MIPS64R2)
+
 /* Strictly follow the architecture standard:
    - Disallow "special" instruction handling for PMON/SPIM.
    Note that we still maintain Count/Compare to match the host clock. */
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.71
diff -u -d -p -r1.71 op.c
--- target-mips/op.c    16 Sep 2007 21:08:04 -0000      1.71
+++ target-mips/op.c    19 Sep 2007 21:39:58 -0000
@@ -1847,10 +1847,9 @@ void op_mtc0_status (void)
         (val & (1 << CP0St_UM)))
         env->hflags |= MIPS_HFLAG_UM;
 #ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
+    if  ((env->hflags & MIPS_HFLAG_UM) &&
         !(val & (1 << CP0St_PX)) &&
-        !(val & (1 << CP0St_UX))))
+        !(val & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
     if (val & (1 << CP0St_CU1))
@@ -1906,7 +1905,7 @@ void op_mtc0_cause (void)
 {
     uint32_t mask = 0x00C00300;
 
-    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
+    if (env->insn_flags & INSN_MIPS32R2)
         mask |= 1 << CP0Ca_DC;
 
     env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
@@ -3014,10 +3013,9 @@ void op_eret (void)
         (env->CP0_Status & (1 << CP0St_UM)))
         env->hflags |= MIPS_HFLAG_UM;
 #ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
+     if ((env->hflags & MIPS_HFLAG_UM) &&
         !(env->CP0_Status & (1 << CP0St_PX)) &&
-        !(env->CP0_Status & (1 << CP0St_UX))))
+        !(env->CP0_Status & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
     if (loglevel & CPU_LOG_EXEC)
@@ -3038,10 +3036,9 @@ void op_deret (void)
         (env->CP0_Status & (1 << CP0St_UM)))
         env->hflags |= MIPS_HFLAG_UM;
 #ifdef TARGET_MIPS64
-    if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
-        ((env->hflags & MIPS_HFLAG_UM) &&
+    if ((env->hflags & MIPS_HFLAG_UM) &&
         !(env->CP0_Status & (1 << CP0St_PX)) &&
-        !(env->CP0_Status & (1 << CP0St_UX))))
+        !(env->CP0_Status & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
     if (loglevel & CPU_LOG_EXEC)
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.99
diff -u -d -p -r1.99 translate.c
--- target-mips/translate.c     17 Sep 2007 08:09:53 -0000      1.99
+++ target-mips/translate.c     19 Sep 2007 21:39:59 -0000
@@ -142,7 +142,7 @@ enum {
     OPC_SRL      = 0x02 | OPC_SPECIAL, /* also ROTR */
     OPC_SRA      = 0x03 | OPC_SPECIAL,
     OPC_SLLV     = 0x04 | OPC_SPECIAL,
-    OPC_SRLV     = 0x06 | OPC_SPECIAL,
+    OPC_SRLV     = 0x06 | OPC_SPECIAL, /* also ROTRV */
     OPC_SRAV     = 0x07 | OPC_SPECIAL,
     OPC_DSLLV    = 0x14 | OPC_SPECIAL,
     OPC_DSRLV    = 0x16 | OPC_SPECIAL, /* also DROTRV */
@@ -761,10 +761,10 @@ void check_cp1_registers(DisasContext *c
 }
 
 /* This code generates a "reserved instruction" exception if the
-   CPU is not a MIPS R2 (or higher) CPU. */
-static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
+   CPU does not support the instruction set corresponding to flags. */
+static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
 {
-    if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
+    if (unlikely(!(env->insn_flags & flags)))
         generate_exception(ctx, EXCP_RI);
 }
 
@@ -776,6 +776,14 @@ static inline void check_mips_mt(CPUStat
         generate_exception(ctx, EXCP_RI);
 }
 
+/* This code generates a "reserved instruction" exception if 64-bit
+   instructions are not enabled. */
+static inline void check_mips_64(DisasContext *ctx)
+{
+    if (!(ctx->hflags & MIPS_HFLAG_64))
+        generate_exception(ctx, EXCP_RI);
+}
+
 #if defined(CONFIG_USER_ONLY)
 #define op_ldst(name)        gen_op_##name##_raw()
 #define OP_LD_TABLE(width)
@@ -1024,8 +1032,8 @@ static void gen_flt_ldst (DisasContext *
 }
 
 /* Arithmetic with immediate operand */
-static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
-                           int rs, int16_t imm)
+static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
+                           int rt, int rs, int16_t imm)
 {
     target_ulong uimm;
     const char *opn = "imm arith";
@@ -1132,8 +1140,14 @@ static void gen_arith_imm (DisasContext 
             opn = "srl";
             break;
         case 1:
-            gen_op_rotr();
-            opn = "rotr";
+            /* rotr is decoded as srl on non-R2 CPUs */
+            if (env->insn_flags & INSN_MIPS32R2) {
+                gen_op_rotr();
+                opn = "rotr";
+            } else {
+                gen_op_srl();
+                opn = "srl";
+            }
             break;
         default:
             MIPS_INVAL("invalid srl flag");
@@ -1157,8 +1171,14 @@ static void gen_arith_imm (DisasContext 
             opn = "dsrl";
             break;
         case 1:
-            gen_op_drotr();
-            opn = "drotr";
+            /* drotr is decoded as dsrl on non-R2 CPUs */
+            if (env->insn_flags & INSN_MIPS32R2) {
+                gen_op_drotr();
+                opn = "drotr";
+            } else {
+                gen_op_dsrl();
+                opn = "dsrl";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrl flag");
@@ -1181,8 +1201,14 @@ static void gen_arith_imm (DisasContext 
             opn = "dsrl32";
             break;
         case 1:
-            gen_op_drotr32();
-            opn = "drotr32";
+            /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
+            if (env->insn_flags & INSN_MIPS32R2) {
+                gen_op_drotr32();
+                opn = "drotr32";
+            } else {
+                gen_op_dsrl32();
+                opn = "dsrl32";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrl32 flag");
@@ -1201,7 +1227,7 @@ static void gen_arith_imm (DisasContext 
 }
 
 /* Arithmetic */
-static void gen_arith (DisasContext *ctx, uint32_t opc,
+static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
                        int rd, int rs, int rt)
 {
     const char *opn = "arith";
@@ -1305,8 +1331,14 @@ static void gen_arith (DisasContext *ctx
             opn = "srlv";
             break;
         case 1:
-            gen_op_rotrv();
-            opn = "rotrv";
+            /* rotrv is decoded as srlv on non-R2 CPUs */
+            if (env->insn_flags & INSN_MIPS32R2) {
+                gen_op_rotrv();
+                opn = "rotrv";
+            } else {
+                gen_op_srlv();
+                opn = "srlv";
+            }
             break;
         default:
             MIPS_INVAL("invalid srlv flag");
@@ -1330,8 +1362,14 @@ static void gen_arith (DisasContext *ctx
             opn = "dsrlv";
             break;
         case 1:
-            gen_op_drotrv();
-            opn = "drotrv";
+            /* drotrv is decoded as dsrlv on non-R2 CPUs */
+            if (env->insn_flags & INSN_MIPS32R2) {
+                gen_op_drotrv();
+                opn = "drotrv";
+            } else {
+                gen_op_dsrlv();
+                opn = "dsrlv";
+            }
             break;
         default:
             MIPS_INVAL("invalid dsrlv flag");
@@ -1910,6 +1948,9 @@ static void gen_mfc0 (CPUState *env, Dis
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, INSN_MIPS32);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -2057,7 +2098,7 @@ static void gen_mfc0 (CPUState *env, Dis
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2072,22 +2113,27 @@ static void gen_mfc0 (CPUState *env, Dis
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -2098,7 +2144,7 @@ static void gen_mfc0 (CPUState *env, Dis
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -2155,17 +2201,17 @@ static void gen_mfc0 (CPUState *env, Dis
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsmap();
             rn = "SRSMap";
             break;
@@ -2200,7 +2246,7 @@ static void gen_mfc0 (CPUState *env, Dis
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -2274,8 +2320,7 @@ static void gen_mfc0 (CPUState *env, Dis
         switch (sel) {
         case 0:
 #ifdef TARGET_MIPS64
-           if (!(ctx->hflags & MIPS_HFLAG_64))
-               goto die;
+            check_insn(env, ctx, INSN_MIPS64);
             gen_op_mfc0_xcontext();
             rn = "XContext";
             break;
@@ -2471,6 +2516,9 @@ static void gen_mtc0 (CPUState *env, Dis
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, INSN_MIPS32);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -2618,7 +2666,7 @@ static void gen_mtc0 (CPUState *env, Dis
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -2633,22 +2681,27 @@ static void gen_mtc0 (CPUState *env, Dis
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -2659,7 +2712,7 @@ static void gen_mtc0 (CPUState *env, Dis
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -2717,21 +2770,21 @@ static void gen_mtc0 (CPUState *env, Dis
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -2770,7 +2823,7 @@ static void gen_mtc0 (CPUState *env, Dis
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -2849,8 +2902,7 @@ static void gen_mtc0 (CPUState *env, Dis
         switch (sel) {
         case 0:
 #ifdef TARGET_MIPS64
-           if (!(ctx->hflags & MIPS_HFLAG_64))
-               goto die;
+            check_insn(env, ctx, INSN_MIPS64);
             gen_op_mtc0_xcontext();
             rn = "XContext";
             break;
@@ -3064,6 +3116,9 @@ static void gen_dmfc0 (CPUState *env, Di
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, INSN_MIPS64);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -3211,7 +3266,7 @@ static void gen_dmfc0 (CPUState *env, Di
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3226,22 +3281,27 @@ static void gen_dmfc0 (CPUState *env, Di
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -3252,7 +3312,7 @@ static void gen_dmfc0 (CPUState *env, Di
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_hwrena();
             rn = "HWREna";
             break;
@@ -3309,17 +3369,17 @@ static void gen_dmfc0 (CPUState *env, Di
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_intctl();
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsctl();
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_srsmap();
             rn = "SRSMap";
             break;
@@ -3354,7 +3414,7 @@ static void gen_dmfc0 (CPUState *env, Di
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mfc0_ebase();
             rn = "EBase";
             break;
@@ -3418,6 +3478,7 @@ static void gen_dmfc0 (CPUState *env, Di
     case 20:
         switch (sel) {
         case 0:
+            check_insn(env, ctx, INSN_MIPS64);
             gen_op_dmfc0_xcontext();
             rn = "XContext";
             break;
@@ -3612,6 +3673,9 @@ static void gen_dmtc0 (CPUState *env, Di
 {
     const char *rn = "invalid";
 
+    if (sel != 0)
+        check_insn(env, ctx, INSN_MIPS64);
+
     switch (reg) {
     case 0:
         switch (sel) {
@@ -3759,7 +3823,7 @@ static void gen_dmtc0 (CPUState *env, Di
             rn = "PageMask";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_pagegrain();
             rn = "PageGrain";
             break;
@@ -3774,22 +3838,27 @@ static void gen_dmtc0 (CPUState *env, Di
             rn = "Wired";
             break;
         case 1:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf0();
             rn = "SRSConf0";
             break;
         case 2:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf1();
             rn = "SRSConf1";
             break;
         case 3:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf2();
             rn = "SRSConf2";
             break;
         case 4:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf3();
             rn = "SRSConf3";
             break;
         case 5:
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsconf4();
             rn = "SRSConf4";
             break;
@@ -3800,7 +3869,7 @@ static void gen_dmtc0 (CPUState *env, Di
     case 7:
         switch (sel) {
         case 0:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_hwrena();
             rn = "HWREna";
             break;
@@ -3858,21 +3927,21 @@ static void gen_dmtc0 (CPUState *env, Di
             rn = "Status";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_intctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "IntCtl";
             break;
         case 2:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsctl();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
             rn = "SRSCtl";
             break;
         case 3:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_srsmap();
             /* Stop translation as we may have switched the execution mode */
             ctx->bstate = BS_STOP;
@@ -3911,7 +3980,7 @@ static void gen_dmtc0 (CPUState *env, Di
             rn = "PRid";
             break;
         case 1:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             gen_op_mtc0_ebase();
             rn = "EBase";
             break;
@@ -3980,6 +4049,7 @@ static void gen_dmtc0 (CPUState *env, Di
     case 20:
         switch (sel) {
         case 0:
+            check_insn(env, ctx, INSN_MIPS64);
             gen_op_mtc0_xcontext();
             rn = "XContext";
             break;
@@ -4535,8 +4605,7 @@ static void gen_cp0 (CPUState *env, Disa
         break;
 #ifdef TARGET_MIPS64
     case OPC_DMFC0:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, INSN_MIPS3);
         if (rt == 0) {
             /* Treat as NOP. */
             return;
@@ -4546,8 +4615,7 @@ static void gen_cp0 (CPUState *env, Disa
         opn = "dmfc0";
         break;
     case OPC_DMTC0:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, INSN_MIPS3);
         GEN_LOAD_REG_TN(T0, rt);
         gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "dmtc0";
@@ -4597,11 +4665,13 @@ static void gen_cp0 (CPUState *env, Disa
         break;
     case OPC_ERET:
         opn = "eret";
+        check_insn(env, ctx, INSN_MIPS3 | INSN_MIPS32);
         gen_op_eret();
         ctx->bstate = BS_EXCP;
         break;
     case OPC_DERET:
         opn = "deret";
+        check_insn(env, ctx, INSN_MIPS32);
         if (!(ctx->hflags & MIPS_HFLAG_DM)) {
             MIPS_INVAL(opn);
             generate_exception(ctx, EXCP_RI);
@@ -4612,6 +4682,7 @@ static void gen_cp0 (CPUState *env, Disa
         break;
     case OPC_WAIT:
         opn = "wait";
+        check_insn(env, ctx, INSN_MIPS3 | INSN_MIPS32);
         /* If we get an exception, we want to restart at next instruction */
         ctx->pc += 4;
         save_cpu_state(ctx, 1);
@@ -4629,12 +4700,15 @@ static void gen_cp0 (CPUState *env, Disa
 }
 
 /* CP1 Branches (before delay slot) */
-static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
+static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
                                  int32_t cc, int32_t offset)
 {
     target_ulong btarget;
     const char *opn = "cp1 cond branch";
 
+    if (cc != 0)
+        check_insn(env, ctx, INSN_MIPS4 | INSN_MIPS32);
+
     btarget = ctx->pc + 4 + offset;
 
     switch (op) {
@@ -5843,14 +5917,15 @@ static void decode_opc (CPUState *env, D
         switch (op1) {
         case OPC_SLL:          /* Arithmetic with immediate */
         case OPC_SRL ... OPC_SRA:
-            gen_arith_imm(ctx, op1, rd, rt, sa);
+            gen_arith_imm(env, ctx, op1, rd, rt, sa);
             break;
+        case OPC_MOVZ ... OPC_MOVN:
+            check_insn(env, ctx, INSN_MIPS4 | INSN_MIPS32);
         case OPC_SLLV:         /* Arithmetic */
         case OPC_SRLV ... OPC_SRAV:
-        case OPC_MOVZ ... OPC_MOVN:
         case OPC_ADD ... OPC_NOR:
         case OPC_SLT ... OPC_SLTU:
-            gen_arith(ctx, op1, rd, rs, rt);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_MULT ... OPC_DIVU:
             gen_muldiv(ctx, op1, rs, rt);
@@ -5899,6 +5974,7 @@ static void decode_opc (CPUState *env, D
             break;
 
         case OPC_MOVCI:
+            check_insn(env, ctx, INSN_MIPS4 | INSN_MIPS32);
             if (env->CP0_Config1 & (1 << CP0C1_FP)) {
                 save_cpu_state(ctx, 1);
                 check_cp1_enabled(ctx);
@@ -5915,20 +5991,20 @@ static void decode_opc (CPUState *env, D
         case OPC_DSRL ... OPC_DSRA:
         case OPC_DSLL32:
         case OPC_DSRL32 ... OPC_DSRA32:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
-            gen_arith_imm(ctx, op1, rd, rt, sa);
+            check_insn(env, ctx, INSN_MIPS3);
+            check_mips_64(ctx);
+            gen_arith_imm(env, ctx, op1, rd, rt, sa);
             break;
         case OPC_DSLLV:
         case OPC_DSRLV ... OPC_DSRAV:
         case OPC_DADD ... OPC_DSUBU:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
-            gen_arith(ctx, op1, rd, rs, rt);
+            check_insn(env, ctx, INSN_MIPS3);
+            check_mips_64(ctx);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_DMULT ... OPC_DDIVU:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, INSN_MIPS3);
+            check_mips_64(ctx);
             gen_muldiv(ctx, op1, rs, rt);
             break;
 #endif
@@ -5943,18 +6019,21 @@ static void decode_opc (CPUState *env, D
         switch (op1) {
         case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
         case OPC_MSUB ... OPC_MSUBU:
+            check_insn(env, ctx, INSN_MIPS32);
             gen_muldiv(ctx, op1, rs, rt);
             break;
         case OPC_MUL:
-            gen_arith(ctx, op1, rd, rs, rt);
+            gen_arith(env, ctx, op1, rd, rs, rt);
             break;
         case OPC_CLZ ... OPC_CLO:
+            check_insn(env, ctx, INSN_MIPS32);
             gen_cl(ctx, op1, rd, rs);
             break;
         case OPC_SDBBP:
             /* XXX: not clear which exception should be raised
              *      when in debug mode...
              */
+            check_insn(env, ctx, INSN_MIPS32);
             if (!(ctx->hflags & MIPS_HFLAG_DM)) {
                 generate_exception(ctx, EXCP_DBp);
             } else {
@@ -5964,8 +6043,8 @@ static void decode_opc (CPUState *env, D
             break;
 #ifdef TARGET_MIPS64
         case OPC_DCLZ ... OPC_DCLO:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, INSN_MIPS64);
+            check_mips_64(ctx);
             gen_cl(ctx, op1, rd, rs);
             break;
 #endif
@@ -5976,14 +6055,15 @@ static void decode_opc (CPUState *env, D
         }
         break;
     case OPC_SPECIAL3:
-         check_mips_r2(env, ctx);
          op1 = MASK_SPECIAL3(ctx->opcode);
          switch (op1) {
          case OPC_EXT:
          case OPC_INS:
+             check_insn(env, ctx, INSN_MIPS32R2);
              gen_bitops(ctx, op1, rt, rs, sa, rd);
              break;
          case OPC_BSHFL:
+             check_insn(env, ctx, INSN_MIPS32R2);
              op2 = MASK_BSHFL(ctx->opcode);
              switch (op2) {
              case OPC_WSBH:
@@ -6006,6 +6086,7 @@ static void decode_opc (CPUState *env, D
             GEN_STORE_TN_REG(rd, T0);
             break;
         case OPC_RDHWR:
+            check_insn(env, ctx, INSN_MIPS32R2);
             switch (rd) {
             case 0:
                 save_cpu_state(ctx, 1);
@@ -6050,13 +6131,13 @@ static void decode_opc (CPUState *env, D
 #ifdef TARGET_MIPS64
         case OPC_DEXTM ... OPC_DEXT:
         case OPC_DINSM ... OPC_DINS:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, INSN_MIPS64R2);
+            check_mips_64(ctx);
             gen_bitops(ctx, op1, rt, rs, sa, rd);
             break;
         case OPC_DBSHFL:
-            if (!(ctx->hflags & MIPS_HFLAG_64))
-                generate_exception(ctx, EXCP_RI);
+            check_insn(env, ctx, INSN_MIPS64R2);
+            check_mips_64(ctx);
             op2 = MASK_DBSHFL(ctx->opcode);
             switch (op2) {
             case OPC_DSBH:
@@ -6092,7 +6173,7 @@ static void decode_opc (CPUState *env, D
             gen_trap(ctx, op1, rs, -1, imm);
             break;
         case OPC_SYNCI:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             /* Treat as NOP. */
             break;
         default:            /* Invalid */
@@ -6120,7 +6201,6 @@ static void decode_opc (CPUState *env, D
             gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
             break;
         case OPC_MFMC0:
-            check_mips_r2(env, ctx);
             op2 = MASK_MFMC0(ctx->opcode);
             switch (op2) {
             case OPC_DMT:
@@ -6140,11 +6220,13 @@ static void decode_opc (CPUState *env, D
                 gen_op_evpe();
                 break;
             case OPC_DI:
+                check_insn(env, ctx, INSN_MIPS32R2);
                 gen_op_di();
                 /* Stop translation as we may have switched the execution mode 
*/
                 ctx->bstate = BS_STOP;
                 break;
             case OPC_EI:
+                check_insn(env, ctx, INSN_MIPS32R2);
                 gen_op_ei();
                 /* Stop translation as we may have switched the execution mode 
*/
                 ctx->bstate = BS_STOP;
@@ -6157,12 +6239,12 @@ static void decode_opc (CPUState *env, D
             GEN_STORE_TN_REG(rt, T0);
             break;
         case OPC_RDPGPR:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             GEN_LOAD_SRSREG_TN(T0, rt);
             GEN_STORE_TN_REG(rd, T0);
             break;
         case OPC_WRPGPR:
-            check_mips_r2(env, ctx);
+            check_insn(env, ctx, INSN_MIPS32R2);
             GEN_LOAD_REG_TN(T0, rt);
             GEN_STORE_TN_SRSREG(rd, T0);
             break;
@@ -6173,7 +6255,7 @@ static void decode_opc (CPUState *env, D
         }
         break;
     case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
-         gen_arith_imm(ctx, op, rt, rs, imm);
+         gen_arith_imm(env, ctx, op, rt, rs, imm);
          break;
     case OPC_J ... OPC_JAL: /* Jump */
          offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
@@ -6191,9 +6273,11 @@ static void decode_opc (CPUState *env, D
          gen_ldst(ctx, op, rt, rs, imm);
          break;
     case OPC_CACHE:
+        check_insn(env, ctx, INSN_MIPS3 | INSN_MIPS32);
         /* Treat as NOP. */
         break;
     case OPC_PREF:
+        check_insn(env, ctx, INSN_MIPS4 | INSN_MIPS32);
         /* Treat as NOP. */
         break;
 
@@ -6219,21 +6303,24 @@ static void decode_opc (CPUState *env, D
             switch (op1) {
             case OPC_MFHC1:
             case OPC_MTHC1:
-                check_mips_r2(env, ctx);
+                check_insn(env, ctx, INSN_MIPS32R2);
             case OPC_MFC1:
             case OPC_CFC1:
             case OPC_MTC1:
             case OPC_CTC1:
+                gen_cp1(ctx, op1, rt, rd);
+                break;
 #ifdef TARGET_MIPS64
             case OPC_DMFC1:
             case OPC_DMTC1:
-#endif
+                check_insn(env, ctx, INSN_MIPS3);
                 gen_cp1(ctx, op1, rt, rd);
                 break;
+#endif
             case OPC_BC1:
             case OPC_BC1ANY2:
             case OPC_BC1ANY4:
-                gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
+                gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
                                     (rt >> 2) & 0x7, imm << 2);
                 return;
             case OPC_S_FMT:
@@ -6315,24 +6402,22 @@ static void decode_opc (CPUState *env, D
     case OPC_LD:
     case OPC_SCD:
     case OPC_SD:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
+        check_insn(env, ctx, INSN_MIPS3);
+        check_mips_64(ctx);
         gen_ldst(ctx, op, rt, rs, imm);
         break;
     case OPC_DADDI ... OPC_DADDIU:
-        if (!(ctx->hflags & MIPS_HFLAG_64))
-            generate_exception(ctx, EXCP_RI);
-        gen_arith_imm(ctx, op, rt, rs, imm);
+        check_insn(env, ctx, INSN_MIPS3);
+        check_mips_64(ctx);
+        gen_arith_imm(env, ctx, op, rt, rs, imm);
         break;
 #endif
-#ifdef MIPS_HAS_MIPS16
     case OPC_JALX:
+        check_insn(env, ctx, INSN_MIPS16);
         /* MIPS16: Not implemented. */
-#endif
-#ifdef MIPS_HAS_MDMX
     case OPC_MDMX:
+        check_insn(env, ctx, INSN_MDMX);
         /* MDMX: Not implemented. */
-#endif
     default:            /* Invalid */
         MIPS_INVAL("major opcode");
         generate_exception(ctx, EXCP_RI);
Index: target-mips/translate_init.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate_init.c,v
retrieving revision 1.20
diff -u -d -p -r1.20 translate_init.c
--- target-mips/translate_init.c        6 Sep 2007 00:18:15 -0000       1.20
+++ target-mips/translate_init.c        19 Sep 2007 21:39:59 -0000
@@ -80,6 +80,7 @@ struct mips_def_t {
     int32_t CP0_SRSConf3;
     int32_t CP0_SRSConf4_rw_bitmask;
     int32_t CP0_SRSConf4;
+    int insn_flags;
 };
 
 /*****************************************************************************/
@@ -98,6 +99,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32,
     },
     {
         .name = "4KEcR1",
@@ -111,6 +113,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32,
     },
     {
         .name = "4KEc",
@@ -124,6 +127,7 @@ static mips_def_t mips_defs[] =
         .SYNCI_Step = 32,
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32R2,
     },
     {
         .name = "24Kc",
@@ -138,6 +142,7 @@ static mips_def_t mips_defs[] =
         .CCRes = 2,
         /* No DSP implemented. */
         .CP0_Status_rw_bitmask = 0x1278FF17,
+        .insn_flags = CPU_MIPS32R2,
     },
     {
         .name = "24Kf",
@@ -154,6 +159,7 @@ static mips_def_t mips_defs[] =
         .CP0_Status_rw_bitmask = 0x3678FF17,
         .CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
                     (1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
+        .insn_flags = CPU_MIPS32R2,
     },
     {
         .name = "34Kf",
@@ -193,6 +199,7 @@ static mips_def_t mips_defs[] =
         .CP0_SRSConf4_rw_bitmask = 0x3fffffff,
         .CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
                     (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
+        .insn_flags = CPU_MIPS32R2,
     },
 #ifdef TARGET_MIPS64
     {
@@ -210,6 +217,7 @@ static mips_def_t mips_defs[] =
        /* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
         .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 40,
+        .insn_flags = CPU_MIPS3,
     },
     {
         .name = "5Kc",
@@ -225,6 +233,7 @@ static mips_def_t mips_defs[] =
         .CCRes = 2,
         .CP0_Status_rw_bitmask = 0x32F8FFFF,
         .SEGBITS = 42,
+        .insn_flags = CPU_MIPS64,
     },
     {
         .name = "5Kf",
@@ -243,6 +252,7 @@ static mips_def_t mips_defs[] =
         .CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 42,
+        .insn_flags = CPU_MIPS64,
     },
     {
         .name = "20Kc",
@@ -264,6 +274,7 @@ static mips_def_t mips_defs[] =
                     (1 << FCR0_D) | (1 << FCR0_S) |
                     (0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
         .SEGBITS = 40,
+        .insn_flags = CPU_MIPS64,
     },
 #endif
 };
@@ -403,7 +414,7 @@ int cpu_mips_register (CPUMIPSState *env
     env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
     env->CP0_SRSCtl = def->CP0_SRSCtl;
 #ifdef TARGET_MIPS64
-    if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
+    if (def->insn_flags & INSN_MIPS3)
     {
         env->hflags |= MIPS_HFLAG_64;
         env->SEGBITS = def->SEGBITS;
@@ -423,6 +434,7 @@ int cpu_mips_register (CPUMIPSState *env
     env->CP0_SRSConf3 = def->CP0_SRSConf3;
     env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
     env->CP0_SRSConf4 = def->CP0_SRSConf4;
+    env->insn_flags = def->insn_flags;
 
 #ifndef CONFIG_USER_ONLY
     mmu_init(env, def);

-- 
  .''`.  Aurelien Jarno             | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   address@hidden         | address@hidden
   `-    people.debian.org/~aurel32 | www.aurel32.net




reply via email to

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