mirror of
https://github.com/digarok/gsplus.git
synced 2024-06-01 08:41:36 +00:00
debugger - add n (next) command
similar to s/step but skips OVER jsr/jsl commands. implemented via a new temporary breakpoint list.
This commit is contained in:
parent
dd3a00a734
commit
0e5f941cd5
|
@ -30,8 +30,8 @@ word32 g_mp_breakpoints[MAX_BREAK_POINTS];
|
|||
int g_num_bp_breakpoints = 0;
|
||||
word32 g_bp_breakpoints[MAX_BREAK_POINTS];
|
||||
|
||||
int g_num_tmp_bp_breakpoints = 0;
|
||||
word32 g_tmp_bp_breakpoints[MAX_BREAK_POINTS];
|
||||
int g_num_tp_breakpoints = 0;
|
||||
word32 g_tp_breakpoints[MAX_BREAK_POINTS];
|
||||
|
||||
int g_dbg_shell = 0;
|
||||
int g_stepping = 0;
|
||||
|
@ -567,6 +567,159 @@ word32 do_list(word32 address, int lines) {
|
|||
return address;
|
||||
}
|
||||
|
||||
#if 0
|
||||
word32 next_pc(void) {
|
||||
/* return next pc, skipping subroutines,
|
||||
accounting for inline calls, and branches
|
||||
*/
|
||||
word32 pc = engine.kpc;
|
||||
|
||||
enum {
|
||||
C = 1 << 0,
|
||||
Z = 1 << 1,
|
||||
I = 1 << 2,
|
||||
D = 1 << 3,
|
||||
X = 1 << 4,
|
||||
M = 1 << 5,
|
||||
V = 1 << 6,
|
||||
N = 1 << 7,
|
||||
E = 1 << 8
|
||||
};
|
||||
|
||||
unsigned opcode = get_memory_c(pc++, 0);
|
||||
unsigned operand = 0;
|
||||
|
||||
unsigned dtype = disasm_types[opcode];
|
||||
unsigned args = dtype >> 8;
|
||||
|
||||
switch (args) {
|
||||
case 4:
|
||||
args = engine.psr & M ? 1 : 2;
|
||||
break;
|
||||
case 5:
|
||||
args = engine.psr & X ? 1 : 2;
|
||||
break;
|
||||
}
|
||||
operand = 0;
|
||||
switch(args) {
|
||||
case 1:
|
||||
operand = get_memory_c(pc, 0);
|
||||
break;
|
||||
case 2:
|
||||
operand = get_memory16_c(pc, 0);
|
||||
break;
|
||||
case 3:
|
||||
operand = get_memory24_c(pc, 0);
|
||||
break;
|
||||
}
|
||||
pc += args;
|
||||
|
||||
switch (opcode) {
|
||||
case 0x20:
|
||||
if ((pc & 0xff0000) == 0 && operand == 0xbf00)
|
||||
return pc + 3;
|
||||
break;
|
||||
case 0x22:
|
||||
if (operand == 0xe100a8)
|
||||
return pc + 6;
|
||||
break;
|
||||
|
||||
case 0x82: /* brl */
|
||||
operand += pc & 0xffff;
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
case 0x80: /* bra */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
|
||||
case 0x90: /* bcc */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (~engine.psr & C)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
case 0xb0: /* bcc */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (engine.psr & C)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
|
||||
case 0x10: /* bpl */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (~engine.psr & N)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
case 0x30: /* bmi */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (engine.psr & N)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
|
||||
case 0x50: /* bvc */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (~engine.psr & V)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
case 0x70: /* bvs */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (engine.psr & V)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
|
||||
case 0xd0: /* bvc */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (~engine.psr & Z)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
case 0xf0: /* beq */
|
||||
operand = (pc + (int8_t)operand) & 0xffff;
|
||||
if (engine.psr & Z)
|
||||
return (pc & 0xff0000) | operand;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* todo --
|
||||
* should use tmp breakpoint instead of g_stepping?
|
||||
* don't want to step into an interrupt, for example.
|
||||
* also, step should steps over gs/os, toolbox calls
|
||||
* (gsbug has protected memory ranges)
|
||||
*/
|
||||
int next_pc(void) {
|
||||
|
||||
word32 pc = engine.kpc;
|
||||
unsigned opcode = get_memory_c(pc++, 0);
|
||||
unsigned operand = 0;
|
||||
|
||||
switch (opcode) {
|
||||
case 0x20: /* jsr abs */
|
||||
operand = get_memory16_c(pc, 0);
|
||||
pc += 2;
|
||||
if ((pc & 0xff0000) == 0 && operand == 0xbf00)
|
||||
pc += 3;
|
||||
return pc;
|
||||
break;
|
||||
case 0xfc: /* jsr (abs,x) */
|
||||
return pc + 2;
|
||||
break;
|
||||
case 0x22: /* jsl */
|
||||
operand = get_memory24_c(pc, 0);
|
||||
pc += 3;
|
||||
if (operand == 0xe100a8)
|
||||
pc += 6;
|
||||
return pc;
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
REG_A,
|
||||
|
@ -796,6 +949,13 @@ void show_bp(int type) {
|
|||
breakpoints = g_mp_breakpoints;
|
||||
num_breakpoints = g_num_mp_breakpoints;
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
breakpoints = g_tp_breakpoints;
|
||||
num_breakpoints = g_num_tp_breakpoints;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
fputs("Invalid breakpoint type\n", stderr);
|
||||
return;
|
||||
|
@ -808,7 +968,7 @@ void show_bp(int type) {
|
|||
}
|
||||
}
|
||||
|
||||
void set_bp(int type, word32 addr) {
|
||||
int set_bp(int type, word32 addr) {
|
||||
int i;
|
||||
|
||||
word32 *breakpoints;
|
||||
|
@ -823,32 +983,40 @@ void set_bp(int type, word32 addr) {
|
|||
breakpoints = g_mp_breakpoints;
|
||||
num_breakpoints = g_num_mp_breakpoints;
|
||||
break;
|
||||
case 'T':
|
||||
breakpoints = g_tp_breakpoints;
|
||||
num_breakpoints = g_num_tp_breakpoints;
|
||||
break;
|
||||
|
||||
default:
|
||||
fputs("Invalid breakpoint type\n", stderr);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_breakpoints; ++i) {
|
||||
if (breakpoints[i] == addr) break;
|
||||
}
|
||||
|
||||
if (i < num_breakpoints) return; /* already set */
|
||||
if (i < num_breakpoints) return 1; /* already set */
|
||||
if (num_breakpoints == MAX_BREAK_POINTS) {
|
||||
printf("Too many breakpoints.\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
breakpoints[num_breakpoints++] = addr;
|
||||
|
||||
switch(type) {
|
||||
case 'B': g_num_bp_breakpoints = num_breakpoints; break;
|
||||
case 'M': g_num_mp_breakpoints = num_breakpoints; break;
|
||||
case 'T': g_num_tp_breakpoints = num_breakpoints; break;
|
||||
}
|
||||
|
||||
qsort(breakpoints, num_breakpoints, sizeof(word32), addr_cmp);
|
||||
fixup_brks();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void delete_bp(int type, word32 addr) {
|
||||
/* returns 1 if address deleted */
|
||||
int delete_bp(int type, word32 addr) {
|
||||
int i;
|
||||
|
||||
word32 *breakpoints;
|
||||
|
@ -863,26 +1031,33 @@ void delete_bp(int type, word32 addr) {
|
|||
breakpoints = g_mp_breakpoints;
|
||||
num_breakpoints = g_num_mp_breakpoints;
|
||||
break;
|
||||
case 'T':
|
||||
breakpoints = g_tp_breakpoints;
|
||||
num_breakpoints = g_num_tp_breakpoints;
|
||||
break;
|
||||
|
||||
default:
|
||||
fputs("Invalid breakpoint type\n", stderr);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_breakpoints; ++i) {
|
||||
if (breakpoints[i] == addr) break;
|
||||
}
|
||||
|
||||
if (i == num_breakpoints) return; /* not set */
|
||||
if (i == num_breakpoints) return 0; /* not set */
|
||||
breakpoints[i] = 0;
|
||||
breakpoints[i] = breakpoints[--num_breakpoints];
|
||||
|
||||
switch(type) {
|
||||
case 'B': g_num_bp_breakpoints = num_breakpoints; break;
|
||||
case 'M': g_num_mp_breakpoints = num_breakpoints; break;
|
||||
case 'T': g_num_tp_breakpoints = num_breakpoints; break;
|
||||
}
|
||||
|
||||
qsort(breakpoints, num_breakpoints, sizeof(word32), addr_cmp);
|
||||
fixup_brks();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1148,6 +1323,23 @@ command:
|
|||
return 1;
|
||||
}
|
||||
|
||||
"n" eol {
|
||||
/* next. steps OVER jsr/jsl */
|
||||
|
||||
if (has_addr) {
|
||||
engine.kpc = addr;
|
||||
}
|
||||
int tmp = next_pc();
|
||||
if (tmp < 0) {
|
||||
g_stepping = 1;
|
||||
} else {
|
||||
g_stepping = 0;
|
||||
set_bp('T', tmp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
";bp" [+-]? eol {
|
||||
char plus = cp[3];
|
||||
if (!has_addr && plus == 0) { show_bp('B'); return 0; }
|
||||
|
@ -1211,8 +1403,12 @@ int debug_shell(int code) {
|
|||
|
||||
/* todo -- only clear IF exit pc == entry pc ? */
|
||||
if (code == RET_BP) {
|
||||
engine.flags |= FLAG_IGNORE_BP;
|
||||
printf("Breakpoint hit:\n");
|
||||
|
||||
/* check for temp. breakpoint */
|
||||
if (!delete_bp('T', engine.kpc)) {
|
||||
engine.flags |= FLAG_IGNORE_BP;
|
||||
printf("Breakpoint hit:\n");
|
||||
}
|
||||
}
|
||||
if (code == RET_MP) {
|
||||
engine.flags |= FLAG_IGNORE_MP;
|
||||
|
|
|
@ -400,8 +400,8 @@ extern word32 slow_mem_changed[];
|
|||
extern int g_num_bp_breakpoints;
|
||||
extern word32 g_bp_breakpoints[];
|
||||
|
||||
extern int g_num_tmp_bp_breakpoints;
|
||||
extern word32 g_tmp_bp_breakpoints[];
|
||||
extern int g_num_tp_breakpoints;
|
||||
extern word32 g_tp_breakpoints[];
|
||||
|
||||
extern int g_num_mp_breakpoints;
|
||||
extern word32 g_mp_breakpoints[];
|
||||
|
@ -412,13 +412,15 @@ extern word32 g_abort_bytes;
|
|||
|
||||
int check_bp_breakpoints(word32 addr) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < g_num_bp_breakpoints; ++i) {
|
||||
if (g_bp_breakpoints[i] == addr) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < g_num_tmp_bp_breakpoints; ++i) {
|
||||
if (g_tmp_bp_breakpoints[i] == addr) {
|
||||
/* temp breakpoints */
|
||||
for (i = 0; i < g_num_tp_breakpoints; ++i) {
|
||||
if (g_tp_breakpoints[i] == addr) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -1043,7 +1045,7 @@ int enter_engine(Engine_reg *engine_ptr) {
|
|||
word32 saved_psr = 0;
|
||||
|
||||
word32 abort_support = g_num_mp_breakpoints ? 1 : 0;
|
||||
word32 kpc_support = g_num_bp_breakpoints + g_num_tmp_bp_breakpoints ? 1 : 0;
|
||||
word32 kpc_support = g_num_bp_breakpoints + g_num_tp_breakpoints ? 1 : 0;
|
||||
|
||||
flags = engine_ptr->flags;
|
||||
if (flags & FLAG_IGNORE_MP) abort_support = 0;
|
||||
|
|
|
@ -172,9 +172,9 @@ void do_debug_intfc(void);
|
|||
word32 dis_get_memory_ptr(word32 addr);
|
||||
void show_one_toolset(FILE *toolfile, int toolnum, word32 addr);
|
||||
void show_toolset_tables(word32 a2bank, word32 addr);
|
||||
void set_bp(int type, word32 addr);
|
||||
int set_bp(int type, word32 addr);
|
||||
void show_bp(int type);
|
||||
void delete_bp(int type, word32 addr);
|
||||
int delete_bp(int type, word32 addr);
|
||||
void do_blank(void);
|
||||
void do_go(void);
|
||||
void do_go_debug(void); // socket debug ver
|
||||
|
|
Loading…
Reference in New Issue
Block a user