Commit 387a8fe505dd733968a798c9d3b88fbdd5f93056

Authored by ths
1 parent b570094d

Optimise instructions accessing CP0, by Aurelien Jarno.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3235 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/cpu.h
@@ -414,24 +414,25 @@ struct CPUMIPSState { @@ -414,24 +414,25 @@ struct CPUMIPSState {
414 int user_mode_only; /* user mode only simulation */ 414 int user_mode_only; /* user mode only simulation */
415 uint32_t hflags; /* CPU State */ 415 uint32_t hflags; /* CPU State */
416 /* TMASK defines different execution modes */ 416 /* TMASK defines different execution modes */
417 -#define MIPS_HFLAG_TMASK 0x007F 417 +#define MIPS_HFLAG_TMASK 0x00FF
418 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */ 418 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */
419 #define MIPS_HFLAG_UM 0x0001 /* user mode */ 419 #define MIPS_HFLAG_UM 0x0001 /* user mode */
420 #define MIPS_HFLAG_DM 0x0002 /* Debug mode */ 420 #define MIPS_HFLAG_DM 0x0002 /* Debug mode */
421 #define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */ 421 #define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */
422 #define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */ 422 #define MIPS_HFLAG_64 0x0008 /* 64-bit instructions enabled */
423 -#define MIPS_HFLAG_FPU 0x0010 /* FPU enabled */  
424 -#define MIPS_HFLAG_F64 0x0020 /* 64-bit FPU enabled */  
425 -#define MIPS_HFLAG_RE 0x0040 /* Reversed endianness */ 423 +#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
  424 +#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
  425 +#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
  426 +#define MIPS_HFLAG_RE 0x0080 /* Reversed endianness */
426 /* If translation is interrupted between the branch instruction and 427 /* If translation is interrupted between the branch instruction and
427 * the delay slot, record what type of branch it is so that we can 428 * the delay slot, record what type of branch it is so that we can
428 * resume translation properly. It might be possible to reduce 429 * resume translation properly. It might be possible to reduce
429 * this from three bits to two. */ 430 * this from three bits to two. */
430 -#define MIPS_HFLAG_BMASK 0x0380  
431 -#define MIPS_HFLAG_B 0x0080 /* Unconditional branch */  
432 -#define MIPS_HFLAG_BC 0x0100 /* Conditional branch */  
433 -#define MIPS_HFLAG_BL 0x0180 /* Likely branch */  
434 -#define MIPS_HFLAG_BR 0x0200 /* branch to register (can't link TB) */ 431 +#define MIPS_HFLAG_BMASK 0x0700
  432 +#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */
  433 +#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */
  434 +#define MIPS_HFLAG_BL 0x0300 /* Likely branch */
  435 +#define MIPS_HFLAG_BR 0x0400 /* branch to register (can't link TB) */
435 target_ulong btarget; /* Jump / branch target */ 436 target_ulong btarget; /* Jump / branch target */
436 int bcond; /* Branch condition (if needed) */ 437 int bcond; /* Branch condition (if needed) */
437 438
target-mips/helper.c
@@ -371,6 +371,7 @@ void do_interrupt (CPUState *env) @@ -371,6 +371,7 @@ void do_interrupt (CPUState *env)
371 env->hflags |= MIPS_HFLAG_DM; 371 env->hflags |= MIPS_HFLAG_DM;
372 env->hflags |= MIPS_HFLAG_64; 372 env->hflags |= MIPS_HFLAG_64;
373 env->hflags &= ~MIPS_HFLAG_UM; 373 env->hflags &= ~MIPS_HFLAG_UM;
  374 + env->hflags |= MIPS_HFLAG_CP0;
374 /* EJTAG probe trap enable is not implemented... */ 375 /* EJTAG probe trap enable is not implemented... */
375 if (!(env->CP0_Status & (1 << CP0St_EXL))) 376 if (!(env->CP0_Status & (1 << CP0St_EXL)))
376 env->CP0_Cause &= ~(1 << CP0Ca_BD); 377 env->CP0_Cause &= ~(1 << CP0Ca_BD);
@@ -397,6 +398,7 @@ void do_interrupt (CPUState *env) @@ -397,6 +398,7 @@ void do_interrupt (CPUState *env)
397 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); 398 env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
398 env->hflags |= MIPS_HFLAG_64; 399 env->hflags |= MIPS_HFLAG_64;
399 env->hflags &= ~MIPS_HFLAG_UM; 400 env->hflags &= ~MIPS_HFLAG_UM;
  401 + env->hflags |= MIPS_HFLAG_CP0;
400 if (!(env->CP0_Status & (1 << CP0St_EXL))) 402 if (!(env->CP0_Status & (1 << CP0St_EXL)))
401 env->CP0_Cause &= ~(1 << CP0Ca_BD); 403 env->CP0_Cause &= ~(1 << CP0Ca_BD);
402 env->PC[env->current_tc] = (int32_t)0xBFC00000; 404 env->PC[env->current_tc] = (int32_t)0xBFC00000;
@@ -499,6 +501,7 @@ void do_interrupt (CPUState *env) @@ -499,6 +501,7 @@ void do_interrupt (CPUState *env)
499 env->CP0_Status |= (1 << CP0St_EXL); 501 env->CP0_Status |= (1 << CP0St_EXL);
500 env->hflags |= MIPS_HFLAG_64; 502 env->hflags |= MIPS_HFLAG_64;
501 env->hflags &= ~MIPS_HFLAG_UM; 503 env->hflags &= ~MIPS_HFLAG_UM;
  504 + env->hflags |= MIPS_HFLAG_CP0;
502 } 505 }
503 env->hflags &= ~MIPS_HFLAG_BMASK; 506 env->hflags &= ~MIPS_HFLAG_BMASK;
504 if (env->CP0_Status & (1 << CP0St_BEV)) { 507 if (env->CP0_Status & (1 << CP0St_BEV)) {
target-mips/op.c
@@ -1852,6 +1852,10 @@ void op_mtc0_status (void) @@ -1852,6 +1852,10 @@ void op_mtc0_status (void)
1852 !(val & (1 << CP0St_UX))) 1852 !(val & (1 << CP0St_UX)))
1853 env->hflags &= ~MIPS_HFLAG_64; 1853 env->hflags &= ~MIPS_HFLAG_64;
1854 #endif 1854 #endif
  1855 + if ((val & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
  1856 + env->hflags |= MIPS_HFLAG_CP0;
  1857 + else
  1858 + env->hflags &= ~MIPS_HFLAG_CP0;
1855 if (val & (1 << CP0St_CU1)) 1859 if (val & (1 << CP0St_CU1))
1856 env->hflags |= MIPS_HFLAG_FPU; 1860 env->hflags |= MIPS_HFLAG_FPU;
1857 else 1861 else
@@ -2316,15 +2320,6 @@ void op_yield(void) @@ -2316,15 +2320,6 @@ void op_yield(void)
2316 # define DEBUG_FPU_STATE() do { } while(0) 2320 # define DEBUG_FPU_STATE() do { } while(0)
2317 #endif 2321 #endif
2318 2322
2319 -void op_cp0_enabled(void)  
2320 -{  
2321 - if (!(env->CP0_Status & (1 << CP0St_CU0)) &&  
2322 - (env->hflags & MIPS_HFLAG_UM)) {  
2323 - CALL_FROM_TB2(do_raise_exception_err, EXCP_CpU, 0);  
2324 - }  
2325 - RETURN();  
2326 -}  
2327 -  
2328 void op_cfc1 (void) 2323 void op_cfc1 (void)
2329 { 2324 {
2330 CALL_FROM_TB1(do_cfc1, PARAM1); 2325 CALL_FROM_TB1(do_cfc1, PARAM1);
@@ -3018,6 +3013,10 @@ void op_eret (void) @@ -3018,6 +3013,10 @@ void op_eret (void)
3018 !(env->CP0_Status & (1 << CP0St_UX))) 3013 !(env->CP0_Status & (1 << CP0St_UX)))
3019 env->hflags &= ~MIPS_HFLAG_64; 3014 env->hflags &= ~MIPS_HFLAG_64;
3020 #endif 3015 #endif
  3016 + if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
  3017 + env->hflags |= MIPS_HFLAG_CP0;
  3018 + else
  3019 + env->hflags &= ~MIPS_HFLAG_CP0;
3021 if (loglevel & CPU_LOG_EXEC) 3020 if (loglevel & CPU_LOG_EXEC)
3022 CALL_FROM_TB0(debug_post_eret); 3021 CALL_FROM_TB0(debug_post_eret);
3023 env->CP0_LLAddr = 1; 3022 env->CP0_LLAddr = 1;
@@ -3041,6 +3040,10 @@ void op_deret (void) @@ -3041,6 +3040,10 @@ void op_deret (void)
3041 !(env->CP0_Status & (1 << CP0St_UX))) 3040 !(env->CP0_Status & (1 << CP0St_UX)))
3042 env->hflags &= ~MIPS_HFLAG_64; 3041 env->hflags &= ~MIPS_HFLAG_64;
3043 #endif 3042 #endif
  3043 + if ((env->CP0_Status & (1 << CP0St_CU0)) || !(env->hflags & MIPS_HFLAG_UM))
  3044 + env->hflags |= MIPS_HFLAG_CP0;
  3045 + else
  3046 + env->hflags &= ~MIPS_HFLAG_CP0;
