From 0d1a29f9fcd161b07a02b9256446235208d379ca Mon Sep 17 00:00:00 2001 From: bellard Date: Tue, 12 Oct 2004 22:01:28 +0000 Subject: [PATCH] correct handling of saved host registers git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162 --- cpu-exec.c | 14 +++----- dyngen-exec.h | 3 -- target-arm/exec.h | 8 +++++ target-i386/exec.h | 57 +++++++++++++++++++++++++++++++- target-i386/helper.c | 77 +++++++++++++++++++++++++------------------- target-ppc/exec.h | 8 +++++ target-sparc/exec.h | 9 ++++++ 7 files changed, 129 insertions(+), 47 deletions(-) diff --git a/cpu-exec.c b/cpu-exec.c index 5229eaa895..b98c22c58e 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -123,37 +123,30 @@ int cpu_exec(CPUState *env1) #if defined(TARGET_I386) #ifdef reg_EAX saved_EAX = EAX; - EAX = env->regs[R_EAX]; #endif #ifdef reg_ECX saved_ECX = ECX; - ECX = env->regs[R_ECX]; #endif #ifdef reg_EDX saved_EDX = EDX; - EDX = env->regs[R_EDX]; #endif #ifdef reg_EBX saved_EBX = EBX; - EBX = env->regs[R_EBX]; #endif #ifdef reg_ESP saved_ESP = ESP; - ESP = env->regs[R_ESP]; #endif #ifdef reg_EBP saved_EBP = EBP; - EBP = env->regs[R_EBP]; #endif #ifdef reg_ESI saved_ESI = ESI; - ESI = env->regs[R_ESI]; #endif #ifdef reg_EDI saved_EDI = EDI; - EDI = env->regs[R_EDI]; #endif - + + env_to_regs(); /* put eflags in CPU temporary format */ CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); DF = 1 - (2 * ((env->eflags >> 10) & 1)); @@ -353,6 +346,8 @@ int cpu_exec(CPUState *env1) spin_lock(&tb_lock); tb_invalidated_flag = 0; + + regs_to_env(); /* XXX: do it just before cpu_gen_code() */ /* find translated block using physical mappings */ phys_pc = get_phys_addr_code(env, (unsigned long)pc); @@ -556,6 +551,7 @@ int cpu_exec(CPUState *env1) #endif } } else { + env_to_regs(); } } /* for(;;) */ diff --git a/dyngen-exec.h b/dyngen-exec.h index 86087ca623..1a3bb2a181 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -93,8 +93,6 @@ extern int printf(const char *, ...); #define AREG1 "r24" #define AREG2 "r25" #define AREG3 "r26" -/* XXX: suppress this hack */ -#if defined(CONFIG_USER_ONLY) #define AREG4 "r16" #define AREG5 "r17" #define AREG6 "r18" @@ -103,7 +101,6 @@ extern int printf(const char *, ...); #define AREG9 "r21" #define AREG10 "r22" #define AREG11 "r23" -#endif #define USE_INT_TO_FLOAT_HELPERS #define BUGGY_GCC_DIV64 #endif diff --git a/target-arm/exec.h b/target-arm/exec.h index 70afdc5d95..14e2072e6c 100644 --- a/target-arm/exec.h +++ b/target-arm/exec.h @@ -38,3 +38,11 @@ static inline int compute_cpsr(void) return env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) | (env->CF << 29) | ((env->VF & 0x80000000) >> 3); } + +static inline void env_to_regs(void) +{ +} + +static inline void regs_to_env(void) +{ +} diff --git a/target-i386/exec.h b/target-i386/exec.h index 680e580b7f..61af5468e7 100644 --- a/target-i386/exec.h +++ b/target-i386/exec.h @@ -20,7 +20,7 @@ #include "config.h" #include "dyngen-exec.h" -/* at least 4 register variables are defines */ +/* at least 4 register variables are defined */ register struct CPUX86State *env asm(AREG0); register uint32_t T0 asm(AREG1); register uint32_t T1 asm(AREG2); @@ -546,3 +546,58 @@ static inline void load_eflags(int eflags, int update_mask) (eflags & update_mask); } +static inline void env_to_regs(void) +{ +#ifdef reg_EAX + EAX = env->regs[R_EAX]; +#endif +#ifdef reg_ECX + ECX = env->regs[R_ECX]; +#endif +#ifdef reg_EDX + EDX = env->regs[R_EDX]; +#endif +#ifdef reg_EBX + EBX = env->regs[R_EBX]; +#endif +#ifdef reg_ESP + ESP = env->regs[R_ESP]; +#endif +#ifdef reg_EBP + EBP = env->regs[R_EBP]; +#endif +#ifdef reg_ESI + ESI = env->regs[R_ESI]; +#endif +#ifdef reg_EDI + EDI = env->regs[R_EDI]; +#endif +} + +static inline void regs_to_env(void) +{ +#ifdef reg_EAX + env->regs[R_EAX] = EAX; +#endif +#ifdef reg_ECX + env->regs[R_ECX] = ECX; +#endif +#ifdef reg_EDX + env->regs[R_EDX] = EDX; +#endif +#ifdef reg_EBX + env->regs[R_EBX] = EBX; +#endif +#ifdef reg_ESP + env->regs[R_ESP] = ESP; +#endif +#ifdef reg_EBP + env->regs[R_EBP] = EBP; +#endif +#ifdef reg_ESI + env->regs[R_ESI] = ESI; +#endif +#ifdef reg_EDI + env->regs[R_EDI] = EDI; +#endif +} diff --git a/target-i386/helper.c b/target-i386/helper.c index 7035e1cb9f..41ebaf221e 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -109,30 +109,7 @@ void cpu_loop_exit(void) { /* NOTE: the register at this point must be saved by hand because longjmp restore them */ -#ifdef reg_EAX - env->regs[R_EAX] = EAX; -#endif -#ifdef reg_ECX - env->regs[R_ECX] = ECX; -#endif -#ifdef reg_EDX - env->regs[R_EDX] = EDX; -#endif -#ifdef reg_EBX - env->regs[R_EBX] = EBX; -#endif -#ifdef reg_ESP - env->regs[R_ESP] = ESP; -#endif -#ifdef reg_EBP - env->regs[R_EBP] = EBP; -#endif -#ifdef reg_ESI - env->regs[R_ESI] = ESI; -#endif -#ifdef reg_EDI - env->regs[R_EDI] = EDI; -#endif + regs_to_env(); longjmp(env->jmp_env, 1); } @@ -384,16 +361,28 @@ static void switch_tss(int tss_selector, /* 32 bit */ stl_kernel(env->tr.base + 0x20, next_eip); stl_kernel(env->tr.base + 0x24, old_eflags); - for(i = 0; i < 8; i++) - stl_kernel(env->tr.base + (0x28 + i * 4), env->regs[i]); + stl_kernel(env->tr.base + (0x28 + 0 * 4), EAX); + stl_kernel(env->tr.base + (0x28 + 1 * 4), ECX); + stl_kernel(env->tr.base + (0x28 + 2 * 4), EDX); + stl_kernel(env->tr.base + (0x28 + 3 * 4), EBX); + stl_kernel(env->tr.base + (0x28 + 4 * 4), ESP); + stl_kernel(env->tr.base + (0x28 + 5 * 4), EBP); + stl_kernel(env->tr.base + (0x28 + 6 * 4), ESI); + stl_kernel(env->tr.base + (0x28 + 7 * 4), EDI); for(i = 0; i < 6; i++) stw_kernel(env->tr.base + (0x48 + i * 4), env->segs[i].selector); } else { /* 16 bit */ stw_kernel(env->tr.base + 0x0e, next_eip); stw_kernel(env->tr.base + 0x10, old_eflags); - for(i = 0; i < 8; i++) - stw_kernel(env->tr.base + (0x12 + i * 2), env->regs[i]); + stw_kernel(env->tr.base + (0x12 + 0 * 2), EAX); + stw_kernel(env->tr.base + (0x12 + 1 * 2), ECX); + stw_kernel(env->tr.base + (0x12 + 2 * 2), EDX); + stw_kernel(env->tr.base + (0x12 + 3 * 2), EBX); + stw_kernel(env->tr.base + (0x12 + 4 * 2), ESP); + stw_kernel(env->tr.base + (0x12 + 5 * 2), EBP); + stw_kernel(env->tr.base + (0x12 + 6 * 2), ESI); + stw_kernel(env->tr.base + (0x12 + 7 * 2), EDI); for(i = 0; i < 4; i++) stw_kernel(env->tr.base + (0x22 + i * 4), env->segs[i].selector); } @@ -437,8 +426,15 @@ static void switch_tss(int tss_selector, if (!(type & 8)) eflags_mask &= 0xffff; load_eflags(new_eflags, eflags_mask); - for(i = 0; i < 8; i++) - env->regs[i] = new_regs[i]; + /* XXX: what to do in 16 bit case ? */ + EAX = new_regs[0]; + ECX = new_regs[1]; + EDX = new_regs[2]; + EBX = new_regs[3]; + ESP = new_regs[4]; + EBP = new_regs[5]; + ESI = new_regs[6]; + EDI = new_regs[7]; if (new_eflags & VM_MASK) { for(i = 0; i < 6; i++) load_seg_vm(i, new_segs[i]); @@ -633,13 +629,13 @@ static void do_interrupt_protected(int intno, int is_int, int error_code, mask = 0xffffffff; else mask = 0xffff; - esp = (env->regs[R_ESP] - (2 << shift)) & mask; + esp = (ESP - (2 << shift)) & mask; ssp = env->segs[R_SS].base + esp; if (shift) stl_kernel(ssp, error_code); else stw_kernel(ssp, error_code); - env->regs[R_ESP] = (esp & mask) | (env->regs[R_ESP] & ~mask); + ESP = (esp & mask) | (ESP & ~mask); } return; case 6: /* 286 interrupt gate */ @@ -868,7 +864,7 @@ void do_interrupt(int intno, int is_int, int error_code, if (intno == 0x0e) { fprintf(logfile, " CR2=%08x", env->cr[2]); } else { - fprintf(logfile, " EAX=%08x", env->regs[R_EAX]); + fprintf(logfile, " EAX=%08x", EAX); } fprintf(logfile, "\n"); #if 0 @@ -911,6 +907,16 @@ void raise_interrupt(int intno, int is_int, int error_code, cpu_loop_exit(); } +/* same as raise_exception_err, but do not restore global registers */ +static void raise_exception_err_norestore(int exception_index, int error_code) +{ + env->exception_index = exception_index; + env->error_code = error_code; + env->exception_is_int = 0; + env->exception_next_eip = 0; + longjmp(env->jmp_env, 1); +} + /* shortcuts to generate exceptions */ void (raise_exception_err)(int exception_index, int error_code) @@ -2584,7 +2590,10 @@ void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) cpu_restore_state(tb, env, pc, NULL); } } - raise_exception_err(EXCP0E_PAGE, env->error_code); + if (retaddr) + raise_exception_err(EXCP0E_PAGE, env->error_code); + else + raise_exception_err_norestore(EXCP0E_PAGE, env->error_code); } env = saved_env; } diff --git a/target-ppc/exec.h b/target-ppc/exec.h index 6377907683..50c51502ce 100644 --- a/target-ppc/exec.h +++ b/target-ppc/exec.h @@ -165,4 +165,12 @@ void dump_store_dbat (int ul, int nr); void dump_store_tb (int ul); void dump_update_tb(uint32_t param); +static inline void env_to_regs(void) +{ +} + +static inline void regs_to_env(void) +{ +} + #endif /* !defined (__PPC_H__) */ diff --git a/target-sparc/exec.h b/target-sparc/exec.h index 941b22a741..1b3d9a0806 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -109,4 +109,13 @@ void memcpy32(uint32_t *dst, const uint32_t *src); #define stq(p, v) stq_data(p, v) #endif /* !defined(CONFIG_USER_ONLY) */ + +static inline void env_to_regs(void) +{ +} + +static inline void regs_to_env(void) +{ +} + #endif