Commit a1d1bb3101db1fea4ff47b74de15208971f8d64e

Authored by aliguori
1 parent d6fc1b39

Refactor and enhance break/watchpoint API (Jan Kiszka)

This patch prepares the QEMU cpu_watchpoint/breakpoint API to allow the
succeeding enhancements this series comes with.

First of all, it overcomes MAX_BREAKPOINTS/MAX_WATCHPOINTS by switching
to dynamically allocated data structures that are kept in linked lists.
This also allows to return a stable reference to the related objects,
required for later introduced x86 debug register support.

Breakpoints and watchpoints are stored with their full information set
and an additional flag field that makes them easily extensible for use
beyond pure guest debugging.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5738 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-all.h
@@ -761,12 +761,23 @@ extern int use_icount; @@ -761,12 +761,23 @@ extern int use_icount;
761 void cpu_interrupt(CPUState *s, int mask); 761 void cpu_interrupt(CPUState *s, int mask);
762 void cpu_reset_interrupt(CPUState *env, int mask); 762 void cpu_reset_interrupt(CPUState *env, int mask);
763 763
764 -int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type);  
765 -int cpu_watchpoint_remove(CPUState *env, target_ulong addr);  
766 -void cpu_watchpoint_remove_all(CPUState *env);  
767 -int cpu_breakpoint_insert(CPUState *env, target_ulong pc);  
768 -int cpu_breakpoint_remove(CPUState *env, target_ulong pc);  
769 -void cpu_breakpoint_remove_all(CPUState *env); 764 +/* Breakpoint/watchpoint flags */
  765 +#define BP_MEM_READ 0x01
  766 +#define BP_MEM_WRITE 0x02
  767 +#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
  768 +#define BP_GDB 0x10
  769 +
  770 +int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
  771 + CPUBreakpoint **breakpoint);
  772 +int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags);
  773 +void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint);
  774 +void cpu_breakpoint_remove_all(CPUState *env, int mask);
  775 +int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
  776 + int flags, CPUWatchpoint **watchpoint);
  777 +int cpu_watchpoint_remove(CPUState *env, target_ulong addr,
  778 + target_ulong len, int flags);
  779 +void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint);
  780 +void cpu_watchpoint_remove_all(CPUState *env, int mask);
770 781
771 #define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */ 782 #define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
772 #define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */ 783 #define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
cpu-defs.h
@@ -82,8 +82,6 @@ typedef uint64_t target_phys_addr_t; @@ -82,8 +82,6 @@ typedef uint64_t target_phys_addr_t;
82 #define EXCP_HLT 0x10001 /* hlt instruction reached */ 82 #define EXCP_HLT 0x10001 /* hlt instruction reached */
83 #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ 83 #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
84 #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ 84 #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
85 -#define MAX_BREAKPOINTS 32  
86 -#define MAX_WATCHPOINTS 32  
87 85
88 #define TB_JMP_CACHE_BITS 12 86 #define TB_JMP_CACHE_BITS 12
89 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) 87 #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
@@ -145,6 +143,19 @@ typedef struct icount_decr_u16 { @@ -145,6 +143,19 @@ typedef struct icount_decr_u16 {
145 struct kvm_run; 143 struct kvm_run;
146 struct KVMState; 144 struct KVMState;
147 145
  146 +typedef struct CPUBreakpoint {
  147 + target_ulong pc;
  148 + int flags; /* BP_* */
  149 + struct CPUBreakpoint *prev, *next;
  150 +} CPUBreakpoint;
  151 +
  152 +typedef struct CPUWatchpoint {
  153 + target_ulong vaddr;
  154 + target_ulong len_mask;
  155 + int flags; /* BP_* */
  156 + struct CPUWatchpoint *prev, *next;
  157 +} CPUWatchpoint;
  158 +
148 #define CPU_TEMP_BUF_NLONGS 128 159 #define CPU_TEMP_BUF_NLONGS 128
149 #define CPU_COMMON \ 160 #define CPU_COMMON \
150 struct TranslationBlock *current_tb; /* currently executing TB */ \ 161 struct TranslationBlock *current_tb; /* currently executing TB */ \
@@ -177,16 +188,11 @@ struct KVMState; @@ -177,16 +188,11 @@ struct KVMState;
177 \ 188 \
178 /* from this point: preserved by CPU reset */ \ 189 /* from this point: preserved by CPU reset */ \
179 /* ice debug support */ \ 190 /* ice debug support */ \
180 - target_ulong breakpoints[MAX_BREAKPOINTS]; \  
181 - int nb_breakpoints; \ 191 + CPUBreakpoint *breakpoints; \
182 int singlestep_enabled; \ 192 int singlestep_enabled; \
183 \ 193 \
184 - struct { \  
185 - target_ulong vaddr; \  
186 - int type; /* PAGE_READ/PAGE_WRITE */ \  
187 - } watchpoint[MAX_WATCHPOINTS]; \  
188 - int nb_watchpoints; \  
189 - int watchpoint_hit; \ 194 + CPUWatchpoint *watchpoints; \
  195 + CPUWatchpoint *watchpoint_hit; \
190 \ 196 \
191 struct GDBRegisterState *gdb_regs; \ 197 struct GDBRegisterState *gdb_regs; \
192 \ 198 \
@@ -537,7 +537,6 @@ void cpu_exec_init(CPUState *env) @@ -537,7 +537,6 @@ void cpu_exec_init(CPUState *env)
537 cpu_index++; 537 cpu_index++;
538 } 538 }
539 env->cpu_index = cpu_index; 539 env->cpu_index = cpu_index;
540 - env->nb_watchpoints = 0;  
541 *penv = env; 540 *penv = env;
542 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY) 541 #if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
543 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION, 542 register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
@@ -1299,107 +1298,150 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc) @@ -1299,107 +1298,150 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
1299 #endif 1298 #endif
1300 1299
1301 /* Add a watchpoint. */ 1300 /* Add a watchpoint. */
1302 -int cpu_watchpoint_insert(CPUState *env, target_ulong addr, int type) 1301 +int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len,
  1302 + int flags, CPUWatchpoint **watchpoint)
