3623bd7a539d98d2ec1937ae89a3427bdd4f9354
[fw/sdcc] / sim / ucsim / cmd.src / cmduc.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/cmduc.cc)
3  *
4  * Copyright (C) 2001,01 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 // prj
29 #include "globals.h"
30 #include "utils.h"
31
32 // sim.src
33 #include "uccl.h"
34
35 // local, cmd.src
36 #include "cmduccl.h"
37
38
39 /*
40  * Command: state
41  *----------------------------------------------------------------------------
42  */
43
44 //int
45 //cl_state_cmd::do_work(class cl_sim *sim,
46 //                    class cl_cmdline *cmdline, class cl_console *con)
47 COMMAND_DO_WORK_UC(cl_state_cmd)
48 {
49   con->dd_printf("CPU state= %s PC= 0x%06x XTAL= %g\n",
50                  get_id_string(cpu_states, uc->state),
51                  uc->PC, 
52                  uc->xtal);
53   con->dd_printf("Total time since last reset= %g sec (%lu clks)\n",
54                  uc->get_rtime(), uc->ticks->ticks);
55   con->dd_printf("Time in isr = %g sec (%lu clks) %3.2g%%\n",
56                  uc->isr_ticks->get_rtime(uc->xtal),
57                  uc->isr_ticks->ticks,
58                  (uc->ticks->ticks == 0)?0.0:
59                  (100.0*((double)(uc->isr_ticks->ticks)/
60                          (double)(uc->ticks->ticks))));
61   con->dd_printf("Time in idle= %g sec (%lu clks) %3.2g%%\n",
62                  uc->idle_ticks->get_rtime(uc->xtal),
63                  uc->idle_ticks->ticks,
64                  (uc->ticks->ticks == 0)?0.0:
65                  (100.0*((double)(uc->idle_ticks->ticks)/
66                          (double)(uc->ticks->ticks))));
67   con->dd_printf("Max value of stack pointer= 0x%06x, avg= 0x%06x\n",
68                  uc->sp_max, uc->sp_avg);
69   return(0);
70 }
71
72
73 /*
74  * Command: file
75  *----------------------------------------------------------------------------
76  */
77
78 //int
79 //cl_file_cmd::do_work(class cl_sim *sim,
80 //                   class cl_cmdline *cmdline, class cl_console *con)
81 COMMAND_DO_WORK_UC(cl_file_cmd)
82 {
83   char *fname= 0;
84   long l;
85   
86   if ((cmdline->param(0) == 0) ||
87       ((fname= cmdline->param(0)->get_svalue()) == NULL))
88     {
89       con->dd_printf("File name is missing.\n");
90       return(0);
91     }
92   if ((l= uc->read_hex_file(fname)) >= 0)
93     con->dd_printf("%ld words read from %s\n", l, fname);
94
95   return(0);
96 }
97
98
99 /*
100  * Command: download
101  *----------------------------------------------------------------------------
102  */
103
104 //int
105 //cl_dl_cmd::do_work(class cl_sim *sim,
106 //                 class cl_cmdline *cmdline, class cl_console *con)
107 COMMAND_DO_WORK_UC(cl_dl_cmd)
108 {
109   long l;
110   
111   if ((l= uc->read_hex_file(NULL)) >= 0)
112     con->dd_printf("%ld words loaded\n", l);
113
114   return(0);
115 }
116
117
118 /*
119  * Command: pc
120  *----------------------------------------------------------------------------
121  */
122
123 //int
124 //cl_pc_cmd::do_work(class cl_sim *sim,
125 //                 class cl_cmdline *cmdline, class cl_console *con)
126 COMMAND_DO_WORK_UC(cl_pc_cmd)
127 {
128   t_addr addr;
129   class cl_cmd_arg *params[1]= { cmdline->param(0) };
130
131   if (params[0])
132     {
133       if (!(params[0]->get_address(uc, &addr)))
134         {
135           con->dd_printf("Error: wrong parameter\n");
136           return(DD_FALSE);
137         }
138       if (addr >= uc->get_mem_size(MEM_ROM))
139         addr= 0;
140       if (!uc->inst_at(addr))
141         con->dd_printf("Warning: maybe not instruction at 0x%06x\n", addr);
142       uc->PC= addr;
143     }
144   uc->print_disass(uc->PC, con);
145   return(DD_FALSE);
146 }
147
148
149 /*
150  * Command: reset
151  *----------------------------------------------------------------------------
152  */
153
154 //int
155 //cl_reset_cmd::do_work(class cl_sim *sim,
156 //                    class cl_cmdline *cmdline, class cl_console *con)
157 COMMAND_DO_WORK_UC(cl_reset_cmd)
158 {
159   uc->reset();
160   return(0);
161 }
162
163
164 /*
165  * Command: dump
166  *----------------------------------------------------------------------------
167  */
168
169 //int
170 //cl_dump_cmd::do_work(class cl_sim *sim,
171 //                   class cl_cmdline *cmdline, class cl_console *con)
172 COMMAND_DO_WORK_UC(cl_dump_cmd)
173 {
174   class cl_mem *mem= 0;
175   long bpl= 8;
176   t_addr start= 0, end;
177   class cl_cmd_arg *params[4]= { cmdline->param(0),
178                                  cmdline->param(1),
179                                  cmdline->param(2),
180                                  cmdline->param(3) };
181
182   if (params[0] &&
183       params[0]->as_bit(uc))
184     {
185       int i= 0;
186       while (params[0] &&
187              params[0]->as_bit(uc))
188         {
189           t_mem m;
190           mem= params[0]->value.bit.mem;
191           m= mem->read(params[0]->value.bit.mem_address);
192           char *sn=
193             uc->symbolic_bit_name((t_addr)-1,
194                                   mem,
195                                   params[0]->value.bit.mem_address,
196                                   params[0]->value.bit.mask);
197           con->dd_printf("%10s ", sn?sn:"");
198           con->dd_printf(mem->addr_format, params[0]->value.bit.mem_address);
199           con->dd_printf(" ");
200           con->dd_printf(mem->data_format, m);
201           con->dd_printf(" %c\n", (m&(params[0]->value.bit.mask))?'1':'0');
202           i++;
203           params[0]= cmdline->param(i);
204         }
205       if (params[0])
206         con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
207     }
208   else if (cmdline->syntax_match(uc, MEMORY))
209     {
210       mem= params[0]->value.memory;
211       mem->dump(con);
212     }
213   else if (cmdline->syntax_match(uc, MEMORY ADDRESS)) {
214     mem  = params[0]->value.memory;
215     start= params[1]->value.address;
216     end  = start+10*8-1;
217     mem->dump(start, end, bpl, con);
218   }
219   else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS)) {
220     mem  = params[0]->value.memory;
221     start= params[1]->value.address;
222     end  = params[2]->value.address;
223     mem->dump(start, end, bpl, con);
224   }
225   else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) {
226     mem  = params[0]->value.memory;
227     start= params[1]->value.address;
228     end  = params[2]->value.address;
229     bpl  = params[3]->value.number;
230     mem->dump(start, end, bpl, con);
231   }
232   else
233     con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
234
235   return(DD_FALSE);;
236 }
237
238
239 /*
240  * Command: di
241  *----------------------------------------------------------------------------
242  */
243
244 //int
245 //cl_di_cmd::do_work(class cl_sim *sim,
246 //                 class cl_cmdline *cmdline, class cl_console *con)
247 COMMAND_DO_WORK_UC(cl_di_cmd)
248 {
249   cmdline->insert_param(0, new cl_cmd_sym_arg("i"));
250   cl_dump_cmd::do_work(uc, cmdline, con);
251   return(0);
252 }
253
254
255 /*
256  * Command: dx
257  *----------------------------------------------------------------------------
258  */
259
260 //int
261 //cl_dx_cmd::do_work(class cl_sim *sim,
262 //                 class cl_cmdline *cmdline, class cl_console *con)
263 COMMAND_DO_WORK_UC(cl_dx_cmd)
264 {
265   cmdline->insert_param(0, new cl_cmd_sym_arg("x"));
266   cl_dump_cmd::do_work(uc, cmdline, con);
267   return(0);
268 }
269
270
271 /*
272  * Command: dch
273  *----------------------------------------------------------------------------
274  */
275
276 //int
277 //cl_dch_cmd::do_work(class cl_sim *sim,
278 //                  class cl_cmdline *cmdline, class cl_console *con)
279 COMMAND_DO_WORK_UC(cl_dch_cmd)
280 {
281   cmdline->insert_param(0, new cl_cmd_sym_arg("r"));
282   cl_dump_cmd::do_work(uc, cmdline, con);
283   return(0);
284 }
285
286
287 /*
288  * Command: ds
289  *----------------------------------------------------------------------------
290  */
291
292 //int
293 //cl_ds_cmd::do_work(class cl_sim *sim,
294 //                 class cl_cmdline *cmdline, class cl_console *con)
295 COMMAND_DO_WORK_UC(cl_ds_cmd)
296 {
297   cmdline->insert_param(0, new cl_cmd_sym_arg("s"));
298   cl_dump_cmd::do_work(uc, cmdline, con);
299   return(0);
300 }
301
302
303 /*
304  * Command: dc
305  *----------------------------------------------------------------------------
306  */
307
308 //int
309 //cl_dc_cmd::do_work(class cl_sim *sim,
310 //                 class cl_cmdline *cmdline, class cl_console *con)
311 COMMAND_DO_WORK_UC(cl_dc_cmd)
312 {
313   t_addr start= last, end= last+20;
314   class cl_cmd_arg *params[2]= { cmdline->param(0),
315                                  cmdline->param(1) };
316   class cl_mem *rom= uc->mem(MEM_ROM);
317
318   if (!rom)
319     return(DD_FALSE);
320   if (params[0] == 0)
321     ;
322   else if (cmdline->syntax_match(uc, ADDRESS)) {
323     start= params[0]->value.address;
324     end= start+20;
325   }
326   else if (cmdline->syntax_match(uc, ADDRESS ADDRESS)) {
327     start= params[0]->value.address;
328     end= params[1]->value.address;
329   }
330   if (start >= rom->size)
331     {
332       con->dd_printf("Error: start address is wrong\n");
333       return(DD_FALSE);
334     }
335   if (end >= rom->size)
336     {
337       con->dd_printf("Error: end address is wrong\n");
338       return(DD_FALSE);
339     }
340
341   for (;
342        start <= end;
343        start+= uc->inst_length(start))
344     uc->print_disass(start, con);
345   last= start;
346   return(DD_FALSE);
347 }
348
349
350 /*
351  * Command: disassemble
352  *----------------------------------------------------------------------------
353  */
354
355 static int disass_last_stop= 0;
356
357 //int
358 //cl_disassemble_cmd::do_work(class cl_sim *sim,
359 //                          class cl_cmdline *cmdline, class cl_console *con)
360 COMMAND_DO_WORK_UC(cl_disassemble_cmd)
361 {
362   t_addr start, realstart;
363   int offset= -1, dir, lines= 20;
364   class cl_cmd_arg *params[4]= { cmdline->param(0),
365                                  cmdline->param(1),
366                                  cmdline->param(2),
367                                  cmdline->param(3) };
368
369   start= disass_last_stop;
370   if (params[0] == 0) ;
371   else if (cmdline->syntax_match(uc, ADDRESS)) {
372     start= params[0]->value.address;
373   }
374   else if (cmdline->syntax_match(uc, ADDRESS NUMBER)) {
375     start= params[0]->value.address;
376     offset= params[1]->value.number;
377   }
378   else if (cmdline->syntax_match(uc, ADDRESS NUMBER NUMBER)) {
379     start= params[0]->value.address;
380     offset= params[1]->value.number;
381     lines= params[2]->value.number;
382   }
383   else
384     {
385       con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
386       return(DD_FALSE);
387     }
388
389   if (lines < 1)
390     {
391       con->dd_printf("Error: wrong `lines' parameter\n");
392       return(DD_FALSE);
393     }
394   if (!uc->there_is_inst())
395     return(DD_FALSE);
396   realstart= start;
397   class cl_mem *rom= uc->mem(MEM_ROM);
398   if (!rom)
399     return(DD_FALSE);
400   while (realstart < rom->size &&
401          !uc->inst_at(realstart))
402     realstart= realstart+1;
403   if (offset)
404     {
405       dir= (offset < 0)?-1:+1;
406       while (offset)
407         {
408           realstart= (realstart+dir) % rom->size;
409           while (!uc->inst_at(realstart))
410             realstart= (realstart+dir) % rom->size;
411           offset+= -dir;
412         }
413     }
414   
415   while (lines)
416     {
417       uc->print_disass(realstart, con);
418       realstart= (realstart+1) % rom->size;
419       while (!uc->inst_at(realstart))
420         realstart= (realstart+1) % rom->size;
421       lines--;
422     }
423
424   disass_last_stop= realstart;
425
426   return(DD_FALSE);;
427 }
428
429
430 /*
431  * Command: fill
432  *----------------------------------------------------------------------------
433  */
434
435 //int
436 //cl_fill_cmd::do_work(class cl_sim *sim,
437 //                   class cl_cmdline *cmdline, class cl_console *con)
438 COMMAND_DO_WORK_UC(cl_fill_cmd)
439 {
440   class cl_mem *mem= 0;
441   t_mem what= 0;
442   t_addr start= 0, end;
443   class cl_cmd_arg *params[4]= { cmdline->param(0),
444                                  cmdline->param(1),
445                                  cmdline->param(2),
446                                  cmdline->param(3) };
447
448   if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) {
449     mem  = params[0]->value.memory;
450     start= params[1]->value.address;
451     end  = params[2]->value.address;
452     what = params[3]->value.number;
453     t_addr i;
454     for (i= start; i <= end; i++)
455       {
456         t_mem d;
457         d= what;
458         mem->write(i, d);
459       }
460   }
461   else
462     con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
463
464   return(DD_FALSE);;
465 }
466
467
468 /*
469  * Command: where
470  *----------------------------------------------------------------------------
471  */
472
473 int
474 cl_where_cmd::do_real_work(class cl_uc *uc,
475                            class cl_cmdline *cmdline, class cl_console *con,
476                            bool case_sensitive)
477 {
478   class cl_mem *mem= 0;
479   class cl_cmd_arg *params[2]= { cmdline->param(0),
480                                  cmdline->param(1) };
481
482   if (cmdline->syntax_match(uc, MEMORY DATALIST)) {
483     mem= params[0]->value.memory;
484     t_mem *array= params[1]->value.data_list.array;
485     int len= params[1]->value.data_list.len;
486     if (!len)
487       {
488         con->dd_printf("Error: nothing to search for\n");
489         return(DD_FALSE);
490       }
491     t_addr addr= 0;
492     bool found= mem->search_next(case_sensitive, array, len, &addr);
493     while (found)
494       {
495         mem->dump(addr, addr+len-1, 8, con);
496         addr++;
497         found= mem->search_next(case_sensitive, array, len, &addr);
498       }
499   }
500   else
501     con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
502
503   return(DD_FALSE);
504 }
505
506 //int
507 //cl_where_cmd::do_work(class cl_sim *sim,
508 //                    class cl_cmdline *cmdline, class cl_console *con)
509 COMMAND_DO_WORK_UC(cl_where_cmd)
510 {
511   return(do_real_work(uc, cmdline, con, DD_FALSE));
512 }
513
514 //int
515 //cl_Where_cmd::do_work(class cl_sim *sim,
516 //                    class cl_cmdline *cmdline, class cl_console *con)
517 COMMAND_DO_WORK_UC(cl_Where_cmd)
518 {
519   return(do_real_work(uc, cmdline, con, DD_TRUE));
520 }
521
522
523 /* End of cmd.src/cmduc.cc */