📄 cpu-exec.c
字号:
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(;;) {#if defined(__sparc__) && !defined(HOST_SOLARIS) /* 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 ((interrupt_request & CPU_INTERRUPT_SMI) && !(env->hflags & HF_SMM_MASK)) { env->interrupt_request &= ~CPU_INTERRUPT_SMI; do_smm_enter();#if defined(__sparc__) && !defined(HOST_SOLARIS) tmp_T0 = 0;#else T0 = 0;#endif } else 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 */#if defined(__sparc__) && !defined(HOST_SOLARIS) 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;#if defined(__sparc__) && !defined(HOST_SOLARIS) 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;#if defined(__sparc__) && !defined(HOST_SOLARIS) 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);#if defined(__sparc__) && !defined(HOST_SOLARIS) 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;#if defined(__sparc__) && !defined(HOST_SOLARIS) 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) { env->interrupt_request &= ~CPU_INTERRUPT_HALT; env->halted = 1; env->exception_index = EXCP_HLT; cpu_loop_exit(); }#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 /* Don't use the cached interupt_request value, do_interrupt may have updated the EXITTB flag. */ 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 */#if defined(__sparc__) && !defined(HOST_SOLARIS) 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_M68K) cpu_m68k_flush_flags(env, env->cc_op); env->cc_op = CC_OP_FLAGS; env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4); 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#if defined(__sparc__) && !defined(HOST_SOLARIS) 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", "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7");#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])), "m" (*(uint8_t *)offsetof(CPUState, regs[6])), "m" (*(uint8_t *)offsetof(CPUState, regs[7])), "m" (*(uint8_t *)offsetof(CPUState, cc_src)), "m" (*(uint8_t *)offsetof(CPUState, tmp0)), "a" (gen_func), "m" (*(uint8_t *)offsetof(CPUState, df)), "m" (*(uint8_t *)offsetof(CPUState, saved_esp)) : "%ecx", "%edx" ); }}#elif defined(__ia64) struct fptr { void *ip; void *gp; } fp; fp.ip = tc_ptr; fp.gp = code_gen_buffer + 2 * (1 << 20); (*(void (*)(void)) &fp)();#else gen_func();#endif env->current_tb = NULL; /* reset soft MMU for next block (it can currently only be set by a memory fault) */#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -