Hi all, Currently hflags is computed at three different places of the code, with a few minor differences.
The patch below adds a compute_hflags() function which does the same job. I am not sure the code is faster, but at least that makes the code more maintainable. It also fixes two small bugs: - The current code assume that writting CP0 Status only allow a transition from kernel to userland. This is wrong in some rare cases when CP0 is accessible as a user. - When leaving debug mode, MIPS_HFLAG_DM should be cleared, not set. Bye, Aurelien Index: target-mips/exec.h =================================================================== RCS file: /sources/qemu/qemu/target-mips/exec.h,v retrieving revision 1.32 diff -u -d -p -r1.32 exec.h --- target-mips/exec.h 16 Sep 2007 21:08:03 -0000 1.32 +++ target-mips/exec.h 25 Sep 2007 15:40:11 -0000 @@ -95,6 +95,7 @@ void do_mfc0_count(void); void do_mtc0_entryhi(uint32_t in); void do_mtc0_status_debug(uint32_t old, uint32_t val); void do_mtc0_status_irqraise_debug(void); +void compute_hflags(CPUState *env); void dump_fpu(CPUState *env); void fpu_dump_state(CPUState *env, FILE *f, int (*fpu_fprintf)(FILE *f, const char *fmt, ...), Index: target-mips/helper.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/helper.c,v retrieving revision 1.50 diff -u -d -p -r1.50 helper.c --- target-mips/helper.c 25 Sep 2007 14:49:46 -0000 1.50 +++ target-mips/helper.c 25 Sep 2007 15:40:11 -0000 @@ -368,10 +368,8 @@ void do_interrupt (CPUState *env) env->CP0_DEPC = env->PC[env->current_tc]; } enter_debug_mode: - env->hflags |= MIPS_HFLAG_DM; - env->hflags |= MIPS_HFLAG_64; + env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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); @@ -396,9 +394,8 @@ void do_interrupt (CPUState *env) env->CP0_ErrorEPC = env->PC[env->current_tc]; } env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV); - env->hflags |= MIPS_HFLAG_64; + env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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,9 +496,8 @@ void do_interrupt (CPUState *env) env->CP0_Cause &= ~(1 << CP0Ca_BD); } env->CP0_Status |= (1 << CP0St_EXL); - env->hflags |= MIPS_HFLAG_64; + env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0; 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.73 diff -u -d -p -r1.73 op.c --- target-mips/op.c 25 Sep 2007 14:49:47 -0000 1.73 +++ target-mips/op.c 25 Sep 2007 15:40:11 -0000 @@ -1841,30 +1841,8 @@ void op_mtc0_status (void) val = T0 & mask; old = env->CP0_Status; - if (!(val & (1 << CP0St_EXL)) && - !(val & (1 << CP0St_ERL)) && - !(env->hflags & MIPS_HFLAG_DM) && - (val & (1 << CP0St_UM))) - env->hflags |= MIPS_HFLAG_UM; -#ifdef TARGET_MIPS64 - if ((env->hflags & MIPS_HFLAG_UM) && - !(val & (1 << CP0St_PX)) && - !(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 - env->hflags &= ~MIPS_HFLAG_FPU; - if (val & (1 << CP0St_FR)) - env->hflags |= MIPS_HFLAG_F64; - else - env->hflags &= ~MIPS_HFLAG_F64; env->CP0_Status = (env->CP0_Status & ~mask) | val; + CALL_FROM_TB1(compute_hflags, env); if (loglevel & CPU_LOG_EXEC) CALL_FROM_TB2(do_mtc0_status_debug, old, val); CALL_FROM_TB1(cpu_mips_update_irq, env); @@ -3002,21 +2980,7 @@ void op_eret (void) env->PC[env->current_tc] = env->CP0_EPC; env->CP0_Status &= ~(1 << CP0St_EXL); } - if (!(env->CP0_Status & (1 << CP0St_EXL)) && - !(env->CP0_Status & (1 << CP0St_ERL)) && - !(env->hflags & MIPS_HFLAG_DM) && - (env->CP0_Status & (1 << CP0St_UM))) - env->hflags |= MIPS_HFLAG_UM; -#ifdef TARGET_MIPS64 - if ((env->hflags & MIPS_HFLAG_UM) && - !(env->CP0_Status & (1 << CP0St_PX)) && - !(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; + CALL_FROM_TB1(compute_hflags, env); if (loglevel & CPU_LOG_EXEC) CALL_FROM_TB0(debug_post_eret); env->CP0_LLAddr = 1; @@ -3028,22 +2992,8 @@ void op_deret (void) if (loglevel & CPU_LOG_EXEC) CALL_FROM_TB0(debug_pre_eret); env->PC[env->current_tc] = env->CP0_DEPC; - env->hflags |= MIPS_HFLAG_DM; - if (!(env->CP0_Status & (1 << CP0St_EXL)) && - !(env->CP0_Status & (1 << CP0St_ERL)) && - !(env->hflags & MIPS_HFLAG_DM) && - (env->CP0_Status & (1 << CP0St_UM))) - env->hflags |= MIPS_HFLAG_UM; -#ifdef TARGET_MIPS64 - if ((env->hflags & MIPS_HFLAG_UM) && - !(env->CP0_Status & (1 << CP0St_PX)) && - !(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; + env->hflags &= MIPS_HFLAG_DM; + CALL_FROM_TB1(compute_hflags, env); if (loglevel & CPU_LOG_EXEC) CALL_FROM_TB0(debug_post_eret); env->CP0_LLAddr = 1; Index: target-mips/op_helper.c =================================================================== RCS file: /sources/qemu/qemu/target-mips/op_helper.c,v retrieving revision 1.59 diff -u -d -p -r1.59 op_helper.c --- target-mips/op_helper.c 17 Sep 2007 08:09:53 -0000 1.59 +++ target-mips/op_helper.c 25 Sep 2007 15:40:12 -0000 @@ -313,6 +313,29 @@ void do_mtc0_status_irqraise_debug(void) fprintf(logfile, "Raise pending IRQs\n"); } +void compute_hflags(CPUState *env) +{ + env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 | + MIPS_HFLAG_FPU | MIPS_HFLAG_UM); + if (!(env->CP0_Status & (1 << CP0St_EXL)) && + !(env->CP0_Status & (1 << CP0St_ERL)) && + !(env->hflags & MIPS_HFLAG_DM) && + (env->CP0_Status & (1 << CP0St_UM))) + env->hflags |= MIPS_HFLAG_UM; +#ifdef TARGET_MIPS64 + if (!(env->hflags & MIPS_HFLAG_UM) || + (env->CP0_Status & (1 << CP0St_PX)) || + (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; + if (env->CP0_Status & (1 << CP0St_CU1)) + env->hflags |= MIPS_HFLAG_FPU; + if (env->CP0_Status & (1 << CP0St_FR)) + env->hflags |= MIPS_HFLAG_F64; +} + void fpu_handle_exception(void) { #ifdef CONFIG_SOFTFLOAT -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' [EMAIL PROTECTED] | [EMAIL PROTECTED] `- people.debian.org/~aurel32 | www.aurel32.net