Optimise instructions accessing CP0, by Aurelien Jarno.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 25 Sep 2007 14:49:47 +0000 (14:49 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Tue, 25 Sep 2007 14:49:47 +0000 (14:49 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3235 c046a42c-6fe2-441c-8c8c-71466251a162

target-mips/cpu.h
target-mips/helper.c
target-mips/op.c
target-mips/translate.c

index f8299ad..569f932 100644 (file)
@@ -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 d0e5b1d..5c19a7c 100644 (file)
@@ -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 dd90163..b353644 100644 (file)
@@ -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 004b2f7..c70480c 100644 (file)
@@ -731,6 +731,12 @@ static inline void generate_exception (DisasContext *ctx, int excp)
     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, DisasContext *ctx, uint32_t opc, int rt, int
         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, DisasContext *ctx, uint32_t opc, int rt, int
     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, DisasContext *ctx, uint32_t opc, int rt, int
     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, DisasContext *ctx, uint32_t opc, int rt, int
             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, DisasContext *ctx)
         }
         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, DisasContext *ctx)
                 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
 }