Commit c0ce998e94fadb7fdc83dbc7455372af933f8fa9
1 parent
31280d92
Use sys-queue.h for break/watchpoint managment (Jan Kiszka)
This switches cpu_break/watchpoint_* to TAILQ wrappers, simplifying the code and also fixing a use after release issue in cpu_break/watchpoint_remove_all. 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@5799 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
13 changed files
with
49 additions
and
84 deletions
cpu-defs.h
| ... | ... | @@ -28,6 +28,7 @@ |
| 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,14 +147,14 @@ struct KVMState; |
| 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,10 +189,10 @@ typedef struct CPUWatchpoint { |
| 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; \ | ... | ... |
cpu-exec.c
| ... | ... | @@ -198,7 +198,7 @@ static void cpu_handle_debug_exception(CPUState *env) |
| 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) | ... | ... |
exec.c
| ... | ... | @@ -537,6 +537,8 @@ void cpu_exec_init(CPUState *env) |
| 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,7 +1304,7 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, |
| 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,25 +1321,10 @@ int cpu_watchpoint_insert(CPUState *env, target_ulong addr, target_ulong len, |
| 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,7 +1340,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, |
| 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,12 +1353,7 @@ int cpu_watchpoint_remove(CPUState *env, target_ulong addr, target_ulong len, |
| 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,11 +1363,12 @@ void cpu_watchpoint_remove_by_ref(CPUState *env, CPUWatchpoint *watchpoint) |
| 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,7 +1376,7 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, |
| 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,25 +1386,10 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc, int flags, |
| 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,7 +1407,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) |
| 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,12 +1423,7 @@ int cpu_breakpoint_remove(CPUState *env, target_ulong pc, int flags) |
| 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,11 +1435,12 @@ void cpu_breakpoint_remove_by_ref(CPUState *env, CPUBreakpoint *breakpoint) |
| 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,7 +1969,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
| 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,7 +2516,7 @@ static void check_watchpoint(int offset, int len_mask, int flags) |
| 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; | ... | ... |
target-alpha/translate.c
| ... | ... | @@ -2363,8 +2363,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, |
| 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; | ... | ... |
target-arm/translate.c
| ... | ... | @@ -8677,8 +8677,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, |
| 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); | ... | ... |
target-cris/translate.c
| ... | ... | @@ -3189,8 +3189,8 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) |
| 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); | ... | ... |
target-i386/helper.c
| ... | ... | @@ -1364,7 +1364,7 @@ static void breakpoint_handler(CPUState *env) |
| 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); | ... | ... |
target-i386/translate.c
| ... | ... | @@ -7606,8 +7606,8 @@ static inline void gen_intermediate_code_internal(CPUState *env, |
| 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; | ... | ... |
target-m68k/translate.c
| ... | ... | @@ -2999,8 +2999,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, |
| 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; | ... | ... |
target-mips/translate.c
| ... | ... | @@ -8286,8 +8286,8 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, |
| 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; | ... | ... |
target-ppc/translate.c
| ... | ... | @@ -7562,8 +7562,8 @@ static always_inline void gen_intermediate_code_internal (CPUState *env, |
| 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(); | ... | ... |
target-sh4/translate.c
| ... | ... | @@ -1776,8 +1776,8 @@ gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
| 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); | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -4816,8 +4816,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, |
| 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); | ... | ... |