1 /* Hey EMACS -*- linux-c -*- */
2 /* $Id: bkpts.c 2770 2008-03-16 17:42:13Z roms $ */
3
4 /* TiEmu - Tiemu Is an EMUlator
5 *
6 * Copyright (c) 2000-2001, Thomas Corvazier, Romain Lievin
7 * Copyright (c) 2001-2003, Romain Lievin
8 * Copyright (c) 2003, Julien Blache
9 * Copyright (c) 2004, Romain Li�vin
10 * Copyright (c) 2005, Romain Li�vin, Kevin Kofler
11 * Copyright (c) 2007, Romain Li�vin
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27
28 /*
29 Breakpoints management
30 Note: addresses are 24 bits but arguments are 32 bits. The MSB is used to store
31 extra informations and save speed for comparison.
32 Searching does not take into account the MSB (24 bits).
33 */
34
35 #include <assert.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <glib.h>
39
40 #include "intl.h"
41 #include "ti68k_int.h"
42 #include "ti68k_err.h"
43 #include "dbg_bkpts.h"
44 #include "handles.h"
45
46 /* Add */
47
ti68k_bkpt_add_address(uint32_t address)48 int ti68k_bkpt_add_address(uint32_t address)
49 {
50 bkpts.code = g_list_append(bkpts.code, GINT_TO_POINTER(address));
51 return g_list_length(bkpts.code) - 1;
52 }
53
ti68k_bkpt_add_access(uint32_t address,int mode)54 int ti68k_bkpt_add_access(uint32_t address, int mode)
55 {
56 if((mode & BK_READ) && (mode & BK_BYTE))
57 bkpts.mem_rb = g_list_append(bkpts.mem_rb, GINT_TO_POINTER(address));
58 else if((mode & BK_READ) && (mode & BK_WORD))
59 bkpts.mem_rw = g_list_append(bkpts.mem_rw, GINT_TO_POINTER(address));
60 else if((mode & BK_READ) && (mode & BK_LONG))
61 bkpts.mem_rl = g_list_append(bkpts.mem_rl, GINT_TO_POINTER(address));
62
63 if((mode & BK_WRITE) && (mode & BK_BYTE))
64 bkpts.mem_wb = g_list_append(bkpts.mem_wb, GINT_TO_POINTER(address));
65 else if((mode & BK_WRITE) && (mode & BK_WORD))
66 bkpts.mem_ww = g_list_append(bkpts.mem_ww, GINT_TO_POINTER(address));
67 else if((mode & BK_WRITE) && (mode & BK_LONG))
68 bkpts.mem_wl = g_list_append(bkpts.mem_wl, GINT_TO_POINTER(address));
69
70 return -1;
71 }
72
ti68k_bkpt_add_range(uint32_t addressMin,uint32_t addressMax,int mode)73 int ti68k_bkpt_add_range(uint32_t addressMin, uint32_t addressMax, int mode)
74 {
75 if(mode & BK_READ)
76 {
77 ADDR_RANGE *s = g_malloc(sizeof(ADDR_RANGE));
78
79 s->val1 = addressMin;
80 s->val2 = addressMax;
81
82 bkpts.mem_rng_r = g_list_append(bkpts.mem_rng_r, s);
83 //return g_list_length(bkpts.mem_rng_r) - 1;
84 }
85
86 if(mode & BK_WRITE)
87 {
88 ADDR_RANGE *s = g_malloc(sizeof(ADDR_RANGE));
89
90 s->val1 = addressMin;
91 s->val2 = addressMax;
92
93 bkpts.mem_rng_w = g_list_append(bkpts.mem_rng_w, s);
94 //return g_list_length(bkpts.mem_rng_w) - 1;
95 }
96
97 return g_list_length(bkpts.mem_rng_r) - 1;
98 }
99
ti68k_bkpt_add_exception(uint32_t number)100 int ti68k_bkpt_add_exception(uint32_t number)
101 {
102 bkpts.exception = g_list_append(bkpts.exception, GINT_TO_POINTER(number));
103 return g_list_length(bkpts.exception)-1;
104 }
105
ti68k_bkpt_add_pgmentry_offset(uint16_t handle,uint16_t offset)106 static int ti68k_bkpt_add_pgmentry_offset(uint16_t handle, uint16_t offset)
107 {
108 bkpts.pgmentry = g_list_append(bkpts.pgmentry, GINT_TO_POINTER(((uint32_t)handle << 16) + (uint32_t)offset));
109 return g_list_length(bkpts.pgmentry)-1;
110 }
111
compute_pgmentry_offset(uint16_t handle)112 static uint16_t compute_pgmentry_offset(uint16_t handle)
113 {
114 uint32_t ptr = heap_deref(handle);
115 uint16_t fsize = mem_rd_word(ptr);
116 unsigned char tag = mem_rd_byte(ptr + fsize + 1);
117 switch (tag)
118 {
119 case 0xF3: /* ASM_TAG: nostub or kernel program */
120 if (mem_rd_long(ptr+6) == 0x36386B50) /* kernel program */
121 return mem_rd_word(ptr+14) + 2; /* offset to _main */
122 else /* nostub program (or kernel library, but it makes no sense to
123 put a program entry breakpoint on a library) */
124 return 2;
125
126 case 0xDC: /* FUNC_TAG: Fargo or TI-BASIC program */
127 if (mem_rd_word(ptr+2) == 0x0032 && mem_rd_long(ptr+4) == 0x45584520
128 && mem_rd_long(ptr+8) == 0x4150504C) /* Fargo II program */
129 {
130 uint16_t export_table_offset = mem_rd_word(ptr+20);
131 return mem_rd_word(ptr+export_table_offset+2); /* offset to _main */
132 }
133 else if (mem_rd_long(ptr+2) == 0x00503130) /* Fargo I program */
134 return mem_rd_word(ptr+16) + 2; /* offset to _main */
135 else /* Fargo library or TI-BASIC, it makes no sense to put a
136 program entry breakpoint here... */
137 return 2;
138
139 default: /* unknown file, we should give some kind of error here... */
140 return 2;
141 }
142 }
143
ti68k_bkpt_add_pgmentry(uint16_t handle)144 int ti68k_bkpt_add_pgmentry(uint16_t handle)
145 {
146 return ti68k_bkpt_add_pgmentry_offset(handle, compute_pgmentry_offset(handle));
147 }
148
ti68k_bkpt_add_bits(uint32_t address,uint8_t checks,uint8_t states)149 int ti68k_bkpt_add_bits(uint32_t address, uint8_t checks, uint8_t states)
150 {
151 ADDR_BIT *s = g_malloc(sizeof(ADDR_BIT));
152
153 s->addr = address;
154 s->checks = checks;
155 s->states = states;
156 bkpts.bits = g_list_append(bkpts.bits, s);
157
158 return g_list_length(bkpts.bits) - 1;
159 }
160
161 /* Delete */
162
compare_func(gconstpointer a,gconstpointer b)163 static gint compare_func(gconstpointer a, gconstpointer b)
164 {
165 ADDR_RANGE *sa = (ADDR_RANGE *)a;
166 ADDR_RANGE *sb = (ADDR_RANGE *)b;
167
168 return !((BKPT_ADDR(sa->val1) == BKPT_ADDR(sb->val1)) &&
169 (BKPT_ADDR(sa->val2) == BKPT_ADDR(sb->val2)));
170 }
171
compare_func2(gconstpointer a,gconstpointer b)172 static gint compare_func2(gconstpointer a, gconstpointer b)
173 {
174 uint32_t aa = GPOINTER_TO_INT(a);
175 uint32_t bb = GPOINTER_TO_INT(b);
176
177 return !(BKPT_ADDR(aa) == BKPT_ADDR(bb));
178 }
179
compare_func3(gconstpointer a,gconstpointer b)180 static gint compare_func3(gconstpointer a, gconstpointer b)
181 {
182 uint32_t aa = GPOINTER_TO_INT(a);
183 uint32_t bb = GPOINTER_TO_INT(b);
184
185 return !(BKPT_ADDR(aa)>>16 == BKPT_ADDR(bb)>>16);
186 }
187
compare_func4(gconstpointer a,gconstpointer b)188 static gint compare_func4(gconstpointer a, gconstpointer b)
189 {
190 ADDR_BIT *sa = (ADDR_BIT *)a;
191 ADDR_BIT *sb = (ADDR_BIT *)b;
192
193 return !(BKPT_ADDR(sa->addr) == BKPT_ADDR(sb->addr));
194 }
195
ti68k_bkpt_del_address(uint32_t address)196 int ti68k_bkpt_del_address(uint32_t address)
197 {
198 GList *elt = g_list_find_custom(bkpts.code, GINT_TO_POINTER(address), compare_func2);
199
200 if(elt != NULL)
201 bkpts.code = g_list_delete_link(bkpts.code, elt);
202 else
203 return -1;
204
205 return 0;
206 }
207
ti68k_bkpt_del_access(uint32_t address,int mode)208 int ti68k_bkpt_del_access(uint32_t address, int mode)
209 {
210 if((mode & BK_READ) && (mode & BK_BYTE))
211 {
212 GList *elt = g_list_find_custom(bkpts.mem_rb, GINT_TO_POINTER(address), compare_func2);
213 if(elt != NULL)
214 bkpts.mem_rb = g_list_delete_link(bkpts.mem_rb, elt);
215 else
216 return -1;
217 }
218 if((mode & BK_READ) && (mode & BK_WORD))
219 {
220 GList *elt = g_list_find_custom(bkpts.mem_rw, GINT_TO_POINTER(address), compare_func2);
221 if(elt != NULL)
222 bkpts.mem_rw = g_list_delete_link(bkpts.mem_rw, elt);
223 else
224 return -1;
225 }
226 if((mode & BK_READ) && (mode & BK_LONG))
227 {
228 GList *elt = g_list_find_custom(bkpts.mem_rl, GINT_TO_POINTER(address), compare_func2);
229 if(elt != NULL)
230 bkpts.mem_rl = g_list_delete_link(bkpts.mem_rl, elt);
231 else
232 return -1;
233 }
234 if((mode & BK_WRITE) && (mode & BK_BYTE))
235 {
236 GList *elt = g_list_find_custom(bkpts.mem_wb, GINT_TO_POINTER(address), compare_func2);
237 if(elt != NULL)
238 bkpts.mem_wb = g_list_delete_link(bkpts.mem_wb, elt);
239 else
240 return -1;
241 }
242 if((mode & BK_WRITE) && (mode & BK_WORD))
243 {
244 GList *elt = g_list_find_custom(bkpts.mem_ww, GINT_TO_POINTER(address), compare_func2);
245 if(elt != NULL)
246 bkpts.mem_ww = g_list_delete_link(bkpts.mem_ww, elt);
247 else
248 return -1;
249 }
250 if((mode & BK_WRITE) && (mode & BK_LONG))
251 {
252 GList *elt = g_list_find_custom(bkpts.mem_wl, GINT_TO_POINTER(address), compare_func2);
253 if(elt != NULL)
254 bkpts.mem_wl = g_list_delete_link(bkpts.mem_wl, elt);
255 else
256 return -1;
257 }
258
259 return 0;
260 }
261
ti68k_bkpt_del_range(uint32_t min,uint32_t max,int mode)262 int ti68k_bkpt_del_range(uint32_t min, uint32_t max, int mode)
263 {
264 ADDR_RANGE s;
265 GList *elt = NULL;
266
267 s.val1 = min;
268 s.val2 = max;
269
270 if (mode & BK_READ)
271 {
272 elt = g_list_find_custom(bkpts.mem_rng_r, &s, compare_func);
273 if(elt != NULL)
274 bkpts.mem_rng_r = g_list_delete_link(bkpts.mem_rng_r, elt);
275 else
276 return -1;
277 }
278
279 if (mode & BK_WRITE)
280 {
281 elt = g_list_find_custom(bkpts.mem_rng_w, &s, compare_func);
282 if(elt != NULL)
283 bkpts.mem_rng_w = g_list_delete_link(bkpts.mem_rng_w, elt);
284 else
285 return -1;
286 }
287
288 return 0;
289 }
290
ti68k_bkpt_del_exception(uint32_t number)291 int ti68k_bkpt_del_exception(uint32_t number)
292 {
293 GList *elt = g_list_find_custom(bkpts.exception, GINT_TO_POINTER(number), compare_func2);
294 if(elt != NULL)
295 bkpts.exception = g_list_delete_link(bkpts.exception, elt);
296 else
297 return -1;
298
299 return 0;
300 }
301
ti68k_bkpt_del_pgmentry(uint16_t handle)302 int ti68k_bkpt_del_pgmentry(uint16_t handle)
303 {
304 GList *elt = g_list_find_custom(bkpts.pgmentry, GINT_TO_POINTER((uint32_t)handle << 16), compare_func3);
305 if(elt != NULL)
306 bkpts.pgmentry = g_list_delete_link(bkpts.pgmentry, elt);
307 else
308 return -1;
309
310 return 0;
311 }
312
ti68k_bkpt_del_bits(uint32_t address)313 int ti68k_bkpt_del_bits(uint32_t address)
314 {
315 ADDR_BIT s;
316 GList *elt = NULL;
317
318 s.addr = address;
319 elt = g_list_find_custom(bkpts.bits, &s, compare_func4);
320 if(elt != NULL)
321 bkpts.bits = g_list_delete_link(bkpts.bits, elt);
322 else
323 return -1;
324
325 return 0;
326 }
327
328 /* Set */
329
ti68k_bkpt_set_address(uint32_t address,uint32_t new_address)330 int ti68k_bkpt_set_address(uint32_t address, uint32_t new_address)
331 {
332 GList *elt = g_list_find_custom(bkpts.code, GINT_TO_POINTER(address), compare_func2);
333 if(elt != NULL)
334 elt->data = GINT_TO_POINTER(new_address);
335 else
336 return -1;
337
338 return 0;
339 }
340
ti68k_bkpt_set_access(uint32_t address,int mode,uint32_t new_address)341 int ti68k_bkpt_set_access(uint32_t address, int mode, uint32_t new_address)
342 {
343 if((mode & BK_READ) && (mode & BK_BYTE))
344 {
345 GList *elt = g_list_find_custom(bkpts.mem_rb, GINT_TO_POINTER(address), compare_func2);
346 if(elt != NULL)
347 elt->data = GINT_TO_POINTER(new_address);
348 else
349 return -1;
350 }
351 else if((mode & BK_READ) && (mode & BK_WORD))
352 {
353 GList *elt = g_list_find_custom(bkpts.mem_rw, GINT_TO_POINTER(address), compare_func2);
354 if(elt != NULL)
355 elt->data = GINT_TO_POINTER(new_address);
356 else
357 return -1;
358 }
359 else if((mode & BK_READ) && (mode & BK_LONG))
360 {
361 GList *elt = g_list_find_custom(bkpts.mem_rl, GINT_TO_POINTER(address), compare_func2);
362 if(elt != NULL)
363 elt->data = GINT_TO_POINTER(new_address);
364 else
365 return -1;
366 }
367
368 if((mode & BK_WRITE) && (mode & BK_BYTE))
369 {
370 GList *elt = g_list_find_custom(bkpts.mem_wb, GINT_TO_POINTER(address), compare_func2);
371 if(elt != NULL)
372 elt->data = GINT_TO_POINTER(new_address);
373 else
374 return -1;
375 }
376 else if((mode & BK_WRITE) && (mode & BK_WORD))
377 {
378 GList *elt = g_list_find_custom(bkpts.mem_ww, GINT_TO_POINTER(address), compare_func2);
379 if(elt != NULL)
380 elt->data = GINT_TO_POINTER(new_address);
381 else
382 return -1;
383 }
384 else if((mode & BK_WRITE) && (mode & BK_LONG))
385 {
386 GList *elt = g_list_find_custom(bkpts.mem_wl, GINT_TO_POINTER(address), compare_func2);
387 if(elt != NULL)
388 elt->data = GINT_TO_POINTER(new_address);
389 else
390 return -1;
391 }
392
393 return 0;
394 }
395
ti68k_bkpt_set_range(uint32_t min,uint32_t max,int mode,uint32_t new_min,uint32_t new_max)396 int ti68k_bkpt_set_range(uint32_t min, uint32_t max, int mode, uint32_t new_min, uint32_t new_max)
397 {
398 ADDR_RANGE s, *p;
399 GList *elt = NULL;
400
401 s.val1 = min;
402 s.val2 = max;
403
404 if (mode & BK_READ)
405 {
406 elt = g_list_find_custom(bkpts.mem_rng_r, &s, compare_func);
407 if(elt == NULL)
408 return -1;
409
410 p = elt->data;
411 p->val1 = new_min;
412 p->val2 = new_max;
413 }
414
415 if (mode & BK_WRITE)
416 {
417 elt = g_list_find_custom(bkpts.mem_rng_w, &s, compare_func);
418 if(elt == NULL)
419 return -1;
420
421 p = elt->data;
422 p->val1 = new_min;
423 p->val2 = new_max;
424 }
425
426 return 0;
427 }
428
ti68k_bkpt_set_exception(uint32_t number,uint32_t new_n)429 int ti68k_bkpt_set_exception(uint32_t number, uint32_t new_n)
430 {
431 GList *elt = g_list_find_custom(bkpts.exception, GINT_TO_POINTER(number), compare_func2);
432 if(elt != NULL)
433 elt->data = GINT_TO_POINTER(new_n);
434 else
435 return -1;
436
437 return 0;
438 }
439
ti68k_bkpt_set_pgmentry(uint16_t handle,uint16_t new_h)440 int ti68k_bkpt_set_pgmentry(uint16_t handle, uint16_t new_h)
441 {
442 GList *elt = g_list_find_custom(bkpts.pgmentry,
443 GINT_TO_POINTER((uint32_t)handle << 16),
444 compare_func2);
445 if(elt != NULL)
446 elt->data = GINT_TO_POINTER(((uint32_t)new_h << 16) + (uint32_t)compute_pgmentry_offset(new_h));
447 else
448 return -1;
449
450 return 0;
451 }
452
ti68k_bkpt_set_bits(uint32_t old_address,uint32_t address)453 int ti68k_bkpt_set_bits(uint32_t old_address, uint32_t address)
454 {
455 ADDR_BIT s, *p;
456 GList *elt = NULL;
457
458 s.addr = old_address;
459 elt = g_list_find_custom(bkpts.bits, &s, compare_func4);
460 if(elt == NULL)
461 return -1;
462
463 p = elt->data;
464 p->addr = address;
465
466 return 0;
467 }
468
469 /* Get */
470
ti68k_bkpt_get_address(unsigned int id,uint32_t * address)471 int ti68k_bkpt_get_address(unsigned int id, uint32_t *address)
472 {
473 if((id+1) > g_list_length(bkpts.code))
474 return -1;
475
476 *address = GPOINTER_TO_INT(g_list_nth(bkpts.code, id)->data);
477 return 0;
478 }
479
ti68k_bkpt_get_access(unsigned int id,uint32_t * address,int mode)480 int ti68k_bkpt_get_access(unsigned int id, uint32_t *address, int mode)
481 {
482 if((mode & BK_READ) && (mode & BK_BYTE))
483 {
484 if((id+1) > g_list_length(bkpts.mem_rb)) return -1;
485 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_rb, id)->data);
486 }
487 else if((mode & BK_READ) && (mode & BK_WORD))
488 {
489 if((id+1) > g_list_length(bkpts.mem_rw)) return -1;
490 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_rw, id)->data);
491 }
492 else if((mode & BK_READ) && (mode & BK_LONG))
493 {
494 if((id+1) > g_list_length(bkpts.mem_rl)) return -1;
495 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_rl, id)->data);
496 }
497
498 if((mode & BK_WRITE) && (mode & BK_BYTE))
499 {
500 if((id+1) > g_list_length(bkpts.mem_wb)) return -1;
501 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_wb, id)->data);
502 }
503 else if((mode & BK_WRITE) && (mode & BK_WORD))
504 {
505 if((id+1) > g_list_length(bkpts.mem_wl)) return -1;
506 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_ww, id)->data);
507 }
508 else if((mode & BK_WRITE) && (mode & BK_LONG))
509 {
510 if((id+1) > g_list_length(bkpts.mem_wl)) return -1;
511 *address = GPOINTER_TO_INT(g_list_nth(bkpts.mem_wl, id)->data);
512 }
513
514 return 0;
515 }
516
ti68k_bkpt_get_range(unsigned int id,uint32_t * min,uint32_t * max,int mode)517 int ti68k_bkpt_get_range(unsigned int id, uint32_t *min, uint32_t *max, int mode)
518 {
519 if(mode & BK_READ)
520 {
521 ADDR_RANGE *s;
522
523 if((id+1) > g_list_length(bkpts.mem_rng_r)) return -1;
524 s = g_list_nth(bkpts.mem_rng_r, id)->data;
525
526 *min = s->val1;
527 *max = s->val2;
528 }
529
530 if(mode & BK_WRITE)
531 {
532 ADDR_RANGE *s;
533
534 if((id+1) > g_list_length(bkpts.mem_rng_w)) return -1;
535 s = g_list_nth(bkpts.mem_rng_w, id)->data;
536
537 *min = s->val1;
538 *max = s->val2;
539 }
540
541 return 0;
542 }
543
ti68k_bkpt_get_exception(unsigned int id,uint32_t * number)544 int ti68k_bkpt_get_exception(unsigned int id, uint32_t *number)
545 {
546 if((id+1) > g_list_length(bkpts.exception))
547 return -1;
548
549 *number = GPOINTER_TO_INT(g_list_nth(bkpts.exception, id)->data);
550 return 0;
551 }
552
ti68k_bkpt_get_pgmentry(unsigned int id,uint16_t * handle)553 int ti68k_bkpt_get_pgmentry(unsigned int id, uint16_t *handle)
554 {
555 if((id+1) > g_list_length(bkpts.pgmentry))
556 return -1;
557
558 *handle = GPOINTER_TO_INT(g_list_nth(bkpts.pgmentry, id)->data) >> 16;
559 return 0;
560 }
561
ti68k_bkpt_get_pgmentry_offset(unsigned int id,uint16_t * handle,uint16_t * offset)562 int ti68k_bkpt_get_pgmentry_offset(unsigned int id, uint16_t *handle, uint16_t *offset)
563 {
564 uint32_t data;
565
566 if((id+1) > g_list_length(bkpts.pgmentry))
567 return -1;
568
569 data = GPOINTER_TO_INT(g_list_nth(bkpts.pgmentry, id)->data);
570 *handle = (uint16_t)(data >> 16);
571 *offset = (uint16_t)(data & 0xffff);
572 return 0;
573 }
574
ti68k_bkpt_get_bits(unsigned int id,uint32_t * address,uint8_t * checks,uint8_t * states)575 int ti68k_bkpt_get_bits(unsigned int id, uint32_t *address, uint8_t *checks, uint8_t *states)
576 {
577 ADDR_BIT *s;
578
579 if((id+1) > g_list_length(bkpts.bits)) return -1;
580 s = g_list_nth(bkpts.bits, id)->data;
581
582 *address = s->addr;
583 *checks = s->checks;
584 *states = s->states;
585
586 return 0;
587 }
588
589 /* Clear */
590
ti68k_bkpt_clear_address(void)591 void ti68k_bkpt_clear_address(void)
592 {
593 g_list_free(bkpts.code);
594 bkpts.code = NULL;
595 }
596
ti68k_bkpt_clear_access(void)597 void ti68k_bkpt_clear_access(void)
598 {
599 g_list_free(bkpts.mem_rb);
600 bkpts.mem_rb = NULL;
601 g_list_free(bkpts.mem_rw);
602 bkpts.mem_rw = NULL;
603 g_list_free(bkpts.mem_rl);
604 bkpts.mem_rl = NULL;
605
606 g_list_free(bkpts.mem_wb);
607 bkpts.mem_wb = NULL;
608 g_list_free(bkpts.mem_ww);
609 bkpts.mem_ww = NULL;
610 g_list_free(bkpts.mem_wl);
611 bkpts.mem_wl = NULL;
612 }
613
ti68k_bkpt_clear_range(void)614 void ti68k_bkpt_clear_range(void)
615 {
616 GList *l;
617
618 l = bkpts.mem_rng_r;
619 while(l != NULL)
620 {
621 g_free(l->data);
622 l = g_list_next(l);
623 }
624 g_list_free(bkpts.mem_rng_r);
625 bkpts.mem_rng_r = NULL;
626
627 l = bkpts.mem_rng_w;
628 while(l != NULL)
629 {
630 g_free(l->data);
631 l = g_list_next(l);
632 }
633 g_list_free(bkpts.mem_rng_w);
634 bkpts.mem_rng_w = NULL;
635 }
636
ti68k_bkpt_clear_exception(void)637 void ti68k_bkpt_clear_exception(void)
638 {
639 g_list_free(bkpts.exception);
640 bkpts.exception = NULL;
641 }
642
ti68k_bkpt_clear_pgmentry(void)643 void ti68k_bkpt_clear_pgmentry(void)
644 {
645 g_list_free(bkpts.pgmentry);
646 bkpts.pgmentry = NULL;
647 }
648
ti68k_bkpt_clear_bits(void)649 void ti68k_bkpt_clear_bits(void)
650 {
651 GList *l;
652
653 for(l = bkpts.bits; l; l = g_list_next(l))
654 g_free(l->data);
655
656 g_list_free(bkpts.bits);
657 bkpts.bits = NULL;
658 }
659
660 /* Others */
661
ti68k_bkpt_set_cause(int type,int mode,int id)662 void ti68k_bkpt_set_cause(int type, int mode, int id)
663 {
664 bkpts.type = type;
665 bkpts.mode = mode;
666 bkpts.id = id;
667 }
668
ti68k_bkpt_get_cause(int * type,int * mode,int * id)669 void ti68k_bkpt_get_cause(int *type, int *mode, int *id)
670 {
671 *type = bkpts.type;
672 *mode = bkpts.mode;
673 *id = bkpts.id;
674 }
675
ti68k_bkpt_clear_all(void)676 void ti68k_bkpt_clear_all(void)
677 {
678 ti68k_bkpt_clear_address();
679 ti68k_bkpt_clear_access();
680 ti68k_bkpt_clear_range();
681 ti68k_bkpt_clear_exception();
682 ti68k_bkpt_clear_pgmentry();
683 ti68k_bkpt_clear_bits();
684
685 ti68k_bkpt_set_cause(0, 0, 0);
686 }
687
688
689 enum target_hw_bp_type
690 {
691 hw_write = 0, /* Common (write) HW watchpoint */
692 hw_read = 1, /* Read HW watchpoint */
693 hw_access = 2, /* Access (read or write) HW watchpoint */
694 };
695
696 /* Wrappers for GDB use */
ti68k_bkpt_add_watchpoint(uint32_t address,uint32_t len,int type)697 int ti68k_bkpt_add_watchpoint(uint32_t address, uint32_t len, int type)
698 {
699 switch (type)
700 {
701 case hw_write:
702 ti68k_bkpt_add_range(address, address + len - 1, BK_WRITE);
703 dbgbkpts_refresh_window();
704 return 0;
705 case hw_read:
706 ti68k_bkpt_add_range(address, address + len - 1, BK_READ);
707 dbgbkpts_refresh_window();
708 return 0;
709 case hw_access:
710 ti68k_bkpt_add_range(address, address + len - 1, BK_READ | BK_WRITE);
711 dbgbkpts_refresh_window();
712 return 0;
713 default:
714 dbgbkpts_refresh_window();
715 return 1;
716 }
717 }
718
ti68k_bkpt_del_watchpoint(uint32_t address,uint32_t len,int type)719 int ti68k_bkpt_del_watchpoint(uint32_t address, uint32_t len, int type)
720 {
721 switch (type)
722 {
723 case hw_write:
724 ti68k_bkpt_del_range(address, address + len - 1, BK_WRITE);
725 dbgbkpts_refresh_window();
726 return 0;
727 case hw_read:
728 ti68k_bkpt_del_range(address, address + len - 1, BK_READ);
729 dbgbkpts_refresh_window();
730 return 0;
731 case hw_access:
732 ti68k_bkpt_del_range(address, address + len - 1, BK_READ | BK_WRITE);
733 dbgbkpts_refresh_window();
734 return 0;
735 default:
736 return 1;
737 }
738 }
739
ti68k_bkpt_stopped_by_watchpoint(void)740 int ti68k_bkpt_stopped_by_watchpoint(void)
741 {
742 return (bkpts.type == BK_TYPE_ACCESS) || (bkpts.type == BK_TYPE_RANGE);
743 }
744
ti68k_bkpt_stopped_data_address(uint32_t * address)745 int ti68k_bkpt_stopped_data_address(uint32_t *address)
746 {
747 uint32_t max;
748
749 switch(bkpts.type)
750 {
751 case BK_TYPE_ACCESS:
752 ti68k_bkpt_get_access(bkpts.id, address, bkpts.mode);
753 return 1;
754 case BK_TYPE_RANGE:
755 ti68k_bkpt_get_range(bkpts.id, address, &max, bkpts.mode);
756 return 1;
757 default:
758 return 0;
759 }
760 }
761