mirror of
https://github.com/rkujawa/rk65c02.git
synced 2024-06-01 05:41:27 +00:00
Introduce trace functionality.
This commit is contained in:
parent
b32be45d10
commit
0b83a263d7
52
src/debug.c
52
src/debug.c
|
@ -3,8 +3,60 @@
|
||||||
#include <utlist.h>
|
#include <utlist.h>
|
||||||
|
|
||||||
#include "rk65c02.h"
|
#include "rk65c02.h"
|
||||||
|
#include "instruction.h"
|
||||||
#include "debug.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
|
bool
|
||||||
debug_breakpoint_remove(rk65c02emu_t *e, uint16_t address)
|
debug_breakpoint_remove(rk65c02emu_t *e, uint16_t address)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,10 +5,15 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "rk65c02.h"
|
#include "rk65c02.h"
|
||||||
|
#include "instruction.h"
|
||||||
|
|
||||||
bool debug_PC_is_breakpoint(rk65c02emu_t *);
|
bool debug_PC_is_breakpoint(rk65c02emu_t *);
|
||||||
bool debug_breakpoint_add(rk65c02emu_t *, uint16_t);
|
bool debug_breakpoint_add(rk65c02emu_t *, uint16_t);
|
||||||
bool debug_breakpoint_remove(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_ */
|
#endif /* _DEBUG_H_ */
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ rk65c02_init(bus_t *b)
|
||||||
e.irq = false;
|
e.irq = false;
|
||||||
|
|
||||||
e.bps_head = NULL;
|
e.bps_head = NULL;
|
||||||
|
e.trace_head = NULL;
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -88,6 +89,9 @@ rk65c02_exec(rk65c02emu_t *e)
|
||||||
{
|
{
|
||||||
instruction_t i;
|
instruction_t i;
|
||||||
instrdef_t id;
|
instrdef_t id;
|
||||||
|
uint16_t tpc; /* saved PC for tracing */
|
||||||
|
|
||||||
|
tpc = e->regs.PC;
|
||||||
|
|
||||||
if (e->irq && (!(e->regs.P & P_IRQ_DISABLE)))
|
if (e->irq && (!(e->regs.P & P_IRQ_DISABLE)))
|
||||||
rk65c02_irq(e);
|
rk65c02_irq(e);
|
||||||
|
@ -107,6 +111,7 @@ rk65c02_exec(rk65c02emu_t *e)
|
||||||
|
|
||||||
if (id.emul != NULL) {
|
if (id.emul != NULL) {
|
||||||
id.emul(e, &id, &i);
|
id.emul(e, &id, &i);
|
||||||
|
|
||||||
if (!instruction_modify_pc(&id))
|
if (!instruction_modify_pc(&id))
|
||||||
program_counter_increment(e, &id);
|
program_counter_increment(e, &id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,6 +120,10 @@ rk65c02_exec(rk65c02emu_t *e)
|
||||||
e->state = STOPPED;
|
e->state = STOPPED;
|
||||||
e->stopreason = EMUERROR;
|
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
|
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: ",
|
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");
|
printf("N");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_SIGN_OVERFLOW)
|
if (regs.P & P_SIGN_OVERFLOW)
|
||||||
printf("V");
|
printf("V");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_UNDEFINED)
|
if (regs.P & P_UNDEFINED)
|
||||||
printf("1");
|
printf("1");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_BREAK)
|
if (regs.P & P_BREAK)
|
||||||
printf("B");
|
printf("B");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_DECIMAL)
|
if (regs.P & P_DECIMAL)
|
||||||
printf("D");
|
printf("D");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_IRQ_DISABLE)
|
if (regs.P & P_IRQ_DISABLE)
|
||||||
printf("I");
|
printf("I");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_ZERO)
|
if (regs.P & P_ZERO)
|
||||||
printf("Z");
|
printf("Z");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
||||||
if (e->regs.P & P_CARRY)
|
if (regs.P & P_CARRY)
|
||||||
printf("C");
|
printf("C");
|
||||||
else
|
else
|
||||||
printf("-");
|
printf("-");
|
||||||
|
|
|
@ -54,14 +54,24 @@ typedef struct breakpoint_t {
|
||||||
struct breakpoint_t *next;
|
struct breakpoint_t *next;
|
||||||
} breakpoint_t;
|
} 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 {
|
struct rk65c02emu {
|
||||||
emu_state_t state;
|
emu_state_t state;
|
||||||
bus_t *bus;
|
bus_t *bus;
|
||||||
reg_state_t regs;
|
reg_state_t regs;
|
||||||
emu_stop_reason_t stopreason;
|
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 */
|
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;
|
typedef struct rk65c02emu rk65c02emu_t;
|
||||||
|
@ -69,7 +79,7 @@ typedef struct rk65c02emu rk65c02emu_t;
|
||||||
rk65c02emu_t rk65c02_init(bus_t *);
|
rk65c02emu_t rk65c02_init(bus_t *);
|
||||||
void rk65c02_start(rk65c02emu_t *);
|
void rk65c02_start(rk65c02emu_t *);
|
||||||
void rk65c02_step(rk65c02emu_t *, uint16_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_dump_stack(rk65c02emu_t *, uint8_t);
|
||||||
void rk65c02_irq(rk65c02emu_t *e);
|
void rk65c02_irq(rk65c02emu_t *e);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user