2 * Copyright © 2008 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 static uint16_t start_address;
23 static enum command_result
24 parse_int(char *value, int *result)
28 *result = strtol(value, &endptr, 0);
30 return command_syntax;
31 return command_success;
34 static enum command_result
35 parse_uint16(char *value, uint16_t *uint16)
38 enum command_result result;
40 result = parse_int(value, &v);
41 if (result != command_success)
43 if (v < 0 || v > 0xffff)
46 return command_success;
49 static enum command_result
50 parse_uint8(char *value, uint8_t *uint8)
53 enum command_result result;
55 result = parse_int(value, &v);
56 if (result != command_success)
58 if (v < 0 || v > 0xff)
61 return command_success;
65 command_quit (int argc, char **argv)
73 dump_bytes(uint8_t *memory, int length, uint16_t start, char *format)
77 for (group = 0; group < length; group += 8) {
78 s51_printf(format, start + group);
79 for (i = group; i < length && i < group + 8; i++)
80 s51_printf("%02x ", memory[i]);
81 for (; i < group + 8; i++)
83 for (i = group; i < length && i < group + 8; i++) {
84 if (isascii(memory[i]) && isprint(memory[i]))
85 s51_printf("%c", memory[i]);
94 command_di (int argc, char **argv)
97 uint8_t memory[65536];
102 return command_error;
103 if (parse_uint16(argv[1], &start) != command_success)
104 return command_error;
105 if (parse_uint16(argv[2], &end) != command_success)
106 return command_error;
107 length = (int) end - (int) start + 1;
108 status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length);
109 dump_bytes(memory, length, start, "0x%02x ");
110 return command_success;
114 command_ds (int argc, char **argv)
117 uint8_t memory[0x100];
122 return command_error;
123 if (parse_uint8(argv[1], &start) != command_success)
124 return command_error;
125 if (parse_uint8(argv[2], &end) != command_success)
126 return command_error;
127 length = (int) end - (int) start + 1;
128 status = ccdbg_read_sfr(s51_dbg, start, memory, length);
129 dump_bytes(memory, length, start, "0x%02x ");
130 return command_success;
134 command_dx (int argc, char **argv)
137 uint8_t memory[65536];
142 return command_error;
143 if (parse_uint16(argv[1], &start) != command_success)
144 return command_error;
145 if (parse_uint16(argv[2], &end) != command_success)
146 return command_error;
147 length = (int) end - (int) start + 1;
148 status = ccdbg_read_memory(s51_dbg, start, memory, length);
149 dump_bytes(memory, length, start, "0x%04x ");
150 return command_success;
154 command_set (int argc, char **argv)
160 enum command_result ret = command_success;
163 return command_error;
164 if (parse_uint16(argv[2], &address) != command_success)
165 return command_error;
167 return command_success;
170 return command_error;
171 for (i = 0; i < len; i++)
172 if (parse_uint8(argv[i+3], &data[i]) != command_success)
173 return command_error;
175 if (strcmp(argv[1], "xram") == 0) {
176 ccdbg_write_memory(s51_dbg, address, data, len);
177 } else if (strcmp(argv[1], "iram") == 0) {
178 ccdbg_write_memory(s51_dbg, address + 0xff00, data, len);
179 } else if (strcmp(argv[1], "sfr") == 0) {
180 ccdbg_write_sfr(s51_dbg, (uint8_t) address, data, len);
188 command_dump (int argc, char **argv)
191 if (strcmp(argv[1], "rom") == 0 ||
192 strcmp(argv[1], "xram") == 0)
193 return command_dx(argc-1, argv+1);
194 if (strcmp(argv[1], "iram") == 0)
195 return command_di(argc-1, argv+1);
196 if (strcmp(argv[1], "sfr") == 0)
197 return command_ds(argc-1, argv+1);
199 return command_error;
203 command_file (int argc, char **argv)
205 struct ao_hex_file *hex;
206 struct ao_hex_image *image;
210 return command_error;
211 file = fopen (argv[1], "r");
213 return command_error;
214 hex = ao_hex_file_read(file, argv[1]);
217 return command_error;
218 if (hex->nrecord == 0) {
219 ao_hex_file_free(hex);
220 return command_error;
222 image = ao_hex_image_create(hex);
223 ao_hex_file_free(hex);
224 start_address = image->address;
225 ccdbg_set_rom(s51_dbg, image);
226 return command_success;
230 command_pc (int argc, char **argv)
234 enum command_result result;
235 result = parse_uint16(argv[1], &pc);
236 if (result != command_success)
238 ccdbg_set_pc(s51_dbg, pc);
240 pc = ccdbg_get_pc(s51_dbg);
241 s51_printf(" 0x%04x 00\n", pc);
243 return command_success;
252 #define CC_NUM_BREAKPOINTS 4
254 static struct cc_break breakpoints[CC_NUM_BREAKPOINTS];
257 disable_breakpoint(int b)
261 status = ccdbg_set_hw_brkpnt(s51_dbg, b, 0, breakpoints[b].address);
262 if (status != 0x00 && status != 0xff)
263 s51_printf("disable_breakpoint status 0x%02x\n", status);
267 enable_breakpoint(int b)
271 status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, breakpoints[b].address);
273 s51_printf("enable_breakpoint status 0x%02x\n", status);
277 enable_breakpoints(void)
280 for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
281 if (breakpoints[b].enabled)
282 enable_breakpoint(b);
286 set_breakpoint(uint16_t address, int temporary)
290 for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
291 if (breakpoints[b].enabled == 0)
293 if (breakpoints[b].address == address)
296 if (b == CC_NUM_BREAKPOINTS) {
297 s51_printf("Error: too many breakpoints requested\n");
298 return command_success;
300 if (breakpoints[b].enabled == 0) {
301 breakpoints[b].address = address;
302 enable_breakpoint(b);
304 ++breakpoints[b].enabled;
305 s51_printf("Breakpoint %d at 0x%04x\n", b, address);
306 breakpoints[b].temporary += temporary;
307 return command_success;
311 clear_breakpoint(uint16_t address, int temporary)
316 for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
317 if (breakpoints[b].enabled != 0 &&
318 ((breakpoints[b].temporary != 0) == (temporary != 0)) &&
319 breakpoints[b].address == address)
322 if (b == CC_NUM_BREAKPOINTS) {
323 s51_printf("Error: no matching breakpoint found\n");
324 return command_success;
326 --breakpoints[b].enabled;
327 breakpoints[b].temporary -= temporary;
328 if (breakpoints[b].enabled == 0) {
329 disable_breakpoint(b);
330 breakpoints[b].address = -1;
332 return command_success;
337 find_breakpoint(uint16_t address)
341 for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
342 if (breakpoints[b].enabled && breakpoints[b].address == address)
344 if (b == CC_NUM_BREAKPOINTS)
350 command_break (int argc, char **argv)
354 enum command_result result;
357 for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
358 if (breakpoints[b].enabled)
359 s51_printf("Breakpoint %d 0x%04x\n",
360 b, breakpoints[b].address);
361 return command_success;
364 return command_error;
365 result = parse_uint16(argv[1], &address);
366 if (result != command_success)
369 return set_breakpoint(address, 0);
373 command_clear (int argc, char **argv)
377 enum command_result result;
380 return command_error;
381 result = parse_uint16(argv[1], &address);
382 if (result != command_success)
384 return clear_breakpoint(address, 0);
388 cc_stopped(uint8_t status)
395 pc = ccdbg_get_pc(s51_dbg);
396 if (status & CC_STATUS_CPU_HALTED) {
397 if ((status & CC_STATUS_HALT_STATUS) != 0) {
400 reason = "Breakpoint";
401 b = find_breakpoint(pc);
402 if (b != -1 && breakpoints[b].temporary)
403 clear_breakpoint(pc, 1);
404 ccdbg_set_pc(s51_dbg, pc);
407 reason = "Interrupt";
409 s51_printf("Stop at 0x%04x: (%d) %s\n",
420 b = find_breakpoint(pc);
422 disable_breakpoint(b);
423 status = ccdbg_step_instr(s51_dbg);
425 enable_breakpoint(b);
430 command_run (int argc, char **argv)
433 enum command_result result;
439 result = parse_uint16(argv[1], &start);
440 if (result != command_success)
443 result = parse_uint16(argv[2], &end);
444 if (result != command_success)
447 if (start_address && start == 0) {
448 start = start_address;
449 s51_printf("Starting at 0x%04x\n", start);
451 ccdbg_set_pc(s51_dbg, start);
454 start = ccdbg_get_pc(s51_dbg);
455 s51_printf("Resume at 0x%04x\n", start);
457 b = find_breakpoint(pc);
460 pc = ccdbg_get_pc(s51_dbg);
461 if (find_breakpoint(pc) != -1) {
462 status = ccdbg_read_status(s51_dbg);
464 return command_success;
467 ccdbg_resume(s51_dbg);
473 command_next (int argc, char **argv)
475 return command_step(argc, argv);
479 command_step (int argc, char **argv)
485 a = cc_step(ccdbg_get_pc(s51_dbg));
486 s51_printf(" ACC= 0x%02x\n", a);
487 pc = ccdbg_get_pc(s51_dbg);
488 ccdbg_read_memory(s51_dbg, pc, &opcode, 1);
489 s51_printf(" ? 0x%04x %02x\n", pc, opcode);
490 return command_success;
494 command_load (int argc, char **argv)
496 char *filename = argv[1];
498 struct ao_hex_file *hex;
499 struct ao_hex_image *image;
502 return command_error;
503 file = fopen(filename, "r");
506 return command_error;
508 hex = ao_hex_file_read(file, filename);
511 return command_error;
513 image = ao_hex_image_create(hex);
514 ao_hex_file_free(hex);
516 fprintf(stderr, "image create failed\n");
517 return command_error;
519 if (image->address >= 0xf000) {
520 printf("Loading %d bytes to RAM at 0x%04x\n",
521 image->length, image->address);
522 ccdbg_write_hex_image(s51_dbg, image, 0);
524 fprintf(stderr, "Can only load to RAM\n");
526 ao_hex_image_free(image);
527 return command_success;
531 command_halt (int argc, char **argv)
535 pc = ccdbg_get_pc(s51_dbg);
536 s51_printf("Halted at 0x%04x\n", pc);
537 return command_success;
541 command_stop (int argc, char **argv)
543 return command_success;
547 command_reset (int argc, char **argv)
549 ccdbg_debug_mode(s51_dbg);
551 enable_breakpoints();
552 return command_success;
556 command_status(int argc, char **argv)
560 status = ccdbg_read_status(s51_dbg);
561 if ((status & CC_STATUS_CHIP_ERASE_DONE) == 0)
562 s51_printf("\tChip erase in progress\n");
563 if (status & CC_STATUS_PCON_IDLE)
564 s51_printf("\tCPU is idle (clock gated)\n");
565 if (status & CC_STATUS_CPU_HALTED)
566 s51_printf("\tCPU halted\n");
568 s51_printf("\tCPU running\n");
569 if ((status & CC_STATUS_POWER_MODE_0) == 0)
570 s51_printf("\tPower Mode 1-3 selected\n");
571 if (status & CC_STATUS_HALT_STATUS)
572 s51_printf("\tHalted by software or hw breakpoint\n");
574 s51_printf("\tHalted by debug command\n");
575 if (status & CC_STATUS_DEBUG_LOCKED)
576 s51_printf("\tDebug interface is locked\n");
577 if ((status & CC_STATUS_OSCILLATOR_STABLE) == 0)
578 s51_printf("\tOscillators are not stable\n");
579 if (status & CC_STATUS_STACK_OVERFLOW)
580 s51_printf("\tStack overflow\n");
581 return command_success;
584 static enum command_result
585 info_breakpoints(int argc, char **argv)
589 enum command_result result;
592 s51_printf("Num Type Disp Hit Cnt Address What\n");
593 for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
594 if (breakpoints[b].enabled) {
595 s51_printf("%-3d fetch %s 1 1 0x%04x uc::disass() unimplemented\n",
597 breakpoints[b].temporary ? "del " : "keep",
598 breakpoints[b].address);
600 return command_success;
605 static enum command_result
606 info_help(int argc, char **argv);
608 static struct command_function infos[] = {
609 { "breakpoints", "b", info_breakpoints, "[b]reakpoints",
610 "List current breakpoints\n" },
611 { "help", "?", info_help, "help",
612 "Print this list\n" },
614 { NULL, NULL, NULL, NULL, NULL },
617 static enum command_result
618 info_help(int argc, char **argv)
620 return command_function_help(infos, argc, argv);
624 command_info(int argc, char **argv)
626 struct command_function *func;
629 return command_error;
630 func = command_string_to_function(infos, argv[1]);
632 return command_syntax;
633 return (*func->func)(argc-1, argv+1);
641 status = ccdbg_read_status(s51_dbg);
642 if (status & CC_STATUS_CPU_HALTED) {
644 return command_success;
646 if (s51_interrupted || s51_check_input()) {
649 status = ccdbg_read_status(s51_dbg);
651 return command_interrupt;