1303 { 1303 {
1304 - int i; 1304 + CPUWatchpoint *wp;
1305 1305
1306 - for (i = 0; i < env->nb_watchpoints; i++) {  
1307 - if (addr == env->watchpoint[i].vaddr)  
1308 - return 0;  
1309 - }  
1310 - if (env->nb_watchpoints >= MAX_WATCHPOINTS)  
1311 - return -1; 1306 + wp = qemu_malloc(sizeof(*wp));
  1307 + if (!wp)
  1308 + return -ENOBUFS;
  1309 +
  1310 + wp->vaddr = addr;
  1311 + wp->len_mask = 0;
  1312 + wp->flags = flags;
  1313 +
  1314 + wp->next = env->watchpoints;
  1315 + wp->prev = NULL;
  1316 + if (wp->next)
  1317 + wp->next->prev = wp;
  1318 + env->watchpoints = wp;
1312 1319
1313 - i = env->nb_watchpoints++;  
1314 - env->watchpoint[i].vaddr = addr;  
1315 - env->watchpoint[i].type = type;  
1316 tlb_flush_page(env, addr); 1320 tlb_flush_page(env, addr);
1317 /* FIXME: This flush is needed because of the hack to make memory ops 1321 /* FIXME: This flush is needed because of the hack to make memory ops
1318 terminate the TB. It can be removed once the proper IO trap and 1322 terminate the TB. It can be removed once the proper IO trap and
1319 re-execute bits are in. */ 1323 re-execute bits are in. */
1320 tb_flush(env); 1324 tb_flush(env);
1321 - return i; 1325 +
  1326 + if (watchpoint)
  1327 + *watchpoint = wp;
  1328 + return 0;
1322 } 1329 }
1323 1330
1324 -/* Remove a watchpoint. */  
1325 -int cpu_watchpoint_remove(CPUState *env, target_ulong addr) 1331 +/* Remove a specific watchpoint. */
  1332 +int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len,
  1333 + int flags)
1326 { 1334 {
1327 - int i; 1335 + CPUWatchpoint *wp;
1328 1336
1329 - for (i = 0; i < env->nb_watchpoints; i++) {  
1330 - if (addr == env->watchpoint[i].vaddr) {  
1331 - env->nb_watchpoints--;  
1332 - env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];  
1333 - tlb_flush_page(env, addr); 1337 + for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
  1338 + if (addr == wp->vaddr && flags == wp->flags) {
  1339 + cpu_watchpoint_remove_by_ref(env, wp);
1334 return 0; 1340 return 0;
1335 } 1341 }
1336 } 1342 }
1337 - return -1; 1343 + return -ENOENT;
1338 } 1344 }
1339 1345
1340 -/* Remove all watchpoints. */  
1341 -void cpu_watchpoint_remove_all(CPUState *env) {  
1342 - int i; 1346 +/* Remove a specific watchpoint by reference. */
  1347 +void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
  1348 +{
  1349 + if (watchpoint->next)
  1350 + watchpoint->next->prev = watchpoint->prev;
  1351 + if (watchpoint->prev)
  1352 + watchpoint->prev->next = watchpoint->next;
  1353 + else
  1354 + env->watchpoints = watchpoint->next;
1343 1355
1344 - for (i = 0; i < env->nb_watchpoints; i++) {  
1345 - tlb_flush_page(env, env->watchpoint[i].vaddr);  
1346 - }  
1347 - env->nb_watchpoints = 0; 1356 + tlb_flush_page(env, watchpoint->vaddr);
  1357 +
  1358 + qemu_free(watchpoint);
  1359 +}
  1360 +
  1361 +/* Remove all matching watchpoints. */
  1362 +void cpu_watchpoint_remove_all(CPUState *env, int mask)
  1363 +{
  1364 + CPUWatchpoint *wp;
  1365 +
  1366 + for (wp = env->watchpoints; wp != NULL; wp = wp->next)
  1367 + if (wp->flags & mask)
  1368 + cpu_watchpoint_remove_by_ref(env, wp);
1348 } 1369 }
1349 1370
1350 -/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a  
1351 - breakpoint is reached */  
1352 -int cpu_breakpoint_insert(CPUState *env, target_ulong pc) 1371 +/* Add a breakpoint. */
  1372 +int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags,
  1373 + CPUBreakpoint **breakpoint)
