diff --git a/cpu-exec.c b/cpu-exec.c index c3d99d4181..51cd2fae22 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -40,14 +40,14 @@ int tb_invalidated_flag; //#define DEBUG_EXEC //#define DEBUG_SIGNAL -#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K) || \ - defined(TARGET_ALPHA) -/* XXX: unify with i386 target */ void cpu_loop_exit(void) { + /* NOTE: the register at this point must be saved by hand because + longjmp restore them */ + regs_to_env(); longjmp(env->jmp_env, 1); } -#endif + #if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K)) #define reg_T2 #endif @@ -249,65 +249,8 @@ int cpu_exec(CPUState *env1) TranslationBlock *tb; uint8_t *tc_ptr; -#if defined(TARGET_I386) - /* handle exit of HALTED state */ - if (env1->hflags & HF_HALTED_MASK) { - /* disable halt condition */ - if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && - (env1->eflags & IF_MASK)) { - env1->hflags &= ~HF_HALTED_MASK; - } else { - return EXCP_HALTED; - } - } -#elif defined(TARGET_PPC) - if (env1->halted) { - if (env1->msr[MSR_EE] && - (env1->interrupt_request & CPU_INTERRUPT_HARD)) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#elif defined(TARGET_SPARC) - if (env1->halted) { - if ((env1->interrupt_request & CPU_INTERRUPT_HARD) && - (env1->psret != 0)) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#elif defined(TARGET_ARM) - if (env1->halted) { - /* An interrupt wakes the CPU even if the I and F CPSR bits are - set. We use EXITTB to silently wake CPU without causing an - actual interrupt. */ - if (env1->interrupt_request & - (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#elif defined(TARGET_MIPS) - if (env1->halted) { - if (env1->interrupt_request & - (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#elif defined(TARGET_ALPHA) || defined(TARGET_M68K) - if (env1->halted) { - if (env1->interrupt_request & CPU_INTERRUPT_HARD) { - env1->halted = 0; - } else { - return EXCP_HALTED; - } - } -#endif + if (cpu_halted(env1) == EXCP_HALTED) + return EXCP_HALTED; cpu_single_env = env1; diff --git a/target-alpha/exec.h b/target-alpha/exec.h index f109160a51..32c27c7354 100644 --- a/target-alpha/exec.h +++ b/target-alpha/exec.h @@ -79,4 +79,14 @@ int cpu_alpha_mtpr (CPUState *env, int iprn, uint64_t val, uint64_t *oldvalp); void do_interrupt (CPUState *env); +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + if (env->interrupt_request & CPU_INTERRUPT_HARD) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} + #endif /* !defined (__ALPHA_EXEC_H__) */ diff --git a/target-arm/exec.h b/target-arm/exec.h index d99dfa5f0f..b25c7e2d47 100644 --- a/target-arm/exec.h +++ b/target-arm/exec.h @@ -48,6 +48,20 @@ static inline void regs_to_env(void) int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu); +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + /* An interrupt wakes the CPU even if the I and F CPSR bits are + set. We use EXITTB to silently wake CPU without causing an + actual interrupt. */ + if (env->interrupt_request & + (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB)) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} + #if !defined(CONFIG_USER_ONLY) #include "softmmu_exec.h" #endif diff --git a/target-i386/exec.h b/target-i386/exec.h index 377f7bd28b..f1cf2b9234 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -575,3 +575,16 @@ static inline void regs_to_env(void) env->regs[R_EDI] = EDI; #endif } + +static inline int cpu_halted(CPUState *env) { + /* handle exit of HALTED state */ + if (env->hflags & HF_HALTED_MASK) + return 0; + /* disable halt condition */ + if ((env->interrupt_request & CPU_INTERRUPT_HARD) && + (env->eflags & IF_MASK)) { + env->hflags &= ~HF_HALTED_MASK; + return 0; + } + return EXCP_HALTED; +} diff --git a/target-i386/helper.c b/target-i386/helper.c index ef4b77e88f..951fdc5732 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -106,14 +106,6 @@ void cpu_unlock(void) spin_unlock(&global_cpu_lock); } -void cpu_loop_exit(void) -{ - /* NOTE: the register at this point must be saved by hand because - longjmp restore them */ - regs_to_env(); - longjmp(env->jmp_env, 1); -} - /* return non zero if error */ static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr, int selector) diff --git a/target-m68k/exec.h b/target-m68k/exec.h index 254f5581ff..331844b413 100644 --- a/target-m68k/exec.h +++ b/target-m68k/exec.h @@ -49,3 +49,13 @@ float64 helper_sub_cmpf64(CPUM68KState *env, float64 src0, float64 src1); void helper_movec(CPUM68KState *env, int reg, uint32_t val); void cpu_loop_exit(void); + +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + if (env->interrupt_request & CPU_INTERRUPT_HARD) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} diff --git a/target-mips/exec.h b/target-mips/exec.h index 6d004102bb..5b0c833848 100644 --- a/target-mips/exec.h +++ b/target-mips/exec.h @@ -56,14 +56,6 @@ register target_ulong T2 asm(AREG3); #include "softmmu_exec.h" #endif /* !defined(CONFIG_USER_ONLY) */ -static inline void env_to_regs(void) -{ -} - -static inline void regs_to_env(void) -{ -} - #ifdef TARGET_MIPS64 #if TARGET_LONG_BITS > HOST_LONG_BITS void do_dsll (void); @@ -240,4 +232,23 @@ FOP_PROTO(le) FOP_PROTO(ngt) #undef FOP_PROTO +static inline void env_to_regs(void) +{ +} + +static inline void regs_to_env(void) +{ +} + +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + if (env->interrupt_request & + (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} + #endif /* !defined(__QEMU_MIPS_EXEC_H__) */ diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index da28645973..c169beb55a 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -24,10 +24,6 @@ /*****************************************************************************/ /* Exceptions processing helpers */ -void cpu_loop_exit(void) -{ - longjmp(env->jmp_env, 1); -} void do_raise_exception_err (uint32_t exception, int error_code) { diff --git a/target-ppc/exec.h b/target-ppc/exec.h index 4f5abe906a..ee5183eb72 100644 --- a/target-ppc/exec.h +++ b/target-ppc/exec.h @@ -122,4 +122,14 @@ static inline void regs_to_env(void) int cpu_ppc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu); +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + if (env->msr[MSR_EE] && (env->interrupt_request & CPU_INTERRUPT_HARD)) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} + #endif /* !defined (__PPC_H__) */ diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index ee46253c79..63180b61e1 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -40,10 +40,6 @@ /*****************************************************************************/ /* Exceptions processing helpers */ -void cpu_loop_exit (void) -{ - longjmp(env->jmp_env, 1); -} void do_raise_exception_err (uint32_t exception, int error_code) { diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c index f02fa588fc..bf39921b4d 100644 --- a/target-sh4/op_helper.c +++ b/target-sh4/op_helper.c @@ -20,11 +20,6 @@ #include #include "exec.h" -void cpu_loop_exit(void) -{ - longjmp(env->jmp_env, 1); -} - void do_raise_exception(void) { cpu_loop_exit(); diff --git a/target-sparc/exec.h b/target-sparc/exec.h index 8a9fa89ec6..0305a0498f 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -115,4 +115,14 @@ static inline void regs_to_env(void) int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu); +static inline int cpu_halted(CPUState *env) { + if (!env->halted) + return 0; + if ((env->interrupt_request & CPU_INTERRUPT_HARD) && (env->psret != 0)) { + env->halted = 0; + return 0; + } + return EXCP_HALTED; +} + #endif