diff --git a/src/debug.c b/src/debug.c index 38f0b1f..90cdfdc 100644 --- a/src/debug.c +++ b/src/debug.c @@ -3,8 +3,60 @@ #include #include "rk65c02.h" +#include "instruction.h" #include "debug.h" +void +debug_trace_set(rk65c02emu_t *e, bool state) +{ + e->trace = state; +} + +void +debug_trace_print_all(rk65c02emu_t *e) +{ + trace_t *tr; + instruction_t i; + + if (e->trace_head == NULL) + return; + + DL_FOREACH(e->trace_head, tr) { + i.opcode = tr->opcode; + i.op1 = tr->op1; + i.op2 = tr->op2; + + printf("TRACE %X:\t", tr->address); + instruction_print(&i); + printf("\t"); + rk65c02_dump_regs(tr->regs); + } + +} + +void +debug_trace_savestate(rk65c02emu_t *e, uint16_t address, instrdef_t *id, + instruction_t *i) +{ + trace_t *tr; + + tr = (trace_t *) malloc(sizeof(trace_t)); + if (tr == NULL) { + fprintf(stderr, "Error allocating trace structure.\n"); + return; + } + + tr->address = address; + + tr->opcode = i->opcode; + tr->op1 = i->op1; + tr->op2 = i->op2; + + tr->regs = e->regs; + + DL_APPEND((e->trace_head), tr); +} + bool debug_breakpoint_remove(rk65c02emu_t *e, uint16_t address) { diff --git a/src/debug.h b/src/debug.h index ec6346d..3a0b51f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -5,10 +5,15 @@ #include #include "rk65c02.h" +#include "instruction.h" bool debug_PC_is_breakpoint(rk65c02emu_t *); bool debug_breakpoint_add(rk65c02emu_t *, uint16_t); bool debug_breakpoint_remove(rk65c02emu_t *, uint16_t); +void debug_trace_set(rk65c02emu_t *, bool); +void debug_trace_savestate(rk65c02emu_t *, uint16_t, instrdef_t *, instruction_t *); +void debug_trace_print_all(rk65c02emu_t *); + #endif /* _DEBUG_H_ */ diff --git a/src/rk65c02.c b/src/rk65c02.c index 2529c78..4960e43 100644 --- a/src/rk65c02.c +++ b/src/rk65c02.c @@ -31,6 +31,7 @@ rk65c02_init(bus_t *b) e.irq = false; e.bps_head = NULL; + e.trace_head = NULL; return e; } @@ -88,6 +89,9 @@ rk65c02_exec(rk65c02emu_t *e) { instruction_t i; instrdef_t id; + uint16_t tpc; /* saved PC for tracing */ + + tpc = e->regs.PC; if (e->irq && (!(e->regs.P & P_IRQ_DISABLE))) rk65c02_irq(e); @@ -107,6 +111,7 @@ rk65c02_exec(rk65c02emu_t *e) if (id.emul != NULL) { id.emul(e, &id, &i); + if (!instruction_modify_pc(&id)) program_counter_increment(e, &id); } else { @@ -115,6 +120,10 @@ rk65c02_exec(rk65c02emu_t *e) e->state = STOPPED; e->stopreason = EMUERROR; } + + if (e->trace) + debug_trace_savestate(e, tpc, &id, &i); + } /* @@ -173,47 +182,47 @@ rk65c02_dump_stack(rk65c02emu_t *e, uint8_t n) } void -rk65c02_dump_regs(rk65c02emu_t *e) +rk65c02_dump_regs(reg_state_t regs) { printf("A: %X X: %X Y: %X PC: %X SP: %X P: ", - e->regs.A, e->regs.X, e->regs.Y, e->regs.PC, e->regs.SP); + regs.A, regs.X, regs.Y, regs.PC, regs.SP); - if (e->regs.P & P_NEGATIVE) + if (regs.P & P_NEGATIVE) printf("N"); else printf("-"); - if (e->regs.P & P_SIGN_OVERFLOW) + if (regs.P & P_SIGN_OVERFLOW) printf("V"); else printf("-"); - if (e->regs.P & P_UNDEFINED) + if (regs.P & P_UNDEFINED) printf("1"); else printf("-"); - if (e->regs.P & P_BREAK) + if (regs.P & P_BREAK) printf("B"); else printf("-"); - if (e->regs.P & P_DECIMAL) + if (regs.P & P_DECIMAL) printf("D"); else printf("-"); - if (e->regs.P & P_IRQ_DISABLE) + if (regs.P & P_IRQ_DISABLE) printf("I"); else printf("-"); - if (e->regs.P & P_ZERO) + if (regs.P & P_ZERO) printf("Z"); else printf("-"); - if (e->regs.P & P_CARRY) + if (regs.P & P_CARRY) printf("C"); else printf("-"); diff --git a/src/rk65c02.h b/src/rk65c02.h index 497ece4..d5b4479 100644 --- a/src/rk65c02.h +++ b/src/rk65c02.h @@ -54,14 +54,24 @@ typedef struct breakpoint_t { struct breakpoint_t *next; } breakpoint_t; +typedef struct trace_t { + uint16_t address; + uint8_t opcode, op1, op2; + reg_state_t regs; + struct trace_t *prev,*next; +} trace_t; + struct rk65c02emu { emu_state_t state; bus_t *bus; reg_state_t regs; emu_stop_reason_t stopreason; - bool irq; /* interrupt request line state, true is asserted */ + bool irq; /* interrupt request line state, true is asserted */ breakpoint_t *bps_head; /* pointer to linked list with breakpoints */ + + bool trace; /* tracing mode enable/disable */ + trace_t *trace_head; /* pointer to linked list with trace log */ }; typedef struct rk65c02emu rk65c02emu_t; @@ -69,7 +79,7 @@ typedef struct rk65c02emu rk65c02emu_t; rk65c02emu_t rk65c02_init(bus_t *); void rk65c02_start(rk65c02emu_t *); void rk65c02_step(rk65c02emu_t *, uint16_t); -void rk65c02_dump_regs(rk65c02emu_t *); +void rk65c02_dump_regs(reg_state_t regs); void rk65c02_dump_stack(rk65c02emu_t *, uint8_t); void rk65c02_irq(rk65c02emu_t *e);