278bca25ace69bf4db2f51eb89f0b3b3405bb589
[fw/altos] / 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 enum command_result
22 parse_int(char *value, int *result)
23 {
24         char *endptr;
25
26         *result = strtol(value, &endptr, 0);
27         if (endptr == value)
28                 return command_syntax;
29         return command_proceed;
30 }
31
32 static enum command_result
33 parse_uint16(char *value, uint16_t *uint16)
34 {
35         int     v;
36         enum command_result result;
37
38         result = parse_int(value, &v);
39         if (result != command_proceed)
40                 return command_error;
41         if (v < 0 || v > 0xffff)
42                 return command_error;
43         *uint16 = v;
44         return command_proceed;
45 }
46
47 enum command_result
48 command_quit (FILE *output, int argc, char **argv)
49 {
50         exit(0);
51         return command_error;
52 }
53
54 static void
55 dump_bytes(FILE *output, uint8_t *memory, int length, uint16_t start)
56 {
57         int group, i;
58         
59         for (group = 0; group < length; group += 8) {
60                 fprintf(output, "0x%04x ", start + group);
61                 for (i = group; i < length && i < group + 8; i++)
62                         fprintf(output, "%02x ", memory[i]);
63                 for (; i < group + 8; i++)
64                         fprintf(output, "   ");
65                 for (i = group; i < length && i < group + 8; i++) {
66                         if (isascii(memory[i]) && isprint(memory[i]))
67                                 fprintf(output, "%c", memory[i]);
68                         else
69                                 fprintf(output, ".");
70                 }
71                 fprintf(output, "\n");
72         }
73 }
74
75 enum command_result
76 command_di (FILE *output, int argc, char **argv)
77 {
78         uint16_t start, end;
79         uint8_t memory[65536];
80         uint8_t status;
81         int length;
82         
83         if (argc != 3)
84                 return command_error;
85         if (parse_uint16(argv[1], &start) != command_proceed)
86                 return command_error;
87         if (parse_uint16(argv[2], &end) != command_proceed)
88                 return command_error;
89         length = (int) end - (int) start + 1;
90         status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length);
91         dump_bytes(output, memory, length, start);
92         return command_proceed;
93 }
94
95 enum command_result
96 command_ds (FILE *output, int argc, char **argv)
97 {
98         uint16_t start, end;
99         uint8_t memory[65536];
100         uint8_t status;
101         int length;
102         
103         if (argc != 3)
104                 return command_error;
105         if (parse_uint16(argv[1], &start) != command_proceed)
106                 return command_error;
107         if (parse_uint16(argv[2], &end) != command_proceed)
108                 return command_error;
109         length = (int) end - (int) start + 1;
110         status = ccdbg_read_memory(s51_dbg, start + 0xdf00, memory, length);
111         dump_bytes(output, memory, length, start);
112         return command_proceed;
113 }
114
115 enum command_result
116 command_dx (FILE *output, int argc, char **argv)
117 {
118         uint16_t start, end;
119         uint8_t memory[65536];
120         uint8_t status;
121         int length;
122         
123         if (argc != 3)
124                 return command_error;
125         if (parse_uint16(argv[1], &start) != command_proceed)
126                 return command_error;
127         if (parse_uint16(argv[2], &end) != command_proceed)
128                 return command_error;
129         length = (int) end - (int) start + 1;
130         status = ccdbg_read_memory(s51_dbg, start, memory, length);
131         dump_bytes(output, memory, length, start);
132         return command_proceed;
133 }
134
135 enum command_result
136 command_set (FILE *output, int argc, char **argv)
137 {
138         return command_error;
139 }
140
141 enum command_result
142 command_dump (FILE *output, int argc, char **argv)
143 {
144         return command_error;
145 }
146
147 enum command_result
148 command_pc (FILE *output, int argc, char **argv)
149 {
150         uint16_t        pc;
151         if (argv[1]) {
152                 enum command_result result;
153                 result = parse_uint16(argv[1], &pc);
154                 if (result != command_proceed)
155                         return result;
156                 ccdbg_set_pc(s51_dbg, pc);
157         } else {
158                 pc = ccdbg_get_pc(s51_dbg);
159                 printf (" 0x%04x\n", pc);
160         }
161         return command_proceed;
162 }
163
164 struct cc_break {
165         int             enabled;
166         int             temporary;
167         uint16_t        address;
168 };
169
170 #define CC_NUM_BREAKPOINTS 4
171
172 static struct cc_break  breakpoints[CC_NUM_BREAKPOINTS];
173
174 enum command_result
175 set_breakpoint(FILE *output, uint16_t address, int temporary)
176 {
177         int b;
178         uint8_t status;
179         for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
180                 if (breakpoints[b].enabled == 0)
181                         break;
182                 if (breakpoints[b].address == address)
183                         break;
184         }
185         if (b == CC_NUM_BREAKPOINTS) {
186                 fprintf(output, "Error: too many breakpoints requested\n");
187                 return command_proceed;
188         }
189         if (breakpoints[b].enabled == 0) {
190                 breakpoints[b].address = address;
191                 status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, address);
192                 fprintf(output, "set_hw_brkpnt status 0x%02x\n", status);
193         }
194         ++breakpoints[b].enabled;
195         fprintf(output, "Breakpoint %d at 0x%04x\n", b, address);
196         breakpoints[b].temporary += temporary;
197         return command_proceed;
198 }
199
200 enum command_result
201 clear_breakpoint(FILE *output, uint16_t address, int temporary)
202 {
203         int b;
204         uint8_t status;
205
206         for (b = 0; b < CC_NUM_BREAKPOINTS; b++) {
207                 if (breakpoints[b].enabled != 0 &&
208                     ((breakpoints[b].temporary != 0) == (temporary != 0)) &&
209                     breakpoints[b].address == address)
210                         break;
211         }
212         if (b == CC_NUM_BREAKPOINTS) {
213                 fprintf(output, "Error: no matching breakpoint found\n");
214                 return command_proceed;
215         }
216         --breakpoints[b].enabled;
217         --breakpoints[b].temporary;
218         if (breakpoints[b].enabled == 0) {
219                 breakpoints[b].address = -1;
220                 ccdbg_set_hw_brkpnt(s51_dbg, b, 0, address);
221                 fprintf(output, "set_hw_brkpnt status 0x%02x\n", status);
222         }
223         return command_proceed;
224 }
225
226 enum command_result
227 command_break (FILE *output, int argc, char **argv)
228 {
229         int b;
230         uint16_t address;
231         enum command_result result;
232
233         if (argc == 1) {
234                 for (b = 0; b < CC_NUM_BREAKPOINTS; b++)
235                         if (breakpoints[b].enabled)
236                                 fprintf(output, "Breakpoint %d 0x%04x\n",
237                                         b, breakpoints[b].address);
238                 return command_proceed;
239         }
240         if (argc != 2)
241                 return command_error;
242         result = parse_uint16(argv[1], &address);
243         if (result != command_proceed)
244                 return result;
245
246         return set_breakpoint(output, address, 0);
247 }
248
249 enum command_result
250 command_clear (FILE *output, int argc, char **argv)
251 {
252         int b;
253         uint16_t address;
254         enum command_result result;
255
256         if (argc != 2)
257                 return command_error;
258         result = parse_uint16(argv[1], &address);
259         if (result != command_proceed)
260                 return result;
261         return clear_breakpoint(output, address, 0);
262 }
263
264 enum command_result
265 command_run (FILE *output, int argc, char **argv)
266 {
267         uint16_t start, end;
268         enum command_result result;
269         
270         if (argv[1]) {
271                 result = parse_uint16(argv[1], &start);
272                 if (result != command_proceed)
273                         return result;
274                 if (argv[2]) {
275                         result = parse_uint16(argv[2], &end);
276                         if (result != command_proceed)
277                                 return result;
278                 }
279                 ccdbg_set_pc(s51_dbg, start);
280         }
281         else
282                 start = ccdbg_get_pc(s51_dbg);
283         fprintf(output, "Resume at 0x%04x\n", start);
284         ccdbg_resume(s51_dbg);
285 //      cc_wait(s51_dbg);
286         return command_proceed;
287 }
288
289 enum command_result
290 command_next (FILE *output, int argc, char **argv)
291 {
292         return command_step(output, argc, argv);
293 }
294
295 enum command_result
296 command_step (FILE *output, int argc, char **argv)
297 {
298         uint16_t pc;
299         uint8_t opcode;
300         uint8_t a;
301
302         a = ccdbg_step_instr(s51_dbg);
303         fprintf(output, " ACC= 0x%02x\n", a);
304         pc = ccdbg_get_pc(s51_dbg);
305         ccdbg_read_memory(s51_dbg, pc, &opcode, 1);
306         fprintf(output, " ? 0x%04x %02x\n", pc, opcode);
307         return command_proceed;
308 }
309
310 enum command_result
311 command_load (FILE *output, int argc, char **argv)
312 {
313         return command_error;
314 }
315
316 enum command_result
317 command_halt (FILE *output, int argc, char **argv)
318 {
319         uint16_t        pc;
320         ccdbg_halt(s51_dbg);
321         pc = ccdbg_get_pc(s51_dbg);
322         fprintf(output, "Halted at 0x%04x\n", pc);
323         return command_proceed;
324 }
325
326 enum command_result
327 command_reset (FILE *output, int argc, char **argv)
328 {
329         ccdbg_debug_mode(s51_dbg);
330         return command_proceed;
331 }
332
333 enum command_result
334 command_status(FILE *output, int argc, char **argv)
335 {
336         uint8_t status;
337
338         status = ccdbg_read_status(s51_dbg);
339         if ((status & CC_STATUS_CHIP_ERASE_DONE) == 0)
340                 fprintf(output, "\tChip erase in progress\n");
341         if (status & CC_STATUS_PCON_IDLE)
342                 fprintf(output, "\tCPU is idle (clock gated)\n");
343         if (status & CC_STATUS_CPU_HALTED)
344                 fprintf(output, "\tCPU halted\n");
345         else
346                 fprintf(output, "\tCPU running\n");
347         if ((status & CC_STATUS_POWER_MODE_0) == 0)
348                 fprintf(output, "\tPower Mode 1-3 selected\n");
349         if (status & CC_STATUS_HALT_STATUS)
350                 fprintf(output, "\tHalted by software or hw breakpoint\n");
351         else
352                 fprintf(output, "\tHalted by debug command\n");
353         if (status & CC_STATUS_DEBUG_LOCKED)
354                 fprintf(output, "\tDebug interface is locked\n");
355         if ((status & CC_STATUS_OSCILLATOR_STABLE) == 0)
356                 fprintf(output, "\tOscillators are not stable\n");
357         if (status & CC_STATUS_STACK_OVERFLOW)
358                 fprintf(output, "\tStack overflow\n");
359         return command_proceed;
360 }
361
362 uint8_t cc_wait(struct ccdbg *dbg)
363 {
364         uint8_t status;
365         for(;;) {
366                 status = ccdbg_read_status(dbg);
367                 if (status & CC_STATUS_CPU_HALTED)
368                         break;
369         }
370         return status;
371 }