mirror of
https://github.com/mauiaaron/apple2.git
synced 2024-12-23 11:31:41 +00:00
65c02 Debugger fixen
* Threading fixes to allow CPU thread to iterate while under control of interface/video thread
This commit is contained in:
parent
c300e3e016
commit
f34eff338b
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -137,6 +137,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern pthread_mutex_t interface_mutex;
|
||||
extern pthread_cond_t interface_cond;
|
||||
extern bool caps_lock;
|
||||
|
||||
#ifdef LINUX_JOYSTICK
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
// presumably other thread executes while we yield and sleep ...
|
||||
if ((err = pthread_yield()))
|
||||
{
|
||||
ERRLOG("pthread_yield ; %d", err);
|
||||
if (c_mygetch(0) != -1) {
|
||||
break;
|
||||
}
|
||||
static struct timespec deltat = { .tv_sec=0, .tv_nsec=1 };
|
||||
nanosleep(&deltat, NULL);
|
||||
} while (!stepping_struct.should_break);
|
||||
|
||||
if ((err = pthread_mutex_lock(&interface_mutex)))
|
||||
{
|
||||
ERRLOG("pthread_mutex_lock : %d", err);
|
||||
if ((err = pthread_cond_signal(&interface_cond))) {
|
||||
ERRLOG("pthread_cond_signal : %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))
|
||||
if (at_haltpt()) {
|
||||
stepping_struct.should_break = true;
|
||||
} else {
|
||||
uint8_t op = get_last_opcode();
|
||||
|
||||
switch (stepping_struct.step_type) {
|
||||
case STEPPING:
|
||||
{
|
||||
do
|
||||
--stepping_struct.step_count;
|
||||
if (stepping_struct.step_count == 0) {
|
||||
stepping_struct.should_break = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NEXTING:
|
||||
{
|
||||
op = get_current_opcode();
|
||||
if (op == 0x20)
|
||||
{
|
||||
++step_frame; /* JSR */
|
||||
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
|
||||
}
|
||||
|
||||
if ((stepping_struct.step_frame == 0) && (stepping_struct.step_count == 0)) {
|
||||
stepping_struct.should_break = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
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();
|
||||
} while (((ch = c_mygetch(0)) == -1) && !at_haltpt() && step_frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
begin_cpu_step();
|
||||
}
|
||||
} while (--step_count && !at_haltpt() && (c_mygetch(0) == -1));
|
||||
|
||||
end_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;
|
||||
}
|
||||
|
||||
|
32
src/timing.c
32
src/timing.c
@ -160,6 +160,9 @@ void cpu_thread(void *dummyptr) {
|
||||
bool negative = false;
|
||||
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;
|
||||
int speaker_neg_feedback = 0;
|
||||
@ -201,15 +204,42 @@ 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user