diff options
Diffstat (limited to 'accel/tcg/translate-all.c')
-rw-r--r-- | accel/tcg/translate-all.c | 27 |
1 files changed, 14 insertions, 13 deletions
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d4190602d1..f409d42d54 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -299,9 +299,11 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) /* The cpu state corresponding to 'searched_pc' is restored. * Called with tb_lock held. + * When reset_icount is true, current TB will be interrupted and + * icount should be recalculated. */ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, - uintptr_t searched_pc) + uintptr_t searched_pc, bool reset_icount) { target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc }; uintptr_t host_pc = (uintptr_t)tb->tc.ptr; @@ -333,14 +335,12 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return -1; found: - if (tb->cflags & CF_USE_ICOUNT) { + if (reset_icount && (tb->cflags & CF_USE_ICOUNT)) { assert(use_icount); - /* Reset the cycle counter to the start of the block. */ - cpu->icount_decr.u16.low += num_insns; - /* Clear the IO flag. */ - cpu->can_do_io = 0; + /* Reset the cycle counter to the start of the block + and shift if to the number of actually executed instructions */ + cpu->icount_decr.u16.low += num_insns - i; } - cpu->icount_decr.u16.low -= i; restore_state_to_opc(env, tb, data); #ifdef CONFIG_PROFILER @@ -351,7 +351,7 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return 0; } -bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc) +bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit) { TranslationBlock *tb; bool r = false; @@ -377,7 +377,7 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc) tb_lock(); tb = tb_find_pc(host_pc); if (tb) { - cpu_restore_state_from_tb(cpu, tb, host_pc); + cpu_restore_state_from_tb(cpu, tb, host_pc, will_exit); if (tb->cflags & CF_NOCACHE) { /* one-shot translation, invalidate it immediately */ tb_phys_invalidate(tb, -1); @@ -1511,7 +1511,8 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, restore the CPU state */ current_tb_modified = 1; - cpu_restore_state_from_tb(cpu, current_tb, cpu->mem_io_pc); + cpu_restore_state_from_tb(cpu, current_tb, + cpu->mem_io_pc, true); cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); } @@ -1634,7 +1635,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) restore the CPU state */ current_tb_modified = 1; - cpu_restore_state_from_tb(cpu, current_tb, pc); + cpu_restore_state_from_tb(cpu, current_tb, pc, true); cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base, ¤t_flags); } @@ -1700,7 +1701,7 @@ void tb_check_watchpoint(CPUState *cpu) tb = tb_find_pc(cpu->mem_io_pc); if (tb) { /* We can use retranslation to find the PC. */ - cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc); + cpu_restore_state_from_tb(cpu, tb, cpu->mem_io_pc, true); tb_phys_invalidate(tb, -1); } else { /* The exception probably happened in a helper. The CPU state should @@ -1736,7 +1737,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) cpu_abort(cpu, "cpu_io_recompile: could not find TB for pc=%p", (void *)retaddr); } - cpu_restore_state_from_tb(cpu, tb, retaddr); + cpu_restore_state_from_tb(cpu, tb, retaddr, true); /* On MIPS and SH, delay slot instructions can only be restarted if they were already the first instruction in the TB. If this is not |