diff --git a/src/asm386/cpu.S b/src/asm386/cpu.S index 7990c527..12f17882 100644 --- a/src/asm386/cpu.S +++ b/src/asm386/cpu.S @@ -2716,8 +2716,6 @@ continue1: xorl %eax, %eax exception: testb $ResetSig, %al jnz ex_reset0 - testb $DebugStepSig, %al - jnz ex_step jmp ex_irq ex_reset0: testb $0xff, SN(joy_button0) // OpenApple @@ -2787,12 +2785,6 @@ emul_reinit: movb $0, SN(cpu65__signal) // Return to timing Debugger hooks ------------------------------------------------------------------------- */ -ex_step: orb $~DebugStepSig, SN(cpu65__signal) - SaveState - call SN(c_stepping_yield) - RestoreState - JumpNextInstruction - E(cpu65_direct_write) /* NB: dependent on register choices */ pushl %edi diff --git a/src/cpu-supp.c b/src/cpu-supp.c index 885ed1cb..47d74a73 100644 --- a/src/cpu-supp.c +++ b/src/cpu-supp.c @@ -119,15 +119,3 @@ void cpu65_uninterrupt(int reason) pthread_mutex_unlock(&irq_mutex); } -void cpu65_set_stepping(int flag) -{ - if (flag) - { - cpu65_interrupt(DebugStepSig); - } - else - { - cpu65_interrupt(0); - } -} - diff --git a/src/cpu.h b/src/cpu.h index 1cf5624f..03cde03c 100644 --- a/src/cpu.h +++ b/src/cpu.h @@ -66,8 +66,6 @@ extern void cpu65_uninterrupt(int reason); extern void cpu65_run(void); -extern void cpu65_set_stepping(int flag); - extern void cpu65_direct_write(int ea,int data); extern struct memory_vector cpu65_vmem[65536]; @@ -84,7 +82,6 @@ extern uint8_t emul_reinitialize; #endif /* !__ASSEMBLER__ */ #define ResetSig 0x02 -#define DebugStepSig 0x04 #define IRQ6522 0x08 #define IRQSpeech 0x10 #define IRQSSC 0x20 diff --git a/src/keys.c b/src/keys.c index 7edd31a4..59f6c26c 100644 --- a/src/keys.c +++ b/src/keys.c @@ -19,9 +19,6 @@ /* from misc.c */ extern uid_t user, privileged; -/* from debugger.c */ -extern void c_do_debugging(); - /* parameters for generic and keyboard-simulated joysticks */ extern short joy_x; extern short joy_y; @@ -30,6 +27,7 @@ extern unsigned char joy_button1; /* mutex used to synchronize between cpu and main threads */ pthread_mutex_t interface_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t interface_cond = PTHREAD_COND_INITIALIZER; #ifdef LINUX_JOYSTICK #include @@ -270,7 +268,7 @@ void c_handle_input(int scancode, int pressed) #ifdef DEBUGGER case kF7: - c_do_debugging(); + c_interface_debugging(); break; #endif diff --git a/src/keys.h b/src/keys.h index dc970c10..2dafa73d 100644 --- a/src/keys.h +++ b/src/keys.h @@ -137,6 +137,7 @@ // ---------------------------------------------------------------------------- extern pthread_mutex_t interface_mutex; +extern pthread_cond_t interface_cond; extern bool caps_lock; #ifdef LINUX_JOYSTICK diff --git a/src/meta/debug.h b/src/meta/debug.h index e5398367..26e36270 100644 --- a/src/meta/debug.h +++ b/src/meta/debug.h @@ -20,25 +20,38 @@ #include "common.h" -/* debugger defines */ -#define BUF_X 39 -#define BUF_Y 22 +#ifdef DEBUGGER +extern volatile bool is_debugging; +#else +#define is_debugging false +#endif + +typedef enum { + STEPPING = 0, + NEXTING, + FINISHING, + UNTILING, + GOING +} stepping_type_t; + +typedef struct stepping_struct_t { + stepping_type_t step_type; + uint16_t step_count; + uint16_t step_frame; + uint16_t step_pc; + bool should_break; +} stepping_struct_t; + +#define DEBUGGER_BUF_X 39 +#define DEBUGGER_BUF_Y 22 #define MAX_BRKPTS 16 -#define SCREEN_X 81 // 80col + 1 -#define SCREEN_Y 24 -#define PROMPT_X 2 -#define PROMPT_Y BUF_Y - 1 -#define PROMPT_END_X BUF_X - 2 -#define command_line command_buf[PROMPT_Y] -#define uchar unsigned char /* debugger commands */ enum token_type { MEM, DIS, REGS, SETMEM, STEP, FINISH, UNTIL, GO, VM, BREAK, WATCH, CLEAR, IGNORE, STATUS, OPCODES, LC, DRIVE, SEARCH, HELP, LOG, BSAVE, BLOAD, SAVE, UNKNOWN }; -enum addressing_mode -{ +typedef enum { addr_implied, addr_accumulator, addr_immediate, @@ -54,27 +67,21 @@ enum addressing_mode addr_j_indirect, /* non-zeropage indirects, used in JMP only */ addr_j_indirect_x, addr_relative -}; +} addressing_mode_t; struct opcode_struct { const char *mnemonic; - enum addressing_mode mode; + addressing_mode_t mode; }; extern const struct opcode_struct *opcodes; -extern int step_next; /* stepping over instructions */ -extern char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */ -extern int num_buffer_lines; /* num lines of output */ -extern int arg1, arg2, arg3; /* command arguments */ -extern int breakpoints[MAX_BRKPTS]; /* memory breakpoints */ -extern int watchpoints[MAX_BRKPTS]; /* memory watchpoints */ - +// Debugger commands void clear_debugger_screen(); void bload(FILE*, char*, int); void show_misc_info(); -unsigned char get_current_opcode(); +uint8_t get_current_opcode(); void dump_mem(int, int, int, int, int); void search_mem(char*, int, int); void set_mem(int, char*); @@ -87,17 +94,15 @@ void show_regs(); void display_help(); void show_lc_info(); void show_disk_info(); -void do_step_or_next(int); -void begin_cpu_step(); -void end_cpu_step(); -int at_haltpt(); -void set_halt_opcode(unsigned char opcode); +void set_halt_opcode(uint8_t opcode); void set_halt_65c02(); void clear_halt_65c02(); -void clear_halt_opcode(unsigned char opcode); +void clear_halt_opcode(uint8_t opcode); void show_opcode_breakpts(); -void c_stepping_yield(); +bool c_debugger_should_break(); +void c_debugger_begin_stepping(stepping_struct_t s); +void c_interface_debugging(); extern const struct opcode_struct opcodes_6502[256]; extern const struct opcode_struct opcodes_65c02[256]; diff --git a/src/meta/debug.l b/src/meta/debug.l index 89583a92..034ea102 100644 --- a/src/meta/debug.l +++ b/src/meta/debug.l @@ -28,6 +28,12 @@ YY_BUFFER_STATE buffer = 0; +extern char second_buf[DEBUGGER_BUF_Y][DEBUGGER_BUF_X];/* scratch buffer for output */ +extern int num_buffer_lines; /* num lines of output */ +extern int arg1, arg2, arg3; /* command arguments */ +extern int breakpoints[MAX_BRKPTS]; /* memory breakpoints */ +extern int watchpoints[MAX_BRKPTS]; /* memory watchpoints */ + /* d{is} {lc1|lc2} {/bank/}{addr} {+}{len} m{em} {lc1|lc2} {/bank/}{addr} {+}{len} @@ -436,50 +442,56 @@ ADDRS [0-9a-fA-F]+ } {BOS}(st?e?p?|ne?x?t?){EOS} { - /* step / step next instruction */ - if (*debugtext == 'n') step_next = 1; - do_step_or_next(1); + stepping_struct_t s = { + .step_type = STEPPING, + .step_count = 1 + }; + + if (*debugtext == 'n') { + s.step_type = NEXTING; + } + + c_debugger_begin_stepping(s); return STEP; } {BOS}(st?e?p?|ne?x?t?){WS}+{HEX}+{EOS} { - /* step / step next instructions */ - if (*debugtext == 'n') step_next = 1; while (!isspace(*debugtext)) ++debugtext; arg1 = strtol(debugtext, (char**)NULL, 16); if ((arg1 < 1) || (arg1 > 255)) arg1 = 255; - do_step_or_next(arg1); + stepping_struct_t s = { + .step_type = STEPPING, + .step_count = arg1 + }; + + if (*debugtext == 'n') { + s.step_type = NEXTING; + } + + c_debugger_begin_stepping(s); return STEP; } {BOS}fi?n?i?s?h?{EOS} { - int step_frame = 1; - unsigned char op; - /* step until finished with curent stack frame */ - while ((c_mygetch(0) == -1) && !at_haltpt()) { - op = get_current_opcode(); + stepping_struct_t s = { + .step_type = FINISHING, + .step_frame = 1 + }; - if (op == 0x20) ++step_frame; /* JSR */ - if (op == 0x60) --step_frame; /* RTS */ - - if (!step_frame) break; /* finished */ - begin_cpu_step(); - } - end_cpu_step(); /* print location */ + c_debugger_begin_stepping(s); return FINISH; } {BOS}un?t?i?l?{EOS} { /* step until PC == next instruction. good for finishing backward loops */ - unsigned char op; + uint8_t op = get_current_opcode(); int delta=0; - op = get_current_opcode(); switch (opcodes[op].mode) { @@ -506,11 +518,12 @@ ADDRS [0-9a-fA-F]+ break; } - arg1 = cpu65_current.pc + delta; + stepping_struct_t s = { + .step_type = UNTILING, + .step_pc = cpu65_current.pc + delta + }; - while ((cpu65_current.pc != arg1) && !at_haltpt() && (c_mygetch(0) == -1)) - begin_cpu_step(); - end_cpu_step(); /* print location */ + c_debugger_begin_stepping(s); return UNTIL; } @@ -520,17 +533,21 @@ ADDRS [0-9a-fA-F]+ /* DANGEROUS! */ cpu65_current.pc = strtol(debugtext, (char**)NULL, 16); - while (!at_haltpt() && (c_mygetch(0) == -1)) - begin_cpu_step(); - end_cpu_step(); /* print location */ + + stepping_struct_t s = { + .step_type = GOING + }; + + c_debugger_begin_stepping(s); return GO; } {BOS}go?{EOS} { - /* run while remaining in debugger console */ - while (!at_haltpt() && (c_mygetch(0) == -1)) - begin_cpu_step(); - end_cpu_step(); /* print location */ + stepping_struct_t s = { + .step_type = GOING + }; + + c_debugger_begin_stepping(s); return GO; } @@ -586,7 +603,7 @@ ADDRS [0-9a-fA-F]+ return BREAK; } - set_halt_opcode((unsigned char)arg1); + set_halt_opcode((uint8_t)arg1); return BREAK; } @@ -655,9 +672,9 @@ ADDRS [0-9a-fA-F]+ sprintf(second_buf[num_buffer_lines++], "invalid opcode"); return CLEAR; } - clear_halt_opcode((unsigned char)arg1); + clear_halt_opcode((uint8_t)arg1); sprintf(second_buf[num_buffer_lines++], "cleared opcode %02X", - (unsigned char)arg1); + (uint8_t)arg1); } return CLEAR; } @@ -740,11 +757,11 @@ ADDRS [0-9a-fA-F]+ {BOS}key{WS}+{HEX}+{EOS} { /* send key code to emulator */ - unsigned char key; + uint8_t key; while (!isspace(*debugtext)) ++debugtext; while (isspace(*debugtext)) ++debugtext; - key = (unsigned char) strtol(debugtext, &debugtext, 16); + key = (uint8_t) strtol(debugtext, &debugtext, 16); apple_ii_64k[0][0xC000] = key; apple_ii_64k[1][0xC000] = key; diff --git a/src/meta/debugger.c b/src/meta/debugger.c index 65b325e4..1e85b323 100644 --- a/src/meta/debugger.c +++ b/src/meta/debugger.c @@ -18,7 +18,19 @@ const struct opcode_struct *opcodes; -int step_next; /* stepping over instructions */ +static stepping_struct_t stepping_struct; + +volatile bool is_debugging = false; + +#define BUF_X DEBUGGER_BUF_X +#define BUF_Y DEBUGGER_BUF_Y +#define SCREEN_X 81 // 80col + 1 +#define SCREEN_Y 24 +#define PROMPT_X 2 +#define PROMPT_Y BUF_Y - 1 +#define PROMPT_END_X BUF_X - 2 +#define command_line command_buf[PROMPT_Y] + char second_buf[BUF_Y][BUF_X]; /* scratch buffer for output */ int num_buffer_lines; /* num lines of output */ int arg1, arg2, arg3; /* command arguments */ @@ -56,7 +68,7 @@ static char screen[SCREEN_Y][SCREEN_X] = static char command_buf[BUF_Y][BUF_X]; /* command line prompt */ char lexbuf[BUF_X+2]; /* comman line to be flex'ed */ -unsigned char current_opcode; +uint8_t current_opcode; int op_breakpoints[256]; /* opcode breakpoints */ @@ -123,13 +135,18 @@ int c_get_current_rambank(int addrs) { return !!(softswitches & SS_ALTZP); } +/* ------------------------------------------------------------------------- + get_last_opcode () - returns the last executed opcode + ------------------------------------------------------------------------- */ +uint8_t get_last_opcode() { + return cpu65_debug.opcode; +} + /* ------------------------------------------------------------------------- get_current_opcode () - returns the opcode from the address that the PC is currently reading from. - returns 0 = bank 0 - 1 = bank 1 ------------------------------------------------------------------------- */ -unsigned char get_current_opcode() { +uint8_t get_current_opcode() { int bank = c_get_current_rambank(cpu65_current.pc); int lcbank = 0; @@ -175,7 +192,7 @@ unsigned char get_current_opcode() { void dump_mem(int addrs, int len, int lc, int do_ascii, int rambank) { int i, j, mod, end; - unsigned char op; + uint8_t op; int orig_addrs = addrs; /* address for display */ /* check which rambank */ @@ -285,7 +302,7 @@ void dump_mem(int addrs, int len, int lc, int do_ascii, int rambank) { void search_mem(char *hexstr, int lc, int rambank) { int i = 0, j = 0, end, op; static char scratch[3]; - unsigned char byte; + uint8_t byte; end = (lc) ? 0x3000 : 0x10000; @@ -299,7 +316,7 @@ void search_mem(char *hexstr, int lc, int rambank) { for (i = 0; i < end; i++) { strncpy(scratch, hexstr+j, 2); /* extract a byte */ - byte = (unsigned char) strtol(scratch, (char**)NULL, 16); + byte = (uint8_t) strtol(scratch, (char**)NULL, 16); if (lc) { @@ -342,7 +359,7 @@ void search_mem(char *hexstr, int lc, int rambank) { ------------------------------------------------------------------------- */ void set_mem(int addrs, char *hexstr) { static char scratch[3]; - unsigned char data; + uint8_t data; if ((addrs < 0) || (addrs > 0xffff)) { @@ -353,7 +370,7 @@ void set_mem(int addrs, char *hexstr) { while (*hexstr) { strncpy(scratch, hexstr, 2); - data = (unsigned char) strtol(scratch, (char**)NULL, 16); + data = (uint8_t) strtol(scratch, (char**)NULL, 16); /* call the set_memory routine, which knows how to route the request */ @@ -379,7 +396,7 @@ void set_mem(int addrs, char *hexstr) { ------------------------------------------------------------------------- */ void set_lc_mem(int addrs, int lcbank, char *hexstr) { static char scratch[3]; - unsigned char data; + uint8_t data; if ((addrs >= 0xd000) && (addrs <= 0xffff)) { @@ -395,7 +412,7 @@ void set_lc_mem(int addrs, int lcbank, char *hexstr) { while (*hexstr) { strncpy(scratch, hexstr, 2); - data = (unsigned char) strtol(scratch, (char**)NULL, 16); + data = (uint8_t) strtol(scratch, (char**)NULL, 16); /* ??? no way to write to aux LC banks */ @@ -432,9 +449,9 @@ void set_lc_mem(int addrs, int lcbank, char *hexstr) { "safely" set memory... ------------------------------------------------------------------------- */ void bload(FILE *f, char *name, int addrs) { - unsigned char *hexstr = NULL; + uint8_t *hexstr = NULL; int len = -1; - unsigned char data; + uint8_t data; if ((addrs < 0) || (addrs > 0xffff)) { @@ -444,7 +461,7 @@ void bload(FILE *f, char *name, int addrs) { while ((len = fread(temp, 1, TEMPSIZE, f))) { - hexstr = (unsigned char*)temp; + hexstr = (uint8_t*)temp; for (; len > 0; len--) { data = *hexstr; @@ -472,7 +489,7 @@ void bload(FILE *f, char *name, int addrs) { void disasm(int addrs, int len, int lc, int rambank) { static char fmt[64]; - unsigned char op; + uint8_t op; char arg1, arg2; int i, j, k, end, orig_addrs = addrs; @@ -557,9 +574,9 @@ void disasm(int addrs, int len, int lc, int rambank) { arg1 = apple_ii_64k[rambank][++j]; } - sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", rambank, k, op, (unsigned char)arg1, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); + sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", rambank, k, op, (uint8_t)arg1, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); - sprintf(second_buf[i], fmt, (unsigned char)arg1); + sprintf(second_buf[i], fmt, (uint8_t)arg1); k+=2; break; @@ -585,8 +602,8 @@ void disasm(int addrs, int len, int lc, int rambank) { arg2 = apple_ii_64k[rambank][++j]; } - sprintf(fmt, "/%02X/%04X: %02X%02X%02X %s %s", rambank, k, op, (unsigned char)arg1, (unsigned char)arg2, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); - sprintf(second_buf[i], fmt, (unsigned char)arg2, (unsigned char)arg1); + sprintf(fmt, "/%02X/%04X: %02X%02X%02X %s %s", rambank, k, op, (uint8_t)arg1, (uint8_t)arg2, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); + sprintf(second_buf[i], fmt, (uint8_t)arg2, (uint8_t)arg1); k+=3; break; @@ -606,14 +623,14 @@ void disasm(int addrs, int len, int lc, int rambank) { arg1 = apple_ii_64k[rambank][++j]; } - sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", rambank, k, op, (unsigned char)arg1, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); + sprintf(fmt, "/%02X/%04X: %02X%02X %s %s", rambank, k, op, (uint8_t)arg1, opcodes[op].mnemonic, disasm_templates[opcodes[op].mode]); if (arg1 < 0) { - sprintf(second_buf[i], fmt, k + arg1 + 2, '-', (unsigned char)(-arg1)); + sprintf(second_buf[i], fmt, k + arg1 + 2, '-', (uint8_t)(-arg1)); } else { - sprintf(second_buf[i], fmt, k + arg1 + 2, '+', (unsigned char)arg1); + sprintf(second_buf[i], fmt, k + arg1 + 2, '+', (uint8_t)arg1); } k+=2; @@ -688,7 +705,7 @@ void show_regs() { ------------------------------------------------------------------------- */ static int will_branch() { - unsigned char op = get_current_opcode(); + uint8_t op = get_current_opcode(); switch (op) { @@ -760,14 +777,14 @@ void clear_halt(int *type, int pt) { /* ------------------------------------------------------------------------- set_halt_opcode () = set a breakpoint on a particular opcode. ------------------------------------------------------------------------- */ -void set_halt_opcode(unsigned char opcode) { +void set_halt_opcode(uint8_t opcode) { op_breakpoints[opcode] = 1; } /* ------------------------------------------------------------------------- clear_halt_opcode () = unset an opcode breakpoint. ------------------------------------------------------------------------- */ -void clear_halt_opcode(unsigned char opcode) { +void clear_halt_opcode(uint8_t opcode) { op_breakpoints[opcode] = 0; } @@ -776,40 +793,40 @@ void clear_halt_opcode(unsigned char opcode) { assumes that you are in //e mode... ------------------------------------------------------------------------- */ void set_halt_65c02() { - set_halt_opcode((uchar)0x02); set_halt_opcode((uchar)0x04); - set_halt_opcode((uchar)0x0C); set_halt_opcode((uchar)0x12); - set_halt_opcode((uchar)0x14); set_halt_opcode((uchar)0x1A); - set_halt_opcode((uchar)0x1C); set_halt_opcode((uchar)0x32); - set_halt_opcode((uchar)0x34); set_halt_opcode((uchar)0x3A); - set_halt_opcode((uchar)0x3C); set_halt_opcode((uchar)0x52); - set_halt_opcode((uchar)0x5A); set_halt_opcode((uchar)0x64); - set_halt_opcode((uchar)0x72); set_halt_opcode((uchar)0x74); - set_halt_opcode((uchar)0x7A); set_halt_opcode((uchar)0x7C); - set_halt_opcode((uchar)0x80); set_halt_opcode((uchar)0x89); - set_halt_opcode((uchar)0x92); set_halt_opcode((uchar)0x9C); - set_halt_opcode((uchar)0x9E); set_halt_opcode((uchar)0xB2); - set_halt_opcode((uchar)0xD2); set_halt_opcode((uchar)0xDA); - set_halt_opcode((uchar)0xF2); set_halt_opcode((uchar)0xFA); + set_halt_opcode((uint8_t)0x02); set_halt_opcode((uint8_t)0x04); + set_halt_opcode((uint8_t)0x0C); set_halt_opcode((uint8_t)0x12); + set_halt_opcode((uint8_t)0x14); set_halt_opcode((uint8_t)0x1A); + set_halt_opcode((uint8_t)0x1C); set_halt_opcode((uint8_t)0x32); + set_halt_opcode((uint8_t)0x34); set_halt_opcode((uint8_t)0x3A); + set_halt_opcode((uint8_t)0x3C); set_halt_opcode((uint8_t)0x52); + set_halt_opcode((uint8_t)0x5A); set_halt_opcode((uint8_t)0x64); + set_halt_opcode((uint8_t)0x72); set_halt_opcode((uint8_t)0x74); + set_halt_opcode((uint8_t)0x7A); set_halt_opcode((uint8_t)0x7C); + set_halt_opcode((uint8_t)0x80); set_halt_opcode((uint8_t)0x89); + set_halt_opcode((uint8_t)0x92); set_halt_opcode((uint8_t)0x9C); + set_halt_opcode((uint8_t)0x9E); set_halt_opcode((uint8_t)0xB2); + set_halt_opcode((uint8_t)0xD2); set_halt_opcode((uint8_t)0xDA); + set_halt_opcode((uint8_t)0xF2); set_halt_opcode((uint8_t)0xFA); } /* ------------------------------------------------------------------------- clear_halt_65c02 () = clear all 65c02 instructions ------------------------------------------------------------------------- */ void clear_halt_65c02() { - clear_halt_opcode((uchar)0x02); clear_halt_opcode((uchar)0x04); - clear_halt_opcode((uchar)0x0C); clear_halt_opcode((uchar)0x12); - clear_halt_opcode((uchar)0x14); clear_halt_opcode((uchar)0x1A); - clear_halt_opcode((uchar)0x1C); clear_halt_opcode((uchar)0x32); - clear_halt_opcode((uchar)0x34); clear_halt_opcode((uchar)0x3A); - clear_halt_opcode((uchar)0x3C); clear_halt_opcode((uchar)0x52); - clear_halt_opcode((uchar)0x5A); clear_halt_opcode((uchar)0x64); - clear_halt_opcode((uchar)0x72); clear_halt_opcode((uchar)0x74); - clear_halt_opcode((uchar)0x7A); clear_halt_opcode((uchar)0x7C); - clear_halt_opcode((uchar)0x80); clear_halt_opcode((uchar)0x89); - clear_halt_opcode((uchar)0x92); clear_halt_opcode((uchar)0x9C); - clear_halt_opcode((uchar)0x9E); clear_halt_opcode((uchar)0xB2); - clear_halt_opcode((uchar)0xD2); clear_halt_opcode((uchar)0xDA); - clear_halt_opcode((uchar)0xF2); clear_halt_opcode((uchar)0xFA); + clear_halt_opcode((uint8_t)0x02); clear_halt_opcode((uint8_t)0x04); + clear_halt_opcode((uint8_t)0x0C); clear_halt_opcode((uint8_t)0x12); + clear_halt_opcode((uint8_t)0x14); clear_halt_opcode((uint8_t)0x1A); + clear_halt_opcode((uint8_t)0x1C); clear_halt_opcode((uint8_t)0x32); + clear_halt_opcode((uint8_t)0x34); clear_halt_opcode((uint8_t)0x3A); + clear_halt_opcode((uint8_t)0x3C); clear_halt_opcode((uint8_t)0x52); + clear_halt_opcode((uint8_t)0x5A); clear_halt_opcode((uint8_t)0x64); + clear_halt_opcode((uint8_t)0x72); clear_halt_opcode((uint8_t)0x74); + clear_halt_opcode((uint8_t)0x7A); clear_halt_opcode((uint8_t)0x7C); + clear_halt_opcode((uint8_t)0x80); clear_halt_opcode((uint8_t)0x89); + clear_halt_opcode((uint8_t)0x92); clear_halt_opcode((uint8_t)0x9C); + clear_halt_opcode((uint8_t)0x9E); clear_halt_opcode((uint8_t)0xB2); + clear_halt_opcode((uint8_t)0xD2); clear_halt_opcode((uint8_t)0xDA); + clear_halt_opcode((uint8_t)0xF2); clear_halt_opcode((uint8_t)0xFA); } /* ------------------------------------------------------------------------- @@ -822,7 +839,7 @@ int at_haltpt() { int i; /* check op_breakpoints */ - unsigned char op = get_current_opcode(); + uint8_t op = get_last_opcode(); if (op_breakpoints[op]) { sprintf(second_buf[num_buffer_lines++], "stopped at %04X bank %d instruction %02X", cpu65_current.pc, c_get_current_rambank(cpu65_current.pc), op); @@ -1043,9 +1060,7 @@ void clear_debugger_screen() { end_cpu_step () - finish a stepping command display the next instruction, and tell whether it will branch ------------------------------------------------------------------------- */ -void end_cpu_step() { - - cpu65_set_stepping(0); +static void end_cpu_step() { clear_debugger_screen(); disasm(cpu65_current.pc, 1, 0, -1); @@ -1057,80 +1072,113 @@ void end_cpu_step() { sprintf(second_buf[num_buffer_lines++], "%s", (branch) ? "will branch" : "will not branch"); } + /* ------------------------------------------------------------------------- begin_cpu_step() - step the CPU set the CPU into stepping mode and yield to CPU thread ------------------------------------------------------------------------- */ -void begin_cpu_step() -{ - cpu65_set_stepping(1); - c_stepping_yield(); -} - -/* ------------------------------------------------------------------------- - c_stepping_yield() - called to yield execution between cpu and main threads when stepping - ------------------------------------------------------------------------- */ -void c_stepping_yield() +static void begin_cpu_step() { int err = 0; - if ((err = pthread_mutex_unlock(&interface_mutex))) - { - ERRLOG("pthread_mutex_unlock : %d", err); + + do { + if ((err = pthread_cond_signal(&interface_cond))) { + ERRLOG("pthread_cond_signal : %d", err); + } + if ((err = pthread_cond_wait(&interface_cond, &interface_mutex))) { + ERRLOG("pthread_cond_wait : %d", err); + } + + if (c_mygetch(0) != -1) { + break; + } + } while (!stepping_struct.should_break); + + if ((err = pthread_cond_signal(&interface_cond))) { + ERRLOG("pthread_cond_signal : %d", err); } - // presumably other thread executes while we yield and sleep ... - if ((err = pthread_yield())) - { - ERRLOG("pthread_yield ; %d", err); - } - static struct timespec deltat = { .tv_sec=0, .tv_nsec=1 }; - nanosleep(&deltat, NULL); - - if ((err = pthread_mutex_lock(&interface_mutex))) - { - ERRLOG("pthread_mutex_lock : %d", err); - } + end_cpu_step(); } /* ------------------------------------------------------------------------- - do_step_or_next () - step into or step over commands + c_debugger_should_break() ------------------------------------------------------------------------- */ -void do_step_or_next(int step_count) { - char ch; - unsigned char op; - int step_frame = 0; +bool c_debugger_should_break() { - /* do step while step_count AND no breaks AND no keypress */ - do - { - op = get_current_opcode(); + // WARNING : this state management function should be called from CPU thread only! - if (step_next && (op == 0x20)) - { - do + if (at_haltpt()) { + stepping_struct.should_break = true; + } else { + uint8_t op = get_last_opcode(); + + switch (stepping_struct.step_type) { + case STEPPING: { - op = get_current_opcode(); - if (op == 0x20) - { - ++step_frame; /* JSR */ + --stepping_struct.step_count; + if (stepping_struct.step_count == 0) { + stepping_struct.should_break = true; + } + } + break; + + case NEXTING: + { + if (stepping_struct.step_count > 0) { + --stepping_struct.step_count; } - if (op == 0x60) - { - --step_frame; /* RTS */ + if (op == 0x20) { + ++stepping_struct.step_frame; // JSR + } + if (op == 0x60) { + --stepping_struct.step_frame; // RTS } - begin_cpu_step(); - } while (((ch = c_mygetch(0)) == -1) && !at_haltpt() && step_frame); - } - else - { - begin_cpu_step(); - } - } while (--step_count && !at_haltpt() && (c_mygetch(0) == -1)); + if ((stepping_struct.step_frame == 0) && (stepping_struct.step_count == 0)) { + stepping_struct.should_break = true; + } + } + break; - end_cpu_step(); + case UNTILING: + { + if (stepping_struct.step_pc == cpu65_current.pc) { + stepping_struct.should_break = true; + } + } + break; + + case FINISHING: + { + if (op == 0x20) { + ++stepping_struct.step_frame; // JSR + } + if (op == 0x60) { + --stepping_struct.step_frame; // RTS + } + + if (stepping_struct.step_frame == 0) { + stepping_struct.should_break = true; + } + } + break; + + case GOING: + break; + } + } + + return stepping_struct.should_break; +} + +/* ------------------------------------------------------------------------- + c_debugger_begin_stepping () - step into or step over commands + ------------------------------------------------------------------------- */ +void c_debugger_begin_stepping(stepping_struct_t s) { + stepping_struct = s; + begin_cpu_step(); } /* ------------------------------------------------------------------------- @@ -1173,7 +1221,6 @@ void do_debug_command() { int i = 0, j = 0, k = 0; /* reset key local vars */ - step_next = 0; num_buffer_lines = 0; /* call lex to perform the command.*/ @@ -1233,14 +1280,15 @@ void do_debug_command() { } /* ------------------------------------------------------------------------- - c_do_debugging() + c_interface_debugging() main debugging console ------------------------------------------------------------------------- */ -void c_do_debugging() { +void c_interface_debugging() { static char lex_initted = 0; + int err = 0; int i; int ch; int command_pos = PROMPT_X; @@ -1275,6 +1323,8 @@ void c_do_debugging() { c_interface_print(0, i, 2, screen[ i ] ); } + is_debugging = true; + for (;;) { /* print command line */ @@ -1289,8 +1339,7 @@ void c_do_debugging() { if (ch == kESC) { - c_interface_exit(-1); - return; + break; } else { @@ -1313,5 +1362,13 @@ void c_do_debugging() { } } } + + c_interface_exit(-1); + is_debugging = false; + if ((err = pthread_cond_signal(&interface_cond))) + { + ERRLOG("pthread_cond_signal : %d", err); + } + return; } diff --git a/src/timing.c b/src/timing.c index 60842a7b..57279a9f 100644 --- a/src/timing.c +++ b/src/timing.c @@ -158,7 +158,10 @@ void cpu_thread(void *dummyptr) { struct timespec t0; // the target timer struct timespec ti, tj; // actual time samples bool negative = false; - long drift_adj_nsecs = 0; // generic drift adjustment between target and actual + long drift_adj_nsecs = 0; // generic drift adjustment between target and actual + + int debugging_cycles0 = 0; + int debugging_cycles = 0; #ifndef NDEBUG unsigned long dbg_ticks = 0; @@ -201,14 +204,41 @@ void cpu_thread(void *dummyptr) { cpu65_cycles_to_execute = 0; } - cpu65_cycle_count = 0; g_nCyclesExecuted = 0; #ifdef AUDIO_ENABLED MB_StartOfCpuExecute(); #endif + if (is_debugging) { + debugging_cycles0 = cpu65_cycles_to_execute; + debugging_cycles = cpu65_cycles_to_execute; + } - cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ... + do { + if (is_debugging) { + cpu65_cycles_to_execute = 1; + } + + cpu65_cycle_count = 0; + cpu65_run(); // run emulation for cpu65_cycles_to_execute cycles ... + + if (is_debugging) { + debugging_cycles -= cpu65_cycle_count; + if (c_debugger_should_break() || (debugging_cycles <= 0)) { + int err = 0; + if ((err = pthread_cond_signal(&interface_cond))) { + ERRLOG("pthread_cond_signal : %d", err); + } + if ((err = pthread_cond_wait(&interface_cond, &interface_mutex))) { + ERRLOG("pthread_cond_wait : %d", err); + } + if (debugging_cycles <= 0) { + cpu65_cycle_count = debugging_cycles0 - debugging_cycles/*<=0*/; + break; + } + } + } + } while (is_debugging); cycles_adjust = cpu65_cycles_to_execute; // counter is decremented in cpu65_run() if (cycles_adjust < 0)