summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu-all.h23
-rw-r--r--cpu-defs.h26
-rw-r--r--exec.c195
-rw-r--r--gdbstub.c137
-rw-r--r--target-alpha/translate.c7
-rw-r--r--target-arm/translate.c9
-rw-r--r--target-cris/translate.c9
-rw-r--r--target-i386/translate.c7
-rw-r--r--target-m68k/translate.c9
-rw-r--r--target-mips/translate.c7
-rw-r--r--target-ppc/translate.c7
-rw-r--r--target-sh4/translate.c7
-rw-r--r--target-sparc/translate.c7
13 files changed, 267 insertions, 183 deletions
diff --git a/cpu-all.h b/cpu-all.h
index cdd79bc73a..1f4f1e76e8 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -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 */
diff --git a/cpu-defs.h b/cpu-defs.h
index 46d4487811..069d312e1e 100644
--- 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)
@@ -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; \
\
diff --git a/exec.c b/exec.c
index 772b1c10be..4619e492fb 100644
--- a/exec.c
+++ b/exec.c
@@ -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);
}
diff --git a/gdbstub.c b/gdbstub.c
index aff8189725..a0fc62d3d7 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -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 8fc9766506..3b90f62922 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 9d52991b40..237c5f6941 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 a10ccb6e79..ac258a9deb 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 5006106a46..0de238b575 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 07f0640c03..49e2cb27df 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 590c2b683b..cc7e71c575 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 d92e04db3e..085c7a1533 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 b05e8fc6f1..eb3366ccc8 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 77fb72396d..e94e3c536c 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();