2506 |
2506 |
static void check_watchpoint(int offset, int len_mask, int flags)
|
2507 |
2507 |
{
|
2508 |
2508 |
CPUState *env = cpu_single_env;
|
|
2509 |
target_ulong pc, cs_base;
|
|
2510 |
TranslationBlock *tb;
|
2509 |
2511 |
target_ulong vaddr;
|
2510 |
2512 |
CPUWatchpoint *wp;
|
|
2513 |
int cpu_flags;
|
2511 |
2514 |
|
|
2515 |
if (env->watchpoint_hit) {
|
|
2516 |
/* We re-entered the check after replacing the TB. Now raise
|
|
2517 |
* the debug interrupt so that is will trigger after the
|
|
2518 |
* current instruction. */
|
|
2519 |
cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
|
|
2520 |
return;
|
|
2521 |
}
|
2512 |
2522 |
vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
|
2513 |
2523 |
for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
|
2514 |
2524 |
if ((vaddr == (wp->vaddr & len_mask) ||
|
2515 |
2525 |
(vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
|
2516 |
2526 |
env->watchpoint_hit = wp;
|
2517 |
|
cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
|
2518 |
|
break;
|
|
2527 |
tb = tb_find_pc(env->mem_io_pc);
|
|
2528 |
if (!tb) {
|
|
2529 |
cpu_abort(env, "check_watchpoint: could not find TB for pc=%p",
|
|
2530 |
(void *)env->mem_io_pc);
|
|
2531 |
}
|
|
2532 |
cpu_restore_state(tb, env, env->mem_io_pc, NULL);
|
|
2533 |
tb_phys_invalidate(tb, -1);
|
|
2534 |
if (wp->flags & BP_STOP_BEFORE_ACCESS) {
|
|
2535 |
env->exception_index = EXCP_DEBUG;
|
|
2536 |
} else {
|
|
2537 |
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
|
|
2538 |
tb_gen_code(env, pc, cs_base, cpu_flags, 1);
|
|
2539 |
}
|
|
2540 |
cpu_resume_from_signal(env, NULL);
|
2519 |
2541 |
}
|
2520 |
2542 |
}
|
2521 |
2543 |
}
|