[ucsim] Fix bug of banked disass
[sdcc.git] / sdcc / sim / ucsim / sim.src / uc.cc
blob0c0607de11b83ca0d63553bf9ba14ad1a41ef9d4
1 /*
2 * Simulator of microcontrollers (uc.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
8 */
10 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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@*/
28 //#include "ddconfig.h"
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <errno.h>
33 #include <ctype.h>
34 #include <string.h>
35 //#include "i_string.h"
37 // prj
38 #include "globals.h"
39 #include "utils.h"
41 // cmd.src
42 //#include "newcmdcl.h"
43 //#include "cmdutil.h"
44 #include "cmd_uccl.h"
45 #include "cmd_bpcl.h"
46 #include "cmd_getcl.h"
47 #include "cmd_setcl.h"
48 #include "cmd_infocl.h"
49 #include "cmd_timercl.h"
50 #include "cmd_statcl.h"
51 #include "cmd_memcl.h"
52 #include "cmd_execcl.h"
54 // local, sim.src
55 #include "uccl.h"
56 //#include "hwcl.h"
57 //#include "memcl.h"
58 //#include "simcl.h"
59 #include "itsrccl.h"
60 #include "simifcl.h"
61 #include "vcdcl.h"
64 static class cl_uc_error_registry uc_error_registry;
67 * Clock counter
70 cl_ticker::cl_ticker(int adir, enum ticker_type atype, const char *aname, bool auser)
72 dir= adir;
73 type= atype;
74 ticks= 0;
75 run = true;
76 set_name(aname);
77 user= auser;
80 cl_ticker::~cl_ticker(void) {}
82 void
83 cl_ticker::tick(int nr, double time)
85 if (dir >= 0)
87 ticks+= nr;
88 rtime+= time;
90 else
92 ticks-= nr;
93 rtime-= time;
97 void
98 cl_ticker::dump(int nr, class cl_console_base *con)
100 const char *type_names[] = { "", ",ISR", ",IDLE", ",HALT" };
102 con->dd_printf("timer #%d(\"%s\") %s%s %.15f sec (%lu clks)\n",
103 nr, get_name("unnamed"),
104 (run ? "ON" : "OFF"),
105 type_names[type],
106 rtime, ticks);
111 * Options of uc
114 cl_xtal_option::cl_xtal_option(class cl_uc *the_uc):
115 cl_optref(the_uc)
117 uc= the_uc;
120 void
121 cl_xtal_option::option_changed(void)
123 if (!uc)
124 return;
125 double d;
126 option->get_value(&d);
127 uc->set_xtal(d);
130 cl_stop_selfjump_option::cl_stop_selfjump_option(class cl_uc *the_uc):
131 cl_optref(the_uc)
133 uc= the_uc;
137 cl_stop_selfjump_option::init(void)
139 cl_optref::init();
140 create(uc, bool_opt, "selfjump_stop", "Stop when jump branches to itself");
141 return 0;
144 void
145 cl_stop_selfjump_option::option_changed(void)
147 bool b;
148 option->get_value(&b);
149 uc->stop_selfjump= b;
153 cl_analyzer_opt::cl_analyzer_opt(class cl_uc *Iuc):
154 cl_bool_option(Iuc, "analyzer", "Analyze and label code")
156 uc= Iuc;
159 void
160 cl_analyzer_opt::set_value(const char *s)
162 bool b;
163 cl_bool_option::set_value(s);
164 get_value(&b);
165 uc->set_analyzer(b);
166 if (uc->analyser_opt) uc->analyser_opt->set_raw(b);
170 cl_analyser_opt::cl_analyser_opt(class cl_uc *Iuc):
171 cl_bool_option(Iuc, "analyser", "Analyse and label code")
173 uc= Iuc;
176 void
177 cl_analyser_opt::set_value(const char *s)
179 bool b;
180 cl_bool_option::set_value(s);
181 get_value(&b);
182 uc->set_analyzer(b);
183 if (uc->analyzer_opt) uc->analyzer_opt->set_raw(b);
186 /* Time measurer */
188 cl_time_measurer::cl_time_measurer(class cl_uc *the_uc):
189 cl_base()
191 to_reach= 0;
192 uc= the_uc;
195 void
196 cl_time_measurer::set_reach(unsigned long val)
198 to_reach= val;
201 void
202 cl_time_measurer::from_now(unsigned long val)
204 set_reach(now() + val);
207 bool
208 cl_time_measurer::reached()
210 return to_reach &&
211 (now() >= to_reach);
214 unsigned long
215 cl_time_measurer::now()
217 return 0;
221 /* value of xtal clock */
223 unsigned long
224 cl_time_clk::now()
226 if (!uc) return 0;
227 return uc->ticks->get_ticks();
231 /* value of virtual clocks */
233 unsigned long
234 cl_time_vclk::now()
236 if (!uc) return 0;
237 return uc->vc.fetch + uc->vc.rd + uc->vc.wr;
241 /* value of fetches */
243 unsigned long
244 cl_time_fclk::now()
246 if (!uc) return 0;
247 return uc->vc.fetch;
251 /* value of reads */
253 unsigned long
254 cl_time_rclk::now()
256 if (!uc) return 0;
257 return uc->vc.rd;
261 /* value of writes */
263 unsigned long
264 cl_time_wclk::now()
266 if (!uc) return 0;
267 return uc->vc.wr;
271 /* OMF file record */
273 cl_omf_rec::cl_omf_rec(void):
274 cl_base()
276 offset= 0;
277 f_offset= 0;
278 type= 0;
279 len= 0;
280 rec= NULL;
281 chk= 0;
284 cl_omf_rec::~cl_omf_rec(void)
286 if (rec)
287 free(rec);
290 unsigned char
291 cl_omf_rec::g(cl_f *f)
293 unsigned char c= f->get_c();
294 offset++;
295 return c;
298 u16_t
299 cl_omf_rec::pick_word(int i)
301 unsigned char h, l;
302 u16_t w;
304 if (i >= len-1)
305 return 0;
306 l= rec[i];
307 h= rec[i+1];
308 w= h*256+l;
309 return w;
312 chars
313 cl_omf_rec::pick_str(int i)
315 unsigned char l, j;
316 chars s= "";
318 if (i >= len-1)
319 return chars("");
320 l= rec[i];
321 j= 0;
322 while (l &&
323 (i < len))
325 s+= rec[i+1+j];
326 l--;
327 j++;
329 return s;
332 bool
333 cl_omf_rec::read(cl_f *f)
335 unsigned char c;
336 int i, l, h;
338 if (rec)
340 free(rec);
341 rec= NULL;
343 f_offset= offset;
344 if (f->eof())
345 return false;
346 c= g(f);
347 type= c;
348 if (f->eof())
349 return false;
350 c= g(f);
351 l= c;
352 if (f->eof())
353 return false;
354 c= g(f);
355 h= c;
356 if (f->eof())
357 return false;
358 len= h*256+l-1;
359 rec= (u8_t*)malloc(len);
360 for (i= 0; i < len; i++)
362 rec[i]= g(f);
363 if (f->eof())
364 return false;
366 chk= g(f);
368 return true;
373 * Execution history
376 cl_exec_hist::cl_exec_hist(class cl_uc *auc):
377 cl_base()
379 uc= auc;
380 len= 10001;
381 hist= (struct t_hist_elem*)malloc(sizeof(struct t_hist_elem) * len);
382 t= h= 0;
385 cl_exec_hist::~cl_exec_hist(void)
387 if (hist)
388 free(hist);
392 cl_exec_hist::init(void)
394 return 0;
397 void
398 cl_exec_hist::put(void)
400 t_addr pc;
401 if (!uc)
402 return;
403 pc= uc->PC;
404 if (t != h)
406 if (hist[h].addr == pc)
408 hist[h].nr++;
409 return;
412 int nh= (h+1)%len;
413 if (t == nh)
414 t= (t+1)%len;
415 h= nh;
416 hist[h].addr= pc;
417 hist[h].nr= 1;
420 void
421 cl_exec_hist::list(class cl_console_base *con, bool inc, int nr)
423 int s, p, ta, l;
424 if (!con)
425 return;
426 if (t==h)
427 return;
428 if (nr > len-1)
429 nr= len-1;
430 if (nr > get_used())
431 nr= get_used();
432 s= h-nr+1;
433 if (s<0)
434 s+= len;
435 //s%= len;
436 ta= (t+1)%len;
438 p= inc?s:h;
441 if (!uc)
443 l= con->dd_cprintf("dump_address", "0x%06x", AU(hist[p].addr));
445 else
447 l= uc->print_disass(hist[p].addr, con, false);
449 if (hist[p].nr > 1)
451 l++; con->dd_printf(" ");
452 while (l%8 != 0)
453 l++, con->dd_printf(" ");
454 con->dd_printf("(%d times)", hist[p].nr);
456 con->dd_printf("\n");
457 if (inc)
459 if (p==h)
460 break;
461 p= (p+1)%len;
463 else
465 if (p==ta)
466 break;
467 if (p==0)
468 p=len-1;
469 else
470 p= (p-1)%len;
472 con->dd_color("answer");
474 while (1);
477 void
478 cl_exec_hist::keep(int nr)
480 if (nr < 0)
481 nr= 0;
482 if (t==h)
483 return;
484 while (get_used() > nr)
485 t= (t+1)%len;
489 cl_exec_hist::get_used()
491 if (t==h)
492 return 0;
493 if (h>t)
494 return h-t;
495 return len-t + h;
498 unsigned int
499 cl_exec_hist::get_insts()
501 unsigned int i= 0;
502 int p;
503 if (t==h)
504 return 0;
505 p= (t+1)%len;
508 i+= hist[p].nr;
509 if (p==h)
510 break;
511 p= (p+1)%len;
513 while (1);
514 return i;
519 * Abstract microcontroller
520 ******************************************************************************
523 cl_uc::cl_uc(class cl_sim *asim):
524 cl_itab()
526 PCmask= 0xffff;
527 type= NULL;
528 //int i;
529 sim = asim;
530 //mems= new cl_list(MEM_TYPES, 1);
531 memchips= new cl_memory_list(this, "memchips");
532 address_spaces= new cl_memory_list(this, "address_spaces");
533 //address_decoders= new cl_list(2, 2);
534 rom= 0;
536 hws = new cl_hws();
537 //options= new cl_list(2, 2);
538 //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
539 xtal_option= new cl_xtal_option(this);
540 xtal_option->init();
541 stop_selfjump_option= new cl_stop_selfjump_option(this);
542 stop_selfjump_option->init();
543 analyzer_opt= NULL;
544 analyser_opt= NULL;
545 counters= new cl_list(2, 2, "counters");
546 ticks= new cl_ticker(+1, TICK_ANY, "time", false);
547 add_counter(ticks, ticks->get_name());
548 isr_ticks= new cl_ticker(+1, TICK_INISR, "isr", false);
549 add_counter(isr_ticks, isr_ticks->get_name());
550 idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle", false);
551 add_counter(idle_ticks, idle_ticks->get_name());
552 halt_ticks= new cl_ticker(+1, TICK_HALT, "halt", false);
553 add_counter(halt_ticks, halt_ticks->get_name());
554 it_levels= new cl_list(2, 2, "it levels");
555 it_sources= new cl_irqs(2, 2);
556 class it_level *il= new it_level(-1, 0, 0, 0);
557 it_levels->push(il);
558 stack_ops= new cl_list(2, 2, "stack operations");
559 errors= new cl_list(2, 2, "errors in uc");
560 events= new cl_list(2, 2, "events in uc");
561 sp_most= 0;
562 //sp_avg= 0;
563 inst_exec= false;
564 hist= new cl_exec_hist(this);
568 cl_uc::~cl_uc(void)
570 //delete mems;
571 delete hws;
572 //delete options;
573 delete ticks;
574 delete isr_ticks;
575 delete idle_ticks;
576 delete halt_ticks;
577 delete counters;
578 events->disconn_all();
579 delete events;
580 delete fbrk;
581 delete ebrk;
582 delete displays;
583 delete it_levels;
584 delete it_sources;
585 delete stack_ops;
586 errors->free_all();
587 delete errors;
588 delete xtal_option;
589 delete address_spaces;
590 delete memchips;
591 //delete address_decoders;
592 delete hist;
597 cl_uc::init(void)
599 int i;
600 double x= 0;
602 set_name("controller");
603 cl_base::init();
604 if (xtal_option->use("xtal"))
605 x= xtal_option->get_value(xtal);
606 if (x==0)
607 x= def_xtal();
608 set_xtal(x);
609 stop_selfjump= false;
610 stop_selfjump_option->option->set_value(stop_selfjump);
611 analyzer= false;
612 analyzer_opt= new cl_analyzer_opt(this);
613 analyzer_opt->init();
614 analyzer_opt->set_raw(analyzer);
615 analyser_opt= new cl_analyser_opt(this);
616 analyser_opt->init();
617 analyser_opt->set_raw(analyzer);
618 application->options->add(analyzer_opt);
619 application->options->add(analyser_opt);
620 vars= new cl_var_list();
621 make_variables();
622 // Some app level vars:
623 reg_cell_var(&(application->cperiod),
624 &(application->period),
625 "cperiod",
626 "Cycles between input checks");
627 reg_cell_var(&(application->ccyc),
628 &(application->cyc),
629 "ccyc",
630 "Nr of cycles executed during simulation");
631 reg_cell_var(&cPC, &PC, "PC", "Program counter");
632 // Memories
633 make_memories();
634 if (rom == NULL)
635 rom= address_space("rom"/*MEM_ROM_ID*/);
636 ebrk= new brk_coll(2, 2, rom);
637 fbrk= new brk_coll(2, 2, rom);
638 displays= new cl_display_list(2, 2, "displays");
639 fbrk->Duplicates= false;
640 brk_counter= 0;
641 stop_at_time= 0;
642 make_cpu_hw();
643 mk_hw_elements();
644 class cl_cmdset *cs= sim->app->get_commander()->cmdset;
645 build_cmdset(cs);
646 irq= false;
647 vcd_break= false;
648 reset();
650 return 0;
651 for (i= 0; i < sim->app->in_files->count; i++)
653 const char *fname= (const char *)(sim->app->in_files->at(i));
654 long l;
655 if ((l= read_hex_file(fname)) >= 0)
657 /*sim->app->get_commander()->all_*/printf("%ld words read from %s\n",
658 l, fname);
661 return(0);
664 const char *
665 cl_uc::id_string(void)
667 return("unknown microcontroller");
670 void
671 cl_uc::reset(void)
673 class it_level *il;
675 irq= false;
676 instPC= PC= 0;
677 state = stGO;
678 ticks->set(0, 0);
679 isr_ticks->set(0, 0);
680 idle_ticks->set(0, 0);
681 halt_ticks->set(0, 0);
682 vc.inst= vc.fetch= vc.rd= vc.wr= 0;
683 /*FIXME should we clear user counters?*/
684 il= (class it_level *)(it_levels->top());
685 while (il &&
686 il->level >= 0)
688 il= (class it_level *)(it_levels->pop());
689 delete il;
690 il= (class it_level *)(it_levels->top());
692 sp_most= 0;
693 //sp_avg= 0;
695 stack_ops->free_all();
697 int i;
698 for (i= 0; i < hws->count; i++)
700 class cl_hw *hw= (class cl_hw *)(hws->at(i));
701 hw->reset();
705 void
706 cl_uc::reg_cell_var(class cl_memory_cell *cell,
707 void *store,
708 chars vname, chars vdesc)
710 if (cell)
712 cell->init();
713 if (store)
714 cell->decode(store);
715 if (vname.nempty())
717 class cl_cvar *v;
718 vars->add(v= new cl_cvar(vname, cell, vdesc));
719 v->init();
720 v->set_by(VBY_PRE);
725 void
726 cl_uc::mk_cvar(class cl_memory_cell *cell, chars vname, chars vdesc,
727 enum var_by vby)
729 class cl_cvar *v;
730 vars->add(v= new cl_cvar(vname, cell, vdesc));
731 v->init();
732 v->set_by(vby);
736 * Making elements
739 void
740 cl_uc::make_memories(void)
744 void
745 cl_uc::make_variables(void)
747 class cl_address_space *as;
748 class cl_option *o= sim->app->options->get_option("var_size");
749 long l, i;
751 if (o)
752 o->get_value(&l);
753 else
754 l= 0x100;
756 class cl_address_decoder *ad;
757 class cl_memory_chip *chip;
759 if (l > 0)
761 variables= as= new cl_address_space("variables", 0, l, 32);
762 as->init();
763 address_spaces->add(as);
765 chip= new cl_chip32("variable_storage", l, 32);
766 chip->init();
767 memchips->add(chip);
768 ad= new cl_address_decoder(variables, chip, 0, l-1, 0);
769 ad->init();
770 variables->decoders->add(ad);
771 ad->activate(0);
773 for (i= 0; i < l; i++)
774 variables->set(i, 0);
778 /*t_addr
779 cl_uc::get_mem_size(char *id)
781 class cl_memory *m= memory(id);
782 return(m?(m->get_size()):0);
786 cl_uc::get_mem_width(char *id)
788 class cl_memory *m= memory(id);
789 return(m?(m->width):8);
792 void
793 cl_uc::make_cpu_hw(void)
795 cpu= NULL;
798 void
799 cl_uc::mk_hw_elements(void)
801 class cl_hw *h;
803 init_add_hw(h= new cl_simulator_interface(this));
804 init_add_hw(h= new cl_vcd(this, 0, "vcd"));
807 void
808 cl_uc::build_cmdset(class cl_cmdset *cmdset)
810 class cl_cmd *cmd;
811 class cl_super_cmd *super_cmd;
812 class cl_cmdset *cset;
814 cmdset->add(cmd= new cl_state_cmd("state", 0));
815 cmd->init();
817 #ifdef STATISTIC
818 cmdset->add(cmd= new cl_statistic_cmd("statistic", 0));
819 cmd->init();
820 #endif
822 cmdset->add(cmd= new cl_file_cmd("file", 0));
823 cmd->init();
824 cmd->add_name("load");
826 cmdset->add(cmd= new cl_dl_cmd("download", 0));
827 cmd->init();
828 cmd->add_name("dl");
830 cmdset->add(cmd= new cl_check_cmd("check", 0));
831 cmd->init();
833 cmdset->add(cmd= new cl_pc_cmd("pc", 0));
834 cmd->init();
836 cmdset->add(cmd= new cl_reset_cmd("reset", 0));
837 cmd->init();
839 cmdset->add(cmd= new cl_tick_cmd("tick", 0));
840 cmd->init();
842 cmdset->add(cmd= new cl_dump_cmd("dump", true));
843 cmd->init();
844 cmd->add_name("d");
846 cmdset->add(cmd= new cl_dch_cmd("dch", true));
847 cmd->init();
849 cmdset->add(cmd= new cl_dc_cmd("dc", true));
850 cmd->init();
852 cmdset->add(cmd= new cl_disassemble_cmd("disassemble", true));
853 cmd->init();
855 cmdset->add(cmd= new cl_fill_cmd("fill", 0));
856 cmd->init();
858 cmdset->add(cmd= new cl_where_cmd("where", 0));
859 cmd->init();
861 cmdset->add(cmd= new cl_Where_cmd("Where", 0));
862 cmd->init();
864 cmdset->add(cmd= new cl_hole_cmd("hole", 0));
865 cmd->init();
867 cmdset->add(cmd= new cl_break_cmd("break", 0));
868 cmd->init();
870 cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0));
871 cmd->init();
873 cmdset->add(cmd= new cl_clear_cmd("clear", 0));
874 cmd->init();
876 cmdset->add(cmd= new cl_delete_cmd("delete", 0));
877 cmd->init();
879 cmdset->add(cmd= new cl_commands_cmd("commands", 0));
880 cmd->init();
882 cmdset->add(cmd= new cl_display_cmd("display", 0));
883 cmd->init();
885 cmdset->add(cmd= new cl_undisplay_cmd("undisplay", 0));
886 cmd->init();
889 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("get"));
890 if (super_cmd)
891 cset= super_cmd->commands;
892 else {
893 cset= new cl_cmdset();
894 cset->init();
896 cset->add(cmd= new cl_get_sfr_cmd("sfr", 0));
897 cmd->init();
898 /*cset->add(cmd= new cl_get_option_cmd("option", 0));
899 cmd->init();*/
900 if (!super_cmd)
902 cmdset->add(cmd= new cl_super_cmd("get", 0, cset));
903 cmd->init();
904 set_get_help(cmd);
909 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("set"));
910 if (super_cmd)
911 cset= super_cmd->commands;
912 else {
913 cset= new cl_cmdset();
914 cset->init();
916 cset->add(cmd= new cl_set_mem_cmd("memory", 0));
917 cmd->add_name("bits");
918 cmd->init();
919 cset->add(cmd= new cl_set_hw_cmd("hardware", 0));
920 cmd->add_name("hw");
921 cmd->init();
922 if (!super_cmd)
924 cmdset->add(cmd= new cl_super_cmd("set", 0, cset));
925 cmd->init();
926 set_set_help(cmd);
930 { // info
931 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("info"));
932 if (super_cmd)
933 cset= super_cmd->get_subcommands();
934 else {
935 cset= new cl_cmdset();
936 cset->init();
938 cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0));
939 cmd->add_name("bp");
940 cmd->init();
941 cset->add(cmd= new cl_info_reg_cmd("registers", 0));
942 cmd->init();
943 cset->add(cmd= new cl_info_hw_cmd("hardware", 0));
944 cmd->add_name("hw");
945 cmd->add_name("h");
946 cmd->init();
948 cset->add(cmd= new cl_info_stack_cmd("stack", 0,
949 "info stack Status of stack of the CPU",
950 "long help of info stack"));
951 cmd->init();
953 cset->add(cmd= new cl_info_memory_cmd("memory", 0));
954 cmd->init();
955 cset->add(cmd= new cl_info_var_cmd("variables", 0));
956 cmd->init();
957 cmd->add_name("vars");
958 cset->add(cmd= new cl_hist_info_cmd("history", 0));
959 cmd->init();
960 if (!super_cmd) {
961 cmdset->add(cmd= new cl_super_cmd("info", 0, cset));
962 cmd->init();
963 set_info_help(cmd);
968 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("timer"));
969 if (super_cmd)
970 cset= super_cmd->get_subcommands();
971 else {
972 cset= new cl_cmdset();
973 cset->init();
975 cset->add(cmd= new cl_timer_add_cmd("add", 0));
976 cmd->init();
977 cmd->add_name("create");
978 cmd->add_name("make");
979 cset->add(cmd= new cl_timer_delete_cmd("delete", 0));
980 cmd->init();
981 cmd->add_name("remove");
982 cset->add(cmd= new cl_timer_get_cmd("get", 0));
983 cmd->init();
984 cset->add(cmd= new cl_timer_run_cmd("run", 0));
985 cmd->init();
986 cmd->add_name("start");
987 cset->add(cmd= new cl_timer_stop_cmd("stop", 0));
988 cmd->init();
989 cset->add(cmd= new cl_timer_value_cmd("set", 0));
990 cmd->init();
991 cmd->add_name("value");
992 cset->add(cmd= new cl_timer_list_cmd("list", 0));
993 cmd->init();
994 if (!super_cmd) {
995 cmdset->add(cmd= new cl_super_cmd("timer", 0, cset));
996 cmd->init();
997 set_timer_help(cmd);
1002 class cl_super_cmd *mem_create, *mem_remove;
1003 class cl_cmdset *mem_create_cset, *mem_remove_cset;
1004 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("memory"));
1005 if (super_cmd)
1006 cset= super_cmd->get_subcommands();
1007 else {
1008 cset= new cl_cmdset();
1009 cset->init();
1012 cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0));
1013 cmd->init();
1015 mem_create= (class cl_super_cmd *)cset->get_cmd("create");
1016 if (mem_create)
1017 mem_create_cset= mem_create->get_subcommands();
1018 else {
1019 mem_create_cset= new cl_cmdset();
1020 mem_create_cset->init();
1023 mem_create_cset->add(cmd= new cl_memory_create_chip_cmd("chip", 0));
1024 cmd->init();
1026 mem_create_cset->add(cmd= new cl_memory_create_addressspace_cmd("addressspace", 0));
1027 cmd->init();
1028 cmd->add_name("addrspace");
1029 cmd->add_name("aspace");
1030 cmd->add_name("as");
1031 cmd->add_name("addrs");
1032 cmd->add_name("addr");
1034 mem_create_cset->add(cmd= new cl_memory_create_addressdecoder_cmd("addressdecoder", 0));
1035 cmd->init();
1036 cmd->add_name("addrdecoder");
1037 cmd->add_name("adecoder");
1038 cmd->add_name("addressdec");
1039 cmd->add_name("addrdec");
1040 cmd->add_name("adec");
1041 cmd->add_name("ad");
1043 mem_create_cset->add(cmd= new cl_memory_create_banker_cmd("banker", 0));
1044 cmd->init();
1045 cmd->add_name("bankswitcher");
1046 cmd->add_name("banksw");
1047 cmd->add_name("bsw");
1048 cmd->add_name("bs");
1050 mem_create_cset->add(cmd= new cl_memory_create_bank_cmd("bank", 0));
1051 cmd->init();
1053 mem_create_cset->add(cmd= new cl_memory_create_bander_cmd("bander", 0));
1054 cmd->init();
1055 cmd->add_name("bitbander");
1056 cmd->add_name("bitband");
1057 cmd->add_name("band");
1058 cmd->add_name("bb");
1060 if (!mem_create)
1061 cset->add(mem_create= new cl_super_cmd("create", 0, mem_create_cset));
1062 mem_create->init();
1063 mem_create->add_name("add");
1064 set_memory_create_help(mem_create);
1066 cset->add(cmd= new cl_info_memory_cmd("info", 0));
1067 cmd->init();
1068 cset->add(cmd= new cl_memory_cell_cmd("cell", 0));
1069 cmd->init();
1070 if (!super_cmd) {
1071 cmdset->add(cmd= new cl_super_cmd("memory", 0, cset));
1072 cmd->init();
1073 set_memory_help(cmd);
1076 mem_remove= (class cl_super_cmd *)cset->get_cmd("remove");
1077 if (mem_remove)
1078 mem_remove_cset= mem_remove->get_subcommands();
1079 else {
1080 mem_remove_cset= new cl_cmdset();
1081 mem_remove_cset->init();
1084 mem_remove_cset->add(cmd= new cl_memory_remove_chip_cmd("chip", 0));
1085 cmd->init();
1087 if (!mem_remove)
1088 cset->add(mem_remove= new cl_super_cmd("remove", 0, mem_remove_cset));
1089 mem_remove->init();
1090 mem_remove->add_name("del");
1091 mem_remove->add_name("rm");
1092 set_memory_remove_help(mem_remove);
1095 super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("history"));
1096 if (super_cmd)
1097 cset= super_cmd->get_subcommands();
1098 else
1100 cset= new cl_cmdset();
1101 cset->init();
1102 cmdset->add(cmd= new cl_super_cmd("history", 0, cset));
1103 cmd->init();
1105 cset->add(cmd= new cl_hist_cmd("_no_parameters_", 0));
1106 cmd->init();
1107 cset->add(cmd= new cl_hist_info_cmd("information", 0));
1108 cmd->init();
1109 cset->add(cmd= new cl_hist_clear_cmd("clear", 0));
1110 cmd->init();
1111 cset->add(cmd= new cl_hist_list_cmd("list", 0));
1112 cmd->add_name("print");
1113 cmd->init();
1115 cmdset->add(cmd= new cl_var_cmd("var", 0));
1116 cmd->init();
1117 cmd->add_name("variable");
1118 cmdset->add(cmd= new cl_rmvar_cmd("rmvar", 0));
1119 cmd->init();
1121 cmdset->add(cmd= new cl_analyze_cmd("analyse", 0));
1122 cmd->add_name("analyze");
1123 cmd->init();
1128 * Read/write simulated memory
1131 t_mem
1132 cl_uc::read_mem(const char *id, t_addr addr)
1134 class cl_address_space *m= address_space(id);
1136 return(m?(m->read(addr)):0);
1139 t_mem
1140 cl_uc::get_mem(const char *id, t_addr addr)
1142 class cl_address_space *m= address_space(id);
1144 return(m?(m->get(addr)):0);
1147 void
1148 cl_uc::write_mem(const char *id, t_addr addr, t_mem val)
1150 class cl_address_space *m= address_space(id);
1152 if (m)
1153 m->write(addr, val);
1156 void
1157 cl_uc::set_mem(const char *id, t_addr addr, t_mem val)
1159 class cl_address_space *m= address_space(id);
1161 if(m)
1162 m->set(addr, val);
1166 class cl_address_space *
1167 cl_uc::address_space(const char *id)
1169 int i;
1171 if (!id ||
1172 !(*id))
1173 return(0);
1174 for (i= 0; i < address_spaces->count; i++)
1176 class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
1177 if (!m ||
1178 !m->have_real_name())
1179 continue;
1180 if (m->is_inamed(id))
1181 return(m);
1183 return(0);
1186 class cl_address_space *
1187 cl_uc::address_space(class cl_memory_cell *cell)
1189 return(address_space(cell, (t_addr*)NULL));
1192 class cl_address_space *
1193 cl_uc::address_space(class cl_memory_cell *cell, t_addr *addr)
1195 int i;
1197 for (i= 0; i < address_spaces->count; i++)
1199 class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
1200 if (!m)
1201 continue;
1202 if (m->is_owned(cell, addr))
1203 return(m);
1205 return(0);
1208 class cl_memory *
1209 cl_uc::memory(const char *id)
1211 int i;
1213 if (!id ||
1214 !(*id))
1215 return(0);
1216 for (i= 0; i < address_spaces->count; i++)
1218 class cl_base *b= address_spaces->object_at(i);
1219 class cl_memory *m= (class cl_memory *)(b);
1220 if (!m ||
1221 !m->have_real_name())
1222 continue;
1223 if (m->is_inamed(id))
1224 return(m);
1226 for (i= 0; i < memchips->count; i++)
1228 class cl_memory *m= (cl_memory *)(memchips->at(i));
1229 if (!m ||
1230 !m->have_real_name())
1231 continue;
1232 if (m->is_inamed(id))
1233 return(m);
1235 return(0);
1238 void
1239 cl_uc::remove_chip(class cl_memory *chip)
1241 class cl_address_space *as;
1242 class cl_address_decoder *ad;
1243 int i, j;
1244 t_index idx;
1245 i= memchips->index_of(chip, &idx);
1246 if (!i)
1247 return;
1248 for (i= 0; i < address_spaces->get_count(); i++)
1250 as= (class cl_address_space *)(address_spaces->at(i));
1251 j= 0;
1252 class cl_list bankers;
1253 bankers.init();
1254 while (j < as->decoders->get_count())
1256 for (j= 0; j < as->decoders->get_count(); j++)
1258 t_addr as_start, as_end;
1259 ad= (class cl_address_decoder *)(as->decoders->at(j));
1260 as_start= ad->as_begin;
1261 as_end= ad->as_end;
1262 if (ad->memchip == chip)
1264 as->undecode_area(NULL, as_start, as_end, NULL);
1265 break;
1267 if (ad->is_banker())
1269 if (ad->uses_chip(chip))
1271 bankers.add(ad);
1276 if (bankers.count > 0)
1278 int i;
1279 for (i= 0; i < bankers.count; i++)
1281 class cl_address_decoder *ad;
1282 ad= (class cl_address_decoder *)(bankers.at(i));
1283 as->decoders->disconn(ad);
1284 delete ad;
1286 bankers.disconn_all();
1289 memchips->disconn(chip);
1290 delete chip;
1294 static long
1295 ReadInt(cl_f *f, bool *ok, int bytes)
1297 char s2[3];
1298 long l= 0;
1299 int c;
1301 *ok= false;
1302 while (bytes)
1304 if (f->eof())
1305 return(0);
1306 c= f->get_c();
1307 if ((c < 0) ||
1308 (c == 0) ||
1309 (c > 0xff))
1310 return 0;
1311 s2[0]= c;
1312 if (f->eof())
1313 return(0);
1314 c= f->get_c();
1315 if ((c < 0) ||
1316 (c == 0) ||
1317 (c > 0xff))
1318 return 0;
1319 s2[1]= c;
1320 s2[2]= '\0';
1321 l= l*256 + strtol(s2, NULL, 16);
1322 bytes--;
1324 *ok= true;
1325 return(l);
1330 * Reading intel hexa file into EROM
1331 *____________________________________________________________________________
1333 * If parameter is a NULL pointer, this function reads data from `cmd_in'
1337 void
1338 cl_uc::set_rom(t_addr addr, t_mem val)
1340 t_addr size= rom->get_size();
1341 if (addr < size)
1343 rom->download(addr, val);
1344 return;
1346 t_addr bank, caddr;
1347 bank= addr / size;
1348 caddr= addr % size;
1349 class cl_banker *d= (class cl_banker *)(rom->get_decoder_of(caddr));
1350 if (d)
1352 if (!d->is_banker())
1354 return;
1356 d->switch_to(bank, NULL);
1357 rom->download(caddr, val);
1358 d->activate(NULL);
1360 else
1365 long
1366 cl_uc::read_hex_file(const char *nam)
1368 cl_f *f;
1370 if (!nam)
1372 fprintf(stderr, "cl_uc::read_hex_file File name not specified\n");
1373 return(-1);
1375 else
1376 if ((f= /*fopen*/mk_io(nam, "r")) == NULL)
1378 fprintf(stderr, "Can't open `%s': %s\n", nam, strerror(errno));
1379 return(-1);
1381 long l= read_hex_file(f);
1382 delete f;
1383 return l;
1386 long
1387 cl_uc::read_hex_file(cl_console_base *con)
1389 cl_f *f;
1390 if (con == NULL)
1391 return -1;
1392 f= con->get_fin();
1393 if (f == NULL)
1394 return -1;
1395 long l= read_hex_file(f);
1396 return l;
1399 long
1400 cl_uc::read_hex_file(cl_f *f)
1402 int c;
1403 long written= 0, recnum= 0;
1405 uint base= 0; // extended address, added to every address
1406 uchar dnum; // data number
1407 uchar rtyp=0; // record type
1408 uint addr= 0; // address
1409 uchar rec[300]; // data record
1410 uchar sum ; // checksum
1411 uchar chk ; // check
1412 int i;
1413 bool ok;
1414 int get_low= 0;
1415 uchar lows[4]= { 0, 0, 0, 0 };
1417 if (!rom)
1419 sim->app->get_commander()->
1420 dd_printf("No ROM address space to read in.\n");
1421 return(-1);
1424 //memset(inst_map, '\0', sizeof(inst_map));
1425 ok= true;
1426 while (ok &&
1427 rtyp != 1)
1429 while (((c= /*getc(f)*/f->get_c()) != ':') &&
1430 (/*c != EOF*/!f->eof()));
1431 if (c != ':')
1433 fprintf(stderr, ": not found\n");
1434 break;
1436 recnum++;
1437 dnum= ReadInt(f, &ok, 1);
1438 chk = dnum;
1439 addr= ReadInt(f, &ok, 2);
1440 chk+= (addr & 0xff);
1441 chk+= ((addr >> 8) & 0xff);
1442 rtyp= ReadInt(f, &ok, 1);
1443 chk+= rtyp;
1444 for (i= 0; ok && (i < dnum); i++)
1446 rec[i]= ReadInt(f, &ok, 1);
1447 chk+= rec[i];
1449 if (ok)
1451 sum= ReadInt(f, &ok, 1);
1452 if (ok)
1454 if (((sum + chk) & 0xff) == 0)
1456 if (rtyp == 0)
1458 if (rom->width > 8)
1459 addr/= 2;
1460 for (i= 0; i < dnum; i++)
1462 if (rom->width <= 8)
1464 set_rom(base+addr, rec[i]);
1465 addr++;
1466 written++;
1468 else if (rom->width <= 16)
1470 switch (get_low)
1472 case 0: lows[0]= rec[i]; get_low++; break;
1473 case 1: lows[1]= rec[i];
1474 set_rom(base+addr, (lows[1]*256)+lows[0]);
1475 addr++;
1476 written++;
1477 get_low= 0;
1478 break;
1481 else if (rom->width <= 32)
1483 switch (get_low)
1485 case 0: lows[0]= rec[i]; get_low++; break;
1486 case 1: lows[1]= rec[i]; get_low++; break;
1487 case 2: lows[2]= rec[i]; get_low++; break;
1488 case 3: lows[3]= rec[i];
1489 set_rom(base+addr,
1490 (lows[3]<<24)+
1491 (lows[2]<<16)+
1492 (lows[1]<<8)+
1493 (lows[0]));
1494 get_low= 0;
1495 lows[3]= lows[2]= lows[1]= lows[0]= 0;
1496 addr++;
1497 written++;
1498 break;
1503 else if (rtyp == 4)
1505 if (dnum >= 2)
1507 base= (rec[0]*256+rec[1]) << 16;
1510 else
1511 if (rtyp != 1)
1512 fprintf(stderr, "Unknown record type %d(0x%x)\n",
1513 rtyp, rtyp);
1515 else
1516 fprintf(stderr, "Checksum error (%x instead of %x) in "
1517 "record %ld.\n", chk, sum, recnum);
1519 else
1520 fprintf(stderr, "Read error in record %ld.\n", recnum);
1523 if (rom->width > 8)
1525 for (i= get_low; i<4; i++)
1526 lows[i]= 0;
1527 rom->set(addr,
1528 (lows[3]<<24)+
1529 (lows[2]<<16)+
1530 (lows[1]<<8)+
1531 (lows[0]));
1534 return(written);
1537 long
1538 cl_uc::read_omf_file(cl_f *f)
1540 long written= 0;
1541 class cl_omf_rec rec;
1542 while (rec.read(f))
1544 if (rec.type == 0x06)
1546 // content
1547 u16_t addr= rec.pick_word(1);
1548 int i= 3;
1549 while (i < rec.len)
1551 set_rom(addr+i, rec.rec[i]);
1552 written++;
1553 i++;
1557 return (written);
1560 long
1561 cl_uc::read_asc_file(cl_f *f)
1563 int c;
1564 chars line= chars();
1565 bool in;
1566 t_addr addr= 0;
1568 in= true;
1569 while ((c= f->get_c()) &&
1570 (!f->eof()))
1572 if (in)
1574 if ((c=='\n') || (c=='\r'))
1576 in= false;
1578 chars word= chars();
1579 const char *s;
1580 // process
1581 line.trim();
1582 line.start_parse();
1583 word= line.token(" ");
1584 s= word.c_str();
1585 if (isxdigit(*s))
1587 t_mem d= chars(s).htoi();//strtoll(s, 0, 16);
1588 set_rom(addr, d);
1589 addr++;
1591 line= "";
1594 else
1595 line.append(c);
1597 else // out
1599 if ((c=='\n') || (c=='\r'))
1601 else
1603 in= true;
1604 line.append(c);
1608 return addr;
1611 long
1612 cl_uc::read_p2h_file(cl_f *f, bool just_check)
1614 chars line= chars();
1615 int c;
1616 long nr= 0;
1617 while ((c= f->get_c()) &&
1618 (!f->eof()))
1620 if ((c=='\n') || (c=='\r'))
1622 line.trim();
1623 line.start_parse();
1624 chars w1= line.token(" \t");
1625 chars w2= line.token(" \t");
1626 chars w3= line.token(" \t");
1627 if (w1.nempty() && w2.nempty() && w3.nempty())
1629 if ((w2 == "//C") || (w2 == "//I"))
1631 t_mem v= w1.htoi();//strtol(w1.c_str(), 0, 16);
1632 t_addr a= w3.htoi();//strtol(w3.c_str(), 0, 16);
1633 if (just_check)
1635 t_mem mv= rom->read(a);
1636 if (mv != v)
1638 application->dd_printf("Diff at %08x, FILE=%08x MEM=%08x\n",
1639 AU32(a), MU32(v), MU32(mv));
1642 else
1643 set_rom(a, v);
1644 nr++;
1647 line= "";
1649 else
1650 line.append(c);
1652 return nr;
1655 long
1656 cl_uc::read_cdb_file(cl_f *f)
1658 class cl_cdb_recs *fns= new cl_cdb_recs();
1659 chars ln;
1660 const char *lc;
1661 long cnt= 0;
1662 class cl_cdb_rec *r;
1664 ln= f->get_s();
1665 while (!ln.empty())
1667 lc= ln.c_str();
1668 if (lc[0] == 'F')
1670 if (ln.len() > 5)
1672 if ((lc[1] == ':') &&
1673 (lc[2] == 'G'))
1675 ln.start_parse(4);
1676 chars n= ln.token("$");
1677 if ((r= fns->rec(n)) != NULL)
1679 class cl_cvar *v;
1680 v= vars->add(n, rom, r->addr, "");
1681 v->set_by(VBY_DEBUG);
1682 fns->del(n);
1683 cnt++;
1685 else
1686 fns->add(new cl_cdb_rec(n));
1690 else if (lc[0] == 'L')
1692 if (ln.len() > 5)
1694 if ((ln[1] == ':') &&
1695 (lc[2] == 'G'))
1697 ln.start_parse(4);
1698 chars n= ln.token("$");
1699 chars t= ln.token(":");
1700 t= ln.token(" ");
1701 t_addr a= t.htoi();//strtol(t.c_str(), 0, 16);
1702 if ((r= fns->rec(n)) != NULL)
1704 fns->del(n);
1705 class cl_cvar *v;
1706 v= vars->add(n, rom, a, "");
1707 v->set_by(VBY_DEBUG);
1708 cnt++;
1710 else
1711 fns->add(new cl_cdb_rec(n, a));
1715 ln= f->get_s();
1717 fns->free_all();
1718 delete fns;
1719 return cnt;
1722 static bool is_area(chars w1, chars w2, chars w3)
1724 if (w1.empty() || w2.empty() || w3.empty())
1725 return false;
1726 if (w1 != "Area")
1727 return false;
1728 if (w2 != "Addr")
1729 return false;
1730 if (w3 != "Size")
1731 return false;
1732 return true;
1735 static bool is_code_seg(chars wlast)
1737 return wlast == "(REL,CON,CODE)";
1740 static bool is_ncode_seg(chars w1, chars wlast)
1742 return (wlast == "(REL,CON)")
1745 (w1 == "CODE") ||
1746 (w1 == "_CODE")
1750 static bool is_addr(chars w)
1752 int l= w.len();
1753 if (l != 8) return false;
1754 const char *s= w.c_str();
1755 int i;
1756 for (i= 0; i<l; i++)
1757 if (!isxdigit(s[i])) return false;
1758 return true;
1761 long
1762 cl_uc::read_map_file(cl_f *f)
1764 int cnt= 0;
1765 chars ln;
1766 chars s, w1, w2, w3, wlast, w;
1767 enum { s_wait_area, s_wait_seginfo, s_wait_sym, s_wait_nsym } stat;
1768 class cl_cvar *v;
1770 stat= s_wait_area;
1771 ln= f->get_s();
1772 while (ln.nempty())
1774 ln= f->get_s();
1775 s= ln.c_str();
1776 ln.start_parse();
1777 w1= ln.token(" \t\v");
1778 if (w1.nempty()) wlast= w1;
1779 w2= ln.token(" \t\v");
1780 if (w2.nempty()) wlast= w2;
1781 w3= ln.token(" \t\v");
1782 if (w3.nempty()) wlast= w3;
1783 w= ln.token(" \t\v");
1784 while (w.nempty())
1786 wlast= w;
1787 w= ln.token(" \t\v");
1789 switch (stat)
1791 case s_wait_area:
1792 if (is_area(w1, w2, w3))
1793 stat= s_wait_seginfo;
1794 break;
1795 case s_wait_seginfo:
1796 if (is_code_seg(wlast))
1797 stat= s_wait_sym;
1798 else if (is_ncode_seg(w1, wlast))
1799 stat= s_wait_nsym;
1800 break;
1801 case s_wait_sym:
1802 if (is_area(w1, w2, w3))
1803 stat= s_wait_seginfo;
1804 else
1806 if ((w1 == "C:") && is_addr(w2) && (w3.c(0) == '_'))
1808 w3= &(w3.c_str()[1]);
1809 t_addr a= w2.htoi();//strtol(w2.c_str(), NULL, 16);
1810 //printf("%s %08x\n", w3.c_str(), AU(a));
1811 v= vars->add(w3, rom, a, "");
1812 v->set_by(VBY_DEBUG);
1813 cnt++;
1816 break;
1817 case s_wait_nsym:
1818 if (is_area(w1, w2, w3))
1819 stat= s_wait_seginfo;
1820 else
1822 if (is_addr(w1) && (w2.c(0) == '_'))
1824 w2= &(w2.c_str()[1]);
1825 t_addr a= w1.htoi();//strtol(w1.c_str(), NULL, 16);
1826 //printf("%s %08x\n", w2.c_str(), AU(a));
1827 v= vars->add(w2, rom, a, "");
1828 v->set_by(VBY_DEBUG);
1829 cnt++;
1832 break;
1835 return cnt;
1838 static int h1(const char *s, int p)
1840 int r= 0;
1841 if (isxdigit(s[p]))
1843 if (s[p]>='a')
1844 r= 10+(s[p]-'a');
1845 else if (s[p]>='A')
1846 r= 10+(s[p]-'A');
1847 else
1848 r= s[p]-'0';
1850 return r;
1853 static int h2(const char *s, int p)
1855 int r= 0;
1856 if (isxdigit(s[p]) && isxdigit(s[p+1]))
1858 r= 16 * h1(s, p);
1859 r+= h1(s, p+1);
1861 return r;
1864 static t_addr a16(const char *s, int p)
1866 t_addr a;
1867 a= h2(s, p);
1868 a<<= 8;
1869 a+= h2(s, p+2);
1870 return a;
1873 static t_addr a24(const char *s, int p)
1875 t_addr a;
1876 a= h2(s, p);
1877 a<<= 8;
1878 a+= h2(s, p+2);
1879 a<<= 8;
1880 a+= h2(s, p+4);
1881 return a;
1884 static t_addr a32(const char *s, int p)
1886 t_addr a;
1887 a= h2(s, p);
1888 a<<= 8;
1889 a+= h2(s, p+2);
1890 a<<= 8;
1891 a+= h2(s, p+4);
1892 a<<= 8;
1893 a+= h2(s, p+6);
1894 return a;
1897 static int s19(class cl_uc *uc, t_addr a, const char *s, int p, int data_bytes)
1899 int b= 0;
1900 if (data_bytes < 1)
1901 return 0;
1902 while (b < data_bytes)
1904 u8_t d= h2(s, p);
1905 uc->set_rom(a, d);
1906 a++;
1907 p+= 2;
1908 b++;
1910 return data_bytes;
1913 long
1914 cl_uc::read_s19_file(cl_f *f)
1916 chars line;
1917 int cnt;
1918 long int written= 0;
1919 while (!f->eof())
1921 line= f->get_s();
1922 if (line.empty())
1923 continue;
1924 const char *s= line.c_str();
1925 if (s[0] != 'S')
1926 continue;
1927 if (line.length() < 4)
1928 continue;
1929 cnt= h2(s, 2);
1930 if (line.length() < 4+cnt*2)
1931 continue;
1932 int b= 0, sum= 0, p= 2;
1933 while (b<cnt)
1935 if (s[p] && s[p+1])
1936 sum+= h2(s, p);
1937 b++;
1938 p+= 2;
1940 if (b!=cnt)
1941 continue;
1942 int chk= h2(s, 2+cnt*2);
1943 sum&= 0xff;
1944 sum^= 0xff;
1945 if (sum != chk)
1946 continue;
1947 t_addr a;
1948 switch (s[1])
1950 case '0': break;
1951 case '1':
1952 a= a16(s, 4);
1953 p= 8;
1954 written+= s19(this, a, s, p, cnt-2-1);
1955 break;
1956 case '2':
1957 a= a24(s, 4);
1958 p= 10;
1959 written+= s19(this, a, s, p, cnt-3-1);
1960 break;
1961 case '3':
1962 a= a32(s, 4);
1963 p= 12;
1964 written+= s19(this, a, s, p, cnt-4-1);
1965 break;
1966 case '4': break;
1967 case '5': break;
1968 case '6': break;
1969 case '7': break;
1970 case '8': break;
1971 case '9': break;
1974 return written;
1977 cl_f *
1978 cl_uc::find_loadable_file(chars nam)
1980 cl_f *f;
1981 bool o;
1982 chars c;
1984 f= mk_io(nam, "r");
1985 o= (f->opened());
1986 if (o)
1987 return f;
1989 c= chars("", "%s.p2h", nam.c_str());
1990 f->open(c, "r");
1991 o= (f->opened());
1992 if (o)
1993 return f;
1994 c= chars("", "%s.asc", nam.c_str());
1995 f->open(c, "r");
1996 o= (f->opened());
1997 if (o)
1998 return f;
1999 c= chars("", "%s.ihx", nam.c_str());
2000 f->open(c, "r");
2001 o= (f->opened());
2002 if (o)
2003 return f;
2004 c= chars("", "%s.hex", nam.c_str());
2005 f->open(c, "r");
2006 o= (f->opened());
2007 if (o)
2008 return f;
2009 c= chars("", "%s.ihex", nam.c_str());
2010 f->open(c, "r");
2011 o= (f->opened());
2012 if (o)
2013 return f;
2014 c= chars("", "%s.s19", nam.c_str());
2015 f->open(c, "r");
2016 o= (f->opened());
2017 if (o)
2018 return f;
2020 c= chars("", "%s.omf", nam.c_str());
2021 f->open(c, "r");
2022 o= (f->opened());
2023 if (o)
2024 return f;
2026 delete f;
2027 return NULL;
2030 long
2031 cl_uc::read_file(chars nam, class cl_console_base *con, bool just_check)
2033 cl_f *f= find_loadable_file(nam);
2034 long l= 0;
2036 if (!f)
2038 if (con)
2039 con->dd_printf("no loadable file found (%s)\n", nam.c_str());
2040 else
2041 printf("no loadable file found (%s)\n", nam.c_str());
2042 return 0;
2044 if (!application->quiet)
2045 printf("Loading from %s\n", f->get_file_name());
2046 if (is_p2h_file(f))
2048 l= read_p2h_file(f, just_check);
2049 if (!application->quiet)
2050 printf("%ld words read from %s\n", l, f->get_fname());
2052 if (is_asc_file(f))
2054 l= read_asc_file(f);
2055 if (!application->quiet)
2056 printf("%ld words read from %s\n", l, f->get_fname());
2058 if (is_hex_file(f))
2060 l= read_hex_file(f);
2061 if (!application->quiet)
2062 printf("%ld words read from %s\n", l, f->get_fname());
2064 else if (is_s19_file(f))
2066 l= read_s19_file(f);
2067 if (!application->quiet)
2068 printf("%ld words read from %s\n", l, f->get_fname());
2070 else if (is_omf_file(f))
2072 l= read_omf_file(f);
2073 if (!application->quiet)
2074 printf("%ld words read from %s\n", l, f->get_fname());
2076 else if (is_cdb_file(f))
2078 l= read_cdb_file(f);
2079 if (!application->quiet)
2080 printf("%ld symbols read from %s\n", l, f->get_fname());
2082 else if (is_map_file(f))
2084 l= read_map_file(f);
2085 if (!application->quiet)
2086 printf("%ld symbols read from %s\n", l, f->get_fname());
2088 if (strcmp(nam, f->get_fname()) != 0)
2090 chars n= nam;
2091 n+= ".cdb";
2092 cl_f *c= mk_io(n, "r");
2093 if (c->opened())
2095 l= read_cdb_file(c);
2096 if (!application->quiet)
2097 printf("%ld symbols read from %s\n", l, c->get_fname());
2099 delete c;
2101 if (strcmp(nam, f->get_fname()) != 0)
2103 chars n= nam;
2104 n+= ".map";
2105 cl_f *c= mk_io(n, "r");
2106 if (c->opened())
2108 l= read_map_file(c);
2109 if (!application->quiet)
2110 printf("%ld symbols read from %s\n", l, c->get_fname());
2112 delete c;
2114 delete f;
2116 if (!just_check)
2117 analyze_init();
2118 return l;
2122 void
2123 cl_uc::set_analyzer(bool val)
2125 analyzer= val;
2126 if (rom)
2127 analyze_init();
2130 void
2131 cl_uc::analyze_init(void)
2133 // Forget everything we knew previously.
2134 for (t_addr addr = rom->get_start_address(); addr < rom->highest_valid_address(); addr++)
2135 del_inst_at(addr);
2137 t_index i = 0;
2138 while (i < vars->by_name.count)
2140 class cl_cvar *v = vars->by_name.at(i);
2141 if (*(v->get_name()) == '.')
2142 vars->del(v->get_name());
2143 else
2144 i++;
2147 if (analyzer)
2148 analyze_start();
2151 void
2152 cl_uc::analyze_start(void)
2154 class cl_var *v = new cl_var(".reset", rom, reset_addr(),
2155 chars("Auto-generated by analyze"), -1, -1);
2156 v->init();
2157 vars->add(v);
2158 v->set_by(VBY_ANALYZE);
2160 analyze(0);
2163 void
2164 cl_uc::analyze(t_addr addr)
2166 set_inst_at(addr);
2168 // If we jumped we should make sure its labeled. However we don't know if the
2169 // target has a valid instruction and only a microprocessor specific analyze
2170 // implementation can follow the execution path. So we tell a white lie.
2171 bool was_inst = inst_at(PC);
2172 set_inst_at(PC);
2174 if (PC != addr + inst_length(addr))
2175 analyze_jump(addr, PC, 'j');
2177 if (!was_inst)
2178 del_inst_at(PC);
2181 void
2182 cl_uc::analyze_jump(t_addr addr, t_addr target, char type, unsigned int bit)
2184 // If the target isn't already labeled we'll create one ourselves.
2185 t_index var_i;
2186 if (!vars->by_addr.search(rom, target, -1, -1, var_i) &&
2187 !vars->by_addr.search(rom, target, rom->width, 0, var_i))
2189 const char *var_name = "";
2190 const char *suffix = "";
2192 switch (type)
2194 case 's': // subroutine call
2195 var_name = "func";
2196 break;
2198 case 't':
2199 case 'f':
2200 suffix = (type == 't' ? "_isset" : "_unset");
2201 switch (bit)
2203 default:
2204 case 0: var_name= "bit0"; break;
2205 case 1: var_name= "bit1"; break;
2206 case 2: var_name= "bit2"; break;
2207 case 3: var_name= "bit3"; break;
2208 case 4: var_name= "bit4"; break;
2209 case 5: var_name= "bit5"; break;
2210 case 6: var_name= "bit6"; break;
2211 case 7: var_name= "bit7"; break;
2213 break;
2215 default:
2216 var_name = (target <= addr ? "loop" : "label");
2217 break;
2220 chars label("", ".%s%s$%u", var_name, suffix, label_index++);
2221 class cl_var *v = new cl_var(label, rom, target, chars("Auto-generated by analyze"), -1, -1);
2222 v->init();
2223 vars->add(v);
2224 v->set_by(VBY_ANALYZE);
2227 // If we didn't know the target was code we do now, but don't cross
2228 // into bankers - we don't know what bank would be selected at
2229 // execution time.
2230 class cl_address_decoder *ad;
2231 if (!inst_at(target) && (ad = rom->get_decoder_of(target)) && !ad->is_banker())
2232 analyze(target);
2236 * Handling instruction map
2238 * `inst_at' is checking if the specified address is in instruction
2239 * map and `set_inst_at' marks the address in the map and
2240 * `del_inst_at' deletes the mark. `there_is_inst' checks if there is
2241 * any mark in the map
2244 bool
2245 cl_uc::inst_at(t_addr addr)
2247 if (!rom)
2248 return(0);
2249 return(rom->get_cell_flag(addr, CELL_INST));
2252 void
2253 cl_uc::set_inst_at(t_addr addr)
2255 if (rom)
2256 rom->set_cell_flag(addr, true, CELL_INST);
2259 void
2260 cl_uc::del_inst_at(t_addr addr)
2262 if (rom)
2263 rom->set_cell_flag(addr, false, CELL_INST);
2266 bool
2267 cl_uc::there_is_inst(void)
2269 if (!rom)
2270 return(0);
2271 bool got= false;
2272 t_addr addr;
2273 for (addr= 0; rom->valid_address(addr) && !got; addr++)
2274 got= rom->get_cell_flag(addr, CELL_INST);
2275 return(got);
2280 * Manipulating HW elements of the CPU
2281 *****************************************************************************
2284 /* Register callback hw objects for mem read/write */
2286 /*void
2287 cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
2289 class cl_m *m;
2290 class cl_memloc *l;
2292 if ((m= (class cl_m*)mems->at(type)))
2294 if ((l= m->read_locs->get_loc(addr)) == 0)
2296 l= new cl_memloc(addr);
2297 l->init();
2298 m->read_locs->add(l);
2300 l->hws->add(hw);
2302 else
2303 printf("cl_uc::register_hw_read TROUBLE\n");
2306 /*void
2307 cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
2311 void
2312 cl_uc::add_hw(class cl_hw *hw)
2314 int i;
2315 if (!hw)
2316 return;
2317 for (i= 0; i < hws->count; i++)
2319 class cl_hw *h= (class cl_hw *)(hws->at(i));
2320 h->new_hw_adding(hw);
2322 hws->add(hw);
2323 for (i= 0; i < hws->count; i++)
2325 class cl_hw *h= (class cl_hw *)(hws->at(i));
2326 if (h != hw)
2327 h->new_hw_added(hw);
2331 void
2332 cl_uc::init_add_hw(class cl_hw *hw)
2334 if (hw)
2336 hw->init();
2337 add_hw(hw);
2342 cl_uc::nuof_hws(void)
2344 return hws->count;
2347 /* Looking for a specific HW element */
2349 class cl_hw *
2350 cl_uc::get_hw(int idx)
2352 if (idx >= hws->count)
2353 return NULL;
2354 return (class cl_hw *)(hws->at(idx));
2357 class cl_hw *
2358 cl_uc::get_hw(enum hw_cath cath, int *idx)
2360 class cl_hw *hw= 0;
2361 int i= 0;
2363 if (idx)
2364 i= *idx;
2365 for (; i < hws->count; i++)
2367 hw= (class cl_hw *)(hws->at(i));
2368 if (hw->category == cath)
2369 break;
2371 if (i >= hws->count)
2372 return(0);
2373 if (idx)
2374 *idx= i;
2375 return(hw);
2378 class cl_hw *
2379 cl_uc::get_hw(const char *id_string, int *idx)
2381 class cl_hw *hw= 0;
2382 int i= 0;
2384 if (idx)
2385 i= *idx;
2386 if (strcmp(id_string, "cpu") == 0)
2387 return cpu;
2388 for (; i < hws->count; i++)
2390 hw= (class cl_hw *)(hws->at(i));
2391 if (strstr(hw->id_string, id_string) == hw->id_string)
2392 break;
2394 if (i >= hws->count)
2395 return(0);
2396 if (idx)
2397 *idx= i;
2398 return(hw);
2401 class cl_hw *
2402 cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
2404 class cl_hw *hw;
2405 int i= 0;
2407 if (idx)
2408 i= *idx;
2409 hw= get_hw(cath, &i);
2410 while (hw &&
2411 hw->id != hwid)
2413 i++;
2414 hw= get_hw(cath, &i);
2416 if (hw &&
2417 idx)
2418 *idx= i;
2419 return(hw);
2422 class cl_hw *
2423 cl_uc::get_hw(const char *id_string, int hwid, int *idx)
2425 class cl_hw *hw;
2426 int i= 0;
2428 if (idx)
2429 i= *idx;
2430 hw= get_hw(id_string, &i);
2431 while (hw &&
2432 hw->id != hwid)
2434 i++;
2435 hw= get_hw(id_string, &i);
2437 if (hw &&
2438 idx)
2439 *idx= i;
2440 return(hw);
2444 cl_uc::get_max_hw_id(enum hw_cath cath)
2446 class cl_hw *hw;
2447 int i, max= -1;
2449 for (i= 0; i < hws->count; i++)
2451 hw= (class cl_hw *)(hws->at(i));
2452 if (hw->id > max)
2453 max= hw->id;
2455 return max;
2459 * Help of the command interpreter
2462 struct dis_entry *
2463 cl_uc::dis_tbl(void)
2465 static struct dis_entry empty= { 0, 0, 0, 0, NULL };
2466 return(&empty);
2469 char *
2470 cl_uc::disass(t_addr addr)
2472 return strdup("uc::disass() unimplemented\n");
2476 cl_uc::print_disass(t_addr addr, class cl_console_base *con, bool nl)
2478 char *dis;
2479 chars cdis, comment;
2480 class cl_brk *b;
2481 int i, l, len= 0;
2482 class cl_option *o= sim->app->options->get_option("black_and_white");
2483 bool bw= false;
2484 if (o) o->get_value(&bw);
2486 if (!rom)
2487 return 0;
2489 cl_vars_iterator vi(vars);
2490 const class cl_var *var = NULL;
2491 if ((var = vi.first(rom, addr)))
2493 len+= con->dd_printf("\n");
2495 do {
2496 len+= con->dd_cprintf("dump_address", rom->addr_format, addr);
2497 len+= con->dd_cprintf("answer", " ");
2498 len+= con->dd_cprintf("dump_label", " <%s>:\n", var->get_name());
2499 } while ((var = vi.next()));
2502 b= fbrk_at(addr);
2503 dis= disassc(addr, &comment);
2504 cdis= dis;
2505 len+= con->dd_cprintf("dump_address", rom->addr_format, addr);
2506 len+= con->dd_cprintf("answer", " %c", (b ? (b->perm == brkFIX ? 'F' : 'D') : ' '));
2507 len+= con->dd_cprintf("answer", "%c", inst_at(addr)?' ':'?');
2508 l= inst_length(addr);
2509 for (i= 0; i < l; i++)
2511 len+= con->dd_printf(" ");
2512 len+= con->dd_cprintf("dump_number", rom->data_format, rom->get(addr+i));
2514 int padding= (longest_inst() - i) * ((rom->width + 3) / 4 + 1);
2515 len+= con->dd_printf("%*.*s", padding, padding, "");
2516 if (comment.nempty())
2517 while (cdis.len() < 25) cdis.append(' ');
2518 len+= con->dd_cprintf("dump_char", " %s", cdis.c_str());
2519 if (comment.nempty())
2520 len+= con->dd_cprintf("comment", " %s", comment.c_str());
2521 if (nl)
2523 if (!bw)
2525 con->dd_printf("\033[0K");
2527 else
2529 while (++len < 70) con->dd_printf(" ");
2531 con->dd_printf("\n");
2533 free((char *)dis);
2534 return len;
2538 cl_uc::print_disass(t_addr addr, class cl_console_base *con)
2540 return print_disass(addr, con, true);
2543 void
2544 cl_uc::print_regs(class cl_console_base *con)
2546 con->dd_printf("No registers\n");
2550 cl_uc::inst_length(t_addr addr)
2552 struct dis_entry *tabl= dis_tbl();
2553 int i;
2554 t_mem code;
2556 if (!rom)
2557 return(0);
2559 code = rom->get(addr);
2560 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
2561 return(tabl[i].mnemonic?tabl[i].length:1);
2565 cl_uc::inst_branch(t_addr addr)
2567 struct dis_entry *tabl= dis_tbl();
2568 int i;
2569 t_mem code;
2571 if (!rom)
2572 return(0);
2574 code = rom->get(addr);
2575 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
2577 return tabl[i].branch;
2580 bool
2581 cl_uc::is_call(t_addr addr)
2583 struct dis_entry *tabl= dis_tbl();
2584 int i;
2585 t_mem code;
2587 if (!rom)
2588 return(0);
2590 code = rom->get(addr);
2591 for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
2593 return tabl[i].is_call;
2597 cl_uc::longest_inst(void)
2599 struct dis_entry *de= dis_tbl();
2600 int max= 0;
2602 while (de &&
2603 de->mnemonic)
2605 if (de->length > max)
2606 max= de->length;
2607 de++;
2609 return(max);
2612 const class cl_var *
2613 cl_uc::addr_name(t_addr addr,
2614 class cl_memory *mem,
2615 int bitnr_high,
2616 int bitnr_low,
2617 chars *buf,
2618 const class cl_var *context)
2620 t_index i;
2621 const cl_var *var = NULL;
2623 if (!mem)
2624 return NULL;
2626 if (vars->by_addr.search(mem, addr, bitnr_high, bitnr_low, i))
2627 var = vars->by_addr.at(i);
2628 else if (vars->by_addr.search(mem, addr, mem->width - 1, 0, i))
2629 var = vars->by_addr.at(i);
2630 else if (bitnr_high >= 0 && vars->by_addr.search(mem, addr, -1, -1, i))
2631 var = vars->by_addr.at(i);
2632 else if (mem->is_address_space())
2634 cl_address_decoder *ad = ((cl_address_space *)mem)->get_decoder_of(addr);
2635 if (ad)
2637 class cl_memory *chip = ad->memchip;
2638 if (chip)
2640 addr = ad->as_to_chip(addr);
2642 if (vars->by_addr.search(chip, addr, bitnr_high, bitnr_low, i))
2643 var = vars->by_addr.at(i);
2644 else if (vars->by_addr.search(chip, addr, chip->width - 1, 0, i))
2645 var = vars->by_addr.at(i);
2646 else if (bitnr_high >= 0 && vars->by_addr.search(chip, addr, -1, -1, i))
2647 var = vars->by_addr.at(i);
2649 else if (vars->by_addr.search(mem, addr, -1, -1, i))
2650 var = vars->by_addr.at(i);
2654 if (var)
2656 const char *name = var->get_name();
2658 // If there is a context var and its name prefixes the var for this
2659 // addr we strip the prefix off.
2660 size_t len= 0;
2661 if (context && (len = strlen(context->get_name())) &&
2662 !strncmp(name, context->get_name(), len) &&
2663 (name[len] == '\0' || name[len] == '_'))
2665 if (name[len] == '\0')
2667 // Same as context, nothing more to add
2668 return var;
2670 else if (name[len] == '_')
2672 // We don't need the prefix - we already had the context
2673 if (buf) buf->appendf(" <%s", &name[len + 1]);
2676 else
2678 // It's all significant, nothing to do with context
2679 if (buf) buf->appendf(" <%s", name);
2682 if (bitnr_high >= 0 &&
2683 (var->bitnr_high != bitnr_high || var->bitnr_low != bitnr_low))
2685 if (bitnr_high == bitnr_low)
2687 if (buf) buf->appendf(".%d", bitnr_high);
2689 else
2691 if (buf) buf->appendf("[%d:%d]", bitnr_high, bitnr_low);
2695 if (buf) buf->appendf(">");
2698 return var;
2701 bool
2702 cl_uc::symbol2address(char *sym,
2703 class cl_memory **mem,
2704 t_addr *addr)
2706 t_index i;
2708 if (!sym ||
2709 !*sym)
2710 return false;
2711 if (vars->by_name.search(sym, i))
2713 class cl_cvar *v= vars->by_name.at(i);
2714 /*if (v->bitnr_low >= 0)
2715 return false;*/
2716 if (!v->is_mem_var())
2717 return false;
2718 if (mem)
2719 *mem= v->get_mem();
2720 if (addr)
2721 *addr= v->get_addr();
2722 return true;
2724 return false;
2727 bool
2728 cl_uc::symbol2cell(char *sym,
2729 class cl_memory_cell **cell)
2731 t_index i;
2733 if (!sym ||
2734 !*sym)
2735 return false;
2736 if (vars->by_name.search(sym, i))
2738 class cl_cvar *v= vars->by_name.at(i);
2739 class cl_memory_cell *c= v->get_cell();
2740 if (c)
2742 if (cell)
2743 *cell= c;
2744 return true;
2747 return false;
2752 * Searching for a name in the specified table
2755 struct name_entry *
2756 cl_uc::get_name_entry(struct name_entry tabl[], char *name)
2758 int i= 0;
2759 char *p;
2761 if (!tabl ||
2762 !name ||
2763 !(*name))
2764 return(0);
2765 for (p= name; *p; *p= toupper(*p), p++);
2766 while (tabl[i].name &&
2767 (!(tabl[i].cpu_type & type->type) ||
2768 (strcmp(tabl[i].name, name) != 0)))
2770 i++;
2772 if (tabl[i].name != NULL)
2773 return(&tabl[i]);
2774 else
2775 return(0);
2778 chars
2779 cl_uc::cell_name(class cl_memory_cell *cell, int bitnr_high, int bitnr_low)
2781 class cl_address_space *as;
2782 t_addr addr;
2783 int i;
2785 if (!cell || !(as = address_space(cell, &addr)))
2786 return chars("");
2788 if (vars->by_addr.search(as, addr, bitnr_high, bitnr_low, i))
2789 return chars(vars->by_addr.at(i)->get_name());
2791 if (bitnr_high != - 1 && vars->by_addr.search(as, addr, -1, -1, i))
2793 if (bitnr_high != bitnr_low)
2794 return chars("", "%s[%d:%d]", vars->by_addr.at(i)->get_name(), bitnr_high, bitnr_low);
2795 else
2796 return chars("", "%s.%d", vars->by_addr.at(i)->get_name(), bitnr_low);
2799 if (bitnr_high == -1)
2800 return chars("", "%s_%06x", as->get_name(), addr);
2801 else if (bitnr_high != bitnr_low)
2802 return chars("", "%s_%06x[%d:%d]", as->get_name(), addr, bitnr_high, bitnr_low);
2803 else
2804 return chars("", "%s_%06x.%d", as->get_name(), addr, bitnr_high);
2807 t_addr
2808 cl_uc::read_addr(class cl_memory *m, t_addr start_addr)
2810 if (!m) return 0;
2811 // 16 bit little endian, by default
2812 return m->read(start_addr) + 256*m->read(start_addr+1);
2816 * Messages to broadcast
2819 bool
2820 cl_uc::handle_event(class cl_event &event)
2822 switch (event.what)
2824 case ev_address_space_added:
2826 //try {
2827 class cl_event_address_space_added &e=
2828 (class cl_event_address_space_added &)(event);
2829 address_space_added(e.as);
2830 e.handle();
2832 //catch (...)
2833 //{ break; }
2834 break;
2836 default:
2837 return(pass_event_down(event));
2838 break;
2840 return(false);
2844 void
2845 cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
2847 if (hws)
2848 hws->mem_cell_changed(mem, addr);
2849 else
2850 printf("JAJ uc\n");//FIXME
2851 if (mems &&
2852 mems->count)
2854 int i;
2855 for (i= 0; i < mems->count; i++)
2862 void
2863 cl_uc::address_space_added(class cl_address_space *as)
2866 if (hws)
2867 hws->address_space_added(as);
2868 else
2869 printf("JAJ uc\n");//FIXME
2875 * Error handling
2878 void
2879 cl_uc::error(class cl_error *error)
2881 errors->add(error);
2882 if ((error->inst= inst_exec))
2883 error->PC= instPC;
2886 void
2887 cl_uc::check_errors(void)
2889 int i;
2890 class cl_commander_base *c= sim->app->get_commander();
2891 bool must_stop= false;
2893 if (c)
2895 for (i= 0; i < errors->count; i++)
2897 class cl_error *error= (class cl_error *)(errors->at(i));
2898 if (!error->is_on())
2899 continue;
2900 error->print(c);
2901 must_stop= must_stop || (error->get_type() & err_stop);
2902 if (error->inst)
2904 class cl_console_base *con;
2905 con= c->actual_console;
2906 if (!con)
2907 con= c->frozen_or_actual();
2908 if (con)
2910 con->dd_printf("Erroneous instruction: ");
2911 print_disass(error->PC, con);
2915 errors->free_all();
2917 else
2918 fprintf(stderr, "no actual console, %d errors\n", errors->count);
2919 if (must_stop)
2920 sim->stop(resERROR);
2925 * Converting bit address into real memory
2928 class cl_address_space *
2929 cl_uc::bit2mem(t_addr bitaddr, t_addr *memaddr, int *bitnr_high, int *bitnr_low)
2931 if (memaddr)
2932 *memaddr= bitaddr;
2934 return rom;
2939 * Execution
2943 cl_uc::tick_hw(int cycles)
2945 class cl_hw *hw;
2946 int c= cycles;
2947 int i;//, cpc= clock_per_cycle();
2949 // tick hws
2950 while (c-- > 0)
2952 int hc= hws->count;
2953 for (i= 0; i < hc; i++)
2955 hw= (class cl_hw *)(hws->at(i));
2956 if ((hw->flags & HWF_INSIDE) &&
2957 (hw->on))
2958 hw->tick(1);
2961 do_extra_hw(cycles);
2962 return(0);
2965 void
2966 cl_uc::do_extra_hw(int cycles)
2970 cl_uc::tick(int cycles)
2972 //class cl_hw *hw;
2973 int i, clocks= cycles * clock_per_cycle();
2974 double time = clocks * xtal_tick;
2976 // increase time
2977 class it_level *il= (class it_level *)(it_levels->top());
2978 for (i= 0; i < counters->count; i++)
2980 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2981 if (t && t->run)
2983 if (t->get_type() == TICK_ANY ||
2984 (il->level >= 0 && (t->get_type() == TICK_INISR)) ||
2985 (state == stIDLE && (t->get_type() == TICK_IDLE)) ||
2986 (state == stPD && (t->get_type() == TICK_HALT)))
2987 t->tick(clocks, time);
2991 //tick_hw(cycles);
2992 inst_ticks+= cycles;
2993 return(0);
2997 cl_uc::tickt(t_mem code)
2999 i8_t *tt= tick_tab(code);
3000 if (tt == NULL)
3001 return tick(1);
3002 int t= tt[code];
3003 if (t)
3004 return tick(t);
3005 return 0;
3008 class cl_ticker *
3009 cl_uc::get_counter(int nr)
3011 if (nr >= counters->count)
3012 return(0);
3013 return((class cl_ticker *)(counters->at(nr)));
3016 class cl_ticker *
3017 cl_uc::get_counter(const char *nam)
3019 int i;
3021 if (!nam)
3022 return(0);
3023 for (i= 0; i < counters->count; i++)
3025 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
3026 if (t &&
3027 t->get_name() &&
3028 strcmp(t->get_name(), nam) == 0)
3029 return(t);
3031 return(0);
3034 void
3035 cl_uc::add_counter(class cl_ticker *ticker, int nr)
3037 while (counters->count <= nr)
3038 counters->add(0);
3039 counters->put_at(nr, ticker);
3042 void
3043 cl_uc::add_counter(class cl_ticker *ticker, const char */*nam*/)
3045 int i;
3047 if (counters->count < 1)
3048 counters->add(0);
3049 for (i= 1; i < counters->count; i++)
3051 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
3052 if (!t)
3054 counters->put_at(i, ticker);
3055 return;
3058 counters->add(ticker);
3061 void
3062 cl_uc::del_counter(int nr)
3064 class cl_ticker *t;
3066 if (nr >= counters->count)
3067 return;
3068 if ((t= (class cl_ticker *)(counters->at(0))) != 0)
3069 delete t;
3070 counters->put_at(nr, 0);
3073 void
3074 cl_uc::del_counter(const char *nam)
3076 int i;
3078 if (!nam)
3079 return;
3080 for (i= 0; i < counters->count; i++)
3082 class cl_ticker *t= (class cl_ticker *)(counters->at(i));
3083 if (t &&
3084 t->get_name() &&
3085 strcmp(t->get_name(), nam) == 0)
3087 delete t;
3088 counters->put_at(i, 0);
3089 return;
3095 * Fetch without checking for breakpoint hit
3098 t_mem
3099 cl_uc::fetch(void)
3101 ulong code;
3103 if (!rom)
3104 return(0);
3106 code= rom->read(PC);
3107 set_PC((PC+1)&PCmask);
3108 vc.fetch++;
3109 return(code);
3113 * Fetch but checking for breakpoint hit first, returns TRUE if
3114 * a breakpoint is hit
3117 bool
3118 cl_uc::do_brk(void)
3120 class cl_brk *brk;
3121 int idx;
3122 bool ret= false;
3124 if ((sim->state & SIM_GO) &&
3125 rom &&
3126 (sim->steps_done > 0))
3128 if (vcd_break)
3130 vcd_break = false;
3131 ret= true;
3133 if (rom->get_cell_flag(PC, CELL_FETCH_BRK))
3134 if ((brk= fbrk->get_bp(PC, &idx)))
3135 if (brk->do_hit())
3137 if (brk->perm == brkDYNAMIC)
3138 fbrk->del_bp(PC);
3139 ret= true;
3143 return ret;
3146 bool
3147 cl_uc::fetch(t_mem *code)
3149 bool ret = do_brk();
3151 if (!ret)
3152 *code= fetch();
3154 return ret;
3158 cl_uc::do_inst(void)
3160 int res= resGO;
3162 save_hist();
3163 if (state == stGO)
3165 pre_inst();
3166 instPC= PC;
3167 res= exec_inst();
3168 if (res == resINV_INST)
3169 /* backup to start of instruction */
3170 PC= instPC;
3171 else
3173 if (analyzer)
3175 if (res == resGO && !inst_at(instPC))
3177 analyze(instPC);
3182 post_inst();
3184 if ((res == resGO) && (PC == instPC) && stop_selfjump && !repeating)
3186 res= resSELFJUMP;
3187 return res;
3190 if ((res == resGO || res == resNOT_DONE))
3192 int r= do_interrupt();
3193 if (r != resGO)
3194 res= r;
3197 return(res);
3201 cl_uc::do_emu(void)
3203 int res= resGO;
3205 if (state == stGO)
3207 pre_emu();
3208 instPC= PC;
3209 res= exec_inst();
3210 if (res == resINV_INST)
3211 /* backup to start of instruction */
3212 PC= instPC;
3214 post_emu();
3216 if ((res == resGO || res == resNOT_DONE))
3218 int r= do_interrupt();
3219 if (r != resGO)
3220 res= r;
3223 return(res);
3226 void
3227 cl_uc::pre_inst(void)
3229 inst_exec= true;
3230 events->disconn_all();
3231 vc.inst++;
3232 inst_ticks= 0;
3233 repeating= false;
3236 void
3237 cl_uc::pre_emu(void)
3239 inst_exec= true;
3240 events->disconn_all();
3241 vc.inst++;
3242 inst_ticks= 0;
3246 cl_uc::exec_inst(void)
3248 return(resGO);
3252 cl_uc::exec_inst_tab(instruction_wrapper_fn itab[])
3254 t_mem c;
3255 int res= resGO;
3256 if (fetch(&c))
3257 return resBREAKPOINT;
3258 if (itab[c] == NULL)
3260 PC= instPC;
3261 return resNOT_DONE;
3263 tickt(c);
3264 res= itab[c](this, c);
3265 if (res == resNOT_DONE)
3267 PC= instPC;
3268 return res;
3270 //tick(1);
3271 return res;
3276 cl_uc::exec_inst_uctab()
3278 t_mem c;
3279 int res= resGO;
3280 if (fetch(&c))
3281 return resBREAKPOINT;
3282 if (uc_itab[c] == NULL)
3284 PC= instPC;
3285 return resNOT_DONE;
3287 tickt(c);
3288 res= (this->*uc_itab[c])(c);
3289 if (res == resNOT_DONE)
3291 PC= instPC;
3292 return res;
3294 //tick(1);
3295 return res;
3299 void
3300 cl_uc::post_inst(void)
3302 cPC.W(PC);
3303 tick_hw(inst_ticks);
3304 if (errors->count)
3305 check_errors();
3306 if (events->count)
3307 check_events();
3308 inst_exec= false;
3311 void
3312 cl_uc::post_emu(void)
3314 tick_hw(inst_ticks);
3315 errors->free_all();
3316 inst_exec= false;
3320 static FILE *pc_dump= NULL;
3322 void
3323 cl_uc::save_hist()
3325 if (juj & 1)
3327 if (pc_dump==NULL) pc_dump= fopen("addr.txt","w");
3328 if (pc_dump!=NULL)
3330 fprintf(pc_dump,"%x 0x%06x\n", MU(application->cyc), AU(PC));
3331 fflush(pc_dump);
3334 hist->put();
3338 cl_uc::inst_unknown(t_mem code)
3340 //PC--;
3341 class cl_error_unknown_code *e= new cl_error_unknown_code(this);
3342 error(e);
3343 return(resGO);
3348 * Interrupt processing
3352 cl_uc::do_interrupt(void)
3354 int i;
3355 bool is_en= it_enabled();
3356 class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
3358 irq= false;
3359 for (i= 0; i < it_sources->count; i++)
3361 class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
3362 is->pass_over();
3364 for (i= 0; i < it_sources->count; i++)
3366 class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
3367 if (is->is_slave())
3369 continue;
3371 if (!is->is_nmi())
3373 if (!is_en)
3375 continue;
3378 bool A= is->is_active();
3379 bool E= is->enabled();
3380 bool P= is->pending();
3381 if (A && E && P)
3383 int pr= priority_of(is->nuof);
3384 int ap;
3385 irq= true;
3386 if (il &&
3387 il->level >= 0)
3389 ap= il->level;
3391 else
3393 ap= priority_main();
3395 if (ap >= pr)
3397 continue;
3399 if (state == stIDLE)
3400 state= stGO;
3401 is->clear();
3402 sim->app->get_commander()->
3403 debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
3404 ticks->get_rtime(), ticks->get_ticks(), object_name(is), PC);
3405 IL= new it_level(pr, is->addr, PC, is);
3406 return(accept_it(IL));
3409 return resGO;
3413 cl_uc::accept_it(class it_level *il)
3415 it_levels->push(il);
3416 return resGO;
3419 class cl_it_src *
3420 cl_uc::search_it_src(int cid_or_nr)
3422 class cl_it_src *it;
3423 int i;
3424 for (i= 0; i<it_sources->get_count(); i++)
3426 it= (class cl_it_src *)(it_sources->at(i));
3427 if (it &&
3429 (it->cid != 0 && it->cid == cid_or_nr) ||
3430 (it->cid != 0 && toupper(it->cid) == toupper(cid_or_nr)) ||
3431 (it->nuof == cid_or_nr)
3434 return it;
3436 return NULL;
3441 * Time related functions
3444 unsigned long
3445 cl_uc::clocks_of_time(double t)
3447 return (unsigned long)(t * xtal);
3451 cl_uc::clock_per_cycle(void)
3453 return(1);
3456 void
3457 cl_uc::touch(void)
3459 class cl_hw *hw;
3460 int i;
3461 for (i= 0; i < hws->count; i++)
3463 hw= (class cl_hw *)(hws->at(i));
3464 hw->touch();
3470 * Stack tracking system
3473 void
3474 cl_uc::stack_write(void)
3476 stack_check_overflow();
3477 return ;
3480 void
3481 cl_uc::stack_write(t_addr sp_before)
3483 stack_check_overflow(sp_before);
3484 return ;
3487 void
3488 cl_uc::stack_write(class cl_stack_op *op)
3490 stack_check_overflow(op);
3491 delete op;
3492 return ;
3493 if (op->get_op() & stack_read_operation)
3495 class cl_error_stack_tracker_wrong_handle *e= new
3496 cl_error_stack_tracker_wrong_handle(false);
3497 e->init();
3498 error(e);
3499 return;
3501 stack_ops->push(op);
3504 void
3505 cl_uc::stack_read(void)
3507 return ;
3510 void
3511 cl_uc::stack_read(class cl_stack_op *op)
3513 delete op;
3514 return ;
3515 class cl_stack_op *top= (class cl_stack_op *)(stack_ops->top());
3517 if (op->get_op() & stack_write_operation)
3519 class cl_error_stack_tracker_wrong_handle *e= new
3520 cl_error_stack_tracker_wrong_handle(true);
3521 e->init();
3522 error(e);
3523 return;
3525 if (!top)
3527 class cl_error *e= new cl_error_stack_tracker_empty(op);
3528 e->init();
3529 error(e);
3530 return;
3533 if (top)
3535 if (!top->match(op))
3537 class cl_error *e= new cl_error_stack_tracker_unmatch(top, op);
3538 e->init();
3539 error(e);
3541 int top_size= top->data_size(), op_size= op->data_size();
3542 if (top_size != op_size)
3544 application->debug("0x%06x %d bytes to read out of stack "
3545 "but %d was pushed in last operation\n",
3546 (int)op->get_pc(), op_size, top_size);
3550 int removed= 0;
3551 while (top &&
3552 top->can_removed(op))
3554 top= (class cl_stack_op *)stack_ops->pop();
3555 delete top;
3556 top= (class cl_stack_op *)stack_ops->top();
3557 removed++;
3559 if (removed != 1)
3561 application->debug("0x%06x %d ops removed from stack-tracker "
3562 "when %s happened, top pc=0x%06x "
3563 "top before=0x%06x op after=0x%06x\n",
3564 (int)op->get_pc(), removed, op->get_op_name(),
3565 top?((int)top->get_pc()):0,
3566 top?((int)top->get_before()):0,
3567 (int)op->get_after());
3570 if (top)
3572 int ta= top->get_after(), oa= op->get_after();
3573 if (ta != oa)
3575 application->debug("0x%06x stack still inconsistent after %s, "
3576 "%d byte(s) should be read out; top after"
3577 "=0x%06x op after=0x%06x\n",
3578 (int)op->get_pc(),
3579 op->get_op_name(),
3580 abs(ta-oa),
3581 ta, oa);
3582 class cl_error *e=
3583 new cl_error_stack_tracker_inconsistent(op, abs(ta-oa));
3584 e->init();
3585 error(e);
3589 delete op;
3592 void
3593 cl_uc::stack_check_overflow(class cl_stack_op *op)
3597 void
3598 cl_uc::stack_check_overflow(void)
3602 void
3603 cl_uc::stack_check_overflow(t_addr sp_before)
3609 * Breakpoint handling
3612 class cl_fetch_brk *
3613 cl_uc::fbrk_at(t_addr addr)
3615 int idx;
3617 return((class cl_fetch_brk *)(fbrk->get_bp(addr, &idx)));
3620 class cl_ev_brk *
3621 cl_uc::ebrk_at(t_addr addr, char *id)
3623 int i;
3624 class cl_ev_brk *eb;
3626 for (i= 0; i < ebrk->count; i++)
3628 eb= (class cl_ev_brk *)(ebrk->at(i));
3629 if (eb->addr == addr &&
3630 !strcmp(eb->id, id))
3631 return(eb);
3633 return(0);
3636 /*void
3637 cl_uc::rm_fbrk(long addr)
3639 fbrk->del_bp(addr);
3642 /* Get a breakpoint specified by its number */
3644 class cl_brk *
3645 cl_uc::brk_by_nr(int nr)
3647 class cl_brk *bp;
3649 if ((bp= fbrk->get_bp(nr)))
3650 return(bp);
3651 if ((bp= ebrk->get_bp(nr)))
3652 return(bp);
3653 return(0);
3656 /* Get a breakpoint from the specified collection by its number */
3658 class cl_brk *
3659 cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
3661 class cl_brk *bp;
3663 if ((bp= bpcoll->get_bp(nr)))
3664 return(bp);
3665 return(0);
3668 /* Remove an event breakpoint specified by its address and id */
3670 void
3671 cl_uc::rm_ebrk(t_addr addr, char *id)
3673 int i;
3674 class cl_ev_brk *eb;
3676 for (i= 0; i < ebrk->count; i++)
3678 eb= (class cl_ev_brk *)(ebrk->at(i));
3679 if (eb->addr == addr &&
3680 !strcmp(eb->id, id))
3681 ebrk->del_bp(i, 0);
3685 /* Remove a breakpoint specified by its number */
3687 bool
3688 cl_uc::rm_brk(int nr)
3690 class cl_brk *bp;
3692 if ((bp= brk_by_nr(fbrk, nr)))
3694 fbrk->del_bp(bp->addr);
3695 return(true);
3697 else if ((bp= brk_by_nr(ebrk, nr)))
3699 ebrk->del_bp(ebrk->index_of(bp), 0);
3700 return(true);
3702 return(false);
3705 void
3706 cl_uc::put_breaks(void)
3709 /* Remove all fetch and event breakpoints */
3711 void
3712 cl_uc::remove_all_breaks(void)
3714 while (fbrk->count)
3716 class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
3717 fbrk->del_bp(brk->addr);
3719 while (ebrk->count)
3720 ebrk->del_bp(ebrk->count-1, 0);
3724 cl_uc::make_new_brknr(void)
3726 if (brk_counter == 0)
3727 return(brk_counter= 1);
3728 if (fbrk->count == 0 &&
3729 ebrk->count == 0)
3730 return(brk_counter= 1);
3731 return(++brk_counter);
3734 class cl_ev_brk *
3735 cl_uc::mk_ebrk(enum brk_perm perm, class cl_address_space *mem,
3736 char op, t_addr addr, int hit)
3738 class cl_ev_brk *b;
3739 op= toupper(op);
3741 b= new cl_ev_brk(mem, make_new_brknr(), addr, perm, hit, op);
3742 b->init();
3743 return(b);
3746 class cl_ev_brk *
3747 cl_uc::mk_ebrk(enum brk_perm perm, class cl_memory_cell *cell,
3748 char op, int hit)
3750 class cl_ev_brk *b;
3751 op= toupper(op);
3753 b= new cl_ev_brk(cell, make_new_brknr(), perm, hit, op);
3754 b->init();
3755 return(b);
3758 void
3759 cl_uc::check_events(void)
3761 int i;
3762 if (events->count)
3763 sim->stop(resEVENTBREAK);
3764 for (i= 0; i < events->count; i++)
3766 class cl_ev_brk *brk=
3767 (class cl_ev_brk *)(events->object_at(i));
3768 brk->breaking();
3772 void
3773 cl_uc::stop_when(class cl_time_measurer *t)
3775 if (stop_at_time != NULL)
3776 delete stop_at_time;
3777 stop_at_time= t;
3782 * Errors
3783 *----------------------------------------------------------------------------
3786 cl_error_unknown_code::cl_error_unknown_code(class cl_uc *the_uc)
3788 uc= the_uc;
3789 classification= uc_error_registry.find("unknown_code");
3792 void
3793 cl_error_unknown_code::print(class cl_commander_base *c)
3795 c->dd_printf("%s: unknown instruction code at ", (char*)get_type_name());
3796 if (uc->rom)
3798 c->dd_printf(uc->rom->addr_format, PC);
3799 c->dd_printf(" (");
3800 c->dd_printf(uc->rom->data_format, uc->rom->get(PC));
3801 c->dd_printf(")");
3803 else
3804 c->dd_printf("0x%06x", AU(PC));
3805 c->dd_printf("\n");
3809 cl_uc_error_registry::cl_uc_error_registry(void)
3811 class cl_error_class *prev = uc_error_registry.find("non-classified");
3812 prev = register_error(new cl_error_class(err_error, "unknown_code", prev, ERROR_OFF));
3815 /* End of uc.cc */