qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] Optimise instructions accessing CP0


From: Aurelien Jarno
Subject: [Qemu-devel] [PATCH] Optimise instructions accessing CP0
Date: Mon, 24 Sep 2007 16:14:20 +0200
User-agent: Mutt/1.5.13 (2006-08-11)

Hi all,

The patch below optimise instructions accessing CP0 by doing access 
rights check at translation time instead of execution time, as it is
already done for other CPx.

This is done by adding a new bit to hflags. Unfortunately that means
reorganising them because there was no space anymore for a new bit.

Bye,
Aurelien

Index: target-mips/cpu.h
===================================================================
RCS file: /sources/qemu/qemu/target-mips/cpu.h,v
retrieving revision 1.44
diff -u -d -p -r1.44 cpu.h
--- target-mips/cpu.h   24 Sep 2007 12:48:00 -0000      1.44
+++ target-mips/cpu.h   24 Sep 2007 14:02:55 -0000
@@ -414,24 +414,25 @@ struct CPUMIPSState {
     int user_mode_only; /* user mode only simulation */
     uint32_t hflags;    /* CPU State */
     /* TMASK defines different execution modes */
-#define MIPS_HFLAG_TMASK  0x007F
+#define MIPS_HFLAG_TMASK  0x00FF
 #define MIPS_HFLAG_MODE   0x0007 /* execution modes                    */
 #define MIPS_HFLAG_UM     0x0001 /* user mode                          */
 #define MIPS_HFLAG_DM     0x0002 /* Debug mode                         */
 #define MIPS_HFLAG_SM     0x0004 /* Supervisor mode                    */
 #define MIPS_HFLAG_64     0x0008 /* 64-bit instructions enabled        */
-#define MIPS_HFLAG_FPU    0x0010 /* FPU enabled                        */
-#define MIPS_HFLAG_F64    0x0020 /* 64-bit FPU enabled                 */
-#define MIPS_HFLAG_RE     0x0040 /* Reversed endianness                */
+#define MIPS_HFLAG_CP0    0x0010 /* CP0 enabled                        */
+#define MIPS_HFLAG_FPU    0x0020 /* FPU enabled                        */
+#define MIPS_HFLAG_F64    0x0040 /* 64-bit FPU enabled                 */
+#define MIPS_HFLAG_RE     0x0080 /* Reversed endianness                */
     /* If translation is interrupted between the branch instruction and
      * the delay slot, record what type of branch it is so that we can
      * resume translation properly.  It might be possible to reduce
      * this from three bits to two.  */
-#define MIPS_HFLAG_BMASK  0x0380
-#define MIPS_HFLAG_B      0x0080 /* Unconditional branch               */
-#define MIPS_HFLAG_BC     0x0100 /* Conditional branch                 */
-#define MIPS_HFLAG_BL     0x0180 /* Likely branch                      */
-#define MIPS_HFLAG_BR     0x0200 /* branch to register (can't link TB) */
+#define MIPS_HFLAG_BMASK  0x0700
+#define MIPS_HFLAG_B      0x0100 /* Unconditional branch               */
+#define MIPS_HFLAG_BC     0x0200 /* Conditional branch                 */
+#define MIPS_HFLAG_BL     0x0300 /* Likely branch                      */
+#define MIPS_HFLAG_BR     0x0400 /* branch to register (can't link TB) */
     target_ulong btarget;        /* Jump / branch target               */
     int bcond;                   /* Branch condition (if needed)       */
 
Index: target-mips/helper.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/helper.c,v
retrieving revision 1.49
diff -u -d -p -r1.49 helper.c
--- target-mips/helper.c        24 Sep 2007 12:48:00 -0000      1.49
+++ target-mips/helper.c        24 Sep 2007 14:02:55 -0000
@@ -371,6 +371,7 @@ void do_interrupt (CPUState *env)
         env->hflags |= MIPS_HFLAG_DM;
         env->hflags |= MIPS_HFLAG_64;
         env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags |= MIPS_HFLAG_CP0;
         /* EJTAG probe trap enable is not implemented... */
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -397,6 +398,7 @@ void do_interrupt (CPUState *env)
         env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
         env->hflags |= MIPS_HFLAG_64;
         env->hflags &= ~MIPS_HFLAG_UM;
+        env->hflags |= MIPS_HFLAG_CP0;
         if (!(env->CP0_Status & (1 << CP0St_EXL)))
             env->CP0_Cause &= ~(1 << CP0Ca_BD);
         env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -499,6 +501,7 @@ void do_interrupt (CPUState *env)
             env->CP0_Status |= (1 << CP0St_EXL);
             env->hflags |= MIPS_HFLAG_64;
             env->hflags &= ~MIPS_HFLAG_UM;
+            env->hflags |= MIPS_HFLAG_CP0;
         }
         env->hflags &= ~MIPS_HFLAG_BMASK;
         if (env->CP0_Status & (1 << CP0St_BEV)) {
Index: target-mips/op.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/op.c,v
retrieving revision 1.72
diff -u -d -p -r1.72 op.c
--- target-mips/op.c    24 Sep 2007 12:48:00 -0000      1.72
+++ target-mips/op.c    24 Sep 2007 14:02:56 -0000
@@ -1852,6 +1852,10 @@ void op_mtc0_status (void)
         !(val & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
+    if ((val & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+        env->hflags |= MIPS_HFLAG_CP0;
+    else
+        env->hflags &= ~MIPS_HFLAG_CP0;
     if (val & (1 << CP0St_CU1))
         env->hflags |= MIPS_HFLAG_FPU;
     else
@@ -2316,15 +2320,6 @@ void op_yield(void)
 # define DEBUG_FPU_STATE() do { } while(0)
 #endif
 
-void op_cp0_enabled(void)
-{
-    if (!(env->CP0_Status & (1 << CP0St_CU0)) &&
-        (env->hflags & MIPS_HFLAG_UM)) {
-        CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);
-    }
-    RETURN();
-}
-
 void op_cfc1 (void)
 {
     CALL_FROM_TB1(do_cfc1, PARAM1);
@@ -3018,6 +3013,10 @@ void op_eret (void)
         !(env->CP0_Status & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+        env->hflags |= MIPS_HFLAG_CP0;
+    else
+        env->hflags &= ~MIPS_HFLAG_CP0;
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB0(debug_post_eret);
     env->CP0_LLAddr = 1;
@@ -3041,6 +3040,10 @@ void op_deret (void)
         !(env->CP0_Status & (1 << CP0St_UX)))
         env->hflags &= ~MIPS_HFLAG_64;
 #endif
+    if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
+        env->hflags |= MIPS_HFLAG_CP0;
+    else
+        env->hflags &= ~MIPS_HFLAG_CP0;
     if (loglevel & CPU_LOG_EXEC)
         CALL_FROM_TB0(debug_post_eret);
     env->CP0_LLAddr = 1;
@@ -3049,9 +3052,8 @@ void op_deret (void)
 
 void op_rdhwr_cpunum(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 0)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 0)))
         T0 = env->CP0_EBase & 0x3ff;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3060,9 +3062,8 @@ void op_rdhwr_cpunum(void)
 
 void op_rdhwr_synci_step(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 1)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 1)))
         T0 = env->SYNCI_Step;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3071,9 +3072,8 @@ void op_rdhwr_synci_step(void)
 
 void op_rdhwr_cc(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 2)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 2)))
         T0 = env->CP0_Count;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3082,9 +3082,8 @@ void op_rdhwr_cc(void)
 
 void op_rdhwr_ccres(void)
 {
-    if (!(env->hflags & MIPS_HFLAG_UM) ||
-        (env->CP0_HWREna & (1 << 3)) ||
-        (env->CP0_Status & (1 << CP0St_CU0)))
+    if ((env->hflags & MIPS_HFLAG_CP0) ||
+        (env->CP0_HWREna & (1 << 3)))
         T0 = env->CCRes;
     else
         CALL_FROM_TB1(do_raise_exception, EXCP_RI);
Index: target-mips/translate.c
===================================================================
RCS file: /sources/qemu/qemu/target-mips/translate.c,v
retrieving revision 1.101
diff -u -d -p -r1.101 translate.c
--- target-mips/translate.c     24 Sep 2007 12:48:00 -0000      1.101
+++ target-mips/translate.c     24 Sep 2007 14:02:58 -0000
@@ -731,6 +731,12 @@ static inline void generate_exception (D
     generate_exception_err (ctx, excp, 0);
 }
 
+static inline void check_cp0_enabled(DisasContext *ctx)
+{
+    if (!(ctx->hflags & MIPS_HFLAG_CP0))
+        generate_exception_err(ctx, EXCP_CpU, 1);
+}
+
 static inline void check_cp1_enabled(DisasContext *ctx)
 {
     if (!(ctx->hflags & MIPS_HFLAG_FPU))
@@ -4600,6 +4606,7 @@ static void gen_cp0 (CPUState *env, Disa
         break;
     case OPC_MTC0:
         GEN_LOAD_REG_TN(T0, rt);
+        save_cpu_state(ctx, 1);
         gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "mtc0";
         break;
@@ -4617,6 +4624,7 @@ static void gen_cp0 (CPUState *env, Disa
     case OPC_DMTC0:
         check_insn(env, ctx, ISA_MIPS3);
         GEN_LOAD_REG_TN(T0, rt);
+        save_cpu_state(ctx, 1);
         gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
         opn = "dmtc0";
         break;
@@ -4666,6 +4674,7 @@ static void gen_cp0 (CPUState *env, Disa
     case OPC_ERET:
         opn = "eret";
         check_insn(env, ctx, ISA_MIPS2);
+        save_cpu_state(ctx, 1);
         gen_op_eret();
         ctx->bstate = BS_EXCP;
         break;
@@ -4676,6 +4685,7 @@ static void gen_cp0 (CPUState *env, Disa
             MIPS_INVAL(opn);
             generate_exception(ctx, EXCP_RI);
         } else {
+            save_cpu_state(ctx, 1);
             gen_op_deret();
             ctx->bstate = BS_EXCP;
         }
@@ -6183,8 +6193,7 @@ static void decode_opc (CPUState *env, D
         }
         break;
     case OPC_CP0:
-        save_cpu_state(ctx, 1);
-        gen_op_cp0_enabled();
+        check_cp0_enabled(ctx);
         op1 = MASK_CP0(ctx->opcode);
         switch (op1) {
         case OPC_MFC0:
@@ -6221,12 +6230,14 @@ static void decode_opc (CPUState *env, D
                 break;
             case OPC_DI:
                 check_insn(env, ctx, ISA_MIPS32R2);
+                save_cpu_state(ctx, 1);
                 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, ISA_MIPS32R2);
+                save_cpu_state(ctx, 1);
                 gen_op_ei();
                 /* Stop translation as we may have switched the execution mode 
*/
                 ctx->bstate = BS_STOP;
@@ -6747,7 +6758,6 @@ void cpu_reset (CPUMIPSState *env)
     } else {
         env->CP0_ErrorEPC = env->PC[env->current_tc];
     }
-    env->hflags = 0;
     env->PC[env->current_tc] = (int32_t)0xBFC00000;
     env->CP0_Wired = 0;
     /* SMP not implemented */
@@ -6771,8 +6781,10 @@ void cpu_reset (CPUMIPSState *env)
 #endif
     env->exception_index = EXCP_NONE;
 #if defined(CONFIG_USER_ONLY)
-    env->hflags |= MIPS_HFLAG_UM;
+    env->hflags = MIPS_HFLAG_UM;
     env->user_mode_only = 1;
+#else
+    env->hflags = MIPS_HFLAG_CP0;
 #endif
 }
 

-- 
  .''`.  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]