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 | 414 | int user_mode_only; /* user mode only simulation */ |
415 | 415 | uint32_t hflags; /* CPU State */ |
416 | 416 | /* TMASK defines different execution modes */ |
417 | -#define MIPS_HFLAG_TMASK 0x007F | |
417 | +#define MIPS_HFLAG_TMASK 0x00FF | |
418 | 418 | #define MIPS_HFLAG_MODE 0x0007 /* execution modes */ |
419 | 419 | #define MIPS_HFLAG_UM 0x0001 /* user mode */ |
420 | 420 | #define MIPS_HFLAG_DM 0x0002 /* Debug mode */ |
421 | 421 | #define MIPS_HFLAG_SM 0x0004 /* Supervisor mode */ |
422 | 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 | 427 | /* If translation is interrupted between the branch instruction and |
427 | 428 | * the delay slot, record what type of branch it is so that we can |
428 | 429 | * resume translation properly. It might be possible to reduce |
429 | 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 | 436 | target_ulong btarget; /* Jump / branch target */ |
436 | 437 | int bcond; /* Branch condition (if needed) */ |
437 | 438 | ... | ... |
target-mips/helper.c
... | ... | @@ -371,6 +371,7 @@ void do_interrupt (CPUState *env) |
371 | 371 | env->hflags |= MIPS_HFLAG_DM; |
372 | 372 | env->hflags |= MIPS_HFLAG_64; |
373 | 373 | env->hflags &= ~MIPS_HFLAG_UM; |
374 | + env->hflags |= MIPS_HFLAG_CP0; | |
374 | 375 | /* EJTAG probe trap enable is not implemented... */ |
375 | 376 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
376 | 377 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
... | ... | @@ -397,6 +398,7 @@ void do_interrupt (CPUState *env) |
397 | 398 | env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); |
398 | 399 | env->hflags |= MIPS_HFLAG_64; |
399 | 400 | env->hflags &= ~MIPS_HFLAG_UM; |
401 | + env->hflags |= MIPS_HFLAG_CP0; | |
400 | 402 | if (!(env->CP0_Status & (1 << CP0St_EXL))) |
401 | 403 | env->CP0_Cause &= ~(1 << CP0Ca_BD); |
402 | 404 | env->PC[env->current_tc] = (int32_t)0xBFC00000; |
... | ... | @@ -499,6 +501,7 @@ void do_interrupt (CPUState *env) |
499 | 501 | env->CP0_Status |= (1 << CP0St_EXL); |
500 | 502 | env->hflags |= MIPS_HFLAG_64; |
501 | 503 | env->hflags &= ~MIPS_HFLAG_UM; |
504 | + env->hflags |= MIPS_HFLAG_CP0; | |
502 | 505 | } |
503 | 506 | env->hflags &= ~MIPS_HFLAG_BMASK; |
504 | 507 | if (env->CP0_Status & (1 << CP0St_BEV)) { | ... | ... |
target-mips/op.c
... | ... | @@ -1852,6 +1852,10 @@ void op_mtc0_status (void) |
1852 | 1852 | !(val & (1 << CP0St_UX))) |
1853 | 1853 | env->hflags &= ~MIPS_HFLAG_64; |
1854 | 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 | 1859 | if (val & (1 << CP0St_CU1)) |
1856 | 1860 | env->hflags |= MIPS_HFLAG_FPU; |
1857 | 1861 | else |
... | ... | @@ -2316,15 +2320,6 @@ void op_yield(void) |
2316 | 2320 | # define DEBUG_FPU_STATE() do { } while(0) |
2317 | 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 | 2323 | void op_cfc1 (void) |
2329 | 2324 | { |
2330 | 2325 | CALL_FROM_TB1(do_cfc1, PARAM1); |
... | ... | @@ -3018,6 +3013,10 @@ void op_eret (void) |
3018 | 3013 | !(env->CP0_Status & (1 << CP0St_UX))) |
3019 | 3014 | env->hflags &= ~MIPS_HFLAG_64; |
3020 | 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 | 3020 | if (loglevel & CPU_LOG_EXEC) |
3022 | 3021 | CALL_FROM_TB0(debug_post_eret); |
3023 | 3022 | env->CP0_LLAddr = 1; |
... | ... | @@ -3041,6 +3040,10 @@ void op_deret (void) |
3041 | 3040 | !(env->CP0_Status & (1 << CP0St_UX))) |
3042 | 3041 | env->hflags &= ~MIPS_HFLAG_64; |
3043 | 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 | 3047 | if (loglevel & CPU_LOG_EXEC) |
3045 | 3048 | CALL_FROM_TB0(debug_post_eret); |
3046 | 3049 | env->CP0_LLAddr = 1; |
... | ... | @@ -3049,9 +3052,8 @@ void op_deret (void) |
3049 | 3052 | |
3050 | 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 | 3057 | T0 = env->CP0_EBase & 0x3ff; |
3056 | 3058 | else |
3057 | 3059 | CALL_FROM_TB1(do_raise_exception, EXCP_RI); |
... | ... | @@ -3060,9 +3062,8 @@ void op_rdhwr_cpunum(void) |
3060 | 3062 | |
3061 | 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 | 3067 | T0 = env->SYNCI_Step; |
3067 | 3068 | else |
3068 | 3069 | CALL_FROM_TB1(do_raise_exception, EXCP_RI); |
... | ... | @@ -3071,9 +3072,8 @@ void op_rdhwr_synci_step(void) |
3071 | 3072 | |
3072 | 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 | 3077 | T0 = env->CP0_Count; |
3078 | 3078 | else |
3079 | 3079 | CALL_FROM_TB1(do_raise_exception, EXCP_RI); |
... | ... | @@ -3082,9 +3082,8 @@ void op_rdhwr_cc(void) |
3082 | 3082 | |
3083 | 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 | 3087 | T0 = env->CCRes; |
3089 | 3088 | else |
3090 | 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 | 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 | 740 | static inline void check_cp1_enabled(DisasContext *ctx) |
735 | 741 | { |
736 | 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 | 4606 | break; |
4601 | 4607 | case OPC_MTC0: |
4602 | 4608 | GEN_LOAD_REG_TN(T0, rt); |
4609 | + save_cpu_state(ctx, 1); | |
4603 | 4610 | gen_mtc0(env, ctx, rd, ctx->opcode & 0x7); |
4604 | 4611 | opn = "mtc0"; |
4605 | 4612 | break; |
... | ... | @@ -4617,6 +4624,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4617 | 4624 | case OPC_DMTC0: |
4618 | 4625 | check_insn(env, ctx, ISA_MIPS3); |
4619 | 4626 | GEN_LOAD_REG_TN(T0, rt); |
4627 | + save_cpu_state(ctx, 1); | |
4620 | 4628 | gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7); |
4621 | 4629 | opn = "dmtc0"; |
4622 | 4630 | break; |
... | ... | @@ -4666,6 +4674,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4666 | 4674 | case OPC_ERET: |
4667 | 4675 | opn = "eret"; |
4668 | 4676 | check_insn(env, ctx, ISA_MIPS2); |
4677 | + save_cpu_state(ctx, 1); | |
4669 | 4678 | gen_op_eret(); |
4670 | 4679 | ctx->bstate = BS_EXCP; |
4671 | 4680 | break; |
... | ... | @@ -4676,6 +4685,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int |
4676 | 4685 | MIPS_INVAL(opn); |
4677 | 4686 | generate_exception(ctx, EXCP_RI); |
4678 | 4687 | } else { |
4688 | + save_cpu_state(ctx, 1); | |
4679 | 4689 | gen_op_deret(); |
4680 | 4690 | ctx->bstate = BS_EXCP; |
4681 | 4691 | } |
... | ... | @@ -6183,8 +6193,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6183 | 6193 | } |
6184 | 6194 | break; |
6185 | 6195 | case OPC_CP0: |
6186 | - save_cpu_state(ctx, 1); | |
6187 | - gen_op_cp0_enabled(); | |
6196 | + check_cp0_enabled(ctx); | |
6188 | 6197 | op1 = MASK_CP0(ctx->opcode); |
6189 | 6198 | switch (op1) { |
6190 | 6199 | case OPC_MFC0: |
... | ... | @@ -6221,12 +6230,14 @@ static void decode_opc (CPUState *env, DisasContext *ctx) |
6221 | 6230 | break; |
6222 | 6231 | case OPC_DI: |
6223 | 6232 | check_insn(env, ctx, ISA_MIPS32R2); |
6233 | + save_cpu_state(ctx, 1); | |
6224 | 6234 | gen_op_di(); |
6225 | 6235 | /* Stop translation as we may have switched the execution mode */ |
6226 | 6236 | ctx->bstate = BS_STOP; |
6227 | 6237 | break; |
6228 | 6238 | case OPC_EI: |
6229 | 6239 | check_insn(env, ctx, ISA_MIPS32R2); |
6240 | + save_cpu_state(ctx, 1); | |
6230 | 6241 | gen_op_ei(); |
6231 | 6242 | /* Stop translation as we may have switched the execution mode */ |
6232 | 6243 | ctx->bstate = BS_STOP; |
... | ... | @@ -6747,7 +6758,6 @@ void cpu_reset (CPUMIPSState *env) |
6747 | 6758 | } else { |
6748 | 6759 | env->CP0_ErrorEPC = env->PC[env->current_tc]; |
6749 | 6760 | } |
6750 | - env->hflags = 0; | |
6751 | 6761 | env->PC[env->current_tc] = (int32_t)0xBFC00000; |
6752 | 6762 | env->CP0_Wired = 0; |
6753 | 6763 | /* SMP not implemented */ |
... | ... | @@ -6771,8 +6781,10 @@ void cpu_reset (CPUMIPSState *env) |
6771 | 6781 | #endif |
6772 | 6782 | env->exception_index = EXCP_NONE; |
6773 | 6783 | #if defined(CONFIG_USER_ONLY) |
6774 | - env->hflags |= MIPS_HFLAG_UM; | |
6784 | + env->hflags = MIPS_HFLAG_UM; | |
6775 | 6785 | env->user_mode_only = 1; |
6786 | +#else | |
6787 | + env->hflags = MIPS_HFLAG_CP0; | |
6776 | 6788 | #endif |
6777 | 6789 | } |
6778 | 6790 | ... | ... |