Use SFR access funcs. Support 'dump' command. Add -m (monitor) flag.
[fw/altos] / s51 / s51-parse.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 struct command_function {
22         char                    *name;
23         char                    *alias;
24         enum command_result     (*func)(int argc, char **argv);
25         char                    *usage;
26         char                    *help;
27 };
28
29 static struct command_function functions[] = {
30         { "help",   "?",  command_help, "help",         "Print this list\n" },
31         { "quit",   "q",  command_quit, "[q]uit",       "Quit\n" },
32         { "di",     "di", command_di,   "di <start> <end>",
33                 "Dump imem\n" },
34         { "ds",     "ds", command_ds,   "ds <start> <end>",
35                 "Dump sprs\n" },
36         { "dx",     "dx", command_dx,   "dx <start> <end>",
37                 "Dump xaddr\n" },
38         { "set",    "t",  command_set,  "se[t] mem <prefix> <start> <end>",
39                 "Set mem {xram|rom|iram|sfr} <start> <end>\n"
40                 "set bit <addr>\n" },
41         { "dump",   "d",  command_dump, "[d]ump <prefix> <start> <end>",
42                 "Dump {xram|rom|iram|sfr} <start> <end>\n" },
43         { "file", "file", command_file, "file <filename>",
44                 "Pretend to load executable from <filename>\n" },
45         { "pc",     "p",  command_pc, "[p]c [addr]",
46                 "Get or set pc value\n" },
47         { "break",  "b",  command_break,"[b]reak <addr>",
48                 "Set break point\n" },
49         { "clear",  "c",  command_clear,"[c]lear <addr>",
50                 "Clear break point\n" },
51         { "run",    "r",  command_run, "[r]un [start] [stop]",
52                 "Run with optional start and temp breakpoint addresses\n" },
53         { "next",   "n",  command_next, "[n]ext",
54                 "Step over one instruction, past any call\n" },
55         { "step",   "s",  command_step, "[s]tep",
56                 "Single step\n" },
57         { "load",   "l",  command_load, "[l]oad <file>",
58                 "Load a hex file into memory or flash" },
59         { "halt",   "h",  command_halt, "[h]alt",
60                 "Halt the processor\n" },
61         { "reset","res",command_reset,  "[res]et",
62                 "Reset the CPU\n" },
63         { "status","status",command_status, "status",
64                 "Display CC1111 debug status\n" },
65 };
66
67 #define NUM_FUNCTIONS (sizeof functions / sizeof functions[0])
68
69 #ifndef FALSE
70 #define FALSE 0
71 #define TRUE 1
72 #endif
73
74 static int
75 string_to_int(char *s, int *v)
76 {
77         char *endptr;
78
79         if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') {
80                 *v = strtol(s, &endptr, 0);
81                 if (endptr == s)
82                         return FALSE;
83         } else if (*s == '\'') {
84                 s++;
85                 if (*s == '\\') {
86                         s++;
87                         switch (*s) {
88                         case 'n':
89                                 *v = '\n';
90                                 break;
91                         case 't':
92                                 *v = '\t';
93                                 break;
94                         default:
95                                 *v = (int) *s;
96                                 break;
97                         }
98                 } else
99                         *v = (int) *s;
100                 s++;
101                 if (*s != '\'')
102                         return FALSE;
103         }
104         else
105                 return FALSE;
106     return TRUE;
107 }
108
109 static struct command_function *
110 command_string_to_function(char *name)
111 {
112         int i;
113         for (i = 0; i < NUM_FUNCTIONS; i++)
114                 if (!strcmp(name, functions[i].name) ||
115                     !strcmp(name, functions[i].alias))
116                         return &functions[i];
117         return NULL;
118 }    
119
120 static int
121 command_split_into_words(char *line, char **argv)
122 {
123         char quotechar;
124         int argc;
125
126         argc = 0;
127         while (*line) {
128                 while (isspace(*line))
129                         line++;
130                 if (!*line)
131                         break;
132                 if (*line == '"') {
133                         quotechar = *line++;
134                         *argv++ = line;
135                         argc++;
136                         while (*line && *line != quotechar)
137                                 line++;
138                         if (*line)
139                                 *line++ = '\0';
140                 } else {
141                         *argv++ = line;
142                         argc++;
143                         while (*line && !isspace(*line))
144                                 line++;
145                         if (*line)
146                                 *line++ = '\0';
147                 }
148         }
149         *argv = 0;
150         return argc;
151 }
152
153 enum command_result
154 command_help(int argc, char **argv)
155 {
156         int i;
157         struct command_function *func;
158
159         if (argc == 1) {
160                 for (i = 0; i < NUM_FUNCTIONS; i++)
161                         s51_printf("%-10s%s\n", functions[i].name,
162                                functions[i].usage);
163         } else {
164                 for (i = 1; i < argc; i++) {
165                         func = command_string_to_function(argv[i]);
166                         if (!func) {
167                                 s51_printf("%-10s unknown command\n", argv[i]);
168                                 return command_syntax;
169                         }
170                         s51_printf("%-10s %s\n%s", func->name,
171                                func->usage, func->help);
172                 }
173         }
174         return command_debug;
175 }
176     
177 static void
178 command_syntax_error(int argc, char **argv)
179 {
180         s51_printf("Syntax error in:");
181         while (*argv)
182                 s51_printf(" %s", *argv++);
183         s51_printf("\n");
184 }
185
186 void
187 command_read (void)
188 {
189         int argc;
190         char line[1024];
191         char *argv[20];
192         enum command_result result;
193         struct command_function *func;
194
195         s51_dbg = ccdbg_open ();
196         if (!s51_dbg) {
197                 perror("ccdbg_open");
198                 exit(1);
199         }
200         ccdbg_debug_mode(s51_dbg);
201         ccdbg_halt(s51_dbg);
202         s51_printf("Welcome to the non-simulated processor\n");
203         for (;;) {
204                 if (s51_read_line (line, sizeof line) == 0)
205                         break;
206                 s51_interrupted = 0;
207                 argc = command_split_into_words(line, argv);
208                 if (argc > 0) {
209                         func = command_string_to_function(argv[0]);
210                         if (!func)
211                                 command_syntax_error(argc, argv);
212                         else
213                         {
214                                 result = (*func->func)(argc, argv);
215                                 if (s51_interrupted)
216                                         result = command_interrupt;
217                                 switch (result) {
218                                 case command_syntax:
219                                         command_syntax_error(argc, argv);
220                                         break;
221                                 case command_error:
222                                         s51_printf("Error\n");
223                                         break;
224                                 case command_success:
225                                         break;
226                                 case command_interrupt:
227                                         ccdbg_halt(s51_dbg);
228                                         s51_printf("Interrupted\n");
229                                         break;
230                                 default:
231                                         break;
232                                 }
233                         }
234                 }
235         }
236         ccdbg_close(s51_dbg);
237         s51_printf("...\n");
238 }
239