From: pbrook Date: Sun, 4 Feb 2007 13:37:44 +0000 (+0000) Subject: Fix 64-bit host register corruption. X-Git-Tag: 0.10.0-0maemo1~3957 X-Git-Url: http://git.maemo.org/git/?a=commitdiff_plain;h=1057eaa709dba09d1c4f7a363877e635797e4623;p=qemu Fix 64-bit host register corruption. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2384 c046a42c-6fe2-441c-8c8c-71466251a162 --- diff --git a/cpu-exec.c b/cpu-exec.c index fcf0698..0b57f0f 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -226,37 +226,9 @@ static inline TranslationBlock *tb_find_fast(void) int cpu_exec(CPUState *env1) { - target_ulong saved_T0, saved_T1; -#if defined(reg_T2) - target_ulong saved_T2; -#endif - CPUState *saved_env; -#if defined(TARGET_I386) -#ifdef reg_EAX - int saved_EAX; -#endif -#ifdef reg_ECX - int saved_ECX; -#endif -#ifdef reg_EDX - int saved_EDX; -#endif -#ifdef reg_EBX - int saved_EBX; -#endif -#ifdef reg_ESP - int saved_ESP; -#endif -#ifdef reg_EBP - int saved_EBP; -#endif -#ifdef reg_ESI - int saved_ESI; -#endif -#ifdef reg_EDI - int saved_EDI; -#endif -#elif defined(TARGET_SPARC) +#define DECLARE_HOST_REGS 1 +#include "hostregs_helper.h" +#if defined(TARGET_SPARC) #if defined(reg_REGWPTR) uint32_t *saved_regwptr; #endif @@ -325,44 +297,15 @@ int cpu_exec(CPUState *env1) cpu_single_env = env1; /* first we save global registers */ - saved_env = env; +#define SAVE_HOST_REGS 1 +#include "hostregs_helper.h" env = env1; - saved_T0 = T0; - saved_T1 = T1; -#if defined(reg_T2) - saved_T2 = T2; -#endif #if defined(__sparc__) && !defined(HOST_SOLARIS) /* we also save i7 because longjmp may not restore it */ asm volatile ("mov %%i7, %0" : "=r" (saved_i7)); #endif #if defined(TARGET_I386) -#ifdef reg_EAX - saved_EAX = EAX; -#endif -#ifdef reg_ECX - saved_ECX = ECX; -#endif -#ifdef reg_EDX - saved_EDX = EDX; -#endif -#ifdef reg_EBX - saved_EBX = EBX; -#endif -#ifdef reg_ESP - saved_ESP = ESP; -#endif -#ifdef reg_EBP - saved_EBP = EBP; -#endif -#ifdef reg_ESI - saved_ESI = ESI; -#endif -#ifdef reg_EDI - saved_EDI = 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); @@ -827,32 +770,6 @@ int cpu_exec(CPUState *env1) #endif /* restore flags in standard format */ env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); - - /* restore global registers */ -#ifdef reg_EAX - EAX = saved_EAX; -#endif -#ifdef reg_ECX - ECX = saved_ECX; -#endif -#ifdef reg_EDX - EDX = saved_EDX; -#endif -#ifdef reg_EBX - EBX = saved_EBX; -#endif -#ifdef reg_ESP - ESP = saved_ESP; -#endif -#ifdef reg_EBP - EBP = saved_EBP; -#endif -#ifdef reg_ESI - ESI = saved_ESI; -#endif -#ifdef reg_EDI - EDI = saved_EDI; -#endif #elif defined(TARGET_ARM) /* XXX: Save/restore host fpu exception state?. */ #elif defined(TARGET_SPARC) @@ -871,15 +788,13 @@ int cpu_exec(CPUState *env1) #else #error unsupported target CPU #endif + + /* restore global registers */ #if defined(__sparc__) && !defined(HOST_SOLARIS) asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); #endif - T0 = saved_T0; - T1 = saved_T1; -#if defined(reg_T2) - T2 = saved_T2; -#endif - env = saved_env; +#include "hostregs_helper.h" + /* fail safe : never use cpu_single_env outside cpu_exec() */ cpu_single_env = NULL; return ret; diff --git a/dyngen-exec.h b/dyngen-exec.h index 2f38785..7b313d6 100644 --- a/dyngen-exec.h +++ b/dyngen-exec.h @@ -62,6 +62,9 @@ typedef signed long long int64_t; #endif #endif +/* XXX: This may be wrong for 64-bit ILP32 hosts. */ +typedef void * host_reg_t; + #define INT8_MIN (-128) #define INT16_MIN (-32767-1) #define INT32_MIN (-2147483647-1) diff --git a/hostregs_helper.h b/hostregs_helper.h new file mode 100644 index 0000000..4fdf8ad --- /dev/null +++ b/hostregs_helper.h @@ -0,0 +1,98 @@ +/* + * Save/restore host registrs. + * + * Copyright (c) 2007 CodeSourcery + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* The GCC global register vairable extension is used to reserve some + host registers for use by dyngen. However only the core parts of the + translation engine are compiled with these settings. We must manually + save/restore these registers when called from regular code. + It is not sufficient to save/restore T0 et. al. as these may be declared + with a datatype smaller than the actual register. */ + +#if defined(DECLARE_HOST_REGS) + +#define DO_REG(REG) \ + register host_reg_t reg_AREG##REG asm(AREG##REG); \ + volatile host_reg_t saved_AREG##REG; + +#elif defined(SAVE_HOST_REGS) + +#define DO_REG(REG) \ + __asm__ __volatile__ ("" : "=r" (reg_AREG##REG)); \ + saved_AREG##REG = reg_AREG##REG; + +#else + +#define DO_REG(REG) \ + reg_AREG##REG = saved_AREG##REG; \ + __asm__ __volatile__ ("" : : "r" (reg_AREG##REG)); + +#endif + +#ifdef AREG0 +DO_REG(0) +#endif + +#ifdef AREG1 +DO_REG(1) +#endif + +#ifdef AREG2 +DO_REG(2) +#endif + +#ifdef AREG3 +DO_REG(3) +#endif + +#ifdef AREG4 +DO_REG(4) +#endif + +#ifdef AREG5 +DO_REG(5) +#endif + +#ifdef AREG6 +DO_REG(6) +#endif + +#ifdef AREG7 +DO_REG(7) +#endif + +#ifdef AREG8 +DO_REG(8) +#endif + +#ifdef AREG9 +DO_REG(9) +#endif + +#ifdef AREG10 +DO_REG(10) +#endif + +#ifdef AREG11 +DO_REG(11) +#endif + +#undef SAVE_HOST_REGS +#undef DECLARE_HOST_REGS +#undef DO_REG