mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 15:23:53 -06:00
Add instruction counter.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4799 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
f6e5889e7f
commit
2e70f6efa8
29 changed files with 830 additions and 117 deletions
93
cpu-exec.c
93
cpu-exec.c
|
@ -82,15 +82,40 @@ void cpu_resume_from_signal(CPUState *env1, void *puc)
|
|||
longjmp(env->jmp_env, 1);
|
||||
}
|
||||
|
||||
/* Execute the code without caching the generated code. An interpreter
|
||||
could be used if available. */
|
||||
static void cpu_exec_nocache(int max_cycles, TranslationBlock *orig_tb)
|
||||
{
|
||||
unsigned long next_tb;
|
||||
TranslationBlock *tb;
|
||||
|
||||
/* Should never happen.
|
||||
We only end up here when an existing TB is too long. */
|
||||
if (max_cycles > CF_COUNT_MASK)
|
||||
max_cycles = CF_COUNT_MASK;
|
||||
|
||||
tb = tb_gen_code(env, orig_tb->pc, orig_tb->cs_base, orig_tb->flags,
|
||||
max_cycles);
|
||||
env->current_tb = tb;
|
||||
/* execute the generated code */
|
||||
next_tb = tcg_qemu_tb_exec(tb->tc_ptr);
|
||||
|
||||
if ((next_tb & 3) == 2) {
|
||||
/* Restore PC. This may happen if async event occurs before
|
||||
the TB starts executing. */
|
||||
CPU_PC_FROM_TB(env, tb);
|
||||
}
|
||||
tb_phys_invalidate(tb, -1);
|
||||
tb_free(tb);
|
||||
}
|
||||
|
||||
static TranslationBlock *tb_find_slow(target_ulong pc,
|
||||
target_ulong cs_base,
|
||||
uint64_t flags)
|
||||
{
|
||||
TranslationBlock *tb, **ptb1;
|
||||
int code_gen_size;
|
||||
unsigned int h;
|
||||
target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
|
||||
uint8_t *tc_ptr;
|
||||
|
||||
tb_invalidated_flag = 0;
|
||||
|
||||
|
@ -124,30 +149,8 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
|
|||
ptb1 = &tb->phys_hash_next;
|
||||
}
|
||||
not_found:
|
||||
/* if no translated code available, then translate it now */
|
||||
tb = tb_alloc(pc);
|
||||
if (!tb) {
|
||||
/* flush must be done */
|
||||
tb_flush(env);
|
||||
/* cannot fail at this point */
|
||||
tb = tb_alloc(pc);
|
||||
/* don't forget to invalidate previous TB info */
|
||||
tb_invalidated_flag = 1;
|
||||
}
|
||||
tc_ptr = code_gen_ptr;
|
||||
tb->tc_ptr = tc_ptr;
|
||||
tb->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
cpu_gen_code(env, tb, &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;
|
||||
if ((pc & TARGET_PAGE_MASK) != virt_page2) {
|
||||
phys_page2 = get_phys_addr_code(env, virt_page2);
|
||||
}
|
||||
tb_link_phys(tb, phys_pc, phys_page2);
|
||||
/* if no translated code available, then translate it now */
|
||||
tb = tb_gen_code(env, pc, cs_base, flags, 0);
|
||||
|
||||
found:
|
||||
/* we add the TB in the virtual pc hash table */
|
||||
|
@ -583,6 +586,7 @@ int cpu_exec(CPUState *env1)
|
|||
of memory exceptions while generating the code, we
|
||||
must recompute the hash index here */
|
||||
next_tb = 0;
|
||||
tb_invalidated_flag = 0;
|
||||
}
|
||||
#ifdef DEBUG_EXEC
|
||||
if ((loglevel & CPU_LOG_EXEC)) {
|
||||
|
@ -604,16 +608,45 @@ int cpu_exec(CPUState *env1)
|
|||
}
|
||||
}
|
||||
spin_unlock(&tb_lock);
|
||||
tc_ptr = tb->tc_ptr;
|
||||
env->current_tb = tb;
|
||||
while (env->current_tb) {
|
||||
tc_ptr = tb->tc_ptr;
|
||||
/* execute the generated code */
|
||||
#if defined(__sparc__) && !defined(HOST_SOLARIS)
|
||||
#undef env
|
||||
env = cpu_single_env;
|
||||
env = cpu_single_env;
|
||||
#define env cpu_single_env
|
||||
#endif
|
||||
next_tb = tcg_qemu_tb_exec(tc_ptr);
|
||||
env->current_tb = NULL;
|
||||
next_tb = tcg_qemu_tb_exec(tc_ptr);
|
||||
env->current_tb = NULL;
|
||||
if ((next_tb & 3) == 2) {
|
||||
/* Instruction counter exired. */
|
||||
int insns_left;
|
||||
tb = (TranslationBlock *)(long)(next_tb & ~3);
|
||||
/* Restore PC. */
|
||||
CPU_PC_FROM_TB(env, tb);
|
||||
insns_left = env->icount_decr.u32;
|
||||
if (env->icount_extra && insns_left >= 0) {
|
||||
/* Refill decrementer and continue execution. */
|
||||
env->icount_extra += insns_left;
|
||||
if (env->icount_extra > 0xffff) {
|
||||
insns_left = 0xffff;
|
||||
} else {
|
||||
insns_left = env->icount_extra;
|
||||
}
|
||||
env->icount_extra -= insns_left;
|
||||
env->icount_decr.u16.low = insns_left;
|
||||
} else {
|
||||
if (insns_left > 0) {
|
||||
/* Execute remaining instructions. */
|
||||
cpu_exec_nocache(insns_left, tb);
|
||||
}
|
||||
env->exception_index = EXCP_INTERRUPT;
|
||||
next_tb = 0;
|
||||
cpu_loop_exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* reset soft MMU for next block (it can currently
|
||||
only be set by a memory fault) */
|
||||
#if defined(USE_KQEMU)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue