Revision c0ce998e

b/cpu-defs.h
28 28
#include <setjmp.h>
29 29
#include <inttypes.h>
30 30
#include "osdep.h"
31
#include "sys-queue.h"
31 32

  
32 33
#ifndef TARGET_LONG_BITS
33 34
#error TARGET_LONG_BITS must be defined before including this header
......
146 147
typedef struct CPUBreakpoint {
147 148
    target_ulong pc;
148 149
    int flags; /* BP_* */
149
    struct CPUBreakpoint *prev, *next;
150
    TAILQ_ENTRY(CPUBreakpoint) entry;
150 151
} CPUBreakpoint;
151 152

  
152 153
typedef struct CPUWatchpoint {
153 154
    target_ulong vaddr;
154 155
    target_ulong len_mask;
155 156
    int flags; /* BP_* */
156
    struct CPUWatchpoint *prev, *next;
157
    TAILQ_ENTRY(CPUWatchpoint) entry;
157 158
} CPUWatchpoint;
158 159

  
159 160
#define CPU_TEMP_BUF_NLONGS 128
......
188 189
                                                                        \
189 190
    /* from this point: preserved by CPU reset */                       \
190 191
    /* ice debug support */                                             \
191
    CPUBreakpoint *breakpoints;                                         \
192
    TAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;            \
192 193
    int singlestep_enabled;                                             \
193 194
                                                                        \
194
    CPUWatchpoint *watchpoints;                                         \
195
    TAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;            \
195 196
    CPUWatchpoint *watchpoint_hit;                                      \
196 197
                                                                        \
197 198
    struct GDBRegisterState *gdb_regs;                                  \
b/cpu-exec.c
198 198
    CPUWatchpoint *wp;
199 199

  
200 200
    if (!env->watchpoint_hit)
201
        for (wp = env->watchpoints; wp != NULL; wp = wp->next)
201
        TAILQ_FOREACH(wp, &env->watchpoints, entry)
202 202
            wp->flags &= ~BP_WATCHPOINT_HIT;
203 203

  
204 204
    if (debug_excp_handler)
b/exec.c
537 537
        cpu_index++;
538 538
    }
539 539
    env->cpu_index = cpu_index;
540
    TAILQ_INIT(&env->breakpoints);
541
    TAILQ_INIT(&env->watchpoints);
540 542
    *penv = env;
541 543
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
542 544
    register_savevm("cpu_common", cpu_index, CPU_COMMON_SAVE_VERSION,
......
1302 1304
                          int flags, CPUWatchpoint **watchpoint)
