main cpu loop is target independent

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@238 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-06-15 19:51:39 +00:00
parent 1e5ffbedde
commit e4533c7a8c

View File

@ -17,18 +17,33 @@
* License along with this library; if not, write to the Free Software * License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "config.h"
#ifdef TARGET_I386
#include "exec-i386.h" #include "exec-i386.h"
#endif
#ifdef TARGET_ARM
#include "exec-arm.h"
#endif
#include "disas.h" #include "disas.h"
//#define DEBUG_EXEC //#define DEBUG_EXEC
//#define DEBUG_SIGNAL //#define DEBUG_SIGNAL
#if defined(TARGET_ARM)
/* XXX: unify with i386 target */
void cpu_loop_exit(void)
{
longjmp(env->jmp_env, 1);
}
#endif
/* main execution loop */ /* main execution loop */
int cpu_x86_exec(CPUX86State *env1) int cpu_exec(CPUState *env1)
{ {
int saved_T0, saved_T1, saved_A0; int saved_T0, saved_T1, saved_T2;
CPUX86State *saved_env; CPUState *saved_env;
#ifdef reg_EAX #ifdef reg_EAX
int saved_EAX; int saved_EAX;
#endif #endif
@ -65,9 +80,15 @@ int cpu_x86_exec(CPUX86State *env1)
/* first we save global registers */ /* first we save global registers */
saved_T0 = T0; saved_T0 = T0;
saved_T1 = T1; saved_T1 = T1;
saved_A0 = A0; saved_T2 = T2;
saved_env = env; saved_env = env;
env = env1; env = env1;
#ifdef __sparc__
/* 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 #ifdef reg_EAX
saved_EAX = EAX; saved_EAX = EAX;
EAX = env->regs[R_EAX]; EAX = env->regs[R_EAX];
@ -100,16 +121,24 @@ int cpu_x86_exec(CPUX86State *env1)
saved_EDI = EDI; saved_EDI = EDI;
EDI = env->regs[R_EDI]; EDI = env->regs[R_EDI];
#endif #endif
#ifdef __sparc__
/* we also save i7 because longjmp may not restore it */
asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
#endif
/* put eflags in CPU temporary format */ /* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1)); DF = 1 - (2 * ((env->eflags >> 10) & 1));
CC_OP = CC_OP_EFLAGS; CC_OP = CC_OP_EFLAGS;
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_ARM)
{
unsigned int psr;
psr = env->cpsr;
env->CF = (psr >> 29) & 1;
env->NZF = (psr & 0xc0000000) ^ 0x40000000;
env->VF = (psr << 3) & 0x80000000;
env->cpsr = psr & ~0xf0000000;
}
#else
#error unsupported target CPU
#endif
env->interrupt_request = 0; env->interrupt_request = 0;
/* prepare setjmp context for exception handling */ /* prepare setjmp context for exception handling */
@ -126,7 +155,7 @@ int cpu_x86_exec(CPUX86State *env1)
} }
#ifdef DEBUG_EXEC #ifdef DEBUG_EXEC
if (loglevel) { if (loglevel) {
/* XXX: save all volatile state in cpu state */ #if defined(TARGET_I386)
/* restore flags in standard format */ /* restore flags in standard format */
env->regs[R_EAX] = EAX; env->regs[R_EAX] = EAX;
env->regs[R_EBX] = EBX; env->regs[R_EBX] = EBX;
@ -139,10 +168,16 @@ int cpu_x86_exec(CPUX86State *env1)
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
cpu_x86_dump_state(env, logfile, 0); cpu_x86_dump_state(env, logfile, 0);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
#elif defined(TARGET_ARM)
cpu_arm_dump_state(env, logfile, 0);
#else
#error unsupported target CPU
#endif
} }
#endif #endif
/* we compute the CPU state. We assume it will not /* we compute the CPU state. We assume it will not
change during the whole generated block. */ change during the whole generated block. */
#if defined(TARGET_I386)
flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT; flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT; flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
flags |= (((unsigned long)env->seg_cache[R_DS].base | flags |= (((unsigned long)env->seg_cache[R_DS].base |
@ -159,6 +194,13 @@ int cpu_x86_exec(CPUX86State *env1)
flags |= (env->eflags & (IOPL_MASK | TF_MASK)); flags |= (env->eflags & (IOPL_MASK | TF_MASK));
cs_base = env->seg_cache[R_CS].base; cs_base = env->seg_cache[R_CS].base;
pc = cs_base + env->eip; pc = cs_base + env->eip;
#elif defined(TARGET_ARM)
flags = 0;
cs_base = 0;
pc = (uint8_t *)env->regs[15];
#else
#error unsupported CPU
#endif
tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base, tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
flags); flags);
if (!tb) { if (!tb) {
@ -178,7 +220,9 @@ int cpu_x86_exec(CPUX86State *env1)
tb->tc_ptr = tc_ptr; tb->tc_ptr = tc_ptr;
tb->cs_base = (unsigned long)cs_base; tb->cs_base = (unsigned long)cs_base;
tb->flags = flags; tb->flags = flags;
ret = cpu_x86_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size); ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size);
#if defined(TARGET_I386)
/* XXX: suppress that, this is incorrect */
/* if invalid instruction, signal it */ /* if invalid instruction, signal it */
if (ret != 0) { if (ret != 0) {
/* NOTE: the tb is allocated but not linked, so we /* NOTE: the tb is allocated but not linked, so we
@ -186,6 +230,7 @@ int cpu_x86_exec(CPUX86State *env1)
spin_unlock(&tb_lock); spin_unlock(&tb_lock);
raise_exception(EXCP06_ILLOP); raise_exception(EXCP06_ILLOP);
} }
#endif
*ptb = tb; *ptb = tb;
tb->hash_next = NULL; tb->hash_next = NULL;
tb_link(tb); tb_link(tb);
@ -202,8 +247,12 @@ int cpu_x86_exec(CPUX86State *env1)
#ifdef __sparc__ #ifdef __sparc__
T0 = tmp_T0; T0 = tmp_T0;
#endif #endif
/* see if we can patch the calling TB */ /* see if we can patch the calling TB. XXX: remove TF test */
if (T0 != 0 && !(env->eflags & TF_MASK)) { if (T0 != 0
#if defined(TARGET_I386)
&& !(env->eflags & TF_MASK)
#endif
) {
spin_lock(&tb_lock); spin_lock(&tb_lock);
tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb); tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
spin_unlock(&tb_lock); spin_unlock(&tb_lock);
@ -232,6 +281,7 @@ int cpu_x86_exec(CPUX86State *env1)
} }
ret = env->exception_index; ret = env->exception_index;
#if defined(TARGET_I386)
/* restore flags in standard format */ /* restore flags in standard format */
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
@ -260,22 +310,34 @@ int cpu_x86_exec(CPUX86State *env1)
#ifdef reg_EDI #ifdef reg_EDI
EDI = saved_EDI; EDI = saved_EDI;
#endif #endif
#elif defined(TARGET_ARM)
{
int ZF;
ZF = (env->NZF == 0);
env->cpsr = env->cpsr | (env->NZF & 0x80000000) | (ZF << 30) |
(env->CF << 29) | ((env->VF & 0x80000000) >> 3);
}
#else
#error unsupported target CPU
#endif
#ifdef __sparc__ #ifdef __sparc__
asm volatile ("mov %0, %%i7" : : "r" (saved_i7)); asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
#endif #endif
T0 = saved_T0; T0 = saved_T0;
T1 = saved_T1; T1 = saved_T1;
A0 = saved_A0; T2 = saved_T2;
env = saved_env; env = saved_env;
return ret; return ret;
} }
void cpu_x86_interrupt(CPUX86State *s) void cpu_interrupt(CPUState *s)
{ {
s->interrupt_request = 1; s->interrupt_request = 1;
} }
#if defined(TARGET_I386)
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{ {
CPUX86State *saved_env; CPUX86State *saved_env;
@ -322,6 +384,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
env = saved_env; env = saved_env;
} }
#endif /* TARGET_I386 */
#undef EAX #undef EAX
#undef ECX #undef ECX
#undef EDX #undef EDX
@ -357,15 +421,22 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
if (tb) { if (tb) {
/* the PC is inside the translated code. It means that we have /* the PC is inside the translated code. It means that we have
a virtual CPU fault */ a virtual CPU fault */
ret = cpu_x86_search_pc(tb, &found_pc, pc); ret = cpu_search_pc(tb, &found_pc, pc);
if (ret < 0) if (ret < 0)
return 0; return 0;
#if defined(TARGET_I386)
env->eip = found_pc - tb->cs_base; env->eip = found_pc - tb->cs_base;
env->cr2 = address; env->cr2 = address;
/* we restore the process signal mask as the sigreturn should /* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */ do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL); sigprocmask(SIG_SETMASK, old_set, NULL);
raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1)); raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1));
#elif defined(TARGET_ARM)
env->regs[15] = found_pc;
/* XXX: do more */
#else
#error unsupported target CPU
#endif
/* never comes here */ /* never comes here */
return 1; return 1;
} else { } else {
@ -375,8 +446,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
#if defined(__i386__) #if defined(__i386__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc) void *puc)
{ {
struct ucontext *uc = puc; struct ucontext *uc = puc;
unsigned long pc; unsigned long pc;
@ -396,8 +467,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__powerpc) #elif defined(__powerpc)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc) void *puc)
{ {
struct ucontext *uc = puc; struct ucontext *uc = puc;
struct pt_regs *regs = uc->uc_mcontext.regs; struct pt_regs *regs = uc->uc_mcontext.regs;
@ -420,7 +491,7 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__alpha__) #elif defined(__alpha__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc) void *puc)
{ {
struct ucontext *uc = puc; struct ucontext *uc = puc;
@ -449,8 +520,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
} }
#elif defined(__sparc__) #elif defined(__sparc__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc) void *puc)
{ {
uint32_t *regs = (uint32_t *)(info + 1); uint32_t *regs = (uint32_t *)(info + 1);
void *sigmask = (regs + 20); void *sigmask = (regs + 20);
@ -482,8 +553,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__arm__) #elif defined(__arm__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info, int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc) void *puc)
{ {
struct ucontext *uc = puc; struct ucontext *uc = puc;
unsigned long pc; unsigned long pc;