From 29ce85b87cf5d8e72cdeff4fd0b002ae1d7642a2 Mon Sep 17 00:00:00 2001 From: Max Regan Date: Mon, 19 Feb 2018 05:13:40 +0000 Subject: [PATCH] gbdb: optimize breakpoints and add runto --- src/apps/gbdb.c | 150 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 116 insertions(+), 34 deletions(-) diff --git a/src/apps/gbdb.c b/src/apps/gbdb.c index 2d4be99..26fc7b1 100644 --- a/src/apps/gbdb.c +++ b/src/apps/gbdb.c @@ -19,13 +19,14 @@ #include "common/tri.h" #define INPUT_MAX_LEN 512 -#define MAX_BREAKPTS 4 /* Should be plenty for anyone */ +#define MAX_BREAKPTS 2 /* Should be plenty for anyone */ #define MAX_RAM_LEN (1 << 20) /* Up to 8Mb Cartridge */ #define UNMAP_BOOTROM_ADDR 0xff50 typedef void (gbdb_cmd)(char *arg_string); static bool cpu_at_breakpoint(void); +static void breakpoint_addr_hit(uint16_t id); static uint8_t ram[MAX_RAM_LEN]; static const char prompt[] = "gbdb >"; @@ -208,6 +209,7 @@ static void step(char *arg_list) if (init_steps + steps <= cpu.metrics.retired_instrs) { gb_log("CPU stopped after %" PRId64 " instructions\n", steps); } else if (cpu_at_breakpoint()) { + breakpoint_addr_hit(cpu.pc); gb_log("Breakpoint hit\n"); } else if (cpu.halted) { gb_log("CPU halted\n"); @@ -438,8 +440,7 @@ static void quit(char *arg_list) exit(0); } -static void run(char *arg_list) -{ +static void do_run(void) { paused = 0; signal(SIGINT, break_execution_handler); while(!cpu.halted && !cpu_at_breakpoint() && !paused) { @@ -451,43 +452,129 @@ static void run(char *arg_list) } else if (paused) { gb_log("Interrupted.\n"); } else { - gb_log("Breakpoint hit\n"); + breakpoint_addr_hit(cpu.pc); + gb_log("Breakpoint hit\n"); } } -static struct { - uint16_t addr; - bool active; +static void run(char *arg_list) +{ + do_run(); +} + +static struct breakpoint { + uint16_t addr; + int id; + bool temp; } breakpoints[MAX_BREAKPTS]; +static int num_breakpoints = 0; + +static struct breakpoint *get_breakpoint(int id) +{ + int i; + + for (i = 0; i < num_breakpoints; i++) { + if (breakpoints[i].id == id) { + return &breakpoints[i]; + } + } + + return NULL; +} + +static int do_set_breakpoint(uint16_t addr, bool temp) +{ + static int id = 0; + if (num_breakpoints < ARRAY_SIZE(breakpoints)) { + breakpoints[num_breakpoints].addr = addr; + breakpoints[num_breakpoints].id = id++; + breakpoints[num_breakpoints].temp = temp; + num_breakpoints++; + } else { + printf("maximum number of breakpoints reached\n"); + } +} + static void set_breakpoint(char *arg_string) { uint16_t addr, i; char *token = strtok(arg_string, " "); - + if (token == NULL) { printf("usage: breakpoint add \n"); return; } addr = parse_val(token); + do_set_breakpoint(addr, false); +} - for (i = 0; i < ARRAY_SIZE(breakpoints); i++) { - if (breakpoints[i].active == false) { - breakpoints[i].addr = addr; - breakpoints[i].active = true; - return; - } +static void runto(char *arg_string) +{ + uint16_t addr, i, rc; + char *token = strtok(arg_string, " "); + + if (token == NULL) { + printf("usage: runto \n"); + return; } - printf("maximum number of breakpoints reached\n"); + addr = parse_val(token); + rc = do_set_breakpoint(addr, true); + if (rc < 0) { + printf("failed to set breakpoint\n"); + return; + } + + do_run(); +} + +static int do_delete_breakpoint(int id) +{ + struct breakpoint *bkpt = get_breakpoint(id); + int index; + + if (bkpt == NULL) { + return -1; + } + + index = bkpt - breakpoints; + memmove(&breakpoints[index], &breakpoints[index + 1], + num_breakpoints - index - 1); + num_breakpoints--; + + return 0; +} + +static void breakpoint_addr_hit(uint16_t addr) +{ + struct breakpoint *bkpt = NULL; + int i; + + for (i = 0; i < num_breakpoints; i++) { + if (breakpoints[i].addr == addr) { + bkpt= &breakpoints[i]; + break; + } + } + + + if (bkpt == NULL) { + printf("No breakpoint found at addr=%d\n", addr); + return; + } + + if (bkpt->temp) { + do_delete_breakpoint(bkpt->id); + } } static void delete_breakpoint(char *arg_string) { - int bkpt; char *token = strtok(arg_string, " "); - + int rc, bkpt; + if (token == NULL) { printf("usage: breakpoint rm \n"); return; @@ -495,27 +582,21 @@ static void delete_breakpoint(char *arg_string) bkpt = parse_val(token); - if (bkpt < 0 || bkpt >= ARRAY_SIZE(breakpoints) || !breakpoints[bkpt].active) { - printf("%d is not a valid breakpoint number\n", bkpt); - return; + rc = do_delete_breakpoint(bkpt); + if (rc < 0) { + printf("%d is not a valid breakpoint number\n", bkpt); } - - breakpoints[bkpt].active = false; } static void display_breakpoints(char *arg_string) { - bool found1 = false; int i; - for (i = 0; i < ARRAY_SIZE(breakpoints); i++) { - if (breakpoints[i].active) { - printf("#%d: 0x%04x\n", i, breakpoints[i].addr); - found1 = true; - } - } - - if(!found1) { + if (num_breakpoints) { + for (i = 0; i < num_breakpoints; i++) { + printf("#%d: 0x%04x\n", breakpoints[i].id, breakpoints[i].addr); + } + } else { printf("No breakpoints set\n"); } } @@ -565,8 +646,8 @@ static void breakpoint(char *arg_list) static bool breakpoint_is_at_addr(uint16_t addr) { int i; - for (i = 0; i < ARRAY_SIZE(breakpoints); i++) { - if (breakpoints[i].active && addr == breakpoints[i].addr) { + for (i = 0; i < num_breakpoints; i++) { + if (breakpoints[i].addr == addr) { return true; } } @@ -576,7 +657,7 @@ static bool breakpoint_is_at_addr(uint16_t addr) { static bool cpu_at_breakpoint(void) { - return breakpoint_is_at_addr(lr35902_get_reg_16(&cpu, LR35902_REG_PC)); + return breakpoint_is_at_addr(cpu.pc); } static void process_cmd(const char *cmd_str, struct tri *commands) @@ -689,6 +770,7 @@ int main(int argc, char **argv) tri_add_string(&commands, "help", help); tri_add_string(&commands, "?", help); tri_add_string(&commands, "breakpoint", breakpoint); + tri_add_string(&commands, "runto", runto); tri_add_string(&commands, "reset", init); tri_add_string(&commands, "assert", assert); tri_add_string(&commands, "set", set);