|
@@ -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
|