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
This commit is contained in:
parent
d07bde88a5
commit
66f1cdbde4
|
@ -161,7 +161,7 @@ ifeq ($(ARCH),sparc)
|
||||||
OP_CFLAGS+=-fno-omit-frame-pointer
|
OP_CFLAGS+=-fno-omit-frame-pointer
|
||||||
else
|
else
|
||||||
BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
|
BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
|
||||||
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
|
HELPER_CFLAGS=$(CFLAGS) -ffixed-i0
|
||||||
# -static is used to avoid g1/g3 usage by the dynamic linker
|
# -static is used to avoid g1/g3 usage by the dynamic linker
|
||||||
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
|
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
|
||||||
endif
|
endif
|
||||||
|
|
74
cpu-exec.c
74
cpu-exec.c
|
@ -40,6 +40,52 @@ int tb_invalidated_flag;
|
||||||
//#define DEBUG_EXEC
|
//#define DEBUG_EXEC
|
||||||
//#define DEBUG_SIGNAL
|
//#define DEBUG_SIGNAL
|
||||||
|
|
||||||
|
#define SAVE_GLOBALS()
|
||||||
|
#define RESTORE_GLOBALS()
|
||||||
|
|
||||||
|
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||||
|
#include <features.h>
|
||||||
|
#if defined(__GLIBC__) && ((__GLIBC__ < 2) || \
|
||||||
|
((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 90)))
|
||||||
|
// Work around ugly bugs in glibc that mangle global register contents
|
||||||
|
|
||||||
|
static volatile void *saved_env;
|
||||||
|
static volatile unsigned long saved_t0, saved_i7;
|
||||||
|
#undef SAVE_GLOBALS
|
||||||
|
#define SAVE_GLOBALS() do { \
|
||||||
|
saved_env = env; \
|
||||||
|
saved_t0 = T0; \
|
||||||
|
asm volatile ("st %%i7, [%0]" : : "r" (&saved_i7)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#undef RESTORE_GLOBALS
|
||||||
|
#define RESTORE_GLOBALS() do { \
|
||||||
|
env = (void *)saved_env; \
|
||||||
|
T0 = saved_t0; \
|
||||||
|
asm volatile ("ld [%0], %%i7" : : "r" (&saved_i7)); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
static int sparc_setjmp(jmp_buf buf)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
SAVE_GLOBALS();
|
||||||
|
ret = setjmp(buf);
|
||||||
|
RESTORE_GLOBALS();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#undef setjmp
|
||||||
|
#define setjmp(jmp_buf) sparc_setjmp(jmp_buf)
|
||||||
|
|
||||||
|
static void sparc_longjmp(jmp_buf buf, int val)
|
||||||
|
{
|
||||||
|
SAVE_GLOBALS();
|
||||||
|
longjmp(buf, val);
|
||||||
|
}
|
||||||
|
#define longjmp(jmp_buf, val) sparc_longjmp(jmp_buf, val)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void cpu_loop_exit(void)
|
void cpu_loop_exit(void)
|
||||||
{
|
{
|
||||||
/* NOTE: the register at this point must be saved by hand because
|
/* NOTE: the register at this point must be saved by hand because
|
||||||
|
@ -133,7 +179,9 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
|
||||||
tb->tc_ptr = tc_ptr;
|
tb->tc_ptr = tc_ptr;
|
||||||
tb->cs_base = cs_base;
|
tb->cs_base = cs_base;
|
||||||
tb->flags = flags;
|
tb->flags = flags;
|
||||||
|
SAVE_GLOBALS();
|
||||||
cpu_gen_code(env, tb, &code_gen_size);
|
cpu_gen_code(env, tb, &code_gen_size);
|
||||||
|
RESTORE_GLOBALS();
|
||||||
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
|
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
|
||||||
|
|
||||||
/* check next page if needed */
|
/* check next page if needed */
|
||||||
|
@ -232,11 +280,7 @@ static inline TranslationBlock *tb_find_fast(void)
|
||||||
return tb;
|
return tb;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
|
||||||
#define BREAK_CHAIN tmp_T0 = 0
|
|
||||||
#else
|
|
||||||
#define BREAK_CHAIN T0 = 0
|
#define BREAK_CHAIN T0 = 0
|
||||||
#endif
|
|
||||||
|
|
||||||
/* main execution loop */
|
/* main execution loop */
|
||||||
|
|
||||||
|
@ -248,10 +292,6 @@ int cpu_exec(CPUState *env1)
|
||||||
#if defined(reg_REGWPTR)
|
#if defined(reg_REGWPTR)
|
||||||
uint32_t *saved_regwptr;
|
uint32_t *saved_regwptr;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
|
||||||
int saved_i7;
|
|
||||||
target_ulong tmp_T0;
|
|
||||||
#endif
|
#endif
|
||||||
int ret, interrupt_request;
|
int ret, interrupt_request;
|
||||||
void (*gen_func)(void);
|
void (*gen_func)(void);
|
||||||
|
@ -267,10 +307,7 @@ int cpu_exec(CPUState *env1)
|
||||||
#define SAVE_HOST_REGS 1
|
#define SAVE_HOST_REGS 1
|
||||||
#include "hostregs_helper.h"
|
#include "hostregs_helper.h"
|
||||||
env = env1;
|
env = env1;
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
SAVE_GLOBALS();
|
||||||
/* we also save i7 because longjmp may not restore it */
|
|
||||||
asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
env_to_regs();
|
env_to_regs();
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
|
@ -380,10 +417,7 @@ int cpu_exec(CPUState *env1)
|
||||||
|
|
||||||
T0 = 0; /* force lookup of first TB */
|
T0 = 0; /* force lookup of first TB */
|
||||||
for(;;) {
|
for(;;) {
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
SAVE_GLOBALS();
|
||||||
/* g1 can be modified by some libc? functions */
|
|
||||||
tmp_T0 = T0;
|
|
||||||
#endif
|
|
||||||
interrupt_request = env->interrupt_request;
|
interrupt_request = env->interrupt_request;
|
||||||
if (__builtin_expect(interrupt_request, 0)
|
if (__builtin_expect(interrupt_request, 0)
|
||||||
#if defined(TARGET_I386)
|
#if defined(TARGET_I386)
|
||||||
|
@ -597,9 +631,7 @@ int cpu_exec(CPUState *env1)
|
||||||
lookup_symbol(tb->pc));
|
lookup_symbol(tb->pc));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
RESTORE_GLOBALS();
|
||||||
T0 = tmp_T0;
|
|
||||||
#endif
|
|
||||||
/* see if we can patch the calling TB. When the TB
|
/* see if we can patch the calling TB. When the TB
|
||||||
spans two pages, we cannot safely do a direct
|
spans two pages, we cannot safely do a direct
|
||||||
jump. */
|
jump. */
|
||||||
|
@ -695,9 +727,7 @@ int cpu_exec(CPUState *env1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* restore global registers */
|
/* restore global registers */
|
||||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
RESTORE_GLOBALS();
|
||||||
asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
|
|
||||||
#endif
|
|
||||||
#include "hostregs_helper.h"
|
#include "hostregs_helper.h"
|
||||||
|
|
||||||
/* fail safe : never use cpu_single_env outside cpu_exec() */
|
/* fail safe : never use cpu_single_env outside cpu_exec() */
|
||||||
|
|
|
@ -1244,12 +1244,14 @@ void OPPROTO op_exception(void)
|
||||||
{
|
{
|
||||||
env->exception_index = PARAM1;
|
env->exception_index = PARAM1;
|
||||||
cpu_loop_exit();
|
cpu_loop_exit();
|
||||||
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_trap_T0(void)
|
void OPPROTO op_trap_T0(void)
|
||||||
{
|
{
|
||||||
env->exception_index = TT_TRAP + (T0 & 0x7f);
|
env->exception_index = TT_TRAP + (T0 & 0x7f);
|
||||||
cpu_loop_exit();
|
cpu_loop_exit();
|
||||||
|
FORCE_RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OPPROTO op_trapcc_T0(void)
|
void OPPROTO op_trapcc_T0(void)
|
||||||
|
|
Loading…
Reference in New Issue