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