1353 { 1374 {
1354 #if defined(TARGET_HAS_ICE) 1375 #if defined(TARGET_HAS_ICE)
1355 - int i; 1376 + CPUBreakpoint *bp;
1356 1377
1357 - for(i = 0; i < env->nb_breakpoints; i++) {  
1358 - if (env->breakpoints[i] == pc)  
1359 - return 0;  
1360 - } 1378 + bp = qemu_malloc(sizeof(*bp));
  1379 + if (!bp)
  1380 + return -ENOBUFS;
1361 1381
1362 - if (env->nb_breakpoints >= MAX_BREAKPOINTS)  
1363 - return -1;  
1364 - env->breakpoints[env->nb_breakpoints++] = pc; 1382 + bp->pc = pc;
  1383 + bp->flags = flags;
  1384 +
  1385 + bp->next = env->breakpoints;
  1386 + bp->prev = NULL;
  1387 + if (bp->next)
  1388 + bp->next->prev = bp;
  1389 + env->breakpoints = bp;
1365 1390
1366 breakpoint_invalidate(env, pc); 1391 breakpoint_invalidate(env, pc);
  1392 +
  1393 + if (breakpoint)
  1394 + *breakpoint = bp;
1367 return 0; 1395 return 0;
1368 #else 1396 #else
1369 - return -1; 1397 + return -ENOSYS;
1370 #endif 1398 #endif
1371 } 1399 }
1372 1400
1373 -/* remove all breakpoints */  
1374 -void cpu_breakpoint_remove_all(CPUState *env) { 1401 +/* Remove a specific breakpoint. */
  1402 +int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags)
  1403 +{
1375 #if defined(TARGET_HAS_ICE) 1404 #if defined(TARGET_HAS_ICE)
1376 - int i;  
1377 - for(i = 0; i < env->nb_breakpoints; i++) {  
1378 - breakpoint_invalidate(env, env->breakpoints[i]); 1405 + CPUBreakpoint *bp;
  1406 +
  1407 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  1408 + if (bp->pc == pc && bp->flags == flags) {
  1409 + cpu_breakpoint_remove_by_ref(env, bp);
  1410 + return 0;
  1411 + }
1379 } 1412 }
1380 - env->nb_breakpoints = 0; 1413 + return -ENOENT;
  1414 +#else
  1415 + return -ENOSYS;
1381 #endif 1416 #endif
1382 } 1417 }
1383 1418
1384 -/* remove a breakpoint */  
1385 -int cpu_breakpoint_remove(CPUState *env, target_ulong pc) 1419 +/* Remove a specific breakpoint by reference. */
  1420 +void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
