From 55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 21 Oct 2008 07:00:00 -0700 Subject: Initial Contribution --- cpu-exec.c | 191 +++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 122 insertions(+), 69 deletions(-) (limited to 'cpu-exec.c') diff --git a/cpu-exec.c b/cpu-exec.c index 60239d4..8d733bd 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -1,6 +1,6 @@ /* * i386 emulator main execution loop - * + * * Copyright (c) 2003-2005 Fabrice Bellard * * This library is free software; you can redistribute it and/or @@ -21,6 +21,22 @@ #include "exec.h" #include "disas.h" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#ifndef _WIN32 +#include +#endif + +extern int qemu_milli_needed; +extern int qemu_milli_check(void); +extern void qemu_check_interrupts(void); + +extern int qemu_cpu_delay; +extern int qemu_cpu_delay_count; + #if !defined(CONFIG_SOFTMMU) #undef EAX #undef ECX @@ -54,7 +70,7 @@ void cpu_loop_exit(void) /* exit the current TB from a signal handler. The host registers are restored in a state compatible with the CPU emulator */ -void cpu_resume_from_signal(CPUState *env1, void *puc) +void cpu_resume_from_signal(CPUState *env1, void *puc) { #if !defined(CONFIG_SOFTMMU) struct ucontext *uc = puc; @@ -83,13 +99,13 @@ static TranslationBlock *tb_find_slow(target_ulong pc, unsigned int h; target_ulong phys_pc, phys_page1, phys_page2, virt_page2; uint8_t *tc_ptr; - + 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, pc); phys_page1 = phys_pc & TARGET_PAGE_MASK; @@ -100,13 +116,13 @@ static TranslationBlock *tb_find_slow(target_ulong pc, tb = *ptb1; if (!tb) goto not_found; - if (tb->pc == pc && + if (tb->pc == pc && tb->page_addr[0] == phys_page1 && - tb->cs_base == cs_base && + tb->cs_base == cs_base && tb->flags == flags) { /* check next page if needed */ if (tb->page_addr[1] != -1) { - virt_page2 = (pc & TARGET_PAGE_MASK) + + virt_page2 = (pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; phys_page2 = get_phys_addr_code(env, virt_page2); if (tb->page_addr[1] == phys_page2) @@ -132,9 +148,13 @@ static TranslationBlock *tb_find_slow(target_ulong pc, tb->tc_ptr = tc_ptr; tb->cs_base = cs_base; tb->flags = flags; +#ifdef CONFIG_TRACE + tb->bb_rec = NULL; + tb->prev_time = 0; +#endif cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); 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 */ virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; phys_page2 = -1; @@ -142,7 +162,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc, phys_page2 = get_phys_addr_code(env, virt_page2); } tb_link_phys(tb, phys_pc, phys_page2); - + found: /* we add the TB in the virtual pc hash table */ env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb; @@ -278,8 +298,8 @@ int cpu_exec(CPUState *env1) } #elif defined(TARGET_PPC) if (env1->halted) { - if (env1->msr[MSR_EE] && - (env1->interrupt_request & + if (env1->msr[MSR_EE] && + (env1->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) { env1->halted = 0; } else { @@ -317,7 +337,7 @@ int cpu_exec(CPUState *env1) } #endif - cpu_single_env = env1; + cpu_single_env = env1; /* first we save global registers */ saved_env = env; @@ -393,9 +413,9 @@ int cpu_exec(CPUState *env1) which will be hanlded outside the cpu execution loop */ #if defined(TARGET_I386) - do_interrupt_user(env->exception_index, - env->exception_is_int, - env->error_code, + do_interrupt_user(env->exception_index, + env->exception_is_int, + env->error_code, env->exception_next_eip); #endif ret = env->exception_index; @@ -405,9 +425,9 @@ int cpu_exec(CPUState *env1) /* simulate a real cpu exception. On i386, it can trigger new exceptions, but we do not handle double or triple faults yet. */ - do_interrupt(env->exception_index, - env->exception_is_int, - env->error_code, + do_interrupt(env->exception_index, + env->exception_is_int, + env->error_code, env->exception_next_eip, 0); #elif defined(TARGET_PPC) do_interrupt(env); @@ -422,7 +442,7 @@ int cpu_exec(CPUState *env1) #endif } env->exception_index = -1; - } + } #ifdef USE_KQEMU if (kqemu_is_ok(env) && env->interrupt_request == 0) { int ret; @@ -452,15 +472,15 @@ 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 */ + /* g1 can be modified by some libc? functions */ tmp_T0 = T0; -#endif +#endif interrupt_request = env->interrupt_request; if (__builtin_expect(interrupt_request, 0)) { #if defined(TARGET_I386) /* if hardware interrupt pending, we execute it */ if ((interrupt_request & CPU_INTERRUPT_HARD) && - (env->eflags & IF_MASK) && + (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) { int intno; env->interrupt_request &= ~CPU_INTERRUPT_HARD; @@ -627,7 +647,7 @@ int cpu_exec(CPUState *env1) #elif defined(TARGET_SH4) cpu_dump_state(env, logfile, fprintf, 0); #else -#error unsupported target CPU +#error unsupported target CPU #endif } #endif @@ -641,7 +661,7 @@ int cpu_exec(CPUState *env1) #endif #if defined(__sparc__) && !defined(HOST_SOLARIS) T0 = tmp_T0; -#endif +#endif /* see if we can patch the calling TB. When the TB spans two pages, we cannot safely do a direct jump. */ @@ -652,7 +672,7 @@ int cpu_exec(CPUState *env1) #endif tb->page_addr[1] == -1 #if defined(TARGET_I386) && defined(USE_CODE_COPY) - && (tb->cflags & CF_CODE_COPY) == + && (tb->cflags & CF_CODE_COPY) == (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY) #endif ) { @@ -660,7 +680,7 @@ int cpu_exec(CPUState *env1) tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb); #if defined(USE_CODE_COPY) /* propagates the FP use info */ - ((TranslationBlock *)(T0 & ~3))->cflags |= + ((TranslationBlock *)(T0 & ~3))->cflags |= (tb->cflags & CF_FP_USED); #endif spin_unlock(&tb_lock); @@ -674,7 +694,7 @@ int cpu_exec(CPUState *env1) __asm__ __volatile__("call %0\n\t" "mov %%o7,%%i0" : /* no outputs */ - : "r" (gen_func) + : "r" (gen_func) : "i0", "i1", "i2", "i3", "i4", "i5", "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7"); @@ -685,6 +705,15 @@ int cpu_exec(CPUState *env1) : /* no outputs */ : "r" (gen_func) : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14"); +#elif defined(TARGET_X86_64) && defined(__i386__) + asm volatile ("push %%ebx\n" + "push %%esi\n" + "push %%edi\n" + "call *%0\n" + "pop %%edi\n" + "pop %%esi\n" + "pop %%ebx\n" + : : "r" (gen_func) : "ebx", "esi", "edi"); #elif defined(TARGET_I386) && defined(USE_CODE_COPY) { if (!(tb->cflags & CF_CODE_COPY)) { @@ -788,6 +817,30 @@ int cpu_exec(CPUState *env1) cpu_loop_exit(); } #endif + +#if 0 /* digit: implement high-resolution polling */ + if (qemu_milli_needed) { + static int counter; + + if (++counter == 50) { + counter = 0; + if (qemu_milli_check()) + qemu_check_interrupts(); + } + } +#endif +/* ANDROID-BEGIN */ + if (qemu_cpu_delay) { + if (++qemu_cpu_delay_count >= qemu_cpu_delay) { + qemu_cpu_delay_count = 0; +#ifdef _WIN32 + Sleep(1); +#else + usleep(1000); +#endif + } + } +/* ANDROID-END */ } } else { env_to_regs(); @@ -852,7 +905,7 @@ int cpu_exec(CPUState *env1) #endif env = saved_env; /* fail safe : never use cpu_single_env outside cpu_exec() */ - cpu_single_env = NULL; + cpu_single_env = NULL; return ret; } @@ -879,7 +932,7 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) env = s; if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) { selector &= 0xffff; - cpu_x86_load_seg_cache(env, seg_reg, selector, + cpu_x86_load_seg_cache(env, seg_reg, selector, (selector << 4), 0xffff, 0); } else { load_seg(seg_reg, selector); @@ -893,7 +946,7 @@ void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32) saved_env = env; env = s; - + helper_fsave((target_ulong)ptr, data32); env = saved_env; @@ -905,7 +958,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) saved_env = env; env = s; - + helper_frstor((target_ulong)ptr, data32); env = saved_env; @@ -922,7 +975,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32) write caused the exception and otherwise 0'. 'old_set' is the signal set which should be restored */ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, - int is_write, sigset_t *old_set, + int is_write, sigset_t *old_set, void *puc) { TranslationBlock *tb; @@ -931,7 +984,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -940,7 +993,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } /* see if it is an MMU fault */ - ret = cpu_x86_handle_mmu_fault(env, address, is_write, + ret = cpu_x86_handle_mmu_fault(env, address, is_write, ((env->hflags & HF_CPL_MASK) == 3), 0); if (ret < 0) return 0; /* not an MMU fault */ @@ -955,7 +1008,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #if 0 - printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", + printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n", env->eip, env->cr[2], env->error_code); #endif /* we restore the process signal mask as the sigreturn should @@ -982,7 +1035,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -1018,7 +1071,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -1050,11 +1103,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { TranslationBlock *tb; int ret; - + if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -1078,7 +1131,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #if 0 - printf("PF exception: NIP=0x%08x error=0x%x %p\n", + printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should @@ -1100,11 +1153,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { TranslationBlock *tb; int ret; - + if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -1128,7 +1181,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, } if (ret == 1) { #if 0 - printf("PF exception: NIP=0x%08x error=0x%x %p\n", + printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should @@ -1150,11 +1203,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, { TranslationBlock *tb; int ret; - + if (cpu_single_env) env = cpu_single_env; /* XXX: find a correct solution for multithread */ #if defined(DEBUG_SIGNAL) - printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", + printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", pc, address, is_write, *(unsigned long *)old_set); #endif /* XXX: locking issue */ @@ -1177,7 +1230,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, cpu_restore_state(tb, env, pc, puc); } #if 0 - printf("PF exception: NIP=0x%08x error=0x%x %p\n", + printf("PF exception: NIP=0x%08x error=0x%x %p\n", env->nip, env->error_code, tb); #endif /* we restore the process signal mask as the sigreturn should @@ -1194,7 +1247,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, #if defined(__i386__) #if defined(USE_CODE_COPY) -static void cpu_send_trap(unsigned long pc, int trap, +static void cpu_send_trap(unsigned long pc, int trap, struct ucontext *uc) { TranslationBlock *tb; @@ -1213,7 +1266,7 @@ static void cpu_send_trap(unsigned long pc, int trap, } #endif -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; @@ -1235,8 +1288,8 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, return 1; } else #endif - return handle_cpu_signal(pc, (unsigned long)info->si_addr, - trapno == 0xe ? + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + trapno == 0xe ? (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0, &uc->uc_sigmask, puc); } @@ -1250,8 +1303,8 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, unsigned long pc; pc = uc->uc_mcontext.gregs[REG_RIP]; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, - uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? + return handle_cpu_signal(pc, (unsigned long)info->si_addr, + uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ? (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0, &uc->uc_sigmask, puc); } @@ -1307,7 +1360,7 @@ typedef struct ucontext SIGCONTEXT; # define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */ #endif /* __APPLE__ */ -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; @@ -1324,13 +1377,13 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000)) is_write = 1; #endif - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__alpha__) -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; @@ -1354,12 +1407,12 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, is_write = 1; } - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } #elif defined(__sparc__) -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { uint32_t *regs = (uint32_t *)(info + 1); @@ -1367,7 +1420,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, unsigned long pc; int is_write; uint32_t insn; - + /* XXX: is there a standard glibc define ? */ pc = regs[1]; /* XXX: need kernel patch to get write flag faster */ @@ -1386,40 +1439,40 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, break; } } - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, sigmask, NULL); } #elif defined(__arm__) -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; - + pc = uc->uc_mcontext.gregs[R15]; /* XXX: compute is_write */ is_write = 0; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask); } #elif defined(__mc68000) -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; - + pc = uc->uc_mcontext.gregs[16]; /* XXX: compute is_write */ is_write = 0; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } @@ -1459,17 +1512,17 @@ int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) #elif defined(__s390__) -int cpu_signal_handler(int host_signum, struct siginfo *info, +int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc) { struct ucontext *uc = puc; unsigned long pc; int is_write; - + pc = uc->uc_mcontext.psw.addr; /* XXX: compute is_write */ is_write = 0; - return handle_cpu_signal(pc, (unsigned long)info->si_addr, + return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); } -- cgit v1.1