1303 1305
{
1304 1306
    target_ulong len_mask = ~(len - 1);
1305
    CPUWatchpoint *wp, *prev_wp;
1307
    CPUWatchpoint *wp;
1306 1308

  
1307 1309
    /* sanity checks: allow power-of-2 lengths, deny unaligned watchpoints */
1308 1310
    if ((len != 1 && len != 2 && len != 4 && len != 8) || (addr & ~len_mask)) {
......
1319 1321
    wp->flags = flags;
1320 1322

  
1321 1323
    /* keep all GDB-injected watchpoints in front */
1322
    if (!(flags & BP_GDB) && env->watchpoints) {
1323
        prev_wp = env->watchpoints;
1324
        while (prev_wp->next != NULL && (prev_wp->next->flags & BP_GDB))
1325
            prev_wp = prev_wp->next;
1326
    } else {
1327
        prev_wp = NULL;
1328
    }
1329

  
1330
    /* Insert new watchpoint */
1331
    if (prev_wp) {
1332
        wp->next = prev_wp->next;
1333
        prev_wp->next = wp;
1334
    } else {
1335
        wp->next = env->watchpoints;
1336
        env->watchpoints = wp;
1337
    }
1338
    if (wp->next)
1339
        wp->next->prev = wp;
1340
    wp->prev = prev_wp;
1324
    if (flags & BP_GDB)
1325
        TAILQ_INSERT_HEAD(&env->watchpoints, wp, entry);
1326
    else
1327
        TAILQ_INSERT_TAIL(&env->watchpoints, wp, entry);
1341 1328

  
1342 1329
    tlb_flush_page(env, addr);
1343 1330

  
......
1353 1340
    target_ulong len_mask = ~(len - 1);
1354 1341
    CPUWatchpoint *wp;
1355 1342

  
1356
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
1343
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
1357 1344
        if (addr == wp->vaddr && len_mask == wp->len_mask
1358 1345
                && flags == (wp->flags & ~BP_WATCHPOINT_HIT)) {
1359 1346
            cpu_watchpoint_remove_by_ref(env, wp);
......
1366 1353
/* Remove a specific watchpoint by reference.  */
1367 1354
void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint)
1368 1355
{
1369
    if (watchpoint->next)
1370
        watchpoint->next->prev = watchpoint->prev;
1371
    if (watchpoint->prev)
1372
        watchpoint->prev->next = watchpoint->next;
1373
    else
1374
        env->watchpoints = watchpoint->next;
1356
    TAILQ_REMOVE(&env->watchpoints, watchpoint, entry);
1375 1357

  
1376 1358
    tlb_flush_page(env, watchpoint->vaddr);
1377 1359

  
......
1381 1363
/* Remove all matching watchpoints.  */
1382 1364
void cpu_watchpoint_remove_all(CPUState *env, int mask)
1383 1365
{
1384
    CPUWatchpoint *wp;
1366
    CPUWatchpoint *wp, *next;
1385 1367

  
1386
    for (wp = env->watchpoints; wp != NULL; wp = wp->next)
1368
    TAILQ_FOREACH_SAFE(wp, &env->watchpoints, entry, next) {
1387 1369
        if (wp->flags & mask)
1388 1370
            cpu_watchpoint_remove_by_ref(env, wp);
1371
    }
1389 1372
}
1390 1373

  
1391 1374
/* Add a breakpoint.  */
......
1393 1376
                          CPUBreakpoint **breakpoint)
1394 1377
{
1395 1378
#if defined(TARGET_HAS_ICE)
1396
    CPUBreakpoint *bp, *prev_bp;
1379
    CPUBreakpoint *bp;
1397 1380

  
1398 1381
    bp = qemu_malloc(sizeof(*bp));
1399 1382
    if (!bp)
......
1403 1386
    bp->flags = flags;
1404 1387

  
1405 1388
    /* keep all GDB-injected breakpoints in front */
1406
    if (!(flags & BP_GDB) && env->breakpoints) {
1407
        prev_bp = env->breakpoints;
1408
        while (prev_bp->next != NULL && (prev_bp->next->flags & BP_GDB))
1409
            prev_bp = prev_bp->next;
1410
    } else {
1411
        prev_bp = NULL;
1412
    }
1413

  
1414
    /* Insert new breakpoint */
1415
    if (prev_bp) {
1416
        bp->next = prev_bp->next;
1417
        prev_bp->next = bp;
1418
    } else {
1419
        bp->next = env->breakpoints;
1420
        env->breakpoints = bp;
1421
    }
1422
    if (bp->next)
1423
        bp->next->prev = bp;
1424
    bp->prev = prev_bp;
1389
    if (flags & BP_GDB)
1390
        TAILQ_INSERT_HEAD(&env->breakpoints, bp, entry);
1391
    else
1392
        TAILQ_INSERT_TAIL(&env->breakpoints, bp, entry);
1425 1393

  
1426 1394
    breakpoint_invalidate(env, pc);
1427 1395

  
......
1439 1407
#if defined(TARGET_HAS_ICE)
1440 1408
    CPUBreakpoint *bp;
1441 1409

  
1442
    for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
1410
    TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1443 1411
        if (bp->pc == pc && bp->flags == flags) {
1444 1412
            cpu_breakpoint_remove_by_ref(env, bp);
1445 1413
            return 0;
......
1455 1423
void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint)
1456 1424
{
1457 1425
#if defined(TARGET_HAS_ICE)
1458
    if (breakpoint->next)
1459
        breakpoint->next->prev = breakpoint->prev;
1460
    if (breakpoint->prev)
1461
        breakpoint->prev->next = breakpoint->next;
1462
    else
1463
        env->breakpoints = breakpoint->next;
1426
    TAILQ_REMOVE(&env->breakpoints, breakpoint, entry);
1464 1427

  
1465 1428
    breakpoint_invalidate(env, breakpoint->pc);
1466 1429

  
......
1472 1435
void cpu_breakpoint_remove_all(CPUState *env, int mask)
1473 1436
{
1474 1437
#if defined(TARGET_HAS_ICE)
1475
    CPUBreakpoint *bp;
1438
    CPUBreakpoint *bp, *next;
1476 1439

  
1477
    for (bp = env->breakpoints; bp != NULL; bp = bp->next)
1440
    TAILQ_FOREACH_SAFE(bp, &env->breakpoints, entry, next) {
1478 1441
        if (bp->flags & mask)
1479 1442
            cpu_breakpoint_remove_by_ref(env, bp);
1443
    }
1480 1444
#endif
1481 1445
}
1482 1446

  
......
2005 1969
    code_address = address;
2006 1970
    /* Make accesses to pages with watchpoints go via the
2007 1971
       watchpoint trap routines.  */
2008
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
1972
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2009 1973
        if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) {
2010 1974
            iotlb = io_mem_watch + paddr;
2011 1975
            /* TODO: The memory case can be optimized by not trapping
......
2552 2516
        return;
2553 2517
    }
2554 2518
    vaddr = (env->mem_io_vaddr & TARGET_PAGE_MASK) + offset;
2555
    for (wp = env->watchpoints; wp != NULL; wp = wp->next) {
2519
    TAILQ_FOREACH(wp, &env->watchpoints, entry) {
2556 2520
        if ((vaddr == (wp->vaddr & len_mask) ||
2557 2521
             (vaddr & wp->len_mask) == wp->vaddr) && (wp->flags & flags)) {
2558 2522
            wp->flags |= BP_WATCHPOINT_HIT;
b/target-alpha/translate.c
2363 2363

  
2364 2364
    gen_icount_start();
2365 2365
    for (ret = 0; ret == 0;) {
2366
        if (unlikely(env->breakpoints)) {
2367
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
2366
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
2367
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
2368 2368
                if (bp->pc == ctx.pc) {
2369 2369
                    gen_excp(&ctx, EXCP_DEBUG, 0);
2370 2370
                    break;
b/target-arm/translate.c
8677 8677
        }
8678 8678
#endif
8679 8679

  
8680
        if (unlikely(env->breakpoints)) {
8681
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
8680
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8681
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8682 8682
                if (bp->pc == dc->pc) {
8683 8683
                    gen_set_condexec(dc);
8684 8684
                    gen_set_pc_im(dc->pc);
b/target-cris/translate.c
3189 3189
{
3190 3190
	CPUBreakpoint *bp;
3191 3191

  
3192
	if (unlikely(env->breakpoints)) {
3193
		for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
3192
	if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
3193
		TAILQ_FOREACH(bp, &env->breakpoints, entry) {
3194 3194
			if (bp->pc == dc->pc) {
3195 3195
				cris_evaluate_flags (dc);
3196 3196
				tcg_gen_movi_tl(env_pc, dc->pc);
b/target-i386/helper.c
1364 1364
                cpu_resume_from_signal(env, NULL);
1365 1365
        }
1366 1366
    } else {
1367
        for (bp = env->breakpoints; bp != NULL; bp = bp->next)
1367
        TAILQ_FOREACH(bp, &env->breakpoints, entry)
1368 1368
            if (bp->pc == env->eip) {
1369 1369
                if (bp->flags & BP_CPU) {
1370 1370
                    check_hw_breakpoints(env, 1);
b/target-i386/translate.c
7606 7606

  
7607 7607
    gen_icount_start();
7608 7608
    for(;;) {
7609
        if (unlikely(env->breakpoints)) {
7610
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
7609
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7610
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
7611 7611
                if (bp->pc == pc_ptr) {
7612 7612
                    gen_debug(dc, pc_ptr - dc->cs_base);
7613 7613
                    break;
b/target-m68k/translate.c
2999 2999
    do {
3000 3000
        pc_offset = dc->pc - pc_start;
3001 3001
        gen_throws_exception = NULL;
3002
        if (unlikely(env->breakpoints)) {
3003
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
3002
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
3003
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
3004 3004
                if (bp->pc == dc->pc) {
3005 3005
                    gen_exception(dc, dc->pc, EXCP_DEBUG);
3006 3006
                    dc->is_jmp = DISAS_JUMP;
b/target-mips/translate.c
8286 8286
#endif
8287 8287
    gen_icount_start();
8288 8288
    while (ctx.bstate == BS_NONE) {
8289
        if (unlikely(env->breakpoints)) {
8290
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
8289
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8290
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8291 8291
                if (bp->pc == ctx.pc) {
8292 8292
                    save_cpu_state(&ctx, 1);
8293 8293
                    ctx.bstate = BS_BRANCH;
b/target-ppc/translate.c
7562 7562
    gen_icount_start();
7563 7563
    /* Set env in case of segfault during code fetch */
7564 7564
    while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
7565
        if (unlikely(env->breakpoints)) {
7566
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
7565
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7566
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
7567 7567
                if (bp->pc == ctx.nip) {
7568 7568
                    gen_update_nip(&ctx, ctx.nip);
7569 7569
                    gen_helper_raise_debug();
b/target-sh4/translate.c
1776 1776
        max_insns = CF_COUNT_MASK;
1777 1777
    gen_icount_start();
1778 1778
    while (ctx.bstate == BS_NONE && gen_opc_ptr < gen_opc_end) {
1779
        if (unlikely(env->breakpoints)) {
1780
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
1779
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
1780
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
1781 1781
                if (ctx.pc == bp->pc) {
1782 1782
		    /* We have hit a breakpoint - make sure PC is up-to-date */
1783 1783
		    tcg_gen_movi_i32(cpu_pc, ctx.pc);
b/target-sparc/translate.c
4816 4816
        max_insns = CF_COUNT_MASK;
4817 4817
    gen_icount_start();
4818 4818
    do {
4819
        if (unlikely(env->breakpoints)) {
4820
            for (bp = env->breakpoints; bp != NULL; bp = bp->next) {
4819
        if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
4820
            TAILQ_FOREACH(bp, &env->breakpoints, entry) {
4821 4821
                if (bp->pc == dc->pc) {
4822 4822
                    if (dc->pc != pc_start)
4823 4823
                        save_state(dc, cpu_cond);

Also available in: Unified diff