1 #ifdef DEBUG_SUPPORT
2 
3 #ifndef DEBUG_H
4 #define DEBUG_H
5 
6 #include "../atomics.h"
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 #include "../defines.h"
13 #include <stdint.h>
14 #include <stdbool.h>
15 
16 #define VERSION_DBG 0x0004
17 
18 /* main user interface */
19 /* please read the comments */
20 
21 /* reason for debug trigger */
22 enum {
23     DBG_USER,              /* request to open the debugger externally */
24     DBG_READY,             /* if reset, debugger ready for new commands */
25     DBG_FROZEN,            /* di \ halt */
26     DBG_BREAKPOINT,        /* hit a breakpoint */
27     DBG_WATCHPOINT_READ,   /* hit a read watchpoint */
28     DBG_WATCHPOINT_WRITE,  /* hit a write watchpoint */
29     DBG_PORT_READ,         /* read a monitored port */
30     DBG_PORT_WRITE,        /* wrote a monitored port */
31     DBG_NMI_TRIGGERED,     /* triggered a non maskable interrupt */
32     DBG_WATCHDOG_TIMEOUT,  /* watchdog timer reset */
33     DBG_MISC_RESET,        /* miscellaneous reset */
34     DBG_STEP,              /* step command executed */
35     DBG_NUMBER
36 };
37 
38 /* available software commands */
39 enum {
40     CMD_NONE,
41     CMD_ABORT,             /* abort() routine hit */
42     CMD_DEBUG,             /* debugger() routine hit */
43     CMD_SET_BREAKPOINT,    /* enable breakpoint: DE=address */
44     CMD_REM_BREAKPOINT,    /* remove breakpoint: DE=address */
45     CMD_SET_R_WATCHPOINT,  /* set read watchpoint: DE=address | C=length */
46     CMD_SET_W_WATCHPOINT,  /* set write watchpoint: DE=address | C=length */
47     CMD_SET_RW_WATCHPOINT, /* set read/write watchpoint: DE=address | C=length */
48     CMD_REM_WATCHPOINT,    /* remove watchpoint: DE=address */
49     CMD_REM_ALL_BREAK,     /* remove all breakpoints */
50     CMD_REM_ALL_WATCH,     /* remove all watchpoints */
51     CMD_SET_E_WATCHPOINT,  /* set empty watchpoint: DE=address | C=length */
52     CMD_NUMBER
53 };
54 
55 /* interface functions */
56 void debug_init(void);                               /* call before starting emulation */
57 void debug_free(void);                               /* call after emulation end */
58 void debug_set_pc(uint32_t addr);                    /* when in gui debug set program counter */
59 void debug_inst_start(void);
60 void debug_inst_fetch(void);
61 void debug_inst_repeat(void);
62 void debug_record_call(uint32_t retAddr, bool stack);
63 void debug_record_ret(uint32_t retAddr, bool stack);
64 void debug_watch(uint32_t addr, int mask, bool set); /* set a breakpoint or a watchpoint */
65 void debug_ports(uint16_t addr, int mask, bool set); /* set port monitor flags */
66 void debug_flag(int mask, bool set);                 /* configure setup of debug core */
67 void debug_step(int mode, uint32_t addr);            /* set a step mode, addr points to the instruction after pc */
68 void debug_open(int reason, uint32_t data);          /* open the debugger (Should only be called from gui_do_stuff) */
69 bool debug_is_open(void);                            /* returns the status of the core debugger */
70 
71 /* masks */
72 #define DBG_MASK_NONE         (0 << 0)
73 #define DBG_IGNORE            (1 << 0)   /* ignore any breakpoints, watchpoints, or similar */
74 #define DBG_SOFT_COMMANDS     (1 << 1)   /* allow software commands from executing code */
75 #define DBG_OPEN_ON_RESET     (1 << 2)   /* open the debugger when a reset is triggered */
76 
77 /* port monitoring */
78 #define DBG_MASK_PORT_READ    (1 << 0)   /* port monitor reads */
79 #define DBG_MASK_PORT_WRITE   (1 << 1)   /* port monitor writes */
80 #define DBG_MASK_PORT_FREEZE  (1 << 2)   /* port freeze value */
81 
82 /* breakpoints / watchpoints */
83 #define DBG_MASK_READ         (1 << 0)   /* read watchpoint */
84 #define DBG_MASK_WRITE        (1 << 1)   /* write watchpoint */
85 #define DBG_MASK_EXEC         (1 << 2)   /* breakpoint */
86 #define DBG_MASK_RW           ((DBG_MASK_READ) | (DBG_MASK_WRITE))
87 
88 
89 /* internal items below this line */
90 #define DBG_INST_START_MARKER (1 << 3)
91 #define DBG_INST_MARKER       (1 << 4)
92 
93 #define DBG_PORT_RANGE        0xFFFF00
94 #define DBGOUT_PORT_RANGE     0xFB0000
95 #define DBGERR_PORT_RANGE     0xFC0000
96 #define DBGEXT_PORT           0xFD0000
97 #define DBG_STACK_SIZE        0x100
98 #define DBG_STACK_MASK        (DBG_STACK_SIZE-1)
99 #define DBG_ADDR_SIZE         0x1000000
100 #define DBG_PORT_SIZE         0x10000
101 #define SIZEOF_DBG_BUFFER     0x1000
102 
103 typedef struct {
104     bool mode : 1;
105     bool popped : 1;
106     uint32_t stack : 24;
107     uint32_t retAddr : 24;
108     uint8_t range : 8;
109 } debug_stack_entry_t;
110 
111 typedef struct {
112     uint32_t cpuNext;
113     uint32_t cpuCycles;
114     uint64_t cpuBaseCycles;
115     uint64_t cpuHaltCycles;
116     int64_t totalCycles, dmaCycles;
117     bool step, stepOver;
118     uint32_t tempExec, stepOut;
119 
120     uint32_t stackIndex, stackSize;
121     debug_stack_entry_t *stack;
122 
123     char buffer[SIZEOF_DBG_BUFFER];
124     char bufferErr[SIZEOF_DBG_BUFFER];
125     uint32_t bufErrPos;
126     uint32_t bufPos;
127 
128     uint8_t *addr;
129     uint8_t *port;
130     _Atomic(int) flags;
131     _Atomic(bool) open;
132     _Atomic(bool) ignore;
133     _Atomic(bool) commands;
134     _Atomic(bool) openOnReset;
135 } debug_state_t;
136 
137 extern debug_state_t debug;
138 
139 enum {
140     DBG_STEP_IN=DBG_STEP+1,
141     DBG_STEP_OUT,
142     DBG_STEP_OVER,
143     DBG_STEP_NEXT,
144     DBG_RUN_UNTIL
145 };
146 
147 /* internal core functions */
148 void debug_step_switch(void);
149 void debug_clear_step(void);
150 
151 #ifdef __cplusplus
152 }
153 #endif
154 
155 #endif
156 
157 #endif
158