Commit 387a8fe505dd733968a798c9d3b88fbdd5f93056
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
Showing
4 changed files
with
49 additions
and
34 deletions
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 |