version 0.5.2
[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       class cl_address_space *rom= uc->address_space(MEM_ROM_ID);
139       if (rom)
140         {
141           if (addr > rom->highest_valid_address())
142             addr= rom->highest_valid_address();
143         }
144       if (!uc->inst_at(addr))
145         con->dd_printf("Warning: maybe not instruction at 0x%06x\n", addr);
146       uc->PC= addr;
147     }
148   uc->print_disass(uc->PC, con);
149   return(DD_FALSE);
150 }
151
152
153 /*
154  * Command: reset
155  *----------------------------------------------------------------------------
156  */
157
158 //int
159 //cl_reset_cmd::do_work(class cl_sim *sim,
160 //                    class cl_cmdline *cmdline, class cl_console *con)
161 COMMAND_DO_WORK_UC(cl_reset_cmd)
162 {
163   uc->reset();
164   return(0);
165 }
166
167
168 /*
169  * Command: dump
170  *----------------------------------------------------------------------------
171  */
172
173 //int
174 //cl_dump_cmd::do_work(class cl_sim *sim,
175 //                   class cl_cmdline *cmdline, class cl_console *con)
176 COMMAND_DO_WORK_UC(cl_dump_cmd)
177 {
178   class cl_memory *mem= 0;
179   long bpl= 8;
180   t_addr start= 0, end;
181   class cl_cmd_arg *params[4]= { cmdline->param(0),
182                                  cmdline->param(1),
183                                  cmdline->param(2),
184                                  cmdline->param(3) };
185
186   if (params[0] &&
187       params[0]->as_bit(uc))
188     {
189       int i= 0;
190       while (params[0] &&
191              params[0]->as_bit(uc))
192         {
193           t_mem m;
194           mem= params[0]->value.bit.mem;
195           m= mem->read(params[0]->value.bit.mem_address);
196           char *sn=
197             uc->symbolic_bit_name((t_addr)-1,
198                                   mem,
199                                   params[0]->value.bit.mem_address,
200                                   params[0]->value.bit.mask);
201           con->dd_printf("%10s ", sn?sn:"");
202           con->dd_printf(mem->addr_format, params[0]->value.bit.mem_address);
203           con->dd_printf(" ");
204           con->dd_printf(mem->data_format, m);
205           con->dd_printf(" %c\n", (m&(params[0]->value.bit.mask))?'1':'0');
206           i++;
207           params[0]= cmdline->param(i);
208         }
209       if (params[0])
210         con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
211     }
212   else
213     {
214       if (!params[0] ||
215           !params[0]->as_memory(uc))
216         {
217           con->dd_printf("No memory specified. Use \"info memory\" for available memories\n");
218           return(DD_FALSE);
219         }
220       if (cmdline->syntax_match(uc, MEMORY))
221         {
222           mem= params[0]->value.memory.memory;
223           mem->dump(con);
224         }
225       else if (cmdline->syntax_match(uc, MEMORY ADDRESS)) {
226         mem  = params[0]->value.memory.memory;
227         start= params[1]->value.address;
228         end  = start+10*8-1;
229         mem->dump(start, end, bpl, con);
230       }
231       else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS)) {
232         mem  = params[0]->value.memory.memory;
233         start= params[1]->value.address;
234         end  = params[2]->value.address;
235         mem->dump(start, end, bpl, con);
236       }
237       else if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) {
238         mem  = params[0]->value.memory.memory;
239         start= params[1]->value.address;
240         end  = params[2]->value.address;
241         bpl  = params[3]->value.number;
242         mem->dump(start, end, bpl, con);
243       }
244       else
245         con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
246     }
247
248   return(DD_FALSE);;
249 }
250
251
252 /*
253  * Command: di
254  *----------------------------------------------------------------------------
255  */
256
257 //int
258 //cl_di_cmd::do_work(class cl_sim *sim,
259 //                 class cl_cmdline *cmdline, class cl_console *con)
260 COMMAND_DO_WORK_UC(cl_di_cmd)
261 {
262   cmdline->insert_param(0, new cl_cmd_sym_arg("iram"));
263   cl_dump_cmd::do_work(uc, cmdline, con);
264   return(0);
265 }
266
267
268 /*
269  * Command: dx
270  *----------------------------------------------------------------------------
271  */
272
273 //int
274 //cl_dx_cmd::do_work(class cl_sim *sim,
275 //                 class cl_cmdline *cmdline, class cl_console *con)
276 COMMAND_DO_WORK_UC(cl_dx_cmd)
277 {
278   cmdline->insert_param(0, new cl_cmd_sym_arg("xram"));
279   cl_dump_cmd::do_work(uc, cmdline, con);
280   return(0);
281 }
282
283
284 /*
285  * Command: dch
286  *----------------------------------------------------------------------------
287  */
288
289 //int
290 //cl_dch_cmd::do_work(class cl_sim *sim,
291 //                  class cl_cmdline *cmdline, class cl_console *con)
292 COMMAND_DO_WORK_UC(cl_dch_cmd)
293 {
294   cmdline->insert_param(0, new cl_cmd_sym_arg("rom"));
295   cl_dump_cmd::do_work(uc, cmdline, con);
296   return(0);
297 }
298
299
300 /*
301  * Command: ds
302  *----------------------------------------------------------------------------
303  */
304
305 //int
306 //cl_ds_cmd::do_work(class cl_sim *sim,
307 //                 class cl_cmdline *cmdline, class cl_console *con)
308 COMMAND_DO_WORK_UC(cl_ds_cmd)
309 {
310   cmdline->insert_param(0, new cl_cmd_sym_arg("sfr"));
311   cl_dump_cmd::do_work(uc, cmdline, con);
312   return(0);
313 }
314
315
316 /*
317  * Command: dc
318  *----------------------------------------------------------------------------
319  */
320
321 //int
322 //cl_dc_cmd::do_work(class cl_sim *sim,
323 //                 class cl_cmdline *cmdline, class cl_console *con)
324 COMMAND_DO_WORK_UC(cl_dc_cmd)
325 {
326   t_addr start= last, end= last+20;
327   class cl_cmd_arg *params[2]= { cmdline->param(0),
328                                  cmdline->param(1) };
329   class cl_address_space *rom= uc->address_space(MEM_ROM_ID);
330
331   if (!rom)
332     return(DD_FALSE);
333   if (params[0] == 0)
334     ;
335   else if (cmdline->syntax_match(uc, ADDRESS)) {
336     start= params[0]->value.address;
337     end= start+20;
338   }
339   else if (cmdline->syntax_match(uc, ADDRESS ADDRESS)) {
340     start= params[0]->value.address;
341     end= params[1]->value.address;
342   }
343   if (start > rom->highest_valid_address())
344     {
345       con->dd_printf("Error: start address is too high\n");
346       return(DD_FALSE);
347     }
348   if (end > rom->highest_valid_address())
349     {
350       con->dd_printf("Error: end address is too high\n");
351       return(DD_FALSE);
352     }
353
354   for (;
355        start <= end;
356        start+= uc->inst_length(start))
357     uc->print_disass(start, con);
358   last= start;
359   return(DD_FALSE);
360 }
361
362
363 /*
364  * Command: disassemble
365  *----------------------------------------------------------------------------
366  */
367
368 static int disass_last_stop= 0;
369
370 //int
371 //cl_disassemble_cmd::do_work(class cl_sim *sim,
372 //                          class cl_cmdline *cmdline, class cl_console *con)
373 COMMAND_DO_WORK_UC(cl_disassemble_cmd)
374 {
375   t_addr start, realstart;
376   int offset= -1, dir, lines= 20;
377   class cl_cmd_arg *params[4]= { cmdline->param(0),
378                                  cmdline->param(1),
379                                  cmdline->param(2),
380                                  cmdline->param(3) };
381
382   start= disass_last_stop;
383   if (params[0] == 0) ;
384   else if (cmdline->syntax_match(uc, ADDRESS)) {
385     start= params[0]->value.address;
386   }
387   else if (cmdline->syntax_match(uc, ADDRESS NUMBER)) {
388     start= params[0]->value.address;
389     offset= params[1]->value.number;
390   }
391   else if (cmdline->syntax_match(uc, ADDRESS NUMBER NUMBER)) {
392     start= params[0]->value.address;
393     offset= params[1]->value.number;
394     lines= params[2]->value.number;
395   }
396   else
397     {
398       con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
399       return(DD_FALSE);
400     }
401
402   if (lines < 1)
403     {
404       con->dd_printf("Error: wrong `lines' parameter\n");
405       return(DD_FALSE);
406     }
407   if (!uc->there_is_inst())
408     return(DD_FALSE);
409   realstart= start;
410   class cl_address_space *rom= uc->address_space(MEM_ROM_ID);
411   if (!rom)
412     return(DD_FALSE);
413   while (realstart <= rom->highest_valid_address() &&
414          !uc->inst_at(realstart))
415     realstart= realstart+1;
416   if (offset)
417     {
418       dir= (offset < 0)?-1:+1;
419       while (offset)
420         {
421           realstart= rom->inc_address(realstart, dir);
422           while (!uc->inst_at(realstart))
423             realstart= rom->inc_address(realstart, dir);
424           offset+= -dir;
425         }
426     }
427   
428   while (lines)
429     {
430       uc->print_disass(realstart, con);
431       realstart= rom->inc_address(realstart, +1) + rom->start_address;
432       while (!uc->inst_at(realstart))
433         realstart= rom->inc_address(realstart, +1) + rom->start_address;
434       lines--;
435     }
436
437   disass_last_stop= realstart;
438
439   return(DD_FALSE);;
440 }
441
442
443 /*
444  * Command: fill
445  *----------------------------------------------------------------------------
446  */
447
448 //int
449 //cl_fill_cmd::do_work(class cl_sim *sim,
450 //                   class cl_cmdline *cmdline, class cl_console *con)
451 COMMAND_DO_WORK_UC(cl_fill_cmd)
452 {
453   class cl_memory *mem= 0;
454   t_mem what= 0;
455   t_addr start= 0, end;
456   class cl_cmd_arg *params[4]= { cmdline->param(0),
457                                  cmdline->param(1),
458                                  cmdline->param(2),
459                                  cmdline->param(3) };
460
461   if (cmdline->syntax_match(uc, MEMORY ADDRESS ADDRESS NUMBER)) {
462     mem  = params[0]->value.memory.memory;
463     start= params[1]->value.address;
464     end  = params[2]->value.address;
465     what = params[3]->value.number;
466     t_addr i;
467     for (i= start; i <= end; i++)
468       {
469         t_mem d;
470         d= what;
471         mem->write(i, d);
472       }
473   }
474   else
475     con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
476
477   return(DD_FALSE);;
478 }
479
480
481 /*
482  * Command: where
483  *----------------------------------------------------------------------------
484  */
485
486 int
487 cl_where_cmd::do_real_work(class cl_uc *uc,
488                            class cl_cmdline *cmdline, class cl_console *con,
489                            bool case_sensitive)
490 {
491   class cl_memory *mem= 0;
492   class cl_cmd_arg *params[2]= { cmdline->param(0),
493                                  cmdline->param(1) };
494
495   if (cmdline->syntax_match(uc, MEMORY DATALIST)) {
496     mem= params[0]->value.memory.memory;
497     t_mem *array= params[1]->value.data_list.array;
498     int len= params[1]->value.data_list.len;
499     if (!len)
500       {
501         con->dd_printf("Error: nothing to search for\n");
502         return(DD_FALSE);
503       }
504     t_addr addr= 0;
505     bool found= mem->search_next(case_sensitive, array, len, &addr);
506     while (found)
507       {
508         mem->dump(addr, addr+len-1, 8, con);
509         addr++;
510         found= mem->search_next(case_sensitive, array, len, &addr);
511       }
512   }
513   else
514     con->dd_printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
515
516   return(DD_FALSE);
517 }
518
519 //int
520 //cl_where_cmd::do_work(class cl_sim *sim,
521 //                    class cl_cmdline *cmdline, class cl_console *con)
522 COMMAND_DO_WORK_UC(cl_where_cmd)
523 {
524   return(do_real_work(uc, cmdline, con, DD_FALSE));
525 }
526
527 //int
528 //cl_Where_cmd::do_work(class cl_sim *sim,
529 //                    class cl_cmdline *cmdline, class cl_console *con)
530 COMMAND_DO_WORK_UC(cl_Where_cmd)
531 {
532   return(do_real_work(uc, cmdline, con, DD_TRUE));
533 }
534
535
536 /* End of cmd.src/cmduc.cc */