1386 { 1421 {
1387 #if defined(TARGET_HAS_ICE) 1422 #if defined(TARGET_HAS_ICE)
1388 - int i;  
1389 - for(i = 0; i < env->nb_breakpoints; i++) {  
1390 - if (env->breakpoints[i] == pc)  
1391 - goto found;  
1392 - }  
1393 - return -1;  
1394 - found:  
1395 - env->nb_breakpoints--;  
1396 - if (i < env->nb_breakpoints)  
1397 - env->breakpoints[i] = env->breakpoints[env->nb_breakpoints]; 1423 + if (breakpoint->next)
  1424 + breakpoint->next->prev = breakpoint->prev;
  1425 + if (breakpoint->prev)
  1426 + breakpoint->prev->next = breakpoint->next;
  1427 + else
  1428 + env->breakpoints = breakpoint->next;
1398 1429
1399 - breakpoint_invalidate(env, pc);  
1400 - return 0;  
1401 -#else  
1402 - return -1; 1430 + breakpoint_invalidate(env, breakpoint->pc);
  1431 +
  1432 + qemu_free(breakpoint);
  1433 +#endif
  1434 +}
  1435 +
  1436 +/* Remove all matching breakpoints. */
  1437 +void cpu_breakpoint_remove_all(CPUState *env, int mask)
  1438 +{
  1439 +#if defined(TARGET_HAS_ICE)
  1440 + CPUBreakpoint *bp;
  1441 +
  1442 + for (bp = env->breakpoints; bp != NULL; bp = bp->next)
  1443 + if (bp->flags & mask)
  1444 + cpu_breakpoint_remove_by_ref(env, bp);
1403 #endif 1445 #endif
1404 } 1446 }
1405 1447
@@ -1881,7 +1923,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, @@ -1881,7 +1923,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1881 target_phys_addr_t addend; 1923 target_phys_addr_t addend;
1882 int ret; 1924 int ret;
1883 CPUTLBEntry *te; 1925 CPUTLBEntry *te;
1884 - int i; 1926 + CPUWatchpoint *wp;
1885 target_phys_addr_t iotlb; 1927 target_phys_addr_t iotlb;
1886 1928
1887 p = phys_page_find(paddr >> TARGET_PAGE_BITS); 1929 p = phys_page_find(paddr >> TARGET_PAGE_BITS);
@@ -1922,8 +1964,8 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, @@ -1922,8 +1964,8 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
1922 code_address = address; 1964 code_address = address;
1923 /* Make accesses to pages with watchpoints go via the 1965 /* Make accesses to pages with watchpoints go via the
1924 watchpoint trap routines. */ 1966 watchpoint trap routines. */
1925 - for (i = 0; i < env->nb_watchpoints; i++) {  
1926 - if (vaddr == (env->watchpoint[i].vaddr & TARGET_PAGE_MASK)) { 1967 + for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
  1968 + if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
1927 iotlb = io_mem_watch + paddr; 1969 iotlb = io_mem_watch + paddr;
1928 /* TODO: The memory case can be optimized by not trapping 1970 /* TODO: The memory case can be optimized by not trapping
1929 reads of pages with a write breakpoint. */ 1971 reads of pages with a write breakpoint. */
@@ -2456,13 +2498,12 @@ static void check_watchpoint(int offset, int flags) @@ -2456,13 +2498,12 @@ static void check_watchpoint(int offset, int flags)
2456 { 2498 {
2457 CPUState *env = cpu_single_env; 2499 CPUState *env = cpu_single_env;
2458 target_ulong vaddr; 2500 target_ulong vaddr;
2459 - int i; 2501 + CPUWatchpoint *wp;
2460 2502
2461 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset; 2503 vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2462 - for (i = 0; i < env->nb_watchpoints; i++) {  
2463 - if (vaddr == env->watchpoint[i].vaddr  
2464 - && (env->watchpoint[i].type & flags)) {  
2465 - env->watchpoint_hit = i + 1; 2504 + for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
  2505 + if (vaddr == wp->vaddr && (wp->flags & flags)) {
  2506 + env->watchpoint_hit = wp;
2466 cpu_interrupt(env, CPU_INTERRUPT_DEBUG); 2507 cpu_interrupt(env, CPU_INTERRUPT_DEBUG);
2467 break; 2508 break;
2468 } 2509 }
@@ -2474,40 +2515,40 @@ static void check_watchpoint(int offset, int flags) @@ -2474,40 +2515,40 @@ static void check_watchpoint(int offset, int flags)
2474 phys routines. */ 2515 phys routines. */
2475 static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr) 2516 static uint32_t watch_mem_readb(void *opaque, target_phys_addr_t addr)
2476 { 2517 {
2477 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); 2518 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2478 return ldub_phys(addr); 2519 return ldub_phys(addr);
2479 } 2520 }
2480 2521
2481 static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr) 2522 static uint32_t watch_mem_readw(void *opaque, target_phys_addr_t addr)
2482 { 2523 {
2483 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); 2524 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2484 return lduw_phys(addr); 2525 return lduw_phys(addr);
2485 } 2526 }
2486 2527
2487 static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr) 2528 static uint32_t watch_mem_readl(void *opaque, target_phys_addr_t addr)
2488 { 2529 {
2489 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_READ); 2530 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_READ);
2490 return ldl_phys(addr); 2531 return ldl_phys(addr);
2491 } 2532 }
2492 2533
2493 static void watch_mem_writeb(void *opaque, target_phys_addr_t addr, 2534 static void watch_mem_writeb(void *opaque, target_phys_addr_t addr,
2494 uint32_t val) 2535 uint32_t val)
2495 { 2536 {
2496 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); 2537 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2497 stb_phys(addr, val); 2538 stb_phys(addr, val);
2498 } 2539 }
2499 2540
2500 static void watch_mem_writew(void *opaque, target_phys_addr_t addr, 2541 static void watch_mem_writew(void *opaque, target_phys_addr_t addr,
2501 uint32_t val) 2542 uint32_t val)
2502 { 2543 {
2503 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); 2544 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2504 stw_phys(addr, val); 2545 stw_phys(addr, val);
2505 } 2546 }
2506 2547
2507 static void watch_mem_writel(void *opaque, target_phys_addr_t addr, 2548 static void watch_mem_writel(void *opaque, target_phys_addr_t addr,
2508 uint32_t val) 2549 uint32_t val)
2509 { 2550 {
2510 - check_watchpoint(addr & ~TARGET_PAGE_MASK, PAGE_WRITE); 2551 + check_watchpoint(addr & ~TARGET_PAGE_MASK, BP_MEM_WRITE);
2511 stl_phys(addr, val); 2552 stl_phys(addr, val);
2512 } 2553 }
2513 2554
gdbstub.c
@@ -1145,10 +1145,70 @@ void gdb_register_coprocessor(CPUState * env, @@ -1145,10 +1145,70 @@ void gdb_register_coprocessor(CPUState * env,
1145 } 1145 }
1146 } 1146 }
1147 1147
  1148 +/* GDB breakpoint/watchpoint types */
  1149 +#define GDB_BREAKPOINT_SW 0
  1150 +#define GDB_BREAKPOINT_HW 1
  1151 +#define GDB_WATCHPOINT_WRITE 2
  1152 +#define GDB_WATCHPOINT_READ 3
  1153 +#define GDB_WATCHPOINT_ACCESS 4
  1154 +
  1155 +#ifndef CONFIG_USER_ONLY
  1156 +static const int xlat_gdb_type[] = {
  1157 + [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE,
  1158 + [GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ,
  1159 + [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS,
  1160 +};
  1161 +#endif
  1162 +
  1163 +static int gdb_breakpoint_insert(CPUState *env, target_ulong addr,
  1164 + target_ulong len, int type)
  1165 +{
  1166 + switch (type) {
  1167 + case GDB_BREAKPOINT_SW:
  1168 + case GDB_BREAKPOINT_HW:
  1169 + return cpu_breakpoint_insert(env, addr, BP_GDB, NULL);
  1170 +#ifndef CONFIG_USER_ONLY
  1171 + case GDB_WATCHPOINT_WRITE:
  1172 + case GDB_WATCHPOINT_READ:
  1173 + case GDB_WATCHPOINT_ACCESS:
  1174 + return cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type],
  1175 + NULL);
  1176 +#endif
  1177 + default:
  1178 + return -ENOSYS;
  1179 + }
  1180 +}
  1181 +
  1182 +static int gdb_breakpoint_remove(CPUState *env, target_ulong addr,
  1183 + target_ulong len, int type)
  1184 +{
  1185 + switch (type) {
  1186 + case GDB_BREAKPOINT_SW:
  1187 + case GDB_BREAKPOINT_HW:
  1188 + return cpu_breakpoint_remove(env, addr, BP_GDB);
  1189 +#ifndef CONFIG_USER_ONLY
  1190 + case GDB_WATCHPOINT_WRITE:
  1191 + case GDB_WATCHPOINT_READ:
  1192 + case GDB_WATCHPOINT_ACCESS:
  1193 + return cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]);
  1194 +#endif
  1195 + default:
  1196 + return -ENOSYS;
  1197 + }
  1198 +}
  1199 +
  1200 +static void gdb_breakpoint_remove_all(CPUState *env)
  1201 +{
  1202 + cpu_breakpoint_remove_all(env, BP_GDB);
  1203 +#ifndef CONFIG_USER_ONLY
  1204 + cpu_watchpoint_remove_all(env, BP_GDB);
  1205 +#endif
  1206 +}
  1207 +