3044 if (loglevel & CPU_LOG_EXEC) 3047 if (loglevel & CPU_LOG_EXEC)
3045 CALL_FROM_TB0(debug_post_eret); 3048 CALL_FROM_TB0(debug_post_eret);
3046 env->CP0_LLAddr = 1; 3049 env->CP0_LLAddr = 1;
@@ -3049,9 +3052,8 @@ void op_deret (void) @@ -3049,9 +3052,8 @@ void op_deret (void)
3049 3052
3050 void op_rdhwr_cpunum(void) 3053 void op_rdhwr_cpunum(void)
3051 { 3054 {
3052 - if (!(env->hflags & MIPS_HFLAG_UM) ||  
3053 - (env->CP0_HWREna & (1 << 0)) ||  
3054 - (env->CP0_Status & (1 << CP0St_CU0))) 3055 + if ((env->hflags & MIPS_HFLAG_CP0) ||
  3056 + (env->CP0_HWREna & (1 << 0)))
3055 T0 = env->CP0_EBase & 0x3ff; 3057 T0 = env->CP0_EBase & 0x3ff;
3056 else 3058 else
3057 CALL_FROM_TB1(do_raise_exception, EXCP_RI); 3059 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3060,9 +3062,8 @@ void op_rdhwr_cpunum(void) @@ -3060,9 +3062,8 @@ void op_rdhwr_cpunum(void)
3060 3062
3061 void op_rdhwr_synci_step(void) 3063 void op_rdhwr_synci_step(void)
3062 { 3064 {
3063 - if (!(env->hflags & MIPS_HFLAG_UM) ||  
3064 - (env->CP0_HWREna & (1 << 1)) ||  
3065 - (env->CP0_Status & (1 << CP0St_CU0))) 3065 + if ((env->hflags & MIPS_HFLAG_CP0) ||
  3066 + (env->CP0_HWREna & (1 << 1)))
3066 T0 = env->SYNCI_Step; 3067 T0 = env->SYNCI_Step;
3067 else 3068 else
3068 CALL_FROM_TB1(do_raise_exception, EXCP_RI); 3069 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3071,9 +3072,8 @@ void op_rdhwr_synci_step(void) @@ -3071,9 +3072,8 @@ void op_rdhwr_synci_step(void)
3071 3072
3072 void op_rdhwr_cc(void) 3073 void op_rdhwr_cc(void)
3073 { 3074 {
3074 - if (!(env->hflags & MIPS_HFLAG_UM) ||  
3075 - (env->CP0_HWREna & (1 << 2)) ||  
3076 - (env->CP0_Status & (1 << CP0St_CU0))) 3075 + if ((env->hflags & MIPS_HFLAG_CP0) ||
  3076 + (env->CP0_HWREna & (1 << 2)))
3077 T0 = env->CP0_Count; 3077 T0 = env->CP0_Count;
3078 else 3078 else
3079 CALL_FROM_TB1(do_raise_exception, EXCP_RI); 3079 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
@@ -3082,9 +3082,8 @@ void op_rdhwr_cc(void) @@ -3082,9 +3082,8 @@ void op_rdhwr_cc(void)
3082 3082
3083 void op_rdhwr_ccres(void) 3083 void op_rdhwr_ccres(void)
3084 { 3084 {
3085 - if (!(env->hflags & MIPS_HFLAG_UM) ||  
3086 - (env->CP0_HWREna & (1 << 3)) ||  
3087 - (env->CP0_Status & (1 << CP0St_CU0))) 3085 + if ((env->hflags & MIPS_HFLAG_CP0) ||
  3086 + (env->CP0_HWREna & (1 << 3)))
3088 T0 = env->CCRes; 3087 T0 = env->CCRes;
3089 else 3088 else
3090 CALL_FROM_TB1(do_raise_exception, EXCP_RI); 3089 CALL_FROM_TB1(do_raise_exception, EXCP_RI);
target-mips/translate.c
@@ -731,6 +731,12 @@ static inline void generate_exception (DisasContext *ctx, int excp) @@ -731,6 +731,12 @@ static inline void generate_exception (DisasContext *ctx, int excp)
731 generate_exception_err (ctx, excp, 0); 731 generate_exception_err (ctx, excp, 0);
732 } 732 }
733 733
  734 +static inline void check_cp0_enabled(DisasContext *ctx)
  735 +{
  736 + if (!(ctx->hflags & MIPS_HFLAG_CP0))
  737 + generate_exception_err(ctx, EXCP_CpU, 1);
  738 +}
  739 +
734 static inline void check_cp1_enabled(DisasContext *ctx) 740 static inline void check_cp1_enabled(DisasContext *ctx)
735 { 741 {
736 if (!(ctx->hflags & MIPS_HFLAG_FPU)) 742 if (!(ctx->hflags & MIPS_HFLAG_FPU))
@@ -4600,6 +4606,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int @@ -4600,6 +4606,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4600 break; 4606 break;
4601 case OPC_MTC0: 4607 case OPC_MTC0:
4602 GEN_LOAD_REG_TN(T0, rt); 4608 GEN_LOAD_REG_TN(T0, rt);
  4609 + save_cpu_state(ctx, 1);
4603 gen_mtc0(env, ctx, rd, ctx->opcode & 0x7); 4610 gen_mtc0(env, ctx, rd, ctx->opcode & 0x7);
4604 opn = "mtc0"; 4611 opn = "mtc0";
4605 break; 4612 break;
@@ -4617,6 +4624,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int @@ -4617,6 +4624,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4617 case OPC_DMTC0: 4624 case OPC_DMTC0:
4618 check_insn(env, ctx, ISA_MIPS3); 4625 check_insn(env, ctx, ISA_MIPS3);
4619 GEN_LOAD_REG_TN(T0, rt); 4626 GEN_LOAD_REG_TN(T0, rt);
  4627 + save_cpu_state(ctx, 1);
4620 gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7); 4628 gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
4621 opn = "dmtc0"; 4629 opn = "dmtc0";
4622 break; 4630 break;
@@ -4666,6 +4674,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int @@ -4666,6 +4674,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4666 case OPC_ERET: 4674 case OPC_ERET:
4667 opn = "eret"; 4675 opn = "eret";
4668 check_insn(env, ctx, ISA_MIPS2); 4676 check_insn(env, ctx, ISA_MIPS2);
  4677 + save_cpu_state(ctx, 1);
4669 gen_op_eret(); 4678 gen_op_eret();
4670 ctx->bstate = BS_EXCP; 4679 ctx->bstate = BS_EXCP;
4671 break; 4680 break;
@@ -4676,6 +4685,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int @@ -4676,6 +4685,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
4676 MIPS_INVAL(opn); 4685 MIPS_INVAL(opn);
4677 generate_exception(ctx, EXCP_RI); 4686 generate_exception(ctx, EXCP_RI);
4678 } else { 4687 } else {
  4688 + save_cpu_state(ctx, 1);
4679 gen_op_deret(); 4689 gen_op_deret();
4680 ctx->bstate = BS_EXCP; 4690 ctx->bstate = BS_EXCP;
4681 } 4691 }
@@ -6183,8 +6193,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -6183,8 +6193,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
6183 } 6193 }
6184 break; 6194 break;
6185 case OPC_CP0: 6195 case OPC_CP0:
6186 - save_cpu_state(ctx, 1);  
6187 - gen_op_cp0_enabled(); 6196 + check_cp0_enabled(ctx);
6188 op1 = MASK_CP0(ctx->opcode); 6197 op1 = MASK_CP0(ctx->opcode);
6189 switch (op1) { 6198 switch (op1) {
6190 case OPC_MFC0: 6199 case OPC_MFC0:
@@ -6221,12 +6230,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -6221,12 +6230,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
6221 break; 6230 break;
6222 case OPC_DI: 6231 case OPC_DI:
6223 check_insn(env, ctx, ISA_MIPS32R2); 6232 check_insn(env, ctx, ISA_MIPS32R2);
  6233 + save_cpu_state(ctx, 1);
6224 gen_op_di(); 6234 gen_op_di();
6225 /* Stop translation as we may have switched the execution mode */ 6235 /* Stop translation as we may have switched the execution mode */
6226 ctx->bstate = BS_STOP; 6236 ctx->bstate = BS_STOP;
6227 break; 6237 break;
6228 case OPC_EI: 6238 case OPC_EI:
6229 check_insn(env, ctx, ISA_MIPS32R2); 6239 check_insn(env, ctx, ISA_MIPS32R2);
  6240 + save_cpu_state(ctx, 1);
6230 gen_op_ei(); 6241 gen_op_ei();
6231 /* Stop translation as we may have switched the execution mode */ 6242 /* Stop translation as we may have switched the execution mode */
6232 ctx->bstate = BS_STOP; 6243 ctx->bstate = BS_STOP;
@@ -6747,7 +6758,6 @@ void cpu_reset (CPUMIPSState *env) @@ -6747,7 +6758,6 @@ void cpu_reset (CPUMIPSState *env)
6747 } else { 6758 } else {
6748 env->CP0_ErrorEPC = env->PC[env->current_tc]; 6759 env->CP0_ErrorEPC = env->PC[env->current_tc];
6749 } 6760 }
6750 - env->hflags = 0;  
6751 env->PC[env->current_tc] = (int32_t)0xBFC00000; 6761 env->PC[env->current_tc] = (int32_t)0xBFC00000;
6752 env->CP0_Wired = 0; 6762 env->CP0_Wired = 0;
6753 /* SMP not implemented */ 6763 /* SMP not implemented */
@@ -6771,8 +6781,10 @@ void cpu_reset (CPUMIPSState *env) @@ -6771,8 +6781,10 @@ void cpu_reset (CPUMIPSState *env)
6771 #endif 6781 #endif
6772 env->exception_index = EXCP_NONE; 6782 env->exception_index = EXCP_NONE;
6773 #if defined(CONFIG_USER_ONLY) 6783 #if defined(CONFIG_USER_ONLY)
6774 - env->hflags |= MIPS_HFLAG_UM; 6784 + env->hflags = MIPS_HFLAG_UM;
6775 env->user_mode_only = 1; 6785 env->user_mode_only = 1;
  6786 +#else
  6787 + env->hflags = MIPS_HFLAG_CP0;
6776 #endif 6788 #endif
6777 } 6789 }
6778 6790