OSDN Git Service

002b80f4cb5f201f81b7d3fc7ebbc12ecf1e1191
[csp-qt/common_source_project-fm7.git] / source / src / vm / debugger.h
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2014.09.02-
6
7         [ debugger ]
8 */
9
10 #ifndef _DEBUGGER_H_
11 #define _DEBUGGER_H_
12
13 //#include "vm.h"
14 //#include "../emu.h"
15 #include "device.h"
16
17 //#ifdef USE_DEBUGGER
18
19 #define MAX_BREAK_POINTS        8
20 #define MAX_COMMAND_LENGTH      64
21 #define MAX_COMMAND_HISTORY     32
22 #define MAX_CPU_TRACE           1024
23
24 typedef struct {
25         struct {
26                 uint32_t addr, mask;
27                 int status;     // 0 = none, 1 = enabled, other = disabled
28         } table[MAX_BREAK_POINTS], stored[MAX_BREAK_POINTS];
29         bool hit;
30         uint32_t hit_addr;
31 } break_point_t;
32
33 class DEBUGGER : public DEVICE
34 {
35 private:
36         DEVICE *d_mem, *d_io;
37         
38         void check_mem_break_points(break_point_t *bp, uint32_t addr, int length)
39         {
40                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
41                         if(bp->table[i].status == 1) {
42                                 if(addr >= bp->table[i].addr && addr < bp->table[i].addr + length) {
43                                         bp->hit = now_suspended = true;
44                                         bp->hit_addr = bp->table[i].addr;
45                                         break;
46                                 }
47                         }
48                 }
49         }
50         void check_io_break_points(break_point_t *bp, uint32_t addr)
51         {
52                 for(int i = 0; i < MAX_BREAK_POINTS; i++) {
53                         if(bp->table[i].status == 1) {
54                                 if((addr & bp->table[i].mask) == (bp->table[i].addr & bp->table[i].mask)) {
55                                         bp->hit = now_suspended = true;
56                                         bp->hit_addr = addr;
57                                         break;
58                                 }
59                         }
60                 }
61         }
62 public:
63         DEBUGGER(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
64         {
65                 memset(&bp, 0, sizeof(bp));
66                 memset(&rbp, 0, sizeof(rbp));
67                 memset(&wbp, 0, sizeof(wbp));
68                 memset(&ibp, 0, sizeof(ibp));
69                 memset(&obp, 0, sizeof(obp));
70                 first_symbol = last_symbol = NULL;
71                 my_tcscpy_s(file_path, _MAX_PATH, _T("debug.bin"));
72                 now_debugging = now_going = now_suspended = now_waiting = false;
73                 memset(history, 0, sizeof(history));
74                 history_ptr = 0;
75                 memset(cpu_trace, 0xff, sizeof(cpu_trace));
76                 prev_cpu_trace = 0xffffffff;
77                 cpu_trace_ptr = 0;
78                 set_device_name(_T("Debugger"));
79         }
80         ~DEBUGGER() {}
81         
82         // common functions
83         void release()
84         {
85                 release_symbols();
86         }
87         void write_data8(uint32_t addr, uint32_t data)
88         {
89                 check_mem_break_points(&wbp, addr, 1);
90                 d_mem->write_data8(addr, data);
91         }
92         uint32_t read_data8(uint32_t addr)
93         {
94                 check_mem_break_points(&rbp, addr, 1);
95                 return d_mem->read_data8(addr);
96         }
97         void write_data16(uint32_t addr, uint32_t data)
98         {
99                 check_mem_break_points(&wbp, addr, 2);
100                 d_mem->write_data16(addr, data);
101         }
102         uint32_t read_data16(uint32_t addr)
103         {
104                 check_mem_break_points(&rbp, addr, 2);
105                 return d_mem->read_data16(addr);
106         }
107         void write_data32(uint32_t addr, uint32_t data)
108         {
109                 check_mem_break_points(&wbp, addr, 4);
110                 d_mem->write_data32(addr, data);
111         }
112         uint32_t read_data32(uint32_t addr)
113         {
114                 check_mem_break_points(&rbp, addr, 4);
115                 return d_mem->read_data32(addr);
116         }
117         void write_data8w(uint32_t addr, uint32_t data, int* wait)
118         {
119                 check_mem_break_points(&wbp, addr, 1);
120                 d_mem->write_data8w(addr, data, wait);
121         }
122         uint32_t read_data8w(uint32_t addr, int* wait)
123         {
124                 check_mem_break_points(&rbp, addr, 1);
125                 return d_mem->read_data8w(addr, wait);
126         }
127         void write_data16w(uint32_t addr, uint32_t data, int* wait)
128         {
129                 check_mem_break_points(&wbp, addr, 2);
130                 d_mem->write_data16w(addr, data, wait);
131         }
132         uint32_t read_data16w(uint32_t addr, int* wait)
133         {
134                 check_mem_break_points(&rbp, addr, 2);
135                 return d_mem->read_data16w(addr, wait);
136         }
137         void write_data32w(uint32_t addr, uint32_t data, int* wait)
138         {
139                 check_mem_break_points(&wbp, addr, 4);
140                 d_mem->write_data32w(addr, data, wait);
141         }
142         uint32_t read_data32w(uint32_t addr, int* wait)
143         {
144                 check_mem_break_points(&rbp, addr, 4);
145                 return d_mem->read_data32w(addr, wait);
146         }
147         uint32_t fetch_op(uint32_t addr, int *wait)
148         {
149                 check_mem_break_points(&rbp, addr, 1);
150                 return d_mem->fetch_op(addr, wait);
151         }
152         void write_io8(uint32_t addr, uint32_t data)
153         {
154                 check_io_break_points(&obp, addr);
155                 d_io->write_io8(addr, data);
156         }
157         uint32_t read_io8(uint32_t addr)
158         {
159                 check_io_break_points(&ibp, addr);
160                 return d_io->read_io8(addr);
161         }
162         void write_io16(uint32_t addr, uint32_t data)
163         {
164                 check_io_break_points(&obp, addr);
165                 d_io->write_io16(addr, data);
166         }
167         uint32_t read_io16(uint32_t addr)
168         {
169                 check_io_break_points(&ibp, addr);
170                 return d_io->read_io16(addr);
171         }
172         void write_io32(uint32_t addr, uint32_t data)
173         {
174                 check_io_break_points(&obp, addr);
175                 d_io->write_io32(addr, data);
176         }
177         uint32_t read_io32(uint32_t addr)
178         {
179                 check_io_break_points(&ibp, addr);
180                 return d_io->read_io32(addr);
181         }
182         void write_io8w(uint32_t addr, uint32_t data, int* wait)
183         {
184                 check_io_break_points(&obp, addr);
185                 d_io->write_io8w(addr, data, wait);
186         }
187         uint32_t read_io8w(uint32_t addr, int* wait)
188         {
189                 check_io_break_points(&ibp, addr);
190                 return d_io->read_io8w(addr, wait);
191         }
192         void write_io16w(uint32_t addr, uint32_t data, int* wait)
193         {
194                 check_io_break_points(&obp, addr);
195                 d_io->write_io16w(addr, data, wait);
196         }
197         uint32_t read_io16w(uint32_t addr, int* wait)
198         {
199                 check_io_break_points(&ibp, addr);
200                 return d_io->read_io16w(addr, wait);
201         }
202         void write_io32w(uint32_t addr, uint32_t data, int* wait)
203         {
204                 check_io_break_points(&obp, addr);
205                 d_io->write_io32w(addr, data, wait);
206         }
207         uint32_t read_io32w(uint32_t addr, int* wait)
208         {
209                 check_io_break_points(&ibp, addr);
210                 return d_io->read_io32w(addr, wait);
211         }
212
213         // unique functions
214         void set_context_mem(DEVICE* device)
215         {
216                 d_mem = device;
217         }
218         void set_context_io(DEVICE* device)
219         {
220                 d_io = device;
221         }
222         void check_break_points(uint32_t addr)
223         {
224                 check_mem_break_points(&bp, addr, 1);
225         }
226         void store_break_points()
227         {
228                 memcpy( bp.stored,  bp.table, sizeof( bp.table));
229                 memcpy(rbp.stored, rbp.table, sizeof(rbp.table));
230                 memcpy(wbp.stored, wbp.table, sizeof(wbp.table));
231                 memcpy(ibp.stored, ibp.table, sizeof(ibp.table));
232                 memcpy(obp.stored, obp.table, sizeof(obp.table));
233                 memset( bp.table, 0, sizeof( bp.table));
234                 memset(rbp.table, 0, sizeof(rbp.table));
235                 memset(wbp.table, 0, sizeof(wbp.table));
236                 memset(ibp.table, 0, sizeof(ibp.table));
237                 memset(obp.table, 0, sizeof(obp.table));
238         }
239         void restore_break_points()
240         {
241                 memcpy( bp.table,  bp.stored, sizeof( bp.table));
242                 memcpy(rbp.table, rbp.stored, sizeof(rbp.table));
243                 memcpy(wbp.table, wbp.stored, sizeof(wbp.table));
244                 memcpy(ibp.table, ibp.stored, sizeof(ibp.table));
245                 memcpy(obp.table, obp.stored, sizeof(obp.table));
246         }
247         bool hit()
248         {
249                 return (bp.hit || rbp.hit || wbp.hit || ibp.hit || obp.hit);
250         }
251         void add_symbol(uint32_t addr, const _TCHAR *name)
252         {
253                 symbol_t *symbol = (symbol_t *)calloc(sizeof(symbol_t), 1);
254                 symbol->addr = addr;
255                 symbol->name = (_TCHAR *)calloc(sizeof(_TCHAR), _tcslen(name) + 1);
256                 my_tcscpy_s(symbol->name, _tcslen(name) + 1, name);
257                 
258                 if(first_symbol == NULL) {
259                         first_symbol = symbol;
260                 } else {
261                         last_symbol->next_symbol = symbol;
262                 }
263                 last_symbol = symbol;
264         }
265         void release_symbols()
266         {
267                 for(symbol_t* symbol = first_symbol; symbol;) {
268                         symbol_t *next_symbol = symbol->next_symbol;
269                         if(symbol->name != NULL) {
270                                 free(symbol->name);
271                         }
272                         free(symbol);
273                         symbol = next_symbol;
274                 }
275                 first_symbol = last_symbol = NULL;
276         }
277         void add_cpu_trace(uint32_t pc)
278         {
279                 if(prev_cpu_trace != pc) {
280                         cpu_trace[cpu_trace_ptr++] = prev_cpu_trace = pc;
281                         cpu_trace_ptr &= (MAX_CPU_TRACE - 1);
282                 }
283         }
284         break_point_t bp, rbp, wbp, ibp, obp;
285         symbol_t *first_symbol, *last_symbol;
286         _TCHAR file_path[_MAX_PATH];
287         bool now_debugging, now_going, now_suspended, now_waiting;
288         _TCHAR history[MAX_COMMAND_HISTORY][MAX_COMMAND_LENGTH + 1];
289         int history_ptr;
290         uint32_t cpu_trace[MAX_CPU_TRACE], prev_cpu_trace;
291         int cpu_trace_ptr;
292 };
293
294 //#endif
295 #endif
296