1148 static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) 1208 static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
1149 { 1209 {
1150 const char *p; 1210 const char *p;
1151 - int ch, reg_size, type; 1211 + int ch, reg_size, type, res;
1152 char buf[MAX_PACKET_LENGTH]; 1212 char buf[MAX_PACKET_LENGTH];
1153 uint8_t mem_buf[MAX_PACKET_LENGTH]; 1213 uint8_t mem_buf[MAX_PACKET_LENGTH];
1154 uint8_t *registers; 1214 uint8_t *registers;
@@ -1168,8 +1228,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) @@ -1168,8 +1228,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
1168 * because gdb is doing and initial connect and the state 1228 * because gdb is doing and initial connect and the state
1169 * should be cleaned up. 1229 * should be cleaned up.
1170 */ 1230 */
1171 - cpu_breakpoint_remove_all(env);  
1172 - cpu_watchpoint_remove_all(env); 1231 + gdb_breakpoint_remove_all(env);
1173 break; 1232 break;
1174 case 'c': 1233 case 'c':
1175 if (*p != '\0') { 1234 if (*p != '\0') {
@@ -1203,8 +1262,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) @@ -1203,8 +1262,7 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
1203 exit(0); 1262 exit(0);
1204 case 'D': 1263 case 'D':
1205 /* Detach packet */ 1264 /* Detach packet */
1206 - cpu_breakpoint_remove_all(env);  
1207 - cpu_watchpoint_remove_all(env); 1265 + gdb_breakpoint_remove_all(env);
1208 gdb_continue(s); 1266 gdb_continue(s);
1209 put_packet(s, "OK"); 1267 put_packet(s, "OK");
1210 break; 1268 break;
@@ -1327,44 +1385,6 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) @@ -1327,44 +1385,6 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
1327 put_packet(s, "OK"); 1385 put_packet(s, "OK");
1328 break; 1386 break;
1329 case 'Z': 1387 case 'Z':
1330 - type = strtoul(p, (char **)&p, 16);  
1331 - if (*p == ',')  
1332 - p++;  
1333 - addr = strtoull(p, (char **)&p, 16);  
1334 - if (*p == ',')  
1335 - p++;  
1336 - len = strtoull(p, (char **)&p, 16);  
1337 - switch (type) {  
1338 - case 0:  
1339 - case 1:  
1340 - if (cpu_breakpoint_insert(env, addr) < 0)  
1341 - goto breakpoint_error;  
1342 - put_packet(s, "OK");  
1343 - break;  
1344 -#ifndef CONFIG_USER_ONLY  
1345 - case 2:  
1346 - type = PAGE_WRITE;  
1347 - goto insert_watchpoint;  
1348 - case 3:  
1349 - type = PAGE_READ;  
1350 - goto insert_watchpoint;  
1351 - case 4:  
1352 - type = PAGE_READ | PAGE_WRITE;  
1353 - insert_watchpoint:  
1354 - if (cpu_watchpoint_insert(env, addr, type) < 0)  
1355 - goto breakpoint_error;  
1356 - put_packet(s, "OK");  
1357 - break;  
1358 -#endif  
1359 - default:  
1360 - put_packet(s, "");  
1361 - break;  
1362 - }  
1363 - break;  
1364 - breakpoint_error:  
1365 - put_packet(s, "E22");  
1366 - break;  
1367 -  
1368 case 'z': 1388 case 'z':
1369 type = strtoul(p, (char **)&p, 16); 1389 type = strtoul(p, (char **)&p, 16);
1370 if (*p == ',') 1390 if (*p == ',')
@@ -1373,17 +1393,16 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf) @@ -1373,17 +1393,16 @@ static int gdb_handle_packet(GDBState *s, CPUState *env, const char *line_buf)
1373 if (*p == ',') 1393 if (*p == ',')
1374 p++; 1394 p++;
1375 len = strtoull(p, (char **)&p, 16); 1395 len = strtoull(p, (char **)&p, 16);
1376 - if (type == 0 || type == 1) {  
1377 - cpu_breakpoint_remove(env, addr);  
1378 - put_packet(s, "OK");  
1379 -#ifndef CONFIG_USER_ONLY  
1380 - } else if (type >= 2 || type <= 4) {  
1381 - cpu_watchpoint_remove(env, addr);  
1382 - put_packet(s, "OK");  
1383 -#endif  
1384 - } else { 1396 + if (ch == 'Z')
  1397 + res = gdb_breakpoint_insert(env, addr, len, type);
  1398 + else
  1399 + res = gdb_breakpoint_remove(env, addr, len, type);
  1400 + if (res >= 0)
  1401 + put_packet(s, "OK");
  1402 + else if (res == -ENOSYS)
1385 put_packet(s, ""); 1403 put_packet(s, "");
1386 - } 1404 + else
  1405 + put_packet(s, "E22");
