65c02 Debugger fixen

* Threading fixes to allow CPU thread to iterate while under control of interface/video thread
This commit is contained in:
Aaron Culliney 2014-03-22 11:24:57 -07:00
parent c300e3e016
commit f34eff338b
9 changed files with 297 additions and 212 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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 <linux/joystick.h>
@ -270,7 +268,7 @@ void c_handle_input(int scancode, int pressed)
#ifdef DEBUGGER
case kF7:
c_do_debugging();
c_interface_debugging();
break;
#endif

View File

@ -137,6 +137,7 @@
// ----------------------------------------------------------------------------
extern pthread_mutex_t interface_mutex;
extern pthread_cond_t interface_cond;
extern bool caps_lock;
#ifdef LINUX_JOYSTICK

View File

@ -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];

View File

@ -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 <n> 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;

View File

@ -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;
}

View File

@ -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)