Commit 4c3a88a284b288e0ed3c097de7fc07111d848003
1 parent
d6b49367
gdb stub breakpoints support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@332 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
11 changed files
with
151 additions
and
25 deletions
cpu-all.h
@@ -313,9 +313,12 @@ extern CPUState *cpu_single_env; | @@ -313,9 +313,12 @@ extern CPUState *cpu_single_env; | ||
313 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ | 313 | #define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ |
314 | void cpu_interrupt(CPUState *s, int mask); | 314 | void cpu_interrupt(CPUState *s, int mask); |
315 | 315 | ||
316 | +int cpu_breakpoint_insert(CPUState *env, uint32_t pc); | ||
317 | +int cpu_breakpoint_remove(CPUState *env, uint32_t pc); | ||
318 | + | ||
316 | /* gdb stub API */ | 319 | /* gdb stub API */ |
317 | extern int gdbstub_fd; | 320 | extern int gdbstub_fd; |
318 | CPUState *cpu_gdbstub_get_env(void *opaque); | 321 | CPUState *cpu_gdbstub_get_env(void *opaque); |
319 | -int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port); | 322 | +int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port); |
320 | 323 | ||
321 | #endif /* CPU_ALL_H */ | 324 | #endif /* CPU_ALL_H */ |
cpu-exec.c
@@ -280,7 +280,7 @@ int cpu_exec(CPUState *env1) | @@ -280,7 +280,7 @@ int cpu_exec(CPUState *env1) | ||
280 | tb->tc_ptr = tc_ptr; | 280 | tb->tc_ptr = tc_ptr; |
281 | tb->cs_base = (unsigned long)cs_base; | 281 | tb->cs_base = (unsigned long)cs_base; |
282 | tb->flags = flags; | 282 | tb->flags = flags; |
283 | - ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size); | 283 | + ret = cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size); |
284 | #if defined(TARGET_I386) | 284 | #if defined(TARGET_I386) |
285 | /* XXX: suppress that, this is incorrect */ | 285 | /* XXX: suppress that, this is incorrect */ |
286 | /* if invalid instruction, signal it */ | 286 | /* if invalid instruction, signal it */ |
cpu-i386.h
@@ -155,6 +155,9 @@ | @@ -155,6 +155,9 @@ | ||
155 | 155 | ||
156 | #define EXCP_INTERRUPT 256 /* async interruption */ | 156 | #define EXCP_INTERRUPT 256 /* async interruption */ |
157 | #define EXCP_HLT 257 /* hlt instruction reached */ | 157 | #define EXCP_HLT 257 /* hlt instruction reached */ |
158 | +#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ | ||
159 | + | ||
160 | +#define MAX_BREAKPOINTS 32 | ||
158 | 161 | ||
159 | enum { | 162 | enum { |
160 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ | 163 | CC_OP_DYNAMIC, /* must use dynamic code to get cc_op */ |
@@ -270,6 +273,9 @@ typedef struct CPUX86State { | @@ -270,6 +273,9 @@ typedef struct CPUX86State { | ||
270 | uint32_t dr[8]; /* debug registers */ | 273 | uint32_t dr[8]; /* debug registers */ |
271 | int interrupt_request; | 274 | int interrupt_request; |
272 | int user_mode_only; /* user mode only simulation */ | 275 | int user_mode_only; /* user mode only simulation */ |
276 | + | ||
277 | + uint32_t breakpoints[MAX_BREAKPOINTS]; | ||
278 | + int nb_breakpoints; | ||
273 | 279 | ||
274 | /* user data */ | 280 | /* user data */ |
275 | void *opaque; | 281 | void *opaque; |
exec.c
@@ -617,6 +617,48 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) | @@ -617,6 +617,48 @@ static void tb_reset_jump_recursive(TranslationBlock *tb) | ||
617 | tb_reset_jump_recursive2(tb, 1); | 617 | tb_reset_jump_recursive2(tb, 1); |
618 | } | 618 | } |
619 | 619 | ||
620 | +/* add a breakpoint */ | ||
621 | +int cpu_breakpoint_insert(CPUState *env, uint32_t pc) | ||
622 | +{ | ||
623 | +#if defined(TARGET_I386) | ||
624 | + int i; | ||
625 | + | ||
626 | + for(i = 0; i < env->nb_breakpoints; i++) { | ||
627 | + if (env->breakpoints[i] == pc) | ||
628 | + return 0; | ||
629 | + } | ||
630 | + | ||
631 | + if (env->nb_breakpoints >= MAX_BREAKPOINTS) | ||
632 | + return -1; | ||
633 | + env->breakpoints[env->nb_breakpoints++] = pc; | ||
634 | + tb_invalidate_page(pc); | ||
635 | + return 0; | ||
636 | +#else | ||
637 | + return -1; | ||
638 | +#endif | ||
639 | +} | ||
640 | + | ||
641 | +/* remove a breakpoint */ | ||
642 | +int cpu_breakpoint_remove(CPUState *env, uint32_t pc) | ||
643 | +{ | ||
644 | +#if defined(TARGET_I386) | ||
645 | + int i; | ||
646 | + for(i = 0; i < env->nb_breakpoints; i++) { | ||
647 | + if (env->breakpoints[i] == pc) | ||
648 | + goto found; | ||
649 | + } | ||
650 | + return -1; | ||
651 | + found: | ||
652 | + memmove(&env->breakpoints[i], &env->breakpoints[i + 1], | ||
653 | + (env->nb_breakpoints - (i + 1)) * sizeof(env->breakpoints[0])); | ||
654 | + env->nb_breakpoints--; | ||
655 | + tb_invalidate_page(pc); | ||
656 | + return 0; | ||
657 | +#else | ||
658 | + return -1; | ||
659 | +#endif | ||
660 | +} | ||
661 | + | ||
620 | /* mask must never be zero */ | 662 | /* mask must never be zero */ |
621 | void cpu_interrupt(CPUState *env, int mask) | 663 | void cpu_interrupt(CPUState *env, int mask) |
622 | { | 664 | { |
exec.h
@@ -58,10 +58,10 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | @@ -58,10 +58,10 @@ extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; | ||
58 | extern FILE *logfile; | 58 | extern FILE *logfile; |
59 | extern int loglevel; | 59 | extern int loglevel; |
60 | 60 | ||
61 | -int gen_intermediate_code(struct TranslationBlock *tb); | ||
62 | -int gen_intermediate_code_pc(struct TranslationBlock *tb); | 61 | +int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); |
62 | +int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); | ||
63 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); | 63 | void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); |
64 | -int cpu_gen_code(struct TranslationBlock *tb, | 64 | +int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, |
65 | int max_code_size, int *gen_code_size_ptr); | 65 | int max_code_size, int *gen_code_size_ptr); |
66 | int cpu_restore_state(struct TranslationBlock *tb, | 66 | int cpu_restore_state(struct TranslationBlock *tb, |
67 | CPUState *env, unsigned long searched_pc); | 67 | CPUState *env, unsigned long searched_pc); |
gdbstub.c
@@ -37,7 +37,7 @@ | @@ -37,7 +37,7 @@ | ||
37 | #include "thunk.h" | 37 | #include "thunk.h" |
38 | #include "exec.h" | 38 | #include "exec.h" |
39 | 39 | ||
40 | -//#define DEBUG_GDB | 40 | +#define DEBUG_GDB |
41 | 41 | ||
42 | int gdbstub_fd = -1; | 42 | int gdbstub_fd = -1; |
43 | 43 | ||
@@ -283,11 +283,11 @@ static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | @@ -283,11 +283,11 @@ static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write) | ||
283 | } | 283 | } |
284 | 284 | ||
285 | /* port = 0 means default port */ | 285 | /* port = 0 means default port */ |
286 | -int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | 286 | +int cpu_gdbstub(void *opaque, int (*main_loop)(void *opaque), int port) |
287 | { | 287 | { |
288 | CPUState *env; | 288 | CPUState *env; |
289 | const char *p; | 289 | const char *p; |
290 | - int ret, ch, nb_regs, i; | 290 | + int ret, ch, nb_regs, i, type; |
291 | char buf[4096]; | 291 | char buf[4096]; |
292 | uint8_t mem_buf[2000]; | 292 | uint8_t mem_buf[2000]; |
293 | uint32_t *registers; | 293 | uint32_t *registers; |
@@ -309,8 +309,19 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | @@ -309,8 +309,19 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | ||
309 | put_packet(buf); | 309 | put_packet(buf); |
310 | break; | 310 | break; |
311 | case 'c': | 311 | case 'c': |
312 | - main_loop(opaque); | ||
313 | - snprintf(buf, sizeof(buf), "S%02x", 0); | 312 | + if (*p != '\0') { |
313 | + addr = strtoul(p, (char **)&p, 16); | ||
314 | + env = cpu_gdbstub_get_env(opaque); | ||
315 | +#if defined(TARGET_I386) | ||
316 | + env->eip = addr; | ||
317 | +#endif | ||
318 | + } | ||
319 | + ret = main_loop(opaque); | ||
320 | + if (ret == EXCP_DEBUG) | ||
321 | + ret = SIGTRAP; | ||
322 | + else | ||
323 | + ret = 0; | ||
324 | + snprintf(buf, sizeof(buf), "S%02x", ret); | ||
314 | put_packet(buf); | 325 | put_packet(buf); |
315 | break; | 326 | break; |
316 | case 'g': | 327 | case 'g': |
@@ -379,6 +390,40 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | @@ -379,6 +390,40 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port) | ||
379 | else | 390 | else |
380 | put_packet("OK"); | 391 | put_packet("OK"); |
381 | break; | 392 | break; |
393 | + case 'Z': | ||
394 | + type = strtoul(p, (char **)&p, 16); | ||
395 | + if (*p == ',') | ||
396 | + p++; | ||
397 | + addr = strtoul(p, (char **)&p, 16); | ||
398 | + if (*p == ',') | ||
399 | + p++; | ||
400 | + len = strtoul(p, (char **)&p, 16); | ||
401 | + if (type == 0 || type == 1) { | ||
402 | + env = cpu_gdbstub_get_env(opaque); | ||
403 | + if (cpu_breakpoint_insert(env, addr) < 0) | ||
404 | + goto breakpoint_error; | ||
405 | + put_packet("OK"); | ||
406 | + } else { | ||
407 | + breakpoint_error: | ||
408 | + put_packet("ENN"); | ||
409 | + } | ||
410 | + break; | ||
411 | + case 'z': | ||
412 | + type = strtoul(p, (char **)&p, 16); | ||
413 | + if (*p == ',') | ||
414 | + p++; | ||
415 | + addr = strtoul(p, (char **)&p, 16); | ||
416 | + if (*p == ',') | ||
417 | + p++; | ||
418 | + len = strtoul(p, (char **)&p, 16); | ||
419 | + if (type == 0 || type == 1) { | ||
420 | + env = cpu_gdbstub_get_env(opaque); | ||
421 | + cpu_breakpoint_remove(env, addr); | ||
422 | + put_packet("OK"); | ||
423 | + } else { | ||
424 | + goto breakpoint_error; | ||
425 | + } | ||
426 | + break; | ||
382 | default: | 427 | default: |
383 | /* put empty packet */ | 428 | /* put empty packet */ |
384 | buf[0] = '\0'; | 429 | buf[0] = '\0'; |
op-i386.c
@@ -471,6 +471,12 @@ void OPPROTO op_hlt(void) | @@ -471,6 +471,12 @@ void OPPROTO op_hlt(void) | ||
471 | cpu_loop_exit(); | 471 | cpu_loop_exit(); |
472 | } | 472 | } |
473 | 473 | ||
474 | +void OPPROTO op_debug(void) | ||
475 | +{ | ||
476 | + env->exception_index = EXCP_DEBUG; | ||
477 | + cpu_loop_exit(); | ||
478 | +} | ||
479 | + | ||
474 | void OPPROTO op_raise_interrupt(void) | 480 | void OPPROTO op_raise_interrupt(void) |
475 | { | 481 | { |
476 | int intno; | 482 | int intno; |
translate-arm.c
@@ -786,7 +786,9 @@ static void disas_arm_insn(DisasContext *s) | @@ -786,7 +786,9 @@ static void disas_arm_insn(DisasContext *s) | ||
786 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 786 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
787 | basic block 'tb'. If search_pc is TRUE, also generate PC | 787 | basic block 'tb'. If search_pc is TRUE, also generate PC |
788 | information for each intermediate instruction. */ | 788 | information for each intermediate instruction. */ |
789 | -static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc) | 789 | +static inline int gen_intermediate_code_internal(CPUState *env, |
790 | + TranslationBlock *tb, | ||
791 | + int search_pc) | ||
790 | { | 792 | { |
791 | DisasContext dc1, *dc = &dc1; | 793 | DisasContext dc1, *dc = &dc1; |
792 | uint16_t *gen_opc_end; | 794 | uint16_t *gen_opc_end; |
@@ -853,14 +855,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -853,14 +855,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
853 | return 0; | 855 | return 0; |
854 | } | 856 | } |
855 | 857 | ||
856 | -int gen_intermediate_code(TranslationBlock *tb) | 858 | +int gen_intermediate_code(CPUState *env, TranslationBlock *tb) |
857 | { | 859 | { |
858 | - return gen_intermediate_code_internal(tb, 0); | 860 | + return gen_intermediate_code_internal(env, tb, 0); |
859 | } | 861 | } |
860 | 862 | ||
861 | -int gen_intermediate_code_pc(TranslationBlock *tb) | 863 | +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
862 | { | 864 | { |
863 | - return gen_intermediate_code_internal(tb, 1); | 865 | + return gen_intermediate_code_internal(env, tb, 1); |
864 | } | 866 | } |
865 | 867 | ||
866 | CPUARMState *cpu_arm_init(void) | 868 | CPUARMState *cpu_arm_init(void) |
translate-i386.c
@@ -1463,6 +1463,15 @@ static void gen_interrupt(DisasContext *s, int intno, | @@ -1463,6 +1463,15 @@ static void gen_interrupt(DisasContext *s, int intno, | ||
1463 | s->is_jmp = 1; | 1463 | s->is_jmp = 1; |
1464 | } | 1464 | } |
1465 | 1465 | ||
1466 | +static void gen_debug(DisasContext *s, unsigned int cur_eip) | ||
1467 | +{ | ||
1468 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
1469 | + gen_op_set_cc_op(s->cc_op); | ||
1470 | + gen_op_jmp_im(cur_eip); | ||
1471 | + gen_op_debug(); | ||
1472 | + s->is_jmp = 1; | ||
1473 | +} | ||
1474 | + | ||
1466 | /* generate a jump to eip. No segment change must happen before as a | 1475 | /* generate a jump to eip. No segment change must happen before as a |
1467 | direct call to the next block may occur */ | 1476 | direct call to the next block may occur */ |
1468 | static void gen_jmp(DisasContext *s, unsigned int eip) | 1477 | static void gen_jmp(DisasContext *s, unsigned int eip) |
@@ -4080,7 +4089,9 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | @@ -4080,7 +4089,9 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) | ||
4080 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for | 4089 | /* generate intermediate code in gen_opc_buf and gen_opparam_buf for |
4081 | basic block 'tb'. If search_pc is TRUE, also generate PC | 4090 | basic block 'tb'. If search_pc is TRUE, also generate PC |
4082 | information for each intermediate instruction. */ | 4091 | information for each intermediate instruction. */ |
4083 | -static inline int gen_intermediate_code_internal(TranslationBlock *tb, int search_pc) | 4092 | +static inline int gen_intermediate_code_internal(CPUState *env, |
4093 | + TranslationBlock *tb, | ||
4094 | + int search_pc) | ||
4084 | { | 4095 | { |
4085 | DisasContext dc1, *dc = &dc1; | 4096 | DisasContext dc1, *dc = &dc1; |
4086 | uint8_t *pc_ptr; | 4097 | uint8_t *pc_ptr; |
@@ -4116,6 +4127,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4116,6 +4127,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
4116 | pc_ptr = pc_start; | 4127 | pc_ptr = pc_start; |
4117 | lj = -1; | 4128 | lj = -1; |
4118 | do { | 4129 | do { |
4130 | + if (env->nb_breakpoints > 0) { | ||
4131 | + for(j = 0; j < env->nb_breakpoints; j++) { | ||
4132 | + if (env->breakpoints[j] == (unsigned long)pc_ptr) { | ||
4133 | + gen_debug(dc, pc_ptr - dc->cs_base); | ||
4134 | + goto the_end; | ||
4135 | + } | ||
4136 | + } | ||
4137 | + } | ||
4119 | if (search_pc) { | 4138 | if (search_pc) { |
4120 | j = gen_opc_ptr - gen_opc_buf; | 4139 | j = gen_opc_ptr - gen_opc_buf; |
4121 | if (lj < j) { | 4140 | if (lj < j) { |
@@ -4160,6 +4179,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4160,6 +4179,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
4160 | if (dc->tf) { | 4179 | if (dc->tf) { |
4161 | gen_op_raise_exception(EXCP01_SSTP); | 4180 | gen_op_raise_exception(EXCP01_SSTP); |
4162 | } | 4181 | } |
4182 | + the_end: | ||
4163 | if (dc->is_jmp != DISAS_TB_JUMP) { | 4183 | if (dc->is_jmp != DISAS_TB_JUMP) { |
4164 | /* indicate that the hash table must be used to find the next TB */ | 4184 | /* indicate that the hash table must be used to find the next TB */ |
4165 | gen_op_movl_T0_0(); | 4185 | gen_op_movl_T0_0(); |
@@ -4202,14 +4222,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | @@ -4202,14 +4222,14 @@ static inline int gen_intermediate_code_internal(TranslationBlock *tb, int searc | ||
4202 | return 0; | 4222 | return 0; |
4203 | } | 4223 | } |
4204 | 4224 | ||
4205 | -int gen_intermediate_code(TranslationBlock *tb) | 4225 | +int gen_intermediate_code(CPUState *env, TranslationBlock *tb) |
4206 | { | 4226 | { |
4207 | - return gen_intermediate_code_internal(tb, 0); | 4227 | + return gen_intermediate_code_internal(env, tb, 0); |
4208 | } | 4228 | } |
4209 | 4229 | ||
4210 | -int gen_intermediate_code_pc(TranslationBlock *tb) | 4230 | +int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb) |
4211 | { | 4231 | { |
4212 | - return gen_intermediate_code_internal(tb, 1); | 4232 | + return gen_intermediate_code_internal(env, tb, 1); |
4213 | } | 4233 | } |
4214 | 4234 | ||
4215 | CPUX86State *cpu_x86_init(void) | 4235 | CPUX86State *cpu_x86_init(void) |
translate.c
@@ -107,13 +107,13 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | @@ -107,13 +107,13 @@ void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) | ||
107 | '*gen_code_size_ptr' contains the size of the generated code (host | 107 | '*gen_code_size_ptr' contains the size of the generated code (host |
108 | code). | 108 | code). |
109 | */ | 109 | */ |
110 | -int cpu_gen_code(TranslationBlock *tb, | 110 | +int cpu_gen_code(CPUState *env, TranslationBlock *tb, |
111 | int max_code_size, int *gen_code_size_ptr) | 111 | int max_code_size, int *gen_code_size_ptr) |
112 | { | 112 | { |
113 | uint8_t *gen_code_buf; | 113 | uint8_t *gen_code_buf; |
114 | int gen_code_size; | 114 | int gen_code_size; |
115 | 115 | ||
116 | - if (gen_intermediate_code(tb) < 0) | 116 | + if (gen_intermediate_code(env, tb) < 0) |
117 | return -1; | 117 | return -1; |
118 | 118 | ||
119 | /* generate machine code */ | 119 | /* generate machine code */ |
@@ -154,7 +154,7 @@ int cpu_restore_state(TranslationBlock *tb, | @@ -154,7 +154,7 @@ int cpu_restore_state(TranslationBlock *tb, | ||
154 | unsigned long tc_ptr; | 154 | unsigned long tc_ptr; |
155 | uint16_t *opc_ptr; | 155 | uint16_t *opc_ptr; |
156 | 156 | ||
157 | - if (gen_intermediate_code_pc(tb) < 0) | 157 | + if (gen_intermediate_code_pc(env, tb) < 0) |
158 | return -1; | 158 | return -1; |
159 | 159 | ||
160 | /* find opc index corresponding to search_pc */ | 160 | /* find opc index corresponding to search_pc */ |
vl.c
@@ -2540,7 +2540,7 @@ CPUState *cpu_gdbstub_get_env(void *opaque) | @@ -2540,7 +2540,7 @@ CPUState *cpu_gdbstub_get_env(void *opaque) | ||
2540 | return global_env; | 2540 | return global_env; |
2541 | } | 2541 | } |
2542 | 2542 | ||
2543 | -void main_loop(void *opaque) | 2543 | +int main_loop(void *opaque) |
2544 | { | 2544 | { |
2545 | struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd; | 2545 | struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd, *gdb_ufd; |
2546 | int ret, n, timeout; | 2546 | int ret, n, timeout; |
@@ -2552,7 +2552,8 @@ void main_loop(void *opaque) | @@ -2552,7 +2552,8 @@ void main_loop(void *opaque) | ||
2552 | ret = cpu_x86_exec(env); | 2552 | ret = cpu_x86_exec(env); |
2553 | if (reset_requested) | 2553 | if (reset_requested) |
2554 | break; | 2554 | break; |
2555 | - | 2555 | + if (ret == EXCP_DEBUG) |
2556 | + return EXCP_DEBUG; | ||
2556 | /* if hlt instruction, we wait until the next IRQ */ | 2557 | /* if hlt instruction, we wait until the next IRQ */ |
2557 | if (ret == EXCP_HLT) | 2558 | if (ret == EXCP_HLT) |
2558 | timeout = 10; | 2559 | timeout = 10; |
@@ -2618,6 +2619,7 @@ void main_loop(void *opaque) | @@ -2618,6 +2619,7 @@ void main_loop(void *opaque) | ||
2618 | timer_irq_pending = 0; | 2619 | timer_irq_pending = 0; |
2619 | } | 2620 | } |
2620 | } | 2621 | } |
2622 | + return EXCP_INTERRUPT; | ||
2621 | } | 2623 | } |
2622 | 2624 | ||
2623 | void help(void) | 2625 | void help(void) |