1387 break; 1406 break;
1388 case 'q': 1407 case 'q':
1389 case 'Q': 1408 case 'Q':
@@ -1504,12 +1523,11 @@ static void gdb_vm_stopped(void *opaque, int reason) @@ -1504,12 +1523,11 @@ static void gdb_vm_stopped(void *opaque, int reason)
1504 1523
1505 if (reason == EXCP_DEBUG) { 1524 if (reason == EXCP_DEBUG) {
1506 if (s->env->watchpoint_hit) { 1525 if (s->env->watchpoint_hit) {
1507 - switch (s->env->watchpoint[s->env->watchpoint_hit - 1].type &  
1508 - (PAGE_READ | PAGE_WRITE)) {  
1509 - case PAGE_READ: 1526 + switch (s->env->watchpoint_hit->flags & BP_MEM_ACCESS) {
  1527 + case BP_MEM_READ:
1510 type = "r"; 1528 type = "r";
1511 break; 1529 break;
1512 - case PAGE_READ | PAGE_WRITE: 1530 + case BP_MEM_ACCESS:
1513 type = "a"; 1531 type = "a";
1514 break; 1532 break;
1515 default: 1533 default:
@@ -1517,10 +1535,9 @@ static void gdb_vm_stopped(void *opaque, int reason) @@ -1517,10 +1535,9 @@ static void gdb_vm_stopped(void *opaque, int reason)
1517 break; 1535 break;
1518 } 1536 }
1519 snprintf(buf, sizeof(buf), "T%02x%swatch:" TARGET_FMT_lx ";", 1537 snprintf(buf, sizeof(buf), "T%02x%swatch:" TARGET_FMT_lx ";",
1520 - SIGTRAP, type,  
1521 - s->env->watchpoint[s->env->watchpoint_hit - 1].vaddr); 1538 + SIGTRAP, type, s->env->watchpoint_hit->vaddr);
1522 put_packet(s, buf); 1539 put_packet(s, buf);
1523 - s->env->watchpoint_hit = 0; 1540 + s->env->watchpoint_hit = NULL;
1524 return; 1541 return;
1525 } 1542 }
1526 tb_flush(s->env); 1543 tb_flush(s->env);
target-alpha/translate.c
@@ -2340,6 +2340,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, @@ -2340,6 +2340,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
2340 target_ulong pc_start; 2340 target_ulong pc_start;
2341 uint32_t insn; 2341 uint32_t insn;
2342 uint16_t *gen_opc_end; 2342 uint16_t *gen_opc_end;
  2343 + CPUBreakpoint *bp;
2343 int j, lj = -1; 2344 int j, lj = -1;
2344 int ret; 2345 int ret;
2345 int num_insns; 2346 int num_insns;
@@ -2362,9 +2363,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, @@ -2362,9 +2363,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
2362 2363
2363 gen_icount_start(); 2364 gen_icount_start();
2364 for (ret = 0; ret == 0;) { 2365 for (ret = 0; ret == 0;) {
2365 - if (env->nb_breakpoints > 0) {  
2366 - for(j = 0; j < env->nb_breakpoints; j++) {  
2367 - if (env->breakpoints[j] == ctx.pc) { 2366 + if (unlikely(env->breakpoints)) {
  2367 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  2368 + if (bp->pc == ctx.pc) {
2368 gen_excp(&ctx, EXCP_DEBUG, 0); 2369 gen_excp(&ctx, EXCP_DEBUG, 0);
2369 break; 2370 break;
2370 } 2371 }
target-arm/translate.c
@@ -8600,6 +8600,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, @@ -8600,6 +8600,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
8600 int search_pc) 8600 int search_pc)
8601 { 8601 {
8602 DisasContext dc1, *dc = &dc1; 8602 DisasContext dc1, *dc = &dc1;
  8603 + CPUBreakpoint *bp;
8603 uint16_t *gen_opc_end; 8604 uint16_t *gen_opc_end;
8604 int j, lj; 8605 int j, lj;
8605 target_ulong pc_start; 8606 target_ulong pc_start;
@@ -8676,9 +8677,9 @@ static inline void gen_intermediate_code_internal(CPUState *env, @@ -8676,9 +8677,9 @@ static inline void gen_intermediate_code_internal(CPUState *env,
8676 } 8677 }
8677 #endif 8678 #endif
8678 8679
8679 - if (env->nb_breakpoints > 0) {  
8680 - for(j = 0; j < env->nb_breakpoints; j++) {  
8681 - if (env->breakpoints[j] == dc->pc) { 8680 + if (unlikely(env->breakpoints)) {
  8681 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  8682 + if (bp->pc == dc->pc) {
8682 gen_set_condexec(dc); 8683 gen_set_condexec(dc);
8683 gen_set_pc_im(dc->pc); 8684 gen_set_pc_im(dc->pc);
8684 gen_exception(EXCP_DEBUG); 8685 gen_exception(EXCP_DEBUG);
@@ -8731,7 +8732,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, @@ -8731,7 +8732,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
8731 /* Terminate the TB on memory ops if watchpoints are present. */ 8732 /* Terminate the TB on memory ops if watchpoints are present. */
8732 /* FIXME: This should be replacd by the deterministic execution 8733 /* FIXME: This should be replacd by the deterministic execution
8733 * IRQ raising bits. */ 8734 * IRQ raising bits. */
8734 - if (dc->is_mem && env->nb_watchpoints) 8735 + if (dc->is_mem && env->watchpoints)
8735 break; 8736 break;
8736 8737
8737 /* Translation stops when a conditional branch is enoutered. 8738 /* Translation stops when a conditional branch is enoutered.
target-cris/translate.c
@@ -3187,10 +3187,11 @@ cris_decoder(DisasContext *dc) @@ -3187,10 +3187,11 @@ cris_decoder(DisasContext *dc)
3187 3187
3188 static void check_breakpoint(CPUState *env, DisasContext *dc) 3188 static void check_breakpoint(CPUState *env, DisasContext *dc)
3189 { 3189 {
3190 - int j;  
3191 - if (env->nb_breakpoints > 0) {  
3192 - for(j = 0; j < env->nb_breakpoints; j++) {  
3193 - if (env->breakpoints[j] == dc->pc) { 3190 + CPUBreakpoint *bp;
  3191 +
  3192 + if (unlikely(env->breakpoints)) {
  3193 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  3194 + if (bp->pc == dc->pc) {
3194 cris_evaluate_flags (dc); 3195 cris_evaluate_flags (dc);
3195 tcg_gen_movi_tl(env_pc, dc->pc); 3196 tcg_gen_movi_tl(env_pc, dc->pc);
3196 t_gen_raise_exception(EXCP_DEBUG); 3197 t_gen_raise_exception(EXCP_DEBUG);
target-i386/translate.c
@@ -7522,6 +7522,7 @@ static inline void gen_intermediate_code_internal(CPUState *env, @@ -7522,6 +7522,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
7522 DisasContext dc1, *dc = &dc1; 7522 DisasContext dc1, *dc = &dc1;
7523 target_ulong pc_ptr; 7523 target_ulong pc_ptr;
7524 uint16_t *gen_opc_end; 7524 uint16_t *gen_opc_end;
  7525 + CPUBreakpoint *bp;
7525 int j, lj, cflags; 7526 int j, lj, cflags;
7526 uint64_t flags; 7527 uint64_t flags;
7527 target_ulong pc_start; 7528 target_ulong pc_start;
@@ -7605,9 +7606,9 @@ static inline void gen_intermediate_code_internal(CPUState *env, @@ -7605,9 +7606,9 @@ static inline void gen_intermediate_code_internal(CPUState *env,
7605 7606
7606 gen_icount_start(); 7607 gen_icount_start();
7607 for(;;) { 7608 for(;;) {
7608 - if (env->nb_breakpoints > 0) {  
7609 - for(j = 0; j < env->nb_breakpoints; j++) {  
7610 - if (env->breakpoints[j] == pc_ptr) { 7609 + if (unlikely(env->breakpoints)) {
  7610 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  7611 + if (bp->pc == pc_ptr) {
7611 gen_debug(dc, pc_ptr - dc->cs_base); 7612 gen_debug(dc, pc_ptr - dc->cs_base);
7612 break; 7613 break;
7613 } 7614 }
target-m68k/translate.c
@@ -2965,6 +2965,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, @@ -2965,6 +2965,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2965 { 2965 {
2966 DisasContext dc1, *dc = &dc1; 2966 DisasContext dc1, *dc = &dc1;
2967 uint16_t *gen_opc_end; 2967 uint16_t *gen_opc_end;
  2968 + CPUBreakpoint *bp;
2968 int j, lj; 2969 int j, lj;
2969 target_ulong pc_start; 2970 target_ulong pc_start;
2970 int pc_offset; 2971 int pc_offset;
@@ -2998,9 +2999,9 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, @@ -2998,9 +2999,9 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
2998 do { 2999 do {
2999 pc_offset = dc->pc - pc_start; 3000 pc_offset = dc->pc - pc_start;
3000 gen_throws_exception = NULL; 3001 gen_throws_exception = NULL;
3001 - if (env->nb_breakpoints > 0) {  
3002 - for(j = 0; j < env->nb_breakpoints; j++) {  
3003 - if (env->breakpoints[j] == dc->pc) { 3002 + if (unlikely(env->breakpoints)) {
  3003 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  3004 + if (bp->pc == dc->pc) {
3004 gen_exception(dc, dc->pc, EXCP_DEBUG); 3005 gen_exception(dc, dc->pc, EXCP_DEBUG);
3005 dc->is_jmp = DISAS_JUMP; 3006 dc->is_jmp = DISAS_JUMP;
3006 break; 3007 break;
@@ -3030,7 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, @@ -3030,7 +3031,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
3030 /* Terminate the TB on memory ops if watchpoints are present. */ 3031 /* Terminate the TB on memory ops if watchpoints are present. */
3031 /* FIXME: This should be replaced by the deterministic execution 3032 /* FIXME: This should be replaced by the deterministic execution
3032 * IRQ raising bits. */ 3033 * IRQ raising bits. */
3033 - if (dc->is_mem && env->nb_watchpoints) 3034 + if (dc->is_mem && env->watchpoints)
3034 break; 3035 break;
3035 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 3036 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3036 !env->singlestep_enabled && 3037 !env->singlestep_enabled &&
target-mips/translate.c
@@ -8246,6 +8246,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -8246,6 +8246,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8246 DisasContext ctx; 8246 DisasContext ctx;
8247 target_ulong pc_start; 8247 target_ulong pc_start;
8248 uint16_t *gen_opc_end; 8248 uint16_t *gen_opc_end;
  8249 + CPUBreakpoint *bp;
8249 int j, lj = -1; 8250 int j, lj = -1;
8250 int num_insns; 8251 int num_insns;
8251 int max_insns; 8252 int max_insns;
@@ -8285,9 +8286,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, @@ -8285,9 +8286,9 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
8285 #endif 8286 #endif
8286 gen_icount_start(); 8287 gen_icount_start();
8287 while (ctx.bstate == BS_NONE) { 8288 while (ctx.bstate == BS_NONE) {
8288 - if (env->nb_breakpoints > 0) {  
8289 - for(j = 0; j < env->nb_breakpoints; j++) {  
8290 - if (env->breakpoints[j] == ctx.pc) { 8289 + if (unlikely(env->breakpoints)) {
  8290 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  8291 + if (bp->pc == ctx.pc) {
8291 save_cpu_state(&ctx, 1); 8292 save_cpu_state(&ctx, 1);
8292 ctx.bstate = BS_BRANCH; 8293 ctx.bstate = BS_BRANCH;
8293 gen_helper_0i(raise_exception, EXCP_DEBUG); 8294 gen_helper_0i(raise_exception, EXCP_DEBUG);
target-ppc/translate.c
@@ -7170,6 +7170,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, @@ -7170,6 +7170,7 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
7170 target_ulong pc_start; 7170 target_ulong pc_start;
7171 uint16_t *gen_opc_end; 7171 uint16_t *gen_opc_end;
7172 int supervisor, little_endian; 7172 int supervisor, little_endian;
  7173 + CPUBreakpoint *bp;
7173 int j, lj = -1; 7174 int j, lj = -1;
7174 int num_insns; 7175 int num_insns;
7175 int max_insns; 7176 int max_insns;
@@ -7224,9 +7225,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, @@ -7224,9 +7225,9 @@ static always_inline void gen_intermediate_code_internal (CPUState *env,
7224 gen_icount_start(); 7225 gen_icount_start();
7225 /* Set env in case of segfault during code fetch */ 7226 /* Set env in case of segfault during code fetch */
7226 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) { 7227 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
7227 - if (unlikely(env->nb_breakpoints > 0)) {  
7228 - for (j = 0; j < env->nb_breakpoints; j++) {  
7229 - if (env->breakpoints[j] == ctx.nip) { 7228 + if (unlikely(env->breakpoints)) {
  7229 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  7230 + if (bp->pc == ctx.nip) {
7230 gen_update_nip(&ctx, ctx.nip); 7231 gen_update_nip(&ctx, ctx.nip);
7231 gen_op_debug(); 7232 gen_op_debug();
7232 break; 7233 break;
target-sh4/translate.c
@@ -1803,6 +1803,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, @@ -1803,6 +1803,7 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1803 DisasContext ctx; 1803 DisasContext ctx;
1804 target_ulong pc_start; 1804 target_ulong pc_start;
1805 static uint16_t *gen_opc_end; 1805 static uint16_t *gen_opc_end;
  1806 + CPUBreakpoint *bp;
1806 int i, ii; 1807 int i, ii;
1807 int num_insns; 1808 int num_insns;
1808 int max_insns; 1809 int max_insns;
@@ -1836,9 +1837,9 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, @@ -1836,9 +1837,9 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb,
1836 max_insns = CF_COUNT_MASK; 1837 max_insns = CF_COUNT_MASK;
1837 gen_icount_start(); 1838 gen_icount_start();
1838 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) { 1839 while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1839 - if (env->nb_breakpoints > 0) {  
1840 - for (i = 0; i < env->nb_breakpoints; i++) {  
1841 - if (ctx.pc == env->breakpoints[i]) { 1840 + if (unlikely(env->breakpoints)) {
  1841 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  1842 + if (ctx.pc == bp->pc) {
1842 /* We have hit a breakpoint - make sure PC is up-to-date */ 1843 /* We have hit a breakpoint - make sure PC is up-to-date */
1843 tcg_gen_movi_i32(cpu_pc, ctx.pc); 1844 tcg_gen_movi_i32(cpu_pc, ctx.pc);
1844 gen_helper_debug(); 1845 gen_helper_debug();
target-sparc/translate.c
@@ -4778,6 +4778,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, @@ -4778,6 +4778,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
4778 target_ulong pc_start, last_pc; 4778 target_ulong pc_start, last_pc;
4779 uint16_t *gen_opc_end; 4779 uint16_t *gen_opc_end;
4780 DisasContext dc1, *dc = &dc1; 4780 DisasContext dc1, *dc = &dc1;
  4781 + CPUBreakpoint *bp;
4781 int j, lj = -1; 4782 int j, lj = -1;
4782 int num_insns; 4783 int num_insns;
4783 int max_insns; 4784 int max_insns;
@@ -4815,9 +4816,9 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, @@ -4815,9 +4816,9 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
4815 max_insns = CF_COUNT_MASK; 4816 max_insns = CF_COUNT_MASK;
4816 gen_icount_start(); 4817 gen_icount_start();
4817 do { 4818 do {
4818 - if (env->nb_breakpoints > 0) {  
4819 - for(j = 0; j < env->nb_breakpoints; j++) {  
4820 - if (env->breakpoints[j] == dc->pc) { 4819 + if (unlikely(env->breakpoints)) {
  4820 + for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
  4821 + if (bp->pc == dc->pc) {
4821 if (dc->pc != pc_start) 4822 if (dc->pc != pc_start)
4822 save_state(dc, cpu_cond); 4823 save_state(dc, cpu_cond);
4823 gen_helper_debug(); 4824 gen_helper_debug();