mirror of https://gitee.com/openkylin/qemu.git
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
|
||||
else
|
||||
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
|
||||
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
|
||||
endif
|
||||
|
|
74
cpu-exec.c
74
cpu-exec.c
|
@ -40,6 +40,52 @@ int tb_invalidated_flag;
|
|||
//#define DEBUG_EXEC
|
||||
//#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)
|
||||
{
|
||||
/* 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->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
SAVE_GLOBALS();
|
||||
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));
|
||||
|
||||
/* check next page if needed */
|
||||
|
@ -232,11 +280,7 @@ static inline TranslationBlock *tb_find_fast(void)
|
|||
return tb;
|
||||
}
|
||||
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
#define BREAK_CHAIN tmp_T0 = 0
|
||||
#else
|
||||
#define BREAK_CHAIN T0 = 0
|
||||
#endif
|
||||
|
||||
/* main execution loop */
|
||||
|
||||
|
@ -248,10 +292,6 @@ int cpu_exec(CPUState *env1)
|
|||
#if defined(reg_REGWPTR)
|
||||
uint32_t *saved_regwptr;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
int saved_i7;
|
||||
target_ulong tmp_T0;
|
||||
#endif
|
||||
int ret, interrupt_request;
|
||||
void (*gen_func)(void);
|
||||
|
@ -267,10 +307,7 @@ int cpu_exec(CPUState *env1)
|
|||
#define SAVE_HOST_REGS 1
|
||||
#include "hostregs_helper.h"
|
||||
env = env1;
|
||||
#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
|
||||
SAVE_GLOBALS();
|
||||
|
||||
env_to_regs();
|
||||
#if defined(TARGET_I386)
|
||||
|
@ -380,10 +417,7 @@ int cpu_exec(CPUState *env1)
|
|||
|
||||
T0 = 0; /* force lookup of first TB */
|
||||
for(;;) {
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
/* g1 can be modified by some libc? functions */
|
||||
tmp_T0 = T0;
|
||||
#endif
|
||||
SAVE_GLOBALS();
|
||||
interrupt_request = env->interrupt_request;
|
||||
if (__builtin_expect(interrupt_request, 0)
|
||||
#if defined(TARGET_I386)
|
||||
|
@ -597,9 +631,7 @@ int cpu_exec(CPUState *env1)
|
|||
lookup_symbol(tb->pc));
|
||||
}
|
||||
#endif
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
T0 = tmp_T0;
|
||||
#endif
|
||||
RESTORE_GLOBALS();
|
||||
/* see if we can patch the calling TB. When the TB
|
||||
spans two pages, we cannot safely do a direct
|
||||
jump. */
|
||||
|
@ -695,9 +727,7 @@ int cpu_exec(CPUState *env1)
|
|||
#endif
|
||||
|
||||
/* restore global registers */
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
|
||||
#endif
|
||||
RESTORE_GLOBALS();
|
||||
#include "hostregs_helper.h"
|
||||
|
||||
/* fail safe : never use cpu_single_env outside cpu_exec() */
|
||||
|
|
|
@ -1244,12 +1244,14 @@ void OPPROTO op_exception(void)
|
|||
{
|
||||
env->exception_index = PARAM1;
|
||||
cpu_loop_exit();
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_trap_T0(void)
|
||||
{
|
||||
env->exception_index = TT_TRAP + (T0 & 0x7f);
|
||||
cpu_loop_exit();
|
||||
FORCE_RET();
|
||||
}
|
||||
|
||||
void OPPROTO op_trapcc_T0(void)
|
||||
|
|
Loading…
Reference in New Issue