Remove unused cctools code paths for old libusb and cp2103 ioctls.
[fw/altos] / cctools / s51 / s51-command.c
1 /*
2  * Copyright © 2008 Keith Packard <keithp@keithp.com>
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #include "s51.h"
20
21 static uint16_t start_address;
22
23 static enum command_result
24 parse_int(char *value, int *result)
25 {
26         char *endptr;
27
28         *result = strtol(value, &endptr, 0);
29         if (endptr == value)
30                 return command_syntax;
31         return command_success;
32 }
33
34 static enum command_result
35 parse_uint16(char *value, uint16_t *uint16)
36 {
37         int     v;
38         enum command_result result;
39
40         result = parse_int(value, &v);
41         if (result != command_success)
42                 return command_error;
43         if (v < 0 || v > 0xffff)
44                 return command_error;
45         *uint16 = v;
46         return command_success;
47 }
48
49 static enum command_result
50 parse_uint8(char *value, uint8_t *uint8)
51 {
52         int     v;
53         enum command_result result;
54
55         result = parse_int(value, &v);
56         if (result != command_success)
57                 return command_error;
58         if (v < 0 || v > 0xff)
59                 return command_error;
60         *uint8 = v;
61         return command_success;
62 }
63
64 enum command_result
65 command_quit (int argc, char **argv)
66 {
67         ccdbg_reset(s51_dbg);
68         exit(0);
69         return command_error;
70 }
71
72 static void
73 dump_bytes(uint8_t *memory, int length, uint16_t start, char *format)
74 {
75         int group, i;
76
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++)
82                         s51_printf("   ");
83                 for (i = group; i < length && i < group + 8; i++) {
84                         if (isascii(memory[i]) && isprint(memory[i]))
85                                 s51_printf("%c", memory[i]);
86                         else
87                                 s51_printf(".");
88                 }
89                 s51_printf("\n");
90         }
91 }
92
93 enum command_result
94 command_di (int argc, char **argv)
95 {
96         uint16_t start, end;
97         uint8_t memory[65536];
98         uint8_t status;
99         int length;
100
101         if (argc != 3)
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;
111 }
112
113 enum command_result
114 command_ds (int argc, char **argv)
115 {
116         uint8_t start, end;
117         uint8_t memory[0x100];
118         uint8_t status;
119         int length;
120
121         if (argc != 3)
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;
131 }
132
133 enum command_result
134 command_dx (int argc, char **argv)
135 {
136         uint16_t start, end;
137         uint8_t memory[65536];
138         uint8_t status;
139         int length;
140
141         if (argc != 3)
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;
151 }
152
153 enum command_result
154 command_set (int argc, char **argv)
155 {
156         uint16_t address;
157         uint8_t *data;
158         int len = argc - 3;
159         int i;
160         enum command_result ret = command_success;
161
162         if (len < 0)
163                 return command_error;
164         if (parse_uint16(argv[2], &address) != command_success)
165                 return command_error;
166         if (len == 0)
167                 return command_success;
168         data = malloc(len);
169         if (!data)
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;
174
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);
181         } else
182                 ret = command_error;
183         free(data);
184         return ret;
185 }
186
187 enum command_result
188 command_dump (int argc, char **argv)
189 {
190         if (argv[1]) {
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);
198         }
199         return command_error;
200 }
201
202 enum command_result
203 command_file (int argc, char **argv)
204 {
205         struct hex_file *hex;
206         struct hex_image *image;
207         FILE *file;
208
209         if (argc != 2)
210                 return command_error;
211         file = fopen (argv[1], "r");
212         if (!file)
213                 return command_error;
214         hex = ccdbg_hex_file_read(file, argv[1]);
215         fclose(file);
216         if (!hex)
217                 return command_error;
218         if (hex->nrecord == 0) {
219                 ccdbg_hex_file_free(hex);
220                 return command_error;
221         }
222         image = ccdbg_hex_image_create(hex);
223         ccdbg_hex_file_free(hex);
224         start_address = image->address;
225         ccdbg_set_rom(s51_dbg, image);
226         return command_success;
227 }
228
229 enum command_result
230 command_pc (int argc, char **argv)
231 {
232         uint16_t        pc;
233         if (argv[1]) {
234                 enum command_result result;
235                 result = parse_uint16(argv[1], &pc);
236                 if (result != command_success)
237                         return result;
238                 ccdbg_set_pc(s51_dbg, pc);
239         } else {
240                 pc = ccdbg_get_pc(s51_dbg);
241                 s51_printf("   0x%04x 00\n", pc);
242         }
243         return command_success;
244 }
245
246 struct cc_break {
247         int             enabled;
248         int             temporary;
249         uint16_t        address;
250 };
251
252 #define CC_NUM_BREAKPOINTS 4
253
254 static struct cc_break  breakpoints[CC_NUM_BREAKPOINTS];
255
256 static void
257 disable_breakpoint(int b)
258 {
259         uint8_t status;
260
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);
264 }
265
266 static void
267 enable_breakpoint(int b)
268 {
269         uint8_t status;
270
271         status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, breakpoints[b].address);
272         if (status != 0xff)
273                 s51_printf("enable_breakpoint status 0x%02x\n", status);
274 }
275
276 static void
277 enable_breakpoints(void)
278 {
279         int b;
280         for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
281                 if (breakpoints[b].enabled)
282                         enable_breakpoint(b);
283 }
284
285 enum command_result
286 set_breakpoint(uint16_t address, int temporary)
287 {
288         int b;
289         uint8_t status;
290         for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
291                 if (breakpoints[b].enabled == 0)
292                         break;
293                 if (breakpoints[b].address == address)
294                         break;
295         }
296         if (b == CC_NUM_BREAKPOINTS) {
297                 s51_printf("Error: too many breakpoints requested\n");
298                 return command_success;
299         }
300         if (breakpoints[b].enabled == 0) {
301                 breakpoints[b].address = address;
302                 enable_breakpoint(b);
303         }
304         ++breakpoints[b].enabled;
305         s51_printf("Breakpoint %d at 0x%04x\n", b, address);
306         breakpoints[b].temporary += temporary;
307         return command_success;
308 }
309
310 enum command_result
311 clear_breakpoint(uint16_t address, int temporary)
312 {
313         int b;
314         uint8_t status;
315
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)
320                         break;
321         }
322         if (b == CC_NUM_BREAKPOINTS) {
323                 s51_printf("Error: no matching breakpoint found\n");
324                 return command_success;
325         }
326         --breakpoints[b].enabled;
327         breakpoints[b].temporary -= temporary;
328         if (breakpoints[b].enabled == 0) {
329                 disable_breakpoint(b);
330                 breakpoints[b].address = -1;
331         }
332         return command_success;
333 }
334
335
336 int
337 find_breakpoint(uint16_t address)
338 {
339         int b;
340
341         for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
342                 if (breakpoints[b].enabled && breakpoints[b].address == address)
343                         break;
344         if (b == CC_NUM_BREAKPOINTS)
345                 return -1;
346         return b;
347 }
348
349 enum command_result
350 command_break (int argc, char **argv)
351 {
352         int b;
353         uint16_t address;
354         enum command_result result;
355
356         if (argc == 1) {
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;
362         }
363         if (argc != 2)
364                 return command_error;
365         result = parse_uint16(argv[1], &address);
366         if (result != command_success)
367                 return result;
368
369         return set_breakpoint(address, 0);
370 }
371
372 enum command_result
373 command_clear (int argc, char **argv)
374 {
375         int b;
376         uint16_t address;
377         enum command_result result;
378
379         if (argc != 2)
380                 return command_error;
381         result = parse_uint16(argv[1], &address);
382         if (result != command_success)
383                 return result;
384         return clear_breakpoint(address, 0);
385 }
386
387 void
388 cc_stopped(uint8_t status)
389 {
390         uint16_t pc;
391         int b;
392         int code;
393         char *reason;
394
395         pc = ccdbg_get_pc(s51_dbg);
396         if (status & CC_STATUS_CPU_HALTED) {
397                 if ((status & CC_STATUS_HALT_STATUS) != 0) {
398                         pc = pc - 1;
399                         code = 104;
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);
405                 } else {
406                         code = 105;
407                         reason = "Interrupt";
408                 }
409                 s51_printf("Stop at 0x%04x: (%d) %s\n",
410                         pc, code, reason);
411         }
412 }
413
414 uint8_t
415 cc_step(uint16_t pc)
416 {
417         int b;
418         uint8_t status;
419
420         b = find_breakpoint(pc);
421         if (b != -1)
422                 disable_breakpoint(b);
423         status = ccdbg_step_instr(s51_dbg);
424         if (b != -1)
425                 enable_breakpoint(b);
426         return status;
427 }
428
429 enum command_result
430 command_run (int argc, char **argv)
431 {
432         uint16_t start, end;
433         enum command_result result;
434         uint16_t pc;
435         uint8_t status;
436         int b;
437
438         if (argv[1]) {
439                 result = parse_uint16(argv[1], &start);
440                 if (result != command_success)
441                         return result;
442                 if (argv[2]) {
443                         result = parse_uint16(argv[2], &end);
444                         if (result != command_success)
445                                 return result;
446                 }
447                 if (start_address && start == 0) {
448                         start = start_address;
449                         s51_printf("Starting at 0x%04x\n", start);
450                 }
451                 ccdbg_set_pc(s51_dbg, start);
452         }
453         else
454                 start = ccdbg_get_pc(s51_dbg);
455         s51_printf("Resume at 0x%04x\n", start);
456         pc = start;
457         b = find_breakpoint(pc);
458         if (b != -1) {
459                 cc_step(pc);
460                 pc = ccdbg_get_pc(s51_dbg);
461                 if (find_breakpoint(pc) != -1) {
462                         status = ccdbg_read_status(s51_dbg);
463                         cc_stopped(status);
464                         return command_success;
465                 }
466         }
467         ccdbg_resume(s51_dbg);
468         result = cc_wait();
469         return result;
470 }
471
472 enum command_result
473 command_next (int argc, char **argv)
474 {
475         return command_step(argc, argv);
476 }
477
478 enum command_result
479 command_step (int argc, char **argv)
480 {
481         uint16_t pc;
482         uint8_t opcode;
483         uint8_t a;
484
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;
491 }
492
493 enum command_result
494 command_load (int argc, char **argv)
495 {
496         char *filename = argv[1];
497         FILE *file;
498         struct hex_file *hex;
499         struct hex_image *image;
500
501         if (!filename)
502                 return command_error;
503         file = fopen(filename, "r");
504         if (!file) {
505                 perror(filename);
506                 return command_error;
507         }
508         hex = ccdbg_hex_file_read(file, filename);
509         fclose(file);
510         if (!hex) {
511                 return command_error;
512         }
513         image = ccdbg_hex_image_create(hex);
514         ccdbg_hex_file_free(hex);
515         if (!image) {
516                 fprintf(stderr, "image create failed\n");
517                 return command_error;
518         }
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);
523         } else {
524                 fprintf(stderr, "Can only load to RAM\n");
525         }
526         ccdbg_hex_image_free(image);
527         return command_success;
528 }
529
530 enum command_result
531 command_halt (int argc, char **argv)
532 {
533         uint16_t        pc;
534         ccdbg_halt(s51_dbg);
535         pc = ccdbg_get_pc(s51_dbg);
536         s51_printf("Halted at 0x%04x\n", pc);
537         return command_success;
538 }
539
540 enum command_result
541 command_stop (int argc, char **argv)
542 {
543         return command_success;
544 }
545
546 enum command_result
547 command_reset (int argc, char **argv)
548 {
549         ccdbg_debug_mode(s51_dbg);
550         ccdbg_halt(s51_dbg);
551         enable_breakpoints();
552         return command_success;
553 }
554
555 enum command_result
556 command_status(int argc, char **argv)
557 {
558         uint8_t status;
559
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");
567         else
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");
573         else
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;
582 }
583
584 static enum command_result
585 info_breakpoints(int argc, char **argv)
586 {
587         int b;
588         uint16_t address;
589         enum command_result result;
590
591         if (argc == 1) {
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",
596                                            b,
597                                            breakpoints[b].temporary ? "del " : "keep",
598                                            breakpoints[b].address);
599                         }
600                 return command_success;
601         }
602
603 }
604
605 static enum command_result
606 info_help(int argc, char **argv);
607
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" },
613
614         { NULL, NULL, NULL, NULL, NULL },
615 };
616
617 static enum command_result
618 info_help(int argc, char **argv)
619 {
620         return command_function_help(infos, argc, argv);
621 }
622
623 enum command_result
624 command_info(int argc, char **argv)
625 {
626         struct command_function *func;
627
628         if (argc < 2)
629                 return command_error;
630         func = command_string_to_function(infos, argv[1]);
631         if (!func)
632                 return command_syntax;
633         return (*func->func)(argc-1, argv+1);
634 }
635
636 enum command_result
637 cc_wait(void)
638 {
639         for(;;) {
640                 uint8_t status;
641                 status = ccdbg_read_status(s51_dbg);
642                 if (status & CC_STATUS_CPU_HALTED) {
643                         cc_stopped(status);
644                         return command_success;
645                 }
646                 if (s51_interrupted || s51_check_input()) {
647
648                         ccdbg_halt(s51_dbg);
649                         status = ccdbg_read_status(s51_dbg);
650                         cc_stopped(status);
651                         return command_interrupt;
652                 }
653         }
654 }