[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH 02/13] Refactor and enhance break/watchpoint API
From: |
Glauber Costa |
Subject: |
Re: [Qemu-devel] [PATCH 02/13] Refactor and enhance break/watchpoint API |
Date: |
Tue, 14 Oct 2008 15:35:18 -0200 |
> /* 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)
Any particular reason you're not simply returning the address of the watchpoint?
Although I must admit it's a matter of personal taste.
> {
> - 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 = len;
> + 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;
> -}
>
> -/* Remove a watchpoint. */
> -int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
> -{
> - int i;
> + if (watchpoint)
> + *watchpoint = wp;
> + return 0;
> +}
>
> - 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);
> +/* Remove a specific watchpoint. */
> +int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
> + int flags)
> +{
> + CPUWatchpoint *wp;
> +
> + for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
> + if (addr == wp->vaddr && len == wp->len && 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);
> }
>
> -/* 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)
> +/* Remove all matching watchpoints. */
> +void cpu_watchpoint_remove_all(CPUState *env, int mask)
> {
> -#if defined(TARGET_HAS_ICE)
> - int i;
> + CPUWatchpoint *wp;
>
> - for(i = 0; i < env->nb_breakpoints; i++) {
> - if (env->breakpoints[i] == pc)
> - return 0;
> - }
> + for (wp = env->watchpoints; wp != NULL; wp = wp->next)
> + if (wp->flags & mask)
> + cpu_watchpoint_remove_by_ref(env, wp);
> +}
>
> - if (env->nb_breakpoints >= MAX_BREAKPOINTS)
> - return -1;
> - env->breakpoints[env->nb_breakpoints++] = pc;
> +/* Add a breakpoint. */
> +int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
> + CPUBreakpoint **breakpoint)
> +{
> +#if defined(TARGET_HAS_ICE)
> + CPUBreakpoint *bp;
> +
> + bp = qemu_malloc(sizeof(*bp));
> + if (!bp)
> + return -ENOBUFS;
> +
> + 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
> }
>
> @@ -1893,7 +1935,7 @@ int tlb_set_page_exec(CPUState *env, tar
> 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);
> @@ -1934,8 +1976,8 @@ int tlb_set_page_exec(CPUState *env, tar
> 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. */
> @@ -2464,13 +2506,12 @@ static void check_watchpoint(int offset,
> {
> 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;
> }
> @@ -2482,40 +2523,40 @@ static void check_watchpoint(int offset,
> 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);
> }
>
> Index: b/gdbstub.c
> ===================================================================
> --- a/gdbstub.c
> +++ b/gdbstub.c
> @@ -1147,10 +1147,64 @@ void gdb_register_coprocessor(CPUState *
> }
> }
>
> +/* 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 ... GDB_BREAKPOINT_HW:
> + return cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
> +#ifndef CONFIG_USER_ONLY
> + case GDB_WATCHPOINT_WRITE ... 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 ... GDB_BREAKPOINT_HW:
> + return cpu_breakpoint_remove(env, addr, BP_GDB);
> +#ifndef CONFIG_USER_ONLY
> + case GDB_WATCHPOINT_WRITE ... 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;
> @@ -1170,8 +1224,7 @@ static int gdb_handle_packet(GDBState *s
> * 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') {
> @@ -1205,8 +1258,7 @@ static int gdb_handle_packet(GDBState *s
> 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;
> @@ -1329,44 +1381,6 @@ static int gdb_handle_packet(GDBState *s
> 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 == ',')
> @@ -1375,17 +1389,16 @@ static int gdb_handle_packet(GDBState *s
> 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':
> @@ -1506,12 +1519,11 @@ static void gdb_vm_stopped(void *opaque,
>
> if (reason == EXCP_DEBUG) {
> if (s->env->watchpoint_hit) {
> - switch (s->env->watchpoint[s->env->watchpoint_hit - 1].flags &
> - (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:
> @@ -1519,10 +1531,9 @@ static void gdb_vm_stopped(void *opaque,
> 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);
> Index: b/cpu-defs.h
> ===================================================================
> --- a/cpu-defs.h
> +++ b/cpu-defs.h
> @@ -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)
> @@ -142,6 +140,19 @@ typedef struct icount_decr_u16 {
> } icount_decr_u16;
> #endif
>
> +typedef struct CPUBreakpoint {
> + target_ulong pc;
> + int flags; /* BP_* */
> + struct CPUBreakpoint *prev, *next;
> +} CPUBreakpoint;
> +
> +typedef struct CPUWatchpoint {
> + target_ulong vaddr;
> + target_ulong len;
> + int flags; /* BP_* */
> + struct CPUWatchpoint *prev, *next;
> +} CPUWatchpoint;
> +
> #define CPU_TEMP_BUF_NLONGS 128
> #define CPU_COMMON \
> struct TranslationBlock *current_tb; /* currently executing TB */ \
> @@ -174,16 +185,11 @@ typedef struct icount_decr_u16 {
> \
> /* 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; \
> \
> Index: b/target-i386/translate.c
> ===================================================================
> --- a/target-i386/translate.c
> +++ b/target-i386/translate.c
> @@ -7533,6 +7533,7 @@ static inline void gen_intermediate_code
> 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;
> @@ -7616,9 +7617,9 @@ static inline void gen_intermediate_code
>
> 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;
> }
> Index: b/target-alpha/translate.c
> ===================================================================
> --- a/target-alpha/translate.c
> +++ b/target-alpha/translate.c
> @@ -2252,6 +2252,7 @@ static always_inline void gen_intermedia
> target_ulong pc_start;
> uint32_t insn;
> uint16_t *gen_opc_end;
> + CPUBreakpoint *bp;
> int j, lj = -1;
> int ret;
> int num_insns;
> @@ -2274,9 +2275,9 @@ static always_inline void gen_intermedia
>
> 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;
> }
> Index: b/target-arm/translate.c
> ===================================================================
> --- a/target-arm/translate.c
> +++ b/target-arm/translate.c
> @@ -8544,6 +8544,7 @@ static inline void gen_intermediate_code
> int search_pc)
> {
> DisasContext dc1, *dc = &dc1;
> + CPUBreakpoint *bp;
> uint16_t *gen_opc_end;
> int j, lj;
> target_ulong pc_start;
> @@ -8620,9 +8621,9 @@ static inline void gen_intermediate_code
> }
> #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);
> @@ -8675,7 +8676,7 @@ static inline void gen_intermediate_code
> /* 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.
> Index: b/target-cris/translate.c
> ===================================================================
> --- a/target-cris/translate.c
> +++ b/target-cris/translate.c
> @@ -3006,10 +3006,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);
> Index: b/target-m68k/translate.c
> ===================================================================
> --- a/target-m68k/translate.c
> +++ b/target-m68k/translate.c
> @@ -2916,6 +2916,7 @@ gen_intermediate_code_internal(CPUState
> {
> DisasContext dc1, *dc = &dc1;
> uint16_t *gen_opc_end;
> + CPUBreakpoint *bp;
> int j, lj;
> target_ulong pc_start;
> int pc_offset;
> @@ -2949,9 +2950,9 @@ gen_intermediate_code_internal(CPUState
> 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;
> @@ -2981,7 +2982,7 @@ gen_intermediate_code_internal(CPUState
> /* 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 &&
> Index: b/target-mips/translate.c
> ===================================================================
> --- a/target-mips/translate.c
> +++ b/target-mips/translate.c
> @@ -8442,6 +8442,7 @@ gen_intermediate_code_internal (CPUState
> DisasContext ctx;
> target_ulong pc_start;
> uint16_t *gen_opc_end;
> + CPUBreakpoint *bp;
> int j, lj = -1;
> int num_insns;
> int max_insns;
> @@ -8481,9 +8482,9 @@ gen_intermediate_code_internal (CPUState
> #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;
> tcg_gen_helper_0_i(do_raise_exception, EXCP_DEBUG);
> Index: b/target-ppc/translate.c
> ===================================================================
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -6198,6 +6198,7 @@ static always_inline void gen_intermedia
> 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;
> @@ -6252,9 +6253,9 @@ static always_inline void gen_intermedia
> 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;
> Index: b/target-sh4/translate.c
> ===================================================================
> --- a/target-sh4/translate.c
> +++ b/target-sh4/translate.c
> @@ -1799,6 +1799,7 @@ gen_intermediate_code_internal(CPUState
> DisasContext ctx;
> target_ulong pc_start;
> static uint16_t *gen_opc_end;
> + CPUBreakpoint *bp;
> int i, ii;
> int num_insns;
> int max_insns;
> @@ -1832,9 +1833,9 @@ gen_intermediate_code_internal(CPUState
> 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);
> tcg_gen_helper_0_0(helper_debug);
> Index: b/target-sparc/translate.c
> ===================================================================
> --- a/target-sparc/translate.c
> +++ b/target-sparc/translate.c
> @@ -4775,6 +4775,7 @@ static inline void gen_intermediate_code
> 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;
> @@ -4812,9 +4813,9 @@ static inline void gen_intermediate_code
> 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);
> tcg_gen_helper_0_0(helper_debug);
>
>
>
>
--
Glauber Costa.
"Free as in Freedom"
http://glommer.net
"The less confident you are, the more serious you have to act."
- [Qemu-devel] [PATCH 06/13] Switch self-modified code recompilation to next_cflags, (continued)
- [Qemu-devel] [PATCH 06/13] Switch self-modified code recompilation to next_cflags, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 03/13] Set mem_io_vaddr on io_read, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 10/13] Introduce BP_WATCHPOINT_HIT flag, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 12/13] Introduce BP_CPU as a breakpoint type, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 02/13] Refactor and enhance break/watchpoint API, Jan Kiszka, 2008/10/14
- Re: [Qemu-devel] [PATCH 02/13] Refactor and enhance break/watchpoint API,
Glauber Costa <=
- [Qemu-devel] [PATCH 13/13] x86: Debug register emulation, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 08/13] Remove premature memop TB terminations, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 07/13] Restore pc on watchpoint hits, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 11/13] Add debug exception hook, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 09/13] qemu: gdbstub: manage CPUs as threads, Jan Kiszka, 2008/10/14
- [Qemu-devel] [PATCH 04/13] Respect length of watchpoints, Jan Kiszka, 2008/10/14