diff options
-rw-r--r-- | cpu-all.h | 23 | ||||
-rw-r--r-- | cpu-defs.h | 26 | ||||
-rw-r--r-- | exec.c | 195 | ||||
-rw-r--r-- | gdbstub.c | 137 | ||||
-rw-r--r-- | target-alpha/translate.c | 7 | ||||
-rw-r--r-- | target-arm/translate.c | 9 | ||||
-rw-r--r-- | target-cris/translate.c | 9 | ||||
-rw-r--r-- | target-i386/translate.c | 7 | ||||
-rw-r--r-- | target-m68k/translate.c | 9 | ||||
-rw-r--r-- | target-mips/translate.c | 7 | ||||
-rw-r--r-- | target-ppc/translate.c | 7 | ||||
-rw-r--r-- | target-sh4/translate.c | 7 | ||||
-rw-r--r-- | target-sparc/translate.c | 7 |
13 files changed, 267 insertions, 183 deletions
@@ -761,12 +761,23 @@ extern int use_icount; void cpu_interrupt(CPUState *s, int mask); void cpu_reset_interrupt(CPUState *env, int mask); -int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type); -int cpu_watchpoint_remove(CPUState *env, target_ulong addr); -void cpu_watchpoint_remove_all(CPUState *env); -int cpu_breakpoint_insert(CPUState *env, target_ulong pc); -int cpu_breakpoint_remove(CPUState *env, target_ulong pc); -void cpu_breakpoint_remove_all(CPUState *env); +/* Breakpoint/watchpoint flags */ +#define BP_MEM_READ 0x01 +#define BP_MEM_WRITE 0x02 +#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE) +#define BP_GDB 0x10 + +int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, + CPUBreakpoint **breakpoint); +int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags); +void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint); +void cpu_breakpoint_remove_all(CPUState *env, int mask); +int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, + int flags, CPUWatchpoint **watchpoint); +int cpu_watchpoint_remove(CPUState *env, target_ulong addr, + target_ulong len, int flags); +void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint); +void cpu_watchpoint_remove_all(CPUState *env, int mask); #define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */ #define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */ @@ -82,8 +82,6 @@ typedef uint64_t target_phys_addr_t; #define EXCP_HLT 0x10001 /* hlt instruction reached */ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ -#define MAX_BREAKPOINTS 32 -#define MAX_WATCHPOINTS 32 #define TB_JMP_CACHE_BITS 12 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) @@ -145,6 +143,19 @@ typedef struct icount_decr_u16 { struct kvm_run; struct KVMState; +typedef struct CPUBreakpoint { + target_ulong pc; + int flags; /* BP_* */ + struct CPUBreakpoint *prev, *next; +} CPUBreakpoint; + +typedef struct CPUWatchpoint { + target_ulong vaddr; + target_ulong len_mask; + int flags; /* BP_* */ + struct CPUWatchpoint *prev, *next; +} CPUWatchpoint; + #define CPU_TEMP_BUF_NLONGS 128 #define CPU_COMMON \ struct TranslationBlock *current_tb; /* currently executing TB */ \ @@ -177,16 +188,11 @@ struct KVMState; \ /* from this point: preserved by CPU reset */ \ /* ice debug support */ \ - target_ulong breakpoints[MAX_BREAKPOINTS]; \ - int nb_breakpoints; \ + CPUBreakpoint *breakpoints; \ int singlestep_enabled; \ \ - struct { \ - target_ulong vaddr; \ - int type; /* PAGE_READ/PAGE_WRITE */ \ - } watchpoint[MAX_WATCHPOINTS]; \ - int nb_watchpoints; \ - int watchpoint_hit; \ + CPUWatchpoint *watchpoints; \ + CPUWatchpoint *watchpoint_hit; \ \ struct GDBRegisterState *gdb_regs; \ \ @@ -537,7 +537,6 @@ void cpu_exec_init(CPUState *env) cpu_index++; } env->cpu_index = cpu_index; - env->nb_watchpoints = 0; *penv = env; #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION, @@ -1299,107 +1298,150 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc) #endif /* Add a watchpoint. */ -int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type) +int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, + int flags, CPUWatchpoint **watchpoint) { - int i; + CPUWatchpoint *wp; - for (i = 0; i < env->nb_watchpoints; i++) { - if (addr == env->watchpoint[i].vaddr) - return 0; - } - if (env->nb_watchpoints >= MAX_WATCHPOINTS) - return -1; + wp = qemu_malloc(sizeof(*wp)); + if (!wp) + return -ENOBUFS; + + wp->vaddr = addr; + wp->len_mask = 0; + wp->flags = flags; + + wp->next = env->watchpoints; + wp->prev = NULL; + if (wp->next) + wp->next->prev = wp; + env->watchpoints = wp; - i = env->nb_watchpoints++; - env->watchpoint[i].vaddr = addr; - env->watchpoint[i].type = type; tlb_flush_page(env, addr); /* FIXME: This flush is needed because of the hack to make memory ops terminate the TB. It can be removed once the proper IO trap and re-execute bits are in. */ tb_flush(env); - return i; + + if (watchpoint) + *watchpoint = wp; + return 0; } -/* Remove a watchpoint. */ -int cpu_watchpoint_remove(CPUState *env, target_ulong addr) +/* Remove a specific watchpoint. */ +int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, + int flags) { - int i; + CPUWatchpoint *wp; - for (i = 0; i < env->nb_watchpoints; i++) { - if (addr == env->watchpoint[i].vaddr) { - env->nb_watchpoints--; - env->watchpoint[i] = env->watchpoint[env->nb_watchpoints]; - tlb_flush_page(env, addr); + for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + if (addr == wp->vaddr && flags == wp->flags) { + cpu_watchpoint_remove_by_ref(env, wp); return 0; } } - return -1; + return -ENOENT; } -/* Remove all watchpoints. */ -void cpu_watchpoint_remove_all(CPUState *env) { - int i; +/* Remove a specific watchpoint by reference. */ +void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) +{ + if (watchpoint->next) + watchpoint->next->prev = watchpoint->prev; + if (watchpoint->prev) + watchpoint->prev->next = watchpoint->next; + else + env->watchpoints = watchpoint->next; - for (i = 0; i < env->nb_watchpoints; i++) { - tlb_flush_page(env, env->watchpoint[i].vaddr); - } - env->nb_watchpoints = 0; + tlb_flush_page(env, watchpoint->vaddr); + + qemu_free(watchpoint); +} + +/* Remove all matching watchpoints. */ +void cpu_watchpoint_remove_all(CPUState *env, int mask) +{ + CPUWatchpoint *wp; + + for (wp = env->watchpoints; wp != NULL; wp = wp->next) + if (wp->flags & mask) + cpu_watchpoint_remove_by_ref(env, wp); } -/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a - breakpoint is reached */ -int cpu_breakpoint_insert(CPUState *env, target_ulong pc) +/* Add a breakpoint. */ +int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, + CPUBreakpoint **breakpoint) { #if defined(TARGET_HAS_ICE) - int i; + CPUBreakpoint *bp; - for(i = 0; i < env->nb_breakpoints; i++) { - if (env->breakpoints[i] == pc) - return 0; - } + bp = qemu_malloc(sizeof(*bp)); + if (!bp) + return -ENOBUFS; - if (env->nb_breakpoints >= MAX_BREAKPOINTS) - return -1; - env->breakpoints[env->nb_breakpoints++] = pc; + bp->pc = pc; + bp->flags = flags; + + bp->next = env->breakpoints; + bp->prev = NULL; + if (bp->next) + bp->next->prev = bp; + env->breakpoints = bp; breakpoint_invalidate(env, pc); + + if (breakpoint) + *breakpoint = bp; return 0; #else - return -1; + return -ENOSYS; #endif } -/* remove all breakpoints */ -void cpu_breakpoint_remove_all(CPUState *env) { +/* Remove a specific breakpoint. */ +int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) +{ #if defined(TARGET_HAS_ICE) - int i; - for(i = 0; i < env->nb_breakpoints; i++) { - breakpoint_invalidate(env, env->breakpoints[i]); + CPUBreakpoint *bp; + + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == pc && bp->flags == flags) { + cpu_breakpoint_remove_by_ref(env, bp); + return 0; + } } - env->nb_breakpoints = 0; + return -ENOENT; +#else + return -ENOSYS; #endif } -/* remove a breakpoint */ -int cpu_breakpoint_remove(CPUState *env, target_ulong pc) +/* Remove a specific breakpoint by reference. */ +void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) { #if defined(TARGET_HAS_ICE) - int i; - for(i = 0; i < env->nb_breakpoints; i++) { - if (env->breakpoints[i] == pc) - goto found; - } - return -1; - found: - env->nb_breakpoints--; - if (i < env->nb_breakpoints) - env->breakpoints[i] = env->breakpoints[env->nb_breakpoints]; + if (breakpoint->next) + breakpoint->next->prev = breakpoint->prev; + if (breakpoint->prev) + breakpoint->prev->next = breakpoint->next; + else + env->breakpoints = breakpoint->next; - breakpoint_invalidate(env, pc); - return 0; -#else - return -1; + breakpoint_invalidate(env, breakpoint->pc); + + qemu_free(breakpoint); +#endif +} + +/* Remove all matching breakpoints. */ +void cpu_breakpoint_remove_all(CPUState *env, int mask) +{ +#if defined(TARGET_HAS_ICE) + CPUBreakpoint *bp; + + for (bp = env->breakpoints; bp != NULL; bp = bp->next) + if (bp->flags & mask) + cpu_breakpoint_remove_by_ref(env, bp); #endif } @@ -1881,7 +1923,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, target_phys_addr_t addend; int ret; CPUTLBEntry *te; - int i; + CPUWatchpoint *wp; target_phys_addr_t iotlb; p = phys_page_find(paddr >> TARGET_PAGE_BITS); @@ -1922,8 +1964,8 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, code_address = address; /* Make accesses to pages with watchpoints go via the watchpoint trap routines. */ - for (i = 0; i < env->nb_watchpoints; i++) { - if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) { + for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { iotlb = io_mem_watch + paddr; /* TODO: The memory case can be optimized by not trapping reads of pages with a write breakpoint. */ @@ -2456,13 +2498,12 @@ static void check_watchpoint(int offset, int flags) { CPUState *env = cpu_single_env; target_ulong vaddr; - int i; + CPUWatchpoint *wp; vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; - for (i = 0; i < env->nb_watchpoints; i++) { - if (vaddr == env->watchpoint[i].vaddr - && (env->watchpoint[i].type & flags)) { - env->watchpoint_hit = i + 1; + for (wp = env->watchpoints; wp != NULL; wp = wp->next) { + if (vaddr == wp->vaddr && (wp->flags & flags)) { + env->watchpoint_hit = wp; cpu_interrupt(env, CPU_INTERRUPT_DEBUG); break; } @@ -2474,40 +2515,40 @@ static void check_watchpoint(int offset, int flags) phys routines. */ static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ); return ldub_phys(addr); } static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ); return lduw_phys(addr); } static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ); return ldl_phys(addr); } static void watch_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE); stb_phys(addr, val); } static void watch_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE); stw_phys(addr, val); } static void watch_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) { - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE); stl_phys(addr, val); } @@ -1145,10 +1145,70 @@ void gdb_register_coprocessor(CPUState * env, } } +/* GDB breakpoint/watchpoint types */ +#define GDB_BREAKPOINT_SW 0 +#define GDB_BREAKPOINT_HW 1 +#define GDB_WATCHPOINT_WRITE 2 +#define GDB_WATCHPOINT_READ 3 +#define GDB_WATCHPOINT_ACCESS 4 + +#ifndef CONFIG_USER_ONLY +static const int xlat_gdb_type[] = { + [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, + [GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ, + [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS, +}; +#endif + +static int gdb_breakpoint_insert(CPUState *env, target_ulong addr, + target_ulong len, int type) +{ + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + return cpu_breakpoint_insert(env, addr, BP_GDB, NULL); +#ifndef CONFIG_USER_ONLY + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + return cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type], + NULL); +#endif + default: + return -ENOSYS; + } +} + +static int gdb_breakpoint_remove(CPUState *env, target_ulong addr, + target_ulong len, int type) +{ + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + return cpu_breakpoint_remove(env, addr, BP_GDB); +#ifndef CONFIG_USER_ONLY + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + return cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]); +#endif + default: + return -ENOSYS; + } +} + +static void gdb_breakpoint_remove_all(CPUState *env) +{ + cpu_breakpoint_remove_all(env, BP_GDB); +#ifndef CONFIG_USER_ONLY + cpu_watchpoint_remove_all(env, BP_GDB); +#endif +} + static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) { const char *p; - int ch, reg_size, type; + int ch, reg_size, type, res; char buf[MAX_PACKET_LENGTH]; uint8_t mem_buf[MAX_PACKET_LENGTH]; uint8_t *registers; @@ -1168,8 +1228,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) * because gdb is doing and initial connect and the state * should be cleaned up. */ - cpu_breakpoint_remove_all(env); - cpu_watchpoint_remove_all(env); + gdb_breakpoint_remove_all(env); break; case 'c': if (*p != '\0') { @@ -1203,8 +1262,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) exit(0); case 'D': /* Detach packet */ - cpu_breakpoint_remove_all(env); - cpu_watchpoint_remove_all(env); + gdb_breakpoint_remove_all(env); gdb_continue(s); put_packet(s, "OK"); break; @@ -1327,44 +1385,6 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) put_packet(s, "OK"); break; case 'Z': - type = strtoul(p, (char **)&p, 16); - if (*p == ',') - p++; - addr = strtoull(p, (char **)&p, 16); - if (*p == ',') - p++; - len = strtoull(p, (char **)&p, 16); - switch (type) { - case 0: - case 1: - if (cpu_breakpoint_insert(env, addr) < 0) - goto breakpoint_error; - put_packet(s, "OK"); - break; -#ifndef CONFIG_USER_ONLY - case 2: - type = PAGE_WRITE; - goto insert_watchpoint; - case 3: - type = PAGE_READ; - goto insert_watchpoint; - case 4: - type = PAGE_READ | PAGE_WRITE; - insert_watchpoint: - if (cpu_watchpoint_insert(env, addr, type) < 0) - goto breakpoint_error; - put_packet(s, "OK"); - break; -#endif - default: - put_packet(s, ""); - break; - } - break; - breakpoint_error: - put_packet(s, "E22"); - break; - case 'z': type = strtoul(p, (char **)&p, 16); if (*p == ',') @@ -1373,17 +1393,16 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) if (*p == ',') p++; len = strtoull(p, (char **)&p, 16); - if (type == 0 || type == 1) { - cpu_breakpoint_remove(env, addr); - put_packet(s, "OK"); -#ifndef CONFIG_USER_ONLY - } else if (type >= 2 || type <= 4) { - cpu_watchpoint_remove(env, addr); - put_packet(s, "OK"); -#endif - } else { + if (ch == 'Z') + res = gdb_breakpoint_insert(env, addr, len, type); + else + res = gdb_breakpoint_remove(env, addr, len, type); + if (res >= 0) + put_packet(s, "OK"); + else if (res == -ENOSYS) put_packet(s, ""); - } + else + put_packet(s, "E22"); break; case 'q': case 'Q': @@ -1504,12 +1523,11 @@ static void gdb_vm_stopped(void *opaque, int reason) if (reason == EXCP_DEBUG) { if (s->env->watchpoint_hit) { - switch (s->env->watchpoint[s->env->watchpoint_hit - 1].type & - (PAGE_READ | PAGE_WRITE)) { - case PAGE_READ: + switch (s->env->watchpoint_hit->flags & BP_MEM_ACCESS) { + case BP_MEM_READ: type = "r"; break; - case PAGE_READ | PAGE_WRITE: + case BP_MEM_ACCESS: type = "a"; break; default: @@ -1517,10 +1535,9 @@ static void gdb_vm_stopped(void *opaque, int reason) break; } snprintf(buf, sizeof(buf), "T%02x%swatch:" TARGET_FMT_lx ";", - SIGTRAP, type, - s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr); + SIGTRAP, type, s->env->watchpoint_hit->vaddr); put_packet(s, buf); - s->env->watchpoint_hit = 0; + s->env->watchpoint_hit = NULL; return; } tb_flush(s->env); diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 8fc9766..3b90f62 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -2340,6 +2340,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, target_ulong pc_start; uint32_t insn; uint16_t *gen_opc_end; + CPUBreakpoint *bp; int j, lj = -1; int ret; int num_insns; @@ -2362,9 +2363,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, gen_icount_start(); for (ret = 0; ret == 0;) { - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == ctx.pc) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == ctx.pc) { gen_excp(&ctx, EXCP_DEBUG, 0); break; } diff --git a/target-arm/translate.c b/target-arm/translate.c index 9d52991..237c5f6 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8600,6 +8600,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, int search_pc) { DisasContext dc1, *dc = &dc1; + CPUBreakpoint *bp; uint16_t *gen_opc_end; int j, lj; target_ulong pc_start; @@ -8676,9 +8677,9 @@ static inline void gen_intermediate_code_internal(CPUState *env, } #endif - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == dc->pc) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == dc->pc) { gen_set_condexec(dc); gen_set_pc_im(dc->pc); gen_exception(EXCP_DEBUG); @@ -8731,7 +8732,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, /* Terminate the TB on memory ops if watchpoints are present. */ /* FIXME: This should be replacd by the deterministic execution * IRQ raising bits. */ - if (dc->is_mem && env->nb_watchpoints) + if (dc->is_mem && env->watchpoints) break; /* Translation stops when a conditional branch is enoutered. diff --git a/target-cris/translate.c b/target-cris/translate.c index a10ccb6..ac258a9 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3187,10 +3187,11 @@ cris_decoder(DisasContext *dc) static void check_breakpoint(CPUState *env, DisasContext *dc) { - int j; - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == dc->pc) { + CPUBreakpoint *bp; + + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == dc->pc) { cris_evaluate_flags (dc); tcg_gen_movi_tl(env_pc, dc->pc); t_gen_raise_exception(EXCP_DEBUG); diff --git a/target-i386/translate.c b/target-i386/translate.c index 5006106..0de238b 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -7522,6 +7522,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; uint16_t *gen_opc_end; + CPUBreakpoint *bp; int j, lj, cflags; uint64_t flags; target_ulong pc_start; @@ -7605,9 +7606,9 @@ static inline void gen_intermediate_code_internal(CPUState *env, gen_icount_start(); for(;;) { - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == pc_ptr) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == pc_ptr) { gen_debug(dc, pc_ptr - dc->cs_base); break; } diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 07f0640..49e2cb2 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2965,6 +2965,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, { DisasContext dc1, *dc = &dc1; uint16_t *gen_opc_end; + CPUBreakpoint *bp; int j, lj; target_ulong pc_start; int pc_offset; @@ -2998,9 +2999,9 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, do { pc_offset = dc->pc - pc_start; gen_throws_exception = NULL; - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == dc->pc) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == dc->pc) { gen_exception(dc, dc->pc, EXCP_DEBUG); dc->is_jmp = DISAS_JUMP; break; @@ -3030,7 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, /* Terminate the TB on memory ops if watchpoints are present. */ /* FIXME: This should be replaced by the deterministic execution * IRQ raising bits. */ - if (dc->is_mem && env->nb_watchpoints) + if (dc->is_mem && env->watchpoints) break; } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && !env->singlestep_enabled && diff --git a/target-mips/translate.c b/target-mips/translate.c index 590c2b6..cc7e71c 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -8246,6 +8246,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, DisasContext ctx; target_ulong pc_start; uint16_t *gen_opc_end; + CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -8285,9 +8286,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, #endif gen_icount_start(); while (ctx.bstate == BS_NONE) { - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == ctx.pc) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == ctx.pc) { save_cpu_state(&ctx, 1); ctx.bstate = BS_BRANCH; gen_helper_0i(raise_exception, EXCP_DEBUG); diff --git a/target-ppc/translate.c b/target-ppc/translate.c index d92e04d..085c7a1 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -7170,6 +7170,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, target_ulong pc_start; uint16_t *gen_opc_end; int supervisor, little_endian; + CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -7224,9 +7225,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, gen_icount_start(); /* Set env in case of segfault during code fetch */ while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { - if (unlikely(env->nb_breakpoints > 0)) { - for (j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == ctx.nip) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == ctx.nip) { gen_update_nip(&ctx, ctx.nip); gen_op_debug(); break; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index b05e8fc..eb3366c 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1803,6 +1803,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, DisasContext ctx; target_ulong pc_start; static uint16_t *gen_opc_end; + CPUBreakpoint *bp; int i, ii; int num_insns; int max_insns; @@ -1836,9 +1837,9 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, max_insns = CF_COUNT_MASK; gen_icount_start(); while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { - if (env->nb_breakpoints > 0) { - for (i = 0; i < env->nb_breakpoints; i++) { - if (ctx.pc == env->breakpoints[i]) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (ctx.pc == bp->pc) { /* We have hit a breakpoint - make sure PC is up-to-date */ tcg_gen_movi_i32(cpu_pc, ctx.pc); gen_helper_debug(); diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 77fb723..e94e3c5 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -4778,6 +4778,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, target_ulong pc_start, last_pc; uint16_t *gen_opc_end; DisasContext dc1, *dc = &dc1; + CPUBreakpoint *bp; int j, lj = -1; int num_insns; int max_insns; @@ -4815,9 +4816,9 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, max_insns = CF_COUNT_MASK; gen_icount_start(); do { - if (env->nb_breakpoints > 0) { - for(j = 0; j < env->nb_breakpoints; j++) { - if (env->breakpoints[j] == dc->pc) { + if (unlikely(env->breakpoints)) { + for (bp = env->breakpoints; bp != NULL; bp = bp->next) { + if (bp->pc == dc->pc) { if (dc->pc != pc_start) save_state(dc, cpu_cond); gen_helper_debug(); |