diff --git a/src/Makefile b/src/Makefile index 0dadc7b..1983576 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ CLI=rk65c02cli CLI_OBJS=rk65c02cli.o -LIB_OBJS=rk65c02.o bus.o instruction.o emulation.o +LIB_OBJS=rk65c02.o bus.o instruction.o emulation.o debug.o LIB_SO=librk65c02.so LIB_STATIC=librk65c02.a @@ -11,6 +11,7 @@ CFLAGS=-Wall -fpic -ggdb 65C02ISA=65c02isa EMULATION=emulation +# TODO: better include handling all : $(LIB_SO) $(LIB_STATIC) $(CLI) diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..9268ff6 --- /dev/null +++ b/src/debug.c @@ -0,0 +1,54 @@ +#include +#include +#include + +#include "rk65c02.h" +#include "debug.h" + +bool +debug_breakpoint_remove(rk65c02emu_t *e, uint16_t address) +{ + breakpoint_t *bp, *tmp; + + if (e->bps_head == NULL) + return false; + + LL_FOREACH_SAFE(e->bps_head, bp, tmp) { + if (bp->address == address) { + LL_DELETE(e->bps_head, bp); + return true; + } + } + + return false; +} + +bool +debug_breakpoint_add(rk65c02emu_t *e, uint16_t address) +{ + breakpoint_t *bp; + + bp = (breakpoint_t *) malloc(sizeof(breakpoint_t)); + bp->address = address; + + LL_APPEND((e->bps_head), bp); + + return true; +} + +bool +debug_PC_is_breakpoint(rk65c02emu_t *e) +{ + breakpoint_t *bp; + + if (e->bps_head == NULL) + return false; + + LL_FOREACH(e->bps_head, bp) { + if (bp->address == e->regs.PC) + return true; + } + + + return false; +} diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..4a370db --- /dev/null +++ b/src/debug.h @@ -0,0 +1,12 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include +#include + +#include "rk65c02.h" + +bool debug_PC_is_breakpoint(rk65c02emu_t *); +bool debug_breakpoint_add(rk65c02emu_t *, uint16_t); +#endif /* _DEBUG_H_ */ + diff --git a/src/rk65c02.c b/src/rk65c02.c index 0226fdc..965011d 100644 --- a/src/rk65c02.c +++ b/src/rk65c02.c @@ -9,6 +9,7 @@ #include "bus.h" #include "instruction.h" #include "rk65c02.h" +#include "debug.h" void rk65c02_exec(rk65c02emu_t *); @@ -29,6 +30,8 @@ rk65c02_init(bus_t *b) e.irq = false; + e.bps_head = NULL; + return e; } @@ -89,7 +92,11 @@ rk65c02_exec(rk65c02emu_t *e) if (e->irq && (!(e->regs.P & P_IRQ_DISABLE))) rk65c02_irq(e); - /* XXX: handle breakpoints and watch points */ + /* XXX: handle watchpoints toos */ + if (debug_PC_is_breakpoint(e)) { + e->state = STOPPED; + e->stopreason = BREAKPOINT; + } /* if disassembly-when-running enabled */ disassemble(e->bus, e->regs.PC); diff --git a/src/rk65c02.h b/src/rk65c02.h index 4f9c52f..497ece4 100644 --- a/src/rk65c02.h +++ b/src/rk65c02.h @@ -29,6 +29,8 @@ struct reg_state { uint8_t P; /* status */ }; +typedef struct reg_state reg_state_t; + #define P_CARRY 0x1 #define P_ZERO 0x2 #define P_IRQ_DISABLE 0x4 @@ -47,7 +49,10 @@ struct reg_state { #define BIT(val,n) ((val) & (1 << (n))) -typedef struct reg_state reg_state_t; +typedef struct breakpoint_t { + uint16_t address; + struct breakpoint_t *next; +} breakpoint_t; struct rk65c02emu { emu_state_t state; @@ -55,6 +60,8 @@ struct rk65c02emu { reg_state_t regs; emu_stop_reason_t stopreason; bool irq; /* interrupt request line state, true is asserted */ + + breakpoint_t *bps_head; /* pointer to linked list with breakpoints */ }; typedef struct rk65c02emu rk65c02emu_t;