mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
correct handling of saved host registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1122 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
b8b5ac6376
commit
0d1a29f9fc
7 changed files with 129 additions and 47 deletions
14
cpu-exec.c
14
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(;;) */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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__) */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue