📄 cpu-exec.c
字号:
#else#error unsupported target CPU#endif env->exception_index = -1; /* prepare setjmp context for exception handling */ for(;;) { if (setjmp(env->jmp_env) == 0) { env->current_tb = NULL; /* if an exception is pending, we execute it here */ if (env->exception_index >= 0) { if (env->exception_index >= EXCP_INTERRUPT) { /* exit request from the cpu execution loop */ ret = env->exception_index; break; } else if (env->user_mode_only) { /* if user mode only, we simulate a fake exception 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, env->exception_next_eip);#endif ret = env->exception_index; break; } else {#if defined(TARGET_I386) /* 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, env->exception_next_eip, 0);#elif defined(TARGET_PPC) do_interrupt(env);#elif defined(TARGET_MIPS) do_interrupt(env);#elif defined(TARGET_SPARC) do_interrupt(env->exception_index);#elif defined(TARGET_ARM) do_interrupt(env);#elif defined(TARGET_SH4) do_interrupt(env);#endif } env->exception_index = -1; } #ifdef USE_KQEMU if (kqemu_is_ok(env) && env->interrupt_request == 0) { int ret; env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); ret = kqemu_cpu_exec(env); /* 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); if (ret == 1) { /* exception */ longjmp(env->jmp_env, 1); } else if (ret == 2) { /* softmmu execution needed */ } else { if (env->interrupt_request != 0) { /* hardware interrupt will be executed just after */ } else { /* otherwise, we restart */ longjmp(env->jmp_env, 1); } } }#endif T0 = 0; /* force lookup of first TB */ for(;;) {#ifdef __sparc__ /* g1 can be modified by some libc? functions */ tmp_T0 = T0;#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->hflags & HF_INHIBIT_IRQ_MASK)) { int intno; env->interrupt_request &= ~CPU_INTERRUPT_HARD; intno = cpu_get_pic_interrupt(env); if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno); } do_interrupt(intno, 0, 0, 0, 1); /* ensure that no TB jump will be modified as the program flow was changed */#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif }#elif defined(TARGET_PPC)#if 0 if ((interrupt_request & CPU_INTERRUPT_RESET)) { cpu_ppc_reset(env); }#endif if (msr_ee != 0) { if ((interrupt_request & CPU_INTERRUPT_HARD)) { /* Raise it */ env->exception_index = EXCP_EXTERNAL; env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD;#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) { /* Raise it */ env->exception_index = EXCP_DECR; env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_TIMER;#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif } }#elif defined(TARGET_MIPS) if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->CP0_Status & (1 << CP0St_IE)) && (env->CP0_Status & env->CP0_Cause & 0x0000FF00) && !(env->hflags & MIPS_HFLAG_EXL) && !(env->hflags & MIPS_HFLAG_ERL) && !(env->hflags & MIPS_HFLAG_DM)) { /* Raise it */ env->exception_index = EXCP_EXT_INTERRUPT; env->error_code = 0; do_interrupt(env); env->interrupt_request &= ~CPU_INTERRUPT_HARD;#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif }#elif defined(TARGET_SPARC) if ((interrupt_request & CPU_INTERRUPT_HARD) && (env->psret != 0)) { int pil = env->interrupt_index & 15; int type = env->interrupt_index & 0xf0; if (((type == TT_EXTINT) && (pil == 15 || pil > env->psrpil)) || type != TT_EXTINT) { env->interrupt_request &= ~CPU_INTERRUPT_HARD; do_interrupt(env->interrupt_index); env->interrupt_index = 0;#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif } } else if (interrupt_request & CPU_INTERRUPT_TIMER) { //do_interrupt(0, 0, 0, 0, 0); env->interrupt_request &= ~CPU_INTERRUPT_TIMER; } else if (interrupt_request & CPU_INTERRUPT_HALT) { env1->halted = 1; return EXCP_HALTED; }#elif defined(TARGET_ARM) if (interrupt_request & CPU_INTERRUPT_FIQ && !(env->uncached_cpsr & CPSR_F)) { env->exception_index = EXCP_FIQ; do_interrupt(env); } if (interrupt_request & CPU_INTERRUPT_HARD && !(env->uncached_cpsr & CPSR_I)) { env->exception_index = EXCP_IRQ; do_interrupt(env); }#elif defined(TARGET_SH4) /* XXXXX */#endif if (env->interrupt_request & CPU_INTERRUPT_EXITTB) { env->interrupt_request &= ~CPU_INTERRUPT_EXITTB; /* ensure that no TB jump will be modified as the program flow was changed */#ifdef __sparc__ tmp_T0 = 0;#else T0 = 0;#endif } if (interrupt_request & CPU_INTERRUPT_EXIT) { env->interrupt_request &= ~CPU_INTERRUPT_EXIT; env->exception_index = EXCP_INTERRUPT; cpu_loop_exit(); } }#ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_TB_CPU)) {#if defined(TARGET_I386) /* restore flags in standard format */#ifdef reg_EAX env->regs[R_EAX] = EAX;#endif#ifdef reg_EBX env->regs[R_EBX] = EBX;#endif#ifdef reg_ECX env->regs[R_ECX] = ECX;#endif#ifdef reg_EDX env->regs[R_EDX] = EDX;#endif#ifdef reg_ESI env->regs[R_ESI] = ESI;#endif#ifdef reg_EDI env->regs[R_EDI] = EDI;#endif#ifdef reg_EBP env->regs[R_EBP] = EBP;#endif#ifdef reg_ESP env->regs[R_ESP] = ESP;#endif env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK); cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP); env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);#elif defined(TARGET_ARM) cpu_dump_state(env, logfile, fprintf, 0);#elif defined(TARGET_SPARC) REGWPTR = env->regbase + (env->cwp * 16); env->regwptr = REGWPTR; cpu_dump_state(env, logfile, fprintf, 0);#elif defined(TARGET_PPC) cpu_dump_state(env, logfile, fprintf, 0);#elif defined(TARGET_MIPS) cpu_dump_state(env, logfile, fprintf, 0);#elif defined(TARGET_SH4) cpu_dump_state(env, logfile, fprintf, 0);#else#error unsupported target CPU #endif }#endif tb = tb_find_fast();#ifdef DEBUG_EXEC if ((loglevel & CPU_LOG_EXEC)) { fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n", (long)tb->tc_ptr, tb->pc, lookup_symbol(tb->pc)); }#endif#ifdef __sparc__ T0 = tmp_T0;#endif /* see if we can patch the calling TB. When the TB spans two pages, we cannot safely do a direct jump. */ { if (T0 != 0 &&#if USE_KQEMU (env->kqemu_enabled != 2) &&#endif tb->page_addr[1] == -1#if defined(TARGET_I386) && defined(USE_CODE_COPY) && (tb->cflags & CF_CODE_COPY) == (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)#endif ) { spin_lock(&tb_lock); tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);#if defined(USE_CODE_COPY) /* propagates the FP use info */ ((TranslationBlock *)(T0 & ~3))->cflags |= (tb->cflags & CF_FP_USED);#endif spin_unlock(&tb_lock); } } tc_ptr = tb->tc_ptr; env->current_tb = tb; /* execute the generated code */ gen_func = (void *)tc_ptr;#if defined(__sparc__) __asm__ __volatile__("call %0\n\t" "mov %%o7,%%i0" : /* no outputs */ : "r" (gen_func) : "i0", "i1", "i2", "i3", "i4", "i5");#elif defined(__arm__) asm volatile ("mov pc, %0\n\t" ".global exec_loop\n\t" "exec_loop:\n\t" : /* no outputs */ : "r" (gen_func) : "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");#elif defined(TARGET_I386) && defined(USE_CODE_COPY){ if (!(tb->cflags & CF_CODE_COPY)) { if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) { save_native_fp_state(env); } gen_func(); } else { if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) { restore_native_fp_state(env); } /* we work with native eflags */ CC_SRC = cc_table[CC_OP].compute_all(); CC_OP = CC_OP_EFLAGS; asm(".globl exec_loop\n" "\n" "debug1:\n" " pushl %%ebp\n" " fs movl %10, %9\n" " fs movl %11, %%eax\n" " andl $0x400, %%eax\n" " fs orl %8, %%eax\n" " pushl %%eax\n" " popf\n" " fs movl %%esp, %12\n" " fs movl %0, %%eax\n" " fs movl %1, %%ecx\n" " fs movl %2, %%edx\n" " fs movl %3, %%ebx\n" " fs movl %4, %%esp\n" " fs movl %5, %%ebp\n" " fs movl %6, %%esi\n" " fs movl %7, %%edi\n" " fs jmp *%9\n" "exec_loop:\n" " fs movl %%esp, %4\n" " fs movl %12, %%esp\n" " fs movl %%eax, %0\n" " fs movl %%ecx, %1\n" " fs movl %%edx, %2\n" " fs movl %%ebx, %3\n" " fs movl %%ebp, %5\n" " fs movl %%esi, %6\n" " fs movl %%edi, %7\n" " pushf\n" " popl %%eax\n" " movl %%eax, %%ecx\n" " andl $0x400, %%ecx\n" " shrl $9, %%ecx\n" " andl $0x8d5, %%eax\n" " fs movl %%eax, %8\n" " movl $1, %%eax\n" " subl %%ecx, %%eax\n" " fs movl %%eax, %11\n" " fs movl %9, %%ebx\n" /* get T0 value */ " popl %%ebp\n" : : "m" (*(uint8_t *)offsetof(CPUState, regs[0])), "m" (*(uint8_t *)offsetof(CPUState, regs[1])), "m" (*(uint8_t *)offsetof(CPUState, regs[2])), "m" (*(uint8_t *)offsetof(CPUState, regs[3])), "m" (*(uint8_t *)offsetof(CPUState, regs[4])), "m" (*(uint8_t *)offsetof(CPUState, regs[5])),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -