version 0.2.39: fix of arith insts and start of re-structure
[fw/sdcc] / sim / ucsim / sim.src / sim.cc
1 /*
2  * Simulator of microcontrollers (sim.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 <stdio.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <ctype.h>
35 #ifdef HAVE_GETOPT_H
36 # include <getopt.h>
37 #endif
38 #include "i_string.h"
39
40 // prj
41 #include "globals.h"
42
43 // cmd
44 #include "cmdsetcl.h"
45 #include "infocl.h"
46 #include "setcl.h"
47 #include "getcl.h"
48 #include "showcl.h"
49 #include "bpcl.h"
50 #include "cmdguicl.h"
51 #include "cmdconfcl.h"
52
53 // local
54 #include "simcl.h"
55
56
57 /*
58  * Simulator
59  */
60
61 cl_sim::cl_sim(char *more_args, int iargc, char *iargv[]):
62   cl_base()
63 {
64   argc= iargc; argv= iargv;
65   uc= 0;
66   cmd= 0;
67   arguments= new cl_list(2, 2);
68   accept_args= more_args?strdup(more_args):0;
69   in_files= new cl_ustrings(2, 2);
70   gui= new cl_gui(this);
71 }
72
73 int
74 cl_sim::init(void)
75 {
76   int i;
77
78   cl_base::init();
79   proc_arguments(argc, argv);
80   class cl_cmdset *cmdset= new cl_cmdset(this);
81   cmdset->init();
82   build_cmd_set(cmdset);
83   if (!(uc= mk_controller()))
84     return(1);
85   uc->init();
86   cmd= new cl_commander(cmdset, this);
87   cmd->init();
88   char *Config= get_sarg(0, "Config");
89   if (Config)
90     {
91       class cl_console *con= cmd->mk_console(Config, 0/*"/dev/tty"*/, this);
92       cmd->add_console(con);
93     }
94   if (cmd->cons->get_count() == 0)
95     {
96       fprintf(stderr, "No command console available.\n");
97       exit(1);
98     }
99   for (i= 0; i < in_files->count; i++)
100     {
101       char *fname= (char *)(in_files->at(i));
102       long l;
103       if ((l= uc->read_hex_file(fname)) >= 0)
104         {
105           cmd->all_printf("%ld words read from %s\n", l, fname);
106           fprintf(stderr, "%ld words read from %s\n", l, fname);
107         }
108       char *prompt;
109       if (arg_avail('P'))
110         cmd->all_print("\0", 1);
111       else
112         cmd->all_printf("%s", (prompt= get_sarg(0, "prompt"))?prompt:"> ") ;
113     }
114   return(0);
115 }
116
117 cl_sim::~cl_sim(void)
118 {
119   if (uc)
120     delete uc;
121 }
122
123 int
124 cl_sim::proc_arguments(int argc, char *argv[])
125 {
126   int i, c;
127   char *opts, *cp;
128
129   opts= (char*)malloc((accept_args?strlen(accept_args):0)+100);
130   strcpy(opts, "c:C:p:PX:vV");
131 #ifdef SOCKET_AVAIL
132   strcat(opts, "Z:r:");
133 #endif
134   if (accept_args)
135     strcat(opts, accept_args);
136   opterr= 0;
137   while((c= getopt(argc, argv, opts)) != -1)
138     switch (c)
139       {
140
141       case 'c':
142         arguments->add(new cl_prg_arg('c', 0, optarg));
143         break;
144
145       case 'C':
146         arguments->add(new cl_prg_arg(0, "Config", optarg));
147         break;
148
149 #ifdef SOCKET_AVAIL
150       case 'Z':
151         // By Sandeep
152         arguments->add(new cl_prg_arg('Z', 0, (long)1));
153         if (!optarg || !isdigit(*optarg))
154           fprintf(stderr, "expected portnumber to follow -Z\n");
155         else {
156           char *p;
157           long l= strtol(optarg, &p, 0);
158           arguments->add(new cl_prg_arg(0, "Zport", l));
159         }
160         break;
161 #endif
162
163       case 'p':
164         arguments->add(new cl_prg_arg(0, "prompt", optarg));
165         break;
166
167       case 'P':
168         arguments->add(new cl_prg_arg('P', 0, (long)1));
169         break;
170
171 #ifdef SOCKET_AVAIL
172       case 'r':
173         arguments->add(new cl_prg_arg('r', 0,
174                                       (long)strtol(optarg, NULL, 0)));
175         break;
176 #endif
177
178       case 'X':
179         {
180           double XTAL;
181           for (cp= optarg; *cp; *cp= toupper(*cp), cp++);
182           XTAL= strtod(optarg, &cp);
183           if (*cp == 'K')
184             XTAL*= 1e3;
185           if (*cp == 'M')
186             XTAL*= 1e6;
187           if (XTAL == 0)
188             {
189               fprintf(stderr, "Xtal frequency must be greather than 0\n");
190               exit(1);
191             }
192           arguments->add(new cl_prg_arg('X', 0, XTAL));
193           break;
194         }
195
196       case 'v':
197         printf("%s: %s\n", argv[0], VERSIONSTR);
198         exit(0);
199         break;
200
201       case 'V':
202         arguments->add(new cl_prg_arg('V', 0, (long)1));
203         break;
204
205       case '?':
206         if ((c= proc_arg(c, optarg)))
207           exit(c);
208         break;
209
210       default:
211         if ((c= proc_arg(c, optarg)))
212           exit(c);
213       }
214   if (!arg_avail("prompt"))
215     arguments->add(new cl_prg_arg(0, "prompt", "> "));
216
217   for (i= optind; i < argc; i++)
218     in_files->add(argv[i]);
219
220   free(opts);
221   return(0);
222 }
223
224 int
225 cl_sim::proc_arg(char arg, char *optarg)
226 {
227   return(0);
228 }
229
230 int
231 cl_sim::arg_avail(char name)
232 {
233   class cl_prg_arg *a;
234   int i;
235
236   for (i= 0; i < arguments->count; i++)
237     {
238       a= (class cl_prg_arg *)(arguments->at(i));
239       if (a->short_name == name)
240         return(1);
241     }
242   return(0);
243 }
244
245 int
246 cl_sim::arg_avail(char *name)
247 {
248   class cl_prg_arg *a;
249   int i;
250
251   for (i= 0; i < arguments->count; i++)
252     {
253       a= (class cl_prg_arg *)(arguments->at(i));
254       if (a->long_name &&
255           strcmp(a->long_name, name) == 0)
256         return(1);
257     }
258   return(0);
259 }
260
261 long long
262 cl_sim::get_iarg(char sname, char *lname)
263 {
264   class cl_prg_arg *a;
265   int i;
266
267   for (i= 0; i < arguments->count; i++)
268     {
269       a= (class cl_prg_arg *)(arguments->at(i));
270       if ((sname && a->short_name == sname) ||
271           (lname && a->long_name && strcmp(a->long_name, lname) == 0))
272         {
273           long iv;
274           if (a->get_ivalue(&iv))
275             return(iv);
276           else
277             //FIXME
278             return(0);
279         }
280     }
281   return(0);
282 }
283
284 char *
285 cl_sim::get_sarg(char sname, char *lname)
286 {
287   class cl_prg_arg *a;
288   int i;
289
290   for (i= 0; i < arguments->count; i++)
291     {
292       a= (class cl_prg_arg *)(arguments->at(i));
293       if ((sname && a->short_name == sname) ||
294           (lname && a->long_name && strcmp(a->long_name, lname) == 0))
295         return(a->get_svalue());
296     }
297   return(0);
298 }
299
300
301 double
302 cl_sim::get_farg(char sname, char *lname)
303 {
304   class cl_prg_arg *a;
305   int i;
306
307   for (i= 0; i < arguments->count; i++)
308     {
309       a= (class cl_prg_arg *)(arguments->at(i));
310       if ((sname && a->short_name == sname) ||
311           (lname && a->long_name && strcmp(a->long_name, lname) == 0))
312         return(a->get_fvalue());
313     }
314   return(0);
315 }
316
317 void *
318 cl_sim::get_parg(char sname, char *lname)
319 {
320   class cl_prg_arg *a;
321   int i;
322
323   for (i= 0; i < arguments->count; i++)
324     {
325       a= (class cl_prg_arg *)(arguments->at(i));
326       if ((sname && a->short_name == sname) ||
327           (lname && a->long_name && strcmp(a->long_name, lname) == 0))
328         return(a->get_pvalue());
329     }
330   return(0);
331 }
332
333 class cl_uc *
334 cl_sim::mk_controller(void)
335 {
336   return(new cl_uc(this));
337 }
338
339 class cl_cmd_arg *
340 cl_sim::mk_cmd_int_arg(long long i)
341 {
342   class cl_cmd_arg *arg= new cl_cmd_int_arg(uc, i);
343   arg->init();
344   return(arg);
345 }
346
347 class cl_cmd_arg *
348 cl_sim::mk_cmd_sym_arg(char *s)
349 {
350   class cl_cmd_arg *arg= new cl_cmd_sym_arg(uc, s);
351   arg->init();
352   return(arg);
353 }
354
355 class cl_cmd_arg *
356 cl_sim::mk_cmd_str_arg(char *s)
357 {
358   class cl_cmd_arg *arg= new cl_cmd_str_arg(uc, s);
359   arg->init();
360   return(arg);
361 }
362
363 class cl_cmd_arg *
364 cl_sim::mk_cmd_bit_arg(class cl_cmd_arg *sfr, class cl_cmd_arg *bit)
365 {
366   class cl_cmd_arg *arg= new cl_cmd_bit_arg(uc, sfr, bit);
367   arg->init();
368   return(arg);
369 }
370
371 class cl_cmd_arg *
372 cl_sim::mk_cmd_array_arg(class cl_cmd_arg *aname, class cl_cmd_arg *aindex)
373 {
374   class cl_cmd_arg *arg= new cl_cmd_array_arg(uc, aname, aindex);
375   arg->init();
376   return(arg);
377 }
378
379
380 /*
381  * Main cycle of the simulator
382  */
383
384 int
385 cl_sim::main(void)
386 {
387   int done= 0;
388
389   while (!done &&
390          (state & SIM_QUIT) == 0)
391     {
392       if (state & SIM_GO)
393         {
394           uc->do_inst(-1);
395           if (cmd->input_avail())
396             {
397               done= cmd->proc_input();
398             }
399         }
400       else
401         {
402           cmd->wait_input();
403           done= cmd->proc_input();
404         }
405     }
406   return(0);
407 }
408
409 /*int
410 cl_sim::do_cmd(char *cmdstr, class cl_console *console)
411 {
412   class cl_cmdline *cmdline;
413   class cl_cmd *cm;
414   int retval= 0;
415
416   cmdline= new cl_cmdline(cmdstr, console);
417   cmdline->init();
418   cm= cmd->cmdset->get_cmd(cmdline);
419   if (cm)
420     retval= cm->work(cmdline, console);
421   delete cmdline;
422   if (cm)
423     return(retval);
424   return(console->interpret(cmdstr));
425 }*/
426
427 void
428 cl_sim::start(class cl_console *con)
429 {
430   state|= SIM_GO;
431   con->flags|= CONS_FROZEN;
432   cmd->frozen_console= con;
433   cmd->set_fd_set();
434 }
435
436 void
437 cl_sim::stop(int reason)
438 {
439   state&= ~SIM_GO;
440   if (cmd->frozen_console)
441     {
442       if (reason == resUSER &&
443           cmd->frozen_console->input_avail())
444         cmd->frozen_console->read_line();
445       cmd->frozen_console->printf("Stop at 0x%06x: (%d) ", uc->PC, reason);
446       switch (reason)
447         {
448         case resHALT:
449           cmd->frozen_console->printf("Halted\n");
450           break;
451         case resINV_ADDR:
452           cmd->frozen_console->printf("Invalid address\n");
453           break;
454         case resSTACK_OV:
455           cmd->frozen_console->printf("Stack overflow\n");
456           break;
457         case resBREAKPOINT:
458           cmd->frozen_console->printf("Breakpoint\n");
459           break;
460         case resINTERRUPT:
461           cmd->frozen_console->printf("Interrupt\n");
462           break;
463         case resWDTRESET:
464           cmd->frozen_console->printf("Watchdog reset\n");
465           break;
466         case resUSER:
467           cmd->frozen_console->printf("User stopped\n");
468           break;
469         case resINV_INST:
470           cmd->frozen_console->printf("Invalid instruction 0x%04x\n",
471                                       uc->get_mem(MEM_ROM, uc->PC));
472           break;
473         default:
474           cmd->frozen_console->printf("Unknown reason\n");
475           break;
476         }
477       cmd->frozen_console->printf("F 0x%06x\n", uc->PC); // for sdcdb
478       //if (cmd->actual_console != cmd->frozen_console)
479       cmd->frozen_console->flags&= ~CONS_FROZEN;
480       cmd->frozen_console->print_prompt();
481       cmd->frozen_console= 0;
482     }
483   cmd->set_fd_set();
484 }
485
486
487 /*
488  */
489
490 void
491 cl_sim::build_cmd_set(class cl_cmdset *cmdset)
492 {
493   class cl_cmd *cmd;
494   class cl_cmdset *cset;
495
496   {
497     cset= new cl_cmdset(this);
498     cset->init();
499     cset->add(cmd= new cl_conf_cmd("_no_parameters_", 0,
500 "conf               Configuration",
501 "long help of conf"));
502     cmd->init();
503     cset->add(cmd= new cl_conf_addmem_cmd("addmem", 0,
504 "conf addmem\n"
505 "                   Make memory",
506 "long help of conf addmem"));
507     cmd->init();
508   }
509   cmdset->add(cmd= new cl_super_cmd("conf", 0,
510 "conf subcommand    Information, see `conf' command for more help",
511 "long help of conf", cset));
512   cmd->init();
513
514   cmdset->add(cmd= new cl_state_cmd("state", 0,
515 "state              State of simulator",
516 "long help of state"));
517   cmd->init();
518
519   cmdset->add(cmd= new cl_file_cmd("file", 0,
520 "file \"FILE\"        Load FILE into ROM",
521 "long help of file"));
522   cmd->init();
523   cmd->add_name("load");
524
525   cmdset->add(cmd= new cl_dl_cmd("download", 0,
526 "download,dl          Load (intel.hex) data",
527 "long help of download"));
528   cmd->init();
529   cmd->add_name("dl");
530
531   {
532     cset= new cl_cmdset(this);
533     cset->init();
534     cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0, 
535 "info breakpoints   Status of user-settable breakpoints",
536 "long help of info breakpoints"));
537     cmd->add_name("bp");
538     cmd->init();
539     cset->add(cmd= new cl_info_reg_cmd("registers", 0, 
540 "info registers     List of integer registers and their contents",
541 "long help of info registers"));
542     cmd->init();
543     cset->add(cmd= new cl_info_hw_cmd("hardware", 0, 
544 "info hardware cathegory\n"
545 "                   Status of hardware elements of the CPU",
546 "long help of info hardware"));
547     cmd->add_name("h    w");
548     cmd->init();
549   }
550   cmdset->add(cmd= new cl_super_cmd("info", 0,
551 "info subcommand    Information, see `info' command for more help",
552 "long help of info", cset));
553   cmd->init();
554
555   {
556     cset= new cl_cmdset(this);
557     cset->init();
558     cset->add(cmd= new cl_get_sfr_cmd("sfr", 0,
559 "get sfr address...\n"
560 "                   Get value of addressed SFRs",
561 "long help of get sfr"));
562     cmd->init();
563     cset->add(cmd= new cl_get_option_cmd("option", 0,
564 "get option name\n"
565 "                   Get value of an option",
566 "long help of get option"));
567     cmd->init();
568   }
569   cmdset->add(cmd= new cl_super_cmd("get", 0,
570 "get subcommand     Get, see `get' command for more help",
571 "long help of get", cset));
572   cmd->init();
573
574   {
575     cset= new cl_cmdset(this);
576     cset->init();
577     cset->add(cmd= new cl_set_mem_cmd("memory", 0,
578 "set memory memory_type address data...\n"
579 "                   Place list of data into memory",
580 "long help of set memory"));
581     cmd->init();
582     cset->add(cmd= new cl_set_bit_cmd("bit", 0,
583 "set bit addr 0|1   Set specified bit to 0 or 1",
584 "long help of set bit"));
585     cmd->init();
586     cset->add(cmd= new cl_set_port_cmd("port", 0,
587 "set port hw data   Set data connected to port",
588 "long help of set port"));
589     cmd->init();
590     cset->add(cmd= new cl_set_option_cmd("option", 0,
591 "set option name value\n"
592 "                   Set value of an option",
593 "long help of set option"));
594     cmd->init();
595   }
596   cmdset->add(cmd= new cl_super_cmd("set", 0,
597 "set subcommand     Set, see `set' command for more help",
598 "long help of set", cset));
599   cmd->init();
600
601   cmdset->add(cmd= new cl_timer_cmd("timer", 0,
602 "timer a|d|g|r|s|v id [direction|value]\n"
603 "                   Timer add|del|get|run|stop|value",
604 "timer add|create|make id [direction] -- create a new timer\n"
605 "timer del id -- delete a timer\n"
606 "timer get id -- list timers\n"
607 "timer run id -- turn a timer ON\n"
608 "timer stop id -- turn a timer OFF\n"
609 "timer value id val -- set value of a timer to `val'"));
610   cmd->init();
611
612   cmdset->add(cmd= new cl_run_cmd("run", 0,
613 "run [start [stop]] Go",
614 "long help of run"));
615   cmd->init();
616   cmd->add_name("go");
617   cmd->add_name("r");
618
619   cmdset->add(cmd= new cl_stop_cmd("stop", 0,
620 "stop               Stop",
621 "long help of stop"));
622   cmd->init();
623
624   cmdset->add(cmd= new cl_step_cmd("step", 0,
625 "step               Step",
626 "long help of step"));
627   cmd->init();
628   cmd->add_name("s");
629
630   cmdset->add(cmd= new cl_next_cmd("next", 0,
631 "next               Next",
632 "long help of next"));
633   cmd->init();
634   cmd->add_name("n");
635
636   cmdset->add(cmd= new cl_pc_cmd("pc", 0,
637 "pc [addr]          Set/get PC",
638 "long help of pc"));
639   cmd->init();
640
641   cmdset->add(cmd= new cl_reset_cmd("reset", 0,
642 "reset              Reset",
643 "long help of reset"));
644   cmd->init();
645
646   cmdset->add(cmd= new cl_dump_cmd("dump", 0,
647 "dump memory_type [start [stop [bytes_per_line]]]\n"
648 "                   Dump memory of specified type\n"
649 "dump bit...        Dump bits",
650 "long help of dump"));
651   cmd->init();
652
653   cmdset->add(cmd= new cl_di_cmd("di", 0,
654 "di [start [stop]]  Dump Internal RAM",
655 "long help of di"));
656   cmd->init();
657
658   cmdset->add(cmd= new cl_dx_cmd("dx", 0,
659 "dx [start [stop]]  Dump External RAM",
660 "long help of dx"));
661   cmd->init();
662
663   cmdset->add(cmd= new cl_ds_cmd("ds", 0,
664 "ds [start [stop]]  Dump SFR",
665 "long help of ds"));
666   cmd->init();
667
668   cmdset->add(cmd= new cl_dch_cmd("dch", 0,
669 "dch [start [stop]] Dump code in hex form",
670 "long help of dch"));
671   cmd->init();
672
673   cmdset->add(cmd= new cl_dc_cmd("dc", 0,
674 "dc [start [stop]]  Dump code in disass form",
675 "long help of dc"));
676   cmd->init();
677
678   cmdset->add(cmd= new cl_disassemble_cmd("disassemble", 0,
679 "disassemble [start [offset [lines]]]\n"
680 "                   Disassemble code",
681 "long help of disassemble"));
682   cmd->init();
683
684   cmdset->add(cmd= new cl_fill_cmd("fill", 0,
685 "fill memory_type start end data\n"
686 "                   Fill memory region with data",
687 "long help of fill"));
688   cmd->init();
689
690   cmdset->add(cmd= new cl_where_cmd("where", 0,
691 "where memory_type data...\n"
692 "                   Case unsensitive search for data",
693 "long help of where"));
694   cmd->init();
695
696   cmdset->add(cmd= new cl_Where_cmd("Where", 0,
697 "Where memory_type data...\n"
698 "                   Case sensitive search for data",
699 "long help of Where"));
700   cmd->init();
701
702   cmdset->add(cmd= new cl_break_cmd("break", 0,
703 "break addr [hit]   Set fix breakpoint\n"
704 "break mem_type r|w addr [hit]\n"
705 "                   Set fix event breakpoint",
706 "long help of break"));
707   cmd->init();
708
709   cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0,
710 "tbreak addr [hit]  Set temporary breakpoint\n"
711 "tbreak mem_type r|w addr [hit]\n"
712 "                   Set temporary event breakpoint",
713 "long help of tbreak"));
714   cmd->init();
715
716   cmdset->add(cmd= new cl_clear_cmd("clear", 0,
717 "clear [addr...]    Clear fix breakpoint",
718 "long help of clear"));
719   cmd->init();
720
721   cmdset->add(cmd= new cl_delete_cmd("delete", 0,
722 "delete [nr...]     Delete breakpoint(s)",
723 "long help of clear"));
724   cmd->init();
725
726   cmdset->add(cmd= new cl_help_cmd("help", 0,
727 "help [command]     Help about command(s)",
728 "long help of help"));
729   cmd->init();
730   cmd->add_name("?");
731
732   cmdset->add(cmd= new cl_quit_cmd("quit", 0,
733 "quit               Quit",
734 "long help of quit"));
735   cmd->init();
736
737   cmdset->add(cmd= new cl_kill_cmd("kill", 0,
738 "kill               Shutdown simulator",
739 "long help of kill"));
740   cmd->init();
741
742   {
743     cset= new cl_cmdset(this);
744     cset->init();
745     cset->add(cmd= new cl_show_copying_cmd("copying", 0, 
746 "show copying       Conditions for redistributing copies of uCsim",
747 "long help of show copying"));
748     cmd->init();
749     cset->add(cmd= new cl_show_warranty_cmd("warranty", 0, 
750 "show warranty      Various kinds of warranty you do not have",
751 "long help of show warranty"));
752     cmd->init();
753   }
754   cmdset->add(cmd= new cl_super_cmd("show", 0,
755 "show subcommand    Generic command for showing things about the uCsim",
756 "long help of show", cset));
757   cmd->init();
758
759   {
760     cset= new cl_cmdset(this);
761     cset->init();
762     cset->add(cmd= new cl_gui_start_cmd("start", 0, 
763 "gui start          Start interfacing with GUI tool",
764 "long help of gui start"));
765     cmd->init();
766     cset->add(cmd= new cl_gui_stop_cmd("stop", 0, 
767 "gui stop           Stop interfacing with GUI tool",
768 "long help of gui stop"));
769     cmd->init();
770   }
771   cmdset->add(cmd= new cl_super_cmd("gui", 0,
772 "gui subcommand     Operations to support GUI tools",
773 "long help of gui", cset));
774   cmd->init();
775 }
776
777
778 /* End of sim.src/sim.cc */