Skip to contentSkip to conversation

Per-CPU instruction decoding implementation

PATCH In review Aurelien Jarno 2 participants 2 messages Sep 19, 2007 – Sep 24, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Per-CPU instruction decoding implementation

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

cpu.h +1 -0
diff -u -d -p -r1.43 cpu.h
@@ -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

helper.c +3 -6
diff -u -d -p -r1.48 helper.c
@@ -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

mips-defs.h +29 -0
diff -u -d -p -r1.15 mips-defs.h
@@ -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

op.c +7 -10
diff -u -d -p -r1.71 op.c
@@ -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

translate.c +171 -86

791 lines not on this page · raw message

Index: target-mips/translate_init.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate_init.c,v retrieving revision 1.20

translate_init.c +13 -1
diff -u -d -p -r1.20 translate_init.c
@@ -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);
Signature · 4 lines
  .''`.  Aurelien Jarno	            | GPG: 1024D/F1BCDB73
 : :' :  Debian developer           | Electrical Engineer
 `. `'   [email protected]         | [email protected]
   `-    people.debian.org/~aurel32 | www.aurel32.net
#1 lore raw
Quoted 6 lines · Aurelien Jarno

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.

I expanded parts of it to (at least theoretically) cover the whole ISA space, renamed INSN -> ISA / ASE, since that's what we actually check for, and fixed a few misassumptions (e.g. Xcontext is MIPS3).

Thiemo