version 0.2.39: fix of arith insts and start of re-structure
[fw/sdcc] / sim / ucsim / cmd.src / cmdset.cc
1 /*
2  * Simulator of microcontrollers (cmd.src/cmdset.cc)
3  *
4  * Copyright (C) 1999,99 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 #include "ddconfig.h"
29
30 #include "i_string.h"
31
32 #include "globals.h"
33 #include "utils.h"
34
35 // sim
36 #include "simcl.h"
37
38 // local
39 #include "cmdsetcl.h"
40 #include "cmdutil.h"
41
42
43 /*
44  * Command: state
45  *----------------------------------------------------------------------------
46  */
47
48 int
49 cl_state_cmd::do_work(class cl_sim *sim,
50                       class cl_cmdline *cmdline, class cl_console *con)
51 {
52   //con->printf("sim state= %d\n", sim->state);
53   con->printf("CPU state= %s PC= 0x%06x XTAL= %g\n",
54               get_id_string(cpu_states, sim->uc->state),
55               sim->uc->PC, 
56               sim->uc->xtal);
57   con->printf("Total time since last reset= %g sec (%lu clks)\n",
58               sim->uc->get_rtime(), sim->uc->ticks->ticks);
59   con->printf("Time in isr = %g sec (%lu clks) %3.2g%%\n",
60               sim->uc->isr_ticks->get_rtime(sim->uc->xtal),
61               sim->uc->isr_ticks->ticks,
62               (sim->uc->ticks->ticks == 0)?0.0:
63               (100.0*((double)(sim->uc->isr_ticks->ticks)/
64                       (double)(sim->uc->ticks->ticks))));
65   con->printf("Time in idle= %g sec (%lu clks) %3.2g%%\n",
66               sim->uc->idle_ticks->get_rtime(sim->uc->xtal),
67               sim->uc->idle_ticks->ticks,
68               (sim->uc->ticks->ticks == 0)?0.0:
69               (100.0*((double)(sim->uc->idle_ticks->ticks)/
70                       (double)(sim->uc->ticks->ticks))));
71   con->printf("Max value of stack pointer= 0x%06x, avg= 0x%06x\n",
72               sim->uc->sp_max, sim->uc->sp_avg);
73   return(0);
74 }
75
76
77 /*
78  * Command: file
79  *----------------------------------------------------------------------------
80  */
81
82 int
83 cl_file_cmd::do_work(class cl_sim *sim,
84                      class cl_cmdline *cmdline, class cl_console *con)
85 {
86   char *fname= 0;
87   long l;
88   
89   if ((cmdline->param(0) == 0) ||
90       ((fname= cmdline->param(0)->get_svalue()) == NULL))
91     {
92       con->printf("File name is missing.\n");
93       return(0);
94     }
95   if ((l= sim->uc->read_hex_file(fname)) >= 0)
96     con->printf("%ld words read from %s\n", l, fname);
97
98   return(0);
99 }
100
101
102 /*
103  * Command: download
104  *----------------------------------------------------------------------------
105  */
106
107 int
108 cl_dl_cmd::do_work(class cl_sim *sim,
109                    class cl_cmdline *cmdline, class cl_console *con)
110 {
111   long l;
112   
113   if ((l= sim->uc->read_hex_file(NULL)) >= 0)
114     con->printf("%ld words loaded\n", l);
115
116   return(0);
117 }
118
119
120 /*
121  * Command: run
122  *----------------------------------------------------------------------------
123  */
124
125 int
126 cl_run_cmd::do_work(class cl_sim *sim,
127                     class cl_cmdline *cmdline, class cl_console *con)
128 {
129   class cl_brk *b;
130   t_addr start, end;
131   class cl_cmd_arg *params[4]= { cmdline->param(0),
132                                  cmdline->param(1),
133                                  cmdline->param(2),
134                                  cmdline->param(3) };
135
136   if (params[0])
137     if (!(params[0]->get_address(&start)))
138       {
139         con->printf("Error: wrong start address\n");
140         return(DD_FALSE);
141       }
142   if (params[1])
143     if (!(params[1]->get_address(&end)))
144       {
145         con->printf("Error: wromg end address\n");
146         return(DD_FALSE);
147       }
148   if (params[0])
149     {
150       if (!sim->uc->inst_at(start))
151         con->printf("Warning: maybe not instruction at 0x%06lx\n", start);
152       sim->uc->PC= start;
153       if (params[1])
154         {
155           if (start == end)
156             {
157               con->printf("Addresses must be different.\n");
158               return(DD_FALSE);
159             }
160           if ((b= sim->uc->fbrk_at(end)))
161             {
162             }
163           else
164             {
165               b= new cl_fetch_brk(sim->uc->make_new_brknr(), end,
166                                   brkDYNAMIC, 1);
167               sim->uc->fbrk->add_bp(b);
168             }
169         }
170     }
171   con->printf("Simulation started, PC=0x%06x\n", sim->uc->PC);
172   if (sim->uc->fbrk_at(start))
173     sim->uc->do_inst(1);
174   sim->start(con);
175   return(DD_FALSE);
176 }
177
178
179 /*
180  * Command: stop
181  *----------------------------------------------------------------------------
182  */
183
184 int
185 cl_stop_cmd::do_work(class cl_sim *sim,
186                      class cl_cmdline *cmdline, class cl_console *con)
187 {
188   sim->stop(resUSER);
189   sim->uc->print_disass(sim->uc->PC, con);
190   return(DD_FALSE);
191 }
192
193
194 /*
195  * Command: step
196  *----------------------------------------------------------------------------
197  */
198
199 int
200 cl_step_cmd::do_work(class cl_sim *sim,
201                      class cl_cmdline *cmdline, class cl_console *con)
202 {
203   sim->uc->do_inst(1);
204   sim->uc->print_regs(con);
205   return(0);
206 }
207
208
209 /*
210  * Command: next
211  *----------------------------------------------------------------------------
212  */
213
214 int
215 cl_next_cmd::do_work(class cl_sim *sim,
216                      class cl_cmdline *cmdline, class cl_console *con)
217 {
218   class cl_brk *b;
219   t_addr next;
220   struct dis_entry *de;
221
222   t_mem code= sim->uc->get_mem(MEM_ROM, sim->uc->PC);
223   int i= 0;
224   de= &(sim->uc->dis_tbl()[i]);
225   while ((code & de->mask) != de->code &&
226          de->mnemonic)
227     {
228       i++;
229       de= &(sim->uc->dis_tbl()[i]);
230     }
231   if ((de->branch == 'a') ||
232       (de->branch == 'l'))
233     {
234       next= sim->uc->PC + de->length;
235       if (!sim->uc->fbrk_at(next))
236         {
237           b= new cl_fetch_brk(sim->uc->make_new_brknr(),
238                               next, brkDYNAMIC, 1);
239           sim->uc->fbrk->add(b);
240         }
241       sim->start(con);
242       //sim->uc->do_inst(-1);
243     }
244   else
245     sim->uc->do_inst(1);
246   sim->uc->print_regs(con);
247   return(DD_FALSE);
248 }
249
250
251 /*
252  * Command: pc
253  *----------------------------------------------------------------------------
254  */
255
256 int
257 cl_pc_cmd::do_work(class cl_sim *sim,
258                    class cl_cmdline *cmdline, class cl_console *con)
259 {
260   t_addr addr;
261   class cl_cmd_arg *params[1]= { cmdline->param(0) };
262
263   if (params[0])
264     {
265       if (!(params[0]->get_address(&addr)))
266         {
267           con->printf("Error: wrong parameter\n");
268           return(DD_FALSE);
269         }
270       if (addr >= sim->uc->get_mem_size(MEM_ROM))
271         addr= 0;
272       if (!sim->uc->inst_at(addr))
273         con->printf("Warning: maybe not instruction at 0x%06x\n", addr);
274       sim->uc->PC= addr;
275     }
276   sim->uc->print_disass(sim->uc->PC, con);
277   return(DD_FALSE);
278 }
279
280
281 /*
282  * Command: reset
283  *----------------------------------------------------------------------------
284  */
285
286 int
287 cl_reset_cmd::do_work(class cl_sim *sim,
288                       class cl_cmdline *cmdline, class cl_console *con)
289 {
290   sim->uc->reset();
291   return(0);
292 }
293
294
295 /*
296  * Command: dump
297  *----------------------------------------------------------------------------
298  */
299
300 int
301 cl_dump_cmd::do_work(class cl_sim *sim,
302                      class cl_cmdline *cmdline, class cl_console *con)
303 {
304   class cl_mem *mem= 0;
305   long bpl= 8;
306   t_addr start= 0, end;
307   class cl_cmd_arg *params[4]= { cmdline->param(0),
308                                  cmdline->param(1),
309                                  cmdline->param(2),
310                                  cmdline->param(3) };
311
312   if (params[0] &&
313       params[0]->as_bit(sim->uc))
314     {
315       int i= 0;
316       while (params[0] &&
317              params[0]->as_bit(sim->uc))
318         {
319           t_mem m;
320           mem= params[0]->value.bit.mem;
321           m= mem->read(params[0]->value.bit.mem_address);
322           char *sn=
323             sim->uc->symbolic_bit_name((t_addr)-1,
324                                        mem,
325                                        params[0]->value.bit.mem_address,
326                                        params[0]->value.bit.mask);
327           con->printf("%10s ", sn?sn:"");
328           con->printf(mem->addr_format, params[0]->value.bit.mem_address);
329           con->printf(" ");
330           con->printf(mem->data_format, m);
331           con->printf(" %c\n", (m&(params[0]->value.bit.mask))?'1':'0');
332           i++;
333           params[0]= cmdline->param(i);
334         }
335       if (params[0])
336         con->printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
337     }
338   else if (cmdline->syntax_match(sim, MEMORY))
339     {
340       mem= params[0]->value.memory;
341       mem->dump(con);
342     }
343   else if (cmdline->syntax_match(sim, MEMORY ADDRESS)) {
344     mem  = params[0]->value.memory;
345     start= params[1]->value.address;
346     end  = start+10*8-1;
347     mem->dump(start, end, bpl, con);
348   }
349   else if (cmdline->syntax_match(sim, MEMORY ADDRESS ADDRESS)) {
350     mem  = params[0]->value.memory;
351     start= params[1]->value.address;
352     end  = params[2]->value.address;
353     mem->dump(start, end, bpl, con);
354   }
355   else if (cmdline->syntax_match(sim, MEMORY ADDRESS ADDRESS NUMBER)) {
356     mem  = params[0]->value.memory;
357     start= params[1]->value.address;
358     end  = params[2]->value.address;
359     bpl  = params[3]->value.number;
360     mem->dump(start, end, bpl, con);
361   }
362   else
363     con->printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
364
365   return(DD_FALSE);;
366 }
367
368
369 /*
370  * Command: di
371  *----------------------------------------------------------------------------
372  */
373
374 int
375 cl_di_cmd::do_work(class cl_sim *sim,
376                    class cl_cmdline *cmdline, class cl_console *con)
377 {
378   cmdline->insert_param(0, new cl_cmd_sym_arg(sim->uc, "i"));
379   cl_dump_cmd::do_work(sim, cmdline, con);
380   return(0);
381 }
382
383
384 /*
385  * Command: dx
386  *----------------------------------------------------------------------------
387  */
388
389 int
390 cl_dx_cmd::do_work(class cl_sim *sim,
391                    class cl_cmdline *cmdline, class cl_console *con)
392 {
393   cmdline->insert_param(0, new cl_cmd_sym_arg(sim->uc, "x"));
394   cl_dump_cmd::do_work(sim, cmdline, con);
395   return(0);
396 }
397
398
399 /*
400  * Command: dch
401  *----------------------------------------------------------------------------
402  */
403
404 int
405 cl_dch_cmd::do_work(class cl_sim *sim,
406                     class cl_cmdline *cmdline, class cl_console *con)
407 {
408   cmdline->insert_param(0, new cl_cmd_sym_arg(sim->uc, "r"));
409   cl_dump_cmd::do_work(sim, cmdline, con);
410   return(0);
411 }
412
413
414 /*
415  * Command: ds
416  *----------------------------------------------------------------------------
417  */
418
419 int
420 cl_ds_cmd::do_work(class cl_sim *sim,
421                    class cl_cmdline *cmdline, class cl_console *con)
422 {
423   cmdline->insert_param(0, new cl_cmd_sym_arg(sim->uc, "s"));
424   cl_dump_cmd::do_work(sim, cmdline, con);
425   return(0);
426 }
427
428
429 /*
430  * Command: dc
431  *----------------------------------------------------------------------------
432  */
433
434 int
435 cl_dc_cmd::do_work(class cl_sim *sim,
436                    class cl_cmdline *cmdline, class cl_console *con)
437 {
438   t_addr start= last, end= last+20;
439   class cl_cmd_arg *params[2]= { cmdline->param(0),
440                                  cmdline->param(1) };
441   class cl_mem *rom= sim->uc->mem(MEM_ROM);
442
443   if (!rom)
444     return(DD_FALSE);
445   if (params[0] == 0)
446     ;
447   else if (cmdline->syntax_match(sim, ADDRESS)) {
448     start= params[0]->value.address;
449     end= start+20;
450   }
451   else if (cmdline->syntax_match(sim, ADDRESS ADDRESS)) {
452     start= params[0]->value.address;
453     end= params[1]->value.address;
454   }
455   if (start >= rom->size)
456     {
457       con->printf("Error: start address is wrong\n");
458       return(DD_FALSE);
459     }
460   if (end >= rom->size)
461     {
462       con->printf("Error: end address is wrong\n");
463       return(DD_FALSE);
464     }
465
466   for (;
467        start <= end;
468        start+= sim->uc->inst_length(rom->get(start)))
469     sim->uc->print_disass(start, con);
470   last= start;
471   return(DD_FALSE);
472 }
473
474
475 /*
476  * Command: disassemble
477  *----------------------------------------------------------------------------
478  */
479
480 static int disass_last_stop= 0;
481
482 int
483 cl_disassemble_cmd::do_work(class cl_sim *sim,
484                             class cl_cmdline *cmdline, class cl_console *con)
485 {
486   t_addr start, realstart;
487   int offset= -1, dir, lines= 20;
488   class cl_cmd_arg *params[4]= { cmdline->param(0),
489                                  cmdline->param(1),
490                                  cmdline->param(2),
491                                  cmdline->param(3) };
492
493   start= disass_last_stop;
494   if (params[0] == 0) ;
495   else if (cmdline->syntax_match(sim, ADDRESS)) {
496     start= params[0]->value.address;
497   }
498   else if (cmdline->syntax_match(sim, ADDRESS NUMBER)) {
499     start= params[0]->value.address;
500     offset= params[1]->value.number;
501   }
502   else if (cmdline->syntax_match(sim, ADDRESS NUMBER NUMBER)) {
503     start= params[0]->value.address;
504     offset= params[1]->value.number;
505     lines= params[2]->value.number;
506   }
507   else
508     {
509       con->printf("%s\n", short_help?short_help:"Error: wrong syntax\n");    
510       return(DD_FALSE);
511     }
512
513   if (lines < 1)
514     {
515       con->printf("Error: wrong `lines' parameter\n");
516       return(DD_FALSE);
517     }
518   if (!sim->uc->there_is_inst())
519     return(DD_FALSE);
520   realstart= start;
521   class cl_mem *rom= sim->uc->mem(MEM_ROM);
522   if (!rom)
523     return(DD_FALSE);
524   while (realstart < rom->size &&
525          !sim->uc->inst_at(realstart))
526     realstart= realstart+1;
527   if (offset)
528     {
529       dir= (offset < 0)?-1:+1;
530       while (offset)
531         {
532           realstart= (realstart+dir) % rom->size;
533           while (!sim->uc->inst_at(realstart))
534             realstart= (realstart+dir) % rom->size;
535           offset+= -dir;
536         }
537     }
538   
539   while (lines)
540     {
541       sim->uc->print_disass(realstart, sim->cmd->actual_console);
542       realstart= (realstart+1) % rom->size;
543       while (!sim->uc->inst_at(realstart))
544         realstart= (realstart+1) % rom->size;
545       lines--;
546     }
547
548   disass_last_stop= realstart;
549
550   return(DD_FALSE);;
551 }
552
553
554 /*
555  * Command: fill
556  *----------------------------------------------------------------------------
557  */
558
559 int
560 cl_fill_cmd::do_work(class cl_sim *sim,
561                      class cl_cmdline *cmdline, class cl_console *con)
562 {
563   class cl_mem *mem= 0;
564   t_mem what= 0;
565   t_addr start= 0, end;
566   class cl_cmd_arg *params[4]= { cmdline->param(0),
567                                  cmdline->param(1),
568                                  cmdline->param(2),
569                                  cmdline->param(3) };
570
571   if (cmdline->syntax_match(sim, MEMORY ADDRESS ADDRESS NUMBER)) {
572     mem  = params[0]->value.memory;
573     start= params[1]->value.address;
574     end  = params[2]->value.address;
575     what = params[3]->value.number;
576     t_addr i;
577     for (i= start; i <= end; i++)
578       {
579         t_mem d;
580         d= what;
581         mem->write(i, &d);
582       }
583   }
584   else
585     con->printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
586
587   return(DD_FALSE);;
588 }
589
590
591 /*
592  * Command: where
593  *----------------------------------------------------------------------------
594  */
595
596 int
597 cl_where_cmd::do_real_work(class cl_sim *sim,
598                            class cl_cmdline *cmdline, class cl_console *con,
599                            bool case_sensitive)
600 {
601   class cl_mem *mem= 0;
602   class cl_cmd_arg *params[2]= { cmdline->param(0),
603                                  cmdline->param(1) };
604
605   if (cmdline->syntax_match(sim, MEMORY DATALIST)) {
606     mem= params[0]->value.memory;
607     t_mem *array= params[1]->value.data_list.array;
608     int len= params[1]->value.data_list.len;
609     if (!len)
610       {
611         con->printf("Error: nothing to search for\n");
612         return(DD_FALSE);
613       }
614     t_addr addr= 0;
615     bool found= mem->search_next(case_sensitive, array, len, &addr);
616     while (found)
617       {
618         mem->dump(addr, addr+len-1, 8, con);
619         addr++;
620         found= mem->search_next(case_sensitive, array, len, &addr);
621       }
622   }
623   else
624     con->printf("%s\n", short_help?short_help:"Error: wrong syntax\n");
625
626   return(DD_FALSE);
627 }
628
629 int
630 cl_where_cmd::do_work(class cl_sim *sim,
631                       class cl_cmdline *cmdline, class cl_console *con)
632 {
633   return(do_real_work(sim, cmdline, con, DD_FALSE));
634 }
635
636 int
637 cl_Where_cmd::do_work(class cl_sim *sim,
638                       class cl_cmdline *cmdline, class cl_console *con)
639 {
640   return(do_real_work(sim, cmdline, con, DD_TRUE));
641 }
642
643
644 /*
645  * Command: help
646  *----------------------------------------------------------------------------
647  */
648
649 int
650 cl_help_cmd::do_work(class cl_sim *sim,
651                      class cl_cmdline *cmdline, class cl_console *con)
652 {
653   class cl_cmd *c;
654   int i;
655   class cl_cmd_arg *parm= cmdline->param(0);
656
657   if (!parm) {
658     for (i= 0; i < sim->cmd->cmdset->count; i++)
659       {
660         c= (class cl_cmd *)(sim->cmd->cmdset->at(i));
661         if (c->short_help)
662           con->printf("%s\n", c->short_help);
663         else
664           con->printf("%s\n", (char*)(c->names->at(0)));
665       }
666   }
667   else if (cmdline->syntax_match(sim, STRING)) {
668     int matches= 0;
669     for (i= 0; i < sim->cmd->cmdset->count; i++)
670       {
671         c= (class cl_cmd *)(sim->cmd->cmdset->at(i));
672         if (c->name_match(parm->value.string.string, DD_FALSE))
673           matches++;
674       }
675     if (!matches)
676       con->printf("No such command\n");
677     else if (matches > 1)
678       for (i= 0; i < sim->cmd->cmdset->count; i++)
679         {
680           c= (class cl_cmd *)(sim->cmd->cmdset->at(i));
681           if (!c->name_match(parm->value.string.string, DD_FALSE))
682             continue;
683           if (c->short_help)
684             con->printf("%s\n", c->short_help);
685           else
686             con->printf("%s\n", (char*)(c->names->at(0)));
687         }
688     else
689       for (i= 0; i < sim->cmd->cmdset->count; i++)
690         {
691           c= (class cl_cmd *)(sim->cmd->cmdset->at(i));
692           if (!c->name_match(parm->value.string.string, DD_FALSE))
693             continue;
694           if (c->short_help)
695             con->printf("%s\n", c->short_help);
696           else
697             con->printf("%s\n", (char*)(c->names->at(0)));
698           int names;
699           con->printf("Names of command:");
700           for (names= 0; names < c->names->count; names++)
701             con->printf(" %s", (char*)(c->names->at(names)));
702           con->printf("\n");
703           if (c->long_help)
704             con->printf("%s\n", c->long_help);
705           else
706             con->printf("%s\n", (char*)(c->names->at(0)));
707         }
708   }
709   else
710     con->printf("%s\n", short_help?short_help:"Error: wrong syntax");
711
712   return(0);
713 }
714
715
716 /*
717  * Command: quit
718  *----------------------------------------------------------------------------
719  */
720
721 int
722 cl_quit_cmd::do_work(class cl_sim *sim,
723                      class cl_cmdline */*cmdline*/, class cl_console */*con*/)
724 {
725   return(1);
726 }
727
728
729 /*
730  * Command: kill
731  *----------------------------------------------------------------------------
732  */
733
734 int
735 cl_kill_cmd::do_work(class cl_sim *sim,
736                      class cl_cmdline */*cmdline*/, class cl_console */*con*/)
737 {
738   sim->state|= SIM_QUIT;
739   return(1);
740 }
741
742
743 /* End of cmd.src/cmdset.cc */