Commit 66f1cdbde44b82e53b5337981f38ca9e837cd5f7

Authored by blueswir1
1 parent d07bde88

Partial fix to Sparc32 Linux host global register mangling problem


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3806 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile.target
... ... @@ -161,7 +161,7 @@ ifeq ($(ARCH),sparc)
161 161 OP_CFLAGS+=-fno-omit-frame-pointer
162 162 else
163 163 BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
164   - HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
  164 + HELPER_CFLAGS=$(CFLAGS) -ffixed-i0
165 165 # -static is used to avoid g1/g3 usage by the dynamic linker
166 166 BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
167 167 endif
... ...
cpu-exec.c
... ... @@ -40,6 +40,52 @@ int tb_invalidated_flag;
40 40 //#define DEBUG_EXEC
41 41 //#define DEBUG_SIGNAL
42 42  
  43 +#define SAVE_GLOBALS()
  44 +#define RESTORE_GLOBALS()
  45 +
  46 +#if defined(__sparc__) && !defined(HOST_SOLARIS)
  47 +#include <features.h>
  48 +#if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
  49 + ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
  50 +// Work around ugly bugs in glibc that mangle global register contents
  51 +
  52 +static volatile void *saved_env;
  53 +static volatile unsigned long saved_t0, saved_i7;
  54 +#undef SAVE_GLOBALS
  55 +#define SAVE_GLOBALS() do { \
  56 + saved_env = env; \
  57 + saved_t0 = T0; \
  58 + asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7)); \
  59 + } while(0)
  60 +
  61 +#undef RESTORE_GLOBALS
  62 +#define RESTORE_GLOBALS() do { \
  63 + env = (void *)saved_env; \
  64 + T0 = saved_t0; \
  65 + asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7)); \
  66 + } while(0)
  67 +
  68 +static int sparc_setjmp(jmp_buf buf)
  69 +{
  70 + int ret;
  71 +
  72 + SAVE_GLOBALS();
  73 + ret = setjmp(buf);
  74 + RESTORE_GLOBALS();
  75 + return ret;
  76 +}
  77 +#undef setjmp
  78 +#define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
  79 +
  80 +static void sparc_longjmp(jmp_buf buf, int val)
  81 +{
  82 + SAVE_GLOBALS();
  83 + longjmp(buf, val);
  84 +}
  85 +#define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
  86 +#endif
  87 +#endif
  88 +
43 89 void cpu_loop_exit(void)
44 90 {
45 91 /* NOTE: the register at this point must be saved by hand because
... ... @@ -133,7 +179,9 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
133 179 tb->tc_ptr = tc_ptr;
134 180 tb->cs_base = cs_base;
135 181 tb->flags = flags;
  182 + SAVE_GLOBALS();
136 183 cpu_gen_code(env, tb, &code_gen_size);
  184 + RESTORE_GLOBALS();
137 185 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
138 186  
139 187 /* check next page if needed */
... ... @@ -232,11 +280,7 @@ static inline TranslationBlock *tb_find_fast(void)
232 280 return tb;
233 281 }
234 282  
235   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
236   -#define BREAK_CHAIN tmp_T0 = 0
237   -#else
238 283 #define BREAK_CHAIN T0 = 0
239   -#endif
240 284  
241 285 /* main execution loop */
242 286  
... ... @@ -249,10 +293,6 @@ int cpu_exec(CPUState *env1)
249 293 uint32_t *saved_regwptr;
250 294 #endif
251 295 #endif
252   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
253   - int saved_i7;
254   - target_ulong tmp_T0;
255   -#endif
256 296 int ret, interrupt_request;
257 297 void (*gen_func)(void);
258 298 TranslationBlock *tb;
... ... @@ -267,10 +307,7 @@ int cpu_exec(CPUState *env1)
267 307 #define SAVE_HOST_REGS 1
268 308 #include "hostregs_helper.h"
269 309 env = env1;
270   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
271   - /* we also save i7 because longjmp may not restore it */
272   - asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
273   -#endif
  310 + SAVE_GLOBALS();
274 311  
275 312 env_to_regs();
276 313 #if defined(TARGET_I386)
... ... @@ -380,10 +417,7 @@ int cpu_exec(CPUState *env1)
380 417  
381 418 T0 = 0; /* force lookup of first TB */
382 419 for(;;) {
383   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
384   - /* g1 can be modified by some libc? functions */
385   - tmp_T0 = T0;
386   -#endif
  420 + SAVE_GLOBALS();
387 421 interrupt_request = env->interrupt_request;
388 422 if (__builtin_expect(interrupt_request, 0)
389 423 #if defined(TARGET_I386)
... ... @@ -597,9 +631,7 @@ int cpu_exec(CPUState *env1)
597 631 lookup_symbol(tb->pc));
598 632 }
599 633 #endif
600   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
601   - T0 = tmp_T0;
602   -#endif
  634 + RESTORE_GLOBALS();
603 635 /* see if we can patch the calling TB. When the TB
604 636 spans two pages, we cannot safely do a direct
605 637 jump. */
... ... @@ -695,9 +727,7 @@ int cpu_exec(CPUState *env1)
695 727 #endif
696 728  
697 729 /* restore global registers */
698   -#if defined(__sparc__) && !defined(HOST_SOLARIS)
699   - asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
700   -#endif
  730 + RESTORE_GLOBALS();
701 731 #include "hostregs_helper.h"
702 732  
703 733 /* fail safe : never use cpu_single_env outside cpu_exec() */
... ...
target-sparc/op.c
... ... @@ -1244,12 +1244,14 @@ void OPPROTO op_exception(void)
1244 1244 {
1245 1245 env->exception_index = PARAM1;
1246 1246 cpu_loop_exit();
  1247 + FORCE_RET();
1247 1248 }
1248 1249  
1249 1250 void OPPROTO op_trap_T0(void)
1250 1251 {
1251 1252 env->exception_index = TT_TRAP + (T0 & 0x7f);
1252 1253 cpu_loop_exit();
  1254 + FORCE_RET();
1253 1255 }
1254 1256  
1255 1257 void OPPROTO op_trapcc_T0(void)
... ...