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
1 changed files with 95 additions and 24 deletions

View File

@ -17,18 +17,33 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef TARGET_I386
#include "exec-i386.h"
#endif
#ifdef TARGET_ARM
#include "exec-arm.h"
#endif
#include "disas.h"
//#define DEBUG_EXEC
//#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 */
int cpu_x86_exec(CPUX86State *env1)
int cpu_exec(CPUState *env1)
{
int saved_T0, saved_T1, saved_A0;
CPUX86State *saved_env;
int saved_T0, saved_T1, saved_T2;
CPUState *saved_env;
#ifdef reg_EAX
int saved_EAX;
#endif
@ -65,9 +80,15 @@ int cpu_x86_exec(CPUX86State *env1)
/* first we save global registers */
saved_T0 = T0;
saved_T1 = T1;
saved_A0 = A0;
saved_T2 = T2;
saved_env = env;
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
saved_EAX = EAX;
EAX = env->regs[R_EAX];
@ -100,16 +121,24 @@ int cpu_x86_exec(CPUX86State *env1)
saved_EDI = EDI;
EDI = env->regs[R_EDI];
#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 */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1));
CC_OP = CC_OP_EFLAGS;
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;
/* prepare setjmp context for exception handling */
@ -126,7 +155,7 @@ int cpu_x86_exec(CPUX86State *env1)
}
#ifdef DEBUG_EXEC
if (loglevel) {
/* XXX: save all volatile state in cpu state */
#if defined(TARGET_I386)
/* restore flags in standard format */
env->regs[R_EAX] = EAX;
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);
cpu_x86_dump_state(env, logfile, 0);
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
/* we compute the CPU state. We assume it will not
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_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
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));
cs_base = env->seg_cache[R_CS].base;
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,
flags);
if (!tb) {
@ -178,7 +220,9 @@ int cpu_x86_exec(CPUX86State *env1)
tb->tc_ptr = tc_ptr;
tb->cs_base = (unsigned long)cs_base;
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 (ret != 0) {
/* NOTE: the tb is allocated but not linked, so we
@ -186,6 +230,7 @@ int cpu_x86_exec(CPUX86State *env1)
spin_unlock(&tb_lock);
raise_exception(EXCP06_ILLOP);
}
#endif
*ptb = tb;
tb->hash_next = NULL;
tb_link(tb);
@ -202,8 +247,12 @@ int cpu_x86_exec(CPUX86State *env1)
#ifdef __sparc__
T0 = tmp_T0;
#endif
/* see if we can patch the calling TB */
if (T0 != 0 && !(env->eflags & TF_MASK)) {
/* see if we can patch the calling TB. XXX: remove TF test */
if (T0 != 0
#if defined(TARGET_I386)
&& !(env->eflags & TF_MASK)
#endif
) {
spin_lock(&tb_lock);
tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
spin_unlock(&tb_lock);
@ -232,6 +281,7 @@ int cpu_x86_exec(CPUX86State *env1)
}
ret = env->exception_index;
#if defined(TARGET_I386)
/* restore flags in standard format */
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
EDI = saved_EDI;
#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__
asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
#endif
T0 = saved_T0;
T1 = saved_T1;
A0 = saved_A0;
T2 = saved_T2;
env = saved_env;
return ret;
}
void cpu_x86_interrupt(CPUX86State *s)
void cpu_interrupt(CPUState *s)
{
s->interrupt_request = 1;
}
#if defined(TARGET_I386)
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
CPUX86State *saved_env;
@ -322,6 +384,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
env = saved_env;
}
#endif /* TARGET_I386 */
#undef EAX
#undef ECX
#undef EDX
@ -357,15 +421,22 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
ret = cpu_x86_search_pc(tb, &found_pc, pc);
ret = cpu_search_pc(tb, &found_pc, pc);
if (ret < 0)
return 0;
#if defined(TARGET_I386)
env->eip = found_pc - tb->cs_base;
env->cr2 = address;
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
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 */
return 1;
} else {
@ -375,8 +446,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
#if defined(__i386__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc)
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
unsigned long pc;
@ -396,8 +467,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__powerpc)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc)
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
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__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
@ -449,8 +520,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
}
#elif defined(__sparc__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc)
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
uint32_t *regs = (uint32_t *)(info + 1);
void *sigmask = (regs + 20);
@ -482,8 +553,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
#elif defined(__arm__)
int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
void *puc)
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
unsigned long pc;