mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 21:40:49 +00:00
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:
parent
1e5ffbedde
commit
e4533c7a8c
@ -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;
|
Loading…
Reference in New Issue
Block a user