1 /*
2  * Simulator of microcontrollers (uc.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 <errno.h>
33 #include <ctype.h>
34 #include "i_string.h"
35 
36 // prj
37 #include "globals.h"
38 #include "utils.h"
39 
40 // cmd.src
41 #include "newcmdcl.h"
42 #include "cmdutil.h"
43 #include "cmd_uccl.h"
44 #include "cmd_bpcl.h"
45 #include "cmd_getcl.h"
46 #include "cmd_setcl.h"
47 #include "cmd_infocl.h"
48 #include "cmd_timercl.h"
49 #include "cmd_statcl.h"
50 #include "cmd_memcl.h"
51 
52 // local, sim.src
53 #include "uccl.h"
54 #include "hwcl.h"
55 #include "memcl.h"
56 #include "simcl.h"
57 #include "itsrccl.h"
58 #include "simifcl.h"
59 #include "vcdcl.h"
60 
61 
62 static class cl_uc_error_registry uc_error_registry;
63 
64 /*
65  * Clock counter
66  */
67 
cl_ticker(int adir,int in_isr,const char * aname)68 cl_ticker::cl_ticker(int adir, int in_isr, const char *aname)
69 {
70   options= TICK_RUN;
71   if (in_isr)
72     options|= TICK_INISR;
73   dir= adir;
74   ticks= 0;
75   set_name(aname);
76 }
77 
~cl_ticker(void)78 cl_ticker::~cl_ticker(void) {}
79 
80 int
tick(int nr)81 cl_ticker::tick(int nr)
82 {
83   if (options&TICK_RUN)
84     ticks+= dir*nr;
85   return(ticks);
86 }
87 
88 double
get_rtime(double xtal)89 cl_ticker::get_rtime(double xtal)
90 {
91   double d;
92 
93   d= (double)ticks/xtal;
94   return(d);
95 }
96 
97 void
dump(int nr,double xtal,class cl_console_base * con)98 cl_ticker::dump(int nr, double xtal, class cl_console_base *con)
99 {
100   con->dd_printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
101 		 nr, get_name("unnamed"),
102 		 (options&TICK_RUN)?"ON":"OFF",
103 		 (options&TICK_INISR)?",ISR":"",
104 		 get_rtime(xtal), ticks);
105 }
106 
107 
108 /*
109  * Options of uc
110  */
111 
cl_xtal_option(class cl_uc * the_uc)112 cl_xtal_option::cl_xtal_option(class cl_uc *the_uc):
113   cl_optref(the_uc)
114 {
115   uc= the_uc;
116 }
117 
118 void
option_changed(void)119 cl_xtal_option::option_changed(void)
120 {
121   if (!uc)
122     return;
123   double d;
124   option->get_value(&d);
125   uc->xtal= d;
126 }
127 
128 
129 /* Time measurer */
130 
cl_time_measurer(class cl_uc * the_uc)131 cl_time_measurer::cl_time_measurer(class cl_uc *the_uc):
132   cl_base()
133 {
134   to_reach= 0;
135   uc= the_uc;
136 }
137 
138 void
set_reach(unsigned long val)139 cl_time_measurer::set_reach(unsigned long val)
140 {
141   to_reach= val;
142 }
143 
144 void
from_now(unsigned long val)145 cl_time_measurer::from_now(unsigned long val)
146 {
147   set_reach(now() + val);
148 }
149 
150 bool
reached()151 cl_time_measurer::reached()
152 {
153   return to_reach &&
154     (now() >= to_reach);
155 }
156 
157 unsigned long
now()158 cl_time_measurer::now()
159 {
160   return 0;
161 }
162 
163 
164 /* value of xtal clock */
165 
166 unsigned long
now()167 cl_time_clk::now()
168 {
169   if (!uc) return 0;
170   return uc->ticks->ticks;
171 }
172 
173 
174 /* value of virtual clocks */
175 
176 unsigned long
now()177 cl_time_vclk::now()
178 {
179   if (!uc) return 0;
180   return uc->vc.fetch + uc->vc.rd + uc->vc.wr;
181 }
182 
183 
184 /* value of fetches */
185 
186 unsigned long
now()187 cl_time_fclk::now()
188 {
189   if (!uc) return 0;
190   return uc->vc.fetch;
191 }
192 
193 
194 /* value of reads */
195 
196 unsigned long
now()197 cl_time_rclk::now()
198 {
199   if (!uc) return 0;
200   return uc->vc.rd;
201 }
202 
203 
204 /* value of writes */
205 
206 unsigned long
now()207 cl_time_wclk::now()
208 {
209   if (!uc) return 0;
210   return uc->vc.wr;
211 }
212 
213 
214 /* OMF file record */
215 
cl_omf_rec(void)216 cl_omf_rec::cl_omf_rec(void):
217   cl_base()
218 {
219   offset= 0;
220   f_offset= 0;
221   type= 0;
222   len= 0;
223   rec= NULL;
224   chk= 0;
225 }
226 
~cl_omf_rec(void)227 cl_omf_rec::~cl_omf_rec(void)
228 {
229   if (rec)
230     free(rec);
231 }
232 
233 unsigned char
g(cl_f * f)234 cl_omf_rec::g(cl_f *f)
235 {
236   unsigned char c= f->get_c();
237   offset++;
238   return c;
239 }
240 
241 u16_t
pick_word(int i)242 cl_omf_rec::pick_word(int i)
243 {
244   unsigned char h, l;
245   u16_t w;
246 
247   if (i >= len-1)
248     return 0;
249   l= rec[i];
250   h= rec[i+1];
251   w= h*256+l;
252   return w;
253 }
254 
255 chars
pick_str(int i)256 cl_omf_rec::pick_str(int i)
257 {
258   unsigned char l, j;
259   chars s= "";
260 
261   if (i >= len-1)
262     return chars("");
263   l= rec[i];
264   j= 0;
265   while (l &&
266 	 (i < len))
267     {
268       s+= rec[i+1+j];
269       l--;
270       j++;
271     }
272   return s;
273 }
274 
275 bool
read(cl_f * f)276 cl_omf_rec::read(cl_f *f)
277 {
278   unsigned char c;
279   int i, l, h;
280 
281   if (rec)
282     {
283       free(rec);
284       rec= NULL;
285     }
286   f_offset= offset;
287   if (f->eof())
288     return false;
289   c= g(f);
290   type= c;
291   if (f->eof())
292     return false;
293   c= g(f);
294   l= c;
295   //printf("l=%02x\n", c);
296   if (f->eof())
297     return false;
298   c= g(f);
299   h= c;
300   //printf("h=%02x\n", c);
301   if (f->eof())
302     return false;
303   len= h*256+l-1;
304   rec= (u8_t*)malloc(len);
305   for (i= 0; i < len; i++)
306     {
307       rec[i]= g(f);
308       if (f->eof())
309 	return false;
310     }
311   chk= g(f);
312 
313   return true;
314 }
315 
316 
317 /*
318  * Abstract microcontroller
319  ******************************************************************************
320  */
321 
cl_uc(class cl_sim * asim)322 cl_uc::cl_uc(class cl_sim *asim):
323   cl_base()
324 {
325   type= NULL;
326   //int i;
327   sim = asim;
328   //mems= new cl_list(MEM_TYPES, 1);
329   memchips= new cl_list(2, 2, "memchips");
330   address_spaces= new cl_address_space_list(this);
331   //address_decoders= new cl_list(2, 2);
332   rom= 0;
333 
334   hws = new cl_hws();
335   //options= new cl_list(2, 2);
336   //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
337   xtal_option= new cl_xtal_option(this);
338   xtal_option->init();
339   ticks= new cl_ticker(+1, 0, "time");
340   isr_ticks= new cl_ticker(+1, TICK_INISR, "isr");
341   idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle");
342   counters= new cl_list(2, 2, "counters");
343   it_levels= new cl_list(2, 2, "it levels");
344   it_sources= new cl_irqs(2, 2);
345   class it_level *il= new it_level(-1, 0, 0, 0);
346   it_levels->push(il);
347   stack_ops= new cl_list(2, 2, "stack operations");
348   errors= new cl_list(2, 2, "errors in uc");
349   events= new cl_list(2, 2, "events in uc");
350   sp_max= 0;
351   sp_avg= 0;
352   inst_exec= false;
353 }
354 
355 
~cl_uc(void)356 cl_uc::~cl_uc(void)
357 {
358   //delete mems;
359   delete hws;
360   //delete options;
361   delete ticks;
362   delete isr_ticks;
363   delete idle_ticks;
364   delete counters;
365   events->disconn_all();
366   delete events;
367   delete fbrk;
368   delete ebrk;
369   delete it_levels;
370   delete it_sources;
371   delete stack_ops;
372   errors->free_all();
373   delete errors;
374   delete xtal_option;
375   delete address_spaces;
376   delete memchips;
377   //delete address_decoders;
378 }
379 
380 
381 int
init(void)382 cl_uc::init(void)
383 {
384   int i;
385 
386   set_name("controller");
387   cl_base::init();
388   if (xtal_option->use("xtal"))
389     xtal= xtal_option->get_value(xtal);
390   else
391     xtal= 11059200;
392   vars= new cl_var_list();
393   make_variables();
394   make_memories();
395   if (rom == NULL)
396     rom= address_space(cchars("rom")/*MEM_ROM_ID*/);
397   ebrk= new brk_coll(2, 2, rom);
398   fbrk= new brk_coll(2, 2, rom);
399   fbrk->Duplicates= false;
400   brk_counter= 0;
401   stop_at_time= 0;
402   make_cpu_hw();
403   mk_hw_elements();
404   class cl_cmdset *cs= sim->app->get_commander()->cmdset;
405   build_cmdset(cs);
406   irq= false;
407   reset();
408 
409   return 0;
410   for (i= 0; i < sim->app->in_files->count; i++)
411     {
412       char *fname= (char *)(sim->app->in_files->at(i));
413       long l;
414       if ((l= read_hex_file(fname)) >= 0)
415 	{
416 	  /*sim->app->get_commander()->all_*/printf("%ld words read from %s\n",
417 						l, fname);
418 	}
419     }
420   return(0);
421 }
422 
423 char *
id_string(void)424 cl_uc::id_string(void)
425 {
426   return((char*)"unknown microcontroller");
427 }
428 
429 void
reset(void)430 cl_uc::reset(void)
431 {
432   class it_level *il;
433 
434   irq= false;
435   instPC= PC= 0;
436   state = stGO;
437   ticks->ticks= 0;
438   isr_ticks->ticks= 0;
439   idle_ticks->ticks= 0;
440   vc.inst= vc.fetch= vc.rd= vc.wr= 0;
441   /*FIXME should we clear user counters?*/
442   il= (class it_level *)(it_levels->top());
443   while (il &&
444 	 il->level >= 0)
445     {
446       il= (class it_level *)(it_levels->pop());
447       delete il;
448       il= (class it_level *)(it_levels->top());
449     }
450   sp_max= 0;
451   sp_avg= 0;
452 
453   stack_ops->free_all();
454 
455   int i;
456   for (i= 0; i < hws->count; i++)
457     {
458       class cl_hw *hw= (class cl_hw *)(hws->at(i));
459       hw->reset();
460     }
461 }
462 
463 /*
464  * Making elements
465  */
466 
467 void
make_memories(void)468 cl_uc::make_memories(void)
469 {
470 }
471 
472 void
make_variables(void)473 cl_uc::make_variables(void)
474 {
475   class cl_address_space *as;
476   class cl_option *o= sim->app->options->get_option("var_size");
477   long l, i;
478 
479   if (o)
480     o->get_value(&l);
481   else
482     l= 0x100;
483 
484   class cl_address_decoder *ad;
485   class cl_memory_chip *chip;
486 
487   if (l > 0)
488     {
489       variables= as= new cl_address_space("variables", 0, l, 32);
490       as->init();
491       address_spaces->add(as);
492 
493       chip= new cl_memory_chip("variable_storage", l, 32);
494       chip->init();
495       memchips->add(chip);
496       ad= new cl_address_decoder(variables, chip, 0, l-1, 0);
497       ad->init();
498       variables->decoders->add(ad);
499       ad->activate(0);
500 
501       for (i= 0; i < l; i++)
502 	variables->set(i, 0);
503     }
504 }
505 
506 /*t_addr
507 cl_uc::get_mem_size(char *id)
508 {
509   class cl_memory *m= memory(id);
510   return(m?(m->get_size()):0);
511 }
512 
513 int
514 cl_uc::get_mem_width(char *id)
515 {
516   class cl_memory *m= memory(id);
517   return(m?(m->width):8);
518 }
519 */
520 void
make_cpu_hw(void)521 cl_uc::make_cpu_hw(void)
522 {
523   cpu= NULL;
524 }
525 
526 void
mk_hw_elements(void)527 cl_uc::mk_hw_elements(void)
528 {
529   class cl_hw *h;
530 
531   add_hw(h= new cl_simulator_interface(this));
532   h->init();
533   add_hw(h= new cl_vcd(this, 0, "vcd"));
534   h->init();
535 }
536 
537 void
build_cmdset(class cl_cmdset * cmdset)538 cl_uc::build_cmdset(class cl_cmdset *cmdset)
539 {
540   class cl_cmd *cmd;
541   class cl_super_cmd *super_cmd;
542   class cl_cmdset *cset;
543 
544   cmdset->add(cmd= new cl_state_cmd("state", 0));
545   cmd->init();
546 
547 #ifdef STATISTIC
548   cmdset->add(cmd= new cl_statistic_cmd("statistic", 0));
549   cmd->init();
550 #endif
551 
552   cmdset->add(cmd= new cl_file_cmd("file", 0));
553   cmd->init();
554   cmd->add_name("load");
555 
556   cmdset->add(cmd= new cl_dl_cmd("download", 0));
557   cmd->init();
558   cmd->add_name("dl");
559 
560   cmdset->add(cmd= new cl_pc_cmd("pc", 0));
561   cmd->init();
562 
563   cmdset->add(cmd= new cl_reset_cmd("reset", 0));
564   cmd->init();
565 
566   cmdset->add(cmd= new cl_dump_cmd("dump", true));
567   cmd->init();
568 
569   cmdset->add(cmd= new cl_dch_cmd("dch", true));
570   cmd->init();
571 
572   cmdset->add(cmd= new cl_dc_cmd("dc", true));
573   cmd->init();
574 
575   cmdset->add(cmd= new cl_disassemble_cmd("disassemble", true));
576   cmd->init();
577 
578   cmdset->add(cmd= new cl_fill_cmd("fill", 0));
579   cmd->init();
580 
581   cmdset->add(cmd= new cl_where_cmd("where", 0));
582   cmd->init();
583 
584   cmdset->add(cmd= new cl_Where_cmd("Where", 0));
585   cmd->init();
586 
587   cmdset->add(cmd= new cl_hole_cmd("hole", 0));
588   cmd->init();
589 
590   cmdset->add(cmd= new cl_break_cmd("break", 0));
591   cmd->init();
592 
593   cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0));
594   cmd->init();
595 
596   cmdset->add(cmd= new cl_clear_cmd("clear", 0));
597   cmd->init();
598 
599   cmdset->add(cmd= new cl_delete_cmd("delete", 0));
600   cmd->init();
601 
602   cmdset->add(cmd= new cl_commands_cmd("commands", 0));
603   cmd->init();
604 
605   {
606     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("get"));
607     if (super_cmd)
608       cset= super_cmd->commands;
609     else {
610       cset= new cl_cmdset();
611       cset->init();
612     }
613     cset->add(cmd= new cl_get_sfr_cmd("sfr", 0));
614     cmd->init();
615     /*cset->add(cmd= new cl_get_option_cmd("option", 0));
616       cmd->init();*/
617   }
618   if (!super_cmd)
619     {
620       cmdset->add(cmd= new cl_super_cmd("get", 0, cset));
621       cmd->init();
622       set_get_help(cmd);
623     }
624 
625   {
626     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("set"));
627     if (super_cmd)
628       cset= super_cmd->commands;
629     else {
630       cset= new cl_cmdset();
631       cset->init();
632     }
633     cset->add(cmd= new cl_set_mem_cmd("memory", 0));
634     cmd->init();
635     cset->add(cmd= new cl_set_bit_cmd("bit", 0));
636     cmd->init();
637     cset->add(cmd= new cl_set_hw_cmd("hardware", 0));
638     cmd->add_name("hw");
639     cmd->init();
640   }
641   if (!super_cmd)
642     {
643       cmdset->add(cmd= new cl_super_cmd("set", 0, cset));
644       cmd->init();
645       set_set_help(cmd);
646     }
647 
648   { // info
649     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("info"));
650     if (super_cmd)
651       cset= super_cmd->get_subcommands();
652     else {
653       cset= new cl_cmdset();
654       cset->init();
655     }
656     cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0));
657     cmd->add_name("bp");
658     cmd->init();
659     cset->add(cmd= new cl_info_reg_cmd("registers", 0));
660     cmd->init();
661     cset->add(cmd= new cl_info_hw_cmd("hardware", 0));
662     cmd->add_name("hw");
663     cmd->init();
664     /*
665     cset->add(cmd= new cl_info_stack_cmd("stack", 0,
666     "info stack         Status of stack of the CPU",
667     "long help of info stack"));
668     cmd->init();
669     */
670     cset->add(cmd= new cl_info_memory_cmd("memory", 0));
671     cmd->init();
672     cset->add(cmd= new cl_info_var_cmd("variables", 0));
673     cmd->init();
674     cmd->add_name("vars");
675   }
676   if (!super_cmd) {
677     cmdset->add(cmd= new cl_super_cmd("info", 0, cset));
678     cmd->init();
679     set_info_help(cmd);
680   }
681 
682   {
683     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("timer"));
684     if (super_cmd)
685       cset= super_cmd->get_subcommands();
686     else {
687       cset= new cl_cmdset();
688       cset->init();
689     }
690     cset->add(cmd= new cl_timer_add_cmd("add", 0));
691     cmd->init();
692     cmd->add_name("create");
693     cmd->add_name("make");
694     cset->add(cmd= new cl_timer_delete_cmd("delete", 0));
695     cmd->init();
696     cmd->add_name("remove");
697     cset->add(cmd= new cl_timer_get_cmd("get", 0));
698     cmd->init();
699     cset->add(cmd= new cl_timer_run_cmd("run", 0));
700     cmd->init();
701     cmd->add_name("start");
702     cset->add(cmd= new cl_timer_stop_cmd("stop", 0));
703     cmd->init();
704     cset->add(cmd= new cl_timer_value_cmd("set", 0));
705     cmd->init();
706     cmd->add_name("value");
707   }
708   if (!super_cmd) {
709     cmdset->add(cmd= new cl_super_cmd("timer", 0, cset));
710     cmd->init();
711     set_timer_help(cmd);
712   }
713 
714   {
715     class cl_super_cmd *mem_create;
716     class cl_cmdset *mem_create_cset;
717     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("memory"));
718     if (super_cmd)
719       cset= super_cmd->get_subcommands();
720     else {
721       cset= new cl_cmdset();
722       cset->init();
723     }
724     /*
725       cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0));
726       cmd->init();
727     */
728     mem_create= (class cl_super_cmd *)cset->get_cmd("create");
729     if (mem_create)
730       mem_create_cset= mem_create->get_subcommands();
731     else {
732       mem_create_cset= new cl_cmdset();
733       mem_create_cset->init();
734     }
735 
736     mem_create_cset->add(cmd= new cl_memory_create_chip_cmd("chip", 0));
737     cmd->init();
738 
739     mem_create_cset->add(cmd= new cl_memory_create_addressspace_cmd("addressspace", 0));
740     cmd->init();
741     cmd->add_name("addrspace");
742     cmd->add_name("aspace");
743     cmd->add_name("as");
744     cmd->add_name("addrs");
745     cmd->add_name("addr");
746 
747     mem_create_cset->add(cmd= new cl_memory_create_addressdecoder_cmd("addressdecoder", 0));
748     cmd->init();
749     cmd->add_name("addrdecoder");
750     cmd->add_name("adecoder");
751     cmd->add_name("addressdec");
752     cmd->add_name("addrdec");
753     cmd->add_name("adec");
754     cmd->add_name("ad");
755 
756     mem_create_cset->add(cmd= new cl_memory_create_banker_cmd("banker", 0));
757     cmd->init();
758     cmd->add_name("bankswitcher");
759     cmd->add_name("banksw");
760     cmd->add_name("bsw");
761     cmd->add_name("bs");
762 
763     mem_create_cset->add(cmd= new cl_memory_create_bank_cmd("bank", 0));
764     cmd->init();
765 
766     mem_create_cset->add(cmd= new cl_memory_create_bander_cmd("bander", 0));
767     cmd->init();
768     cmd->add_name("bitbander");
769     cmd->add_name("bitband");
770     cmd->add_name("band");
771     cmd->add_name("bb");
772 
773     if (!mem_create)
774       cset->add(mem_create= new cl_super_cmd("create", 0, mem_create_cset));
775     mem_create->init();
776     mem_create->add_name("add");
777     set_memory_create_help(mem_create);
778 
779     cset->add(cmd= new cl_info_memory_cmd("info", 0));
780     cmd->init();
781     cset->add(cmd= new cl_memory_cell_cmd("cell", 0));
782     cmd->init();
783   }
784   if (!super_cmd) {
785     cmdset->add(cmd= new cl_super_cmd("memory", 0, cset));
786     cmd->init();
787     set_memory_help(cmd);
788   }
789 
790   cmdset->add(cmd= new cl_var_cmd("var", 0));
791   cmd->init();
792   cmd->add_name("variable");
793 }
794 
795 
796 /*
797  * Read/write simulated memory
798  */
799 
800 t_mem
read_mem(char * id,t_addr addr)801 cl_uc::read_mem(char *id, t_addr addr)
802 {
803   class cl_address_space *m= address_space(id);
804 
805   return(m?(m->read(addr)):0);
806 }
807 
808 t_mem
get_mem(char * id,t_addr addr)809 cl_uc::get_mem(char *id, t_addr addr)
810 {
811   class cl_address_space *m= address_space(id);
812 
813   return(m?(m->get(addr)):0);
814 }
815 
816 void
write_mem(char * id,t_addr addr,t_mem val)817 cl_uc::write_mem(char *id, t_addr addr, t_mem val)
818 {
819   class cl_address_space *m= address_space(id);
820 
821   if (m)
822     m->write(addr, val);
823 }
824 
825 void
set_mem(char * id,t_addr addr,t_mem val)826 cl_uc::set_mem(char *id, t_addr addr, t_mem val)
827 {
828   class cl_address_space *m= address_space(id);
829 
830   if(m)
831     m->set(addr, val);
832 }
833 
834 
835 /*
836 class cl_memory *
837 cl_uc::mem(enum mem_class type)
838 {
839   class cl_m *m;
840 
841   if (mems->count < type)
842     m= (class cl_m *)(mems->at(MEM_DUMMY));
843   else
844     m= (class cl_m *)(mems->at(type));
845   return(m);
846 }
847 */
848 
849 class cl_address_space *
address_space(const char * id)850 cl_uc::address_space(const char *id)
851 {
852   int i;
853 
854   if (!id ||
855       !(*id))
856     return(0);
857   for (i= 0; i < address_spaces->count; i++)
858     {
859       class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
860       if (!m ||
861 	  !m->have_real_name())
862 	continue;
863       if (m->is_inamed(id))
864 	return(m);
865     }
866   return(0);
867 }
868 
869 class cl_address_space *
address_space(class cl_memory_cell * cell)870 cl_uc::address_space(class cl_memory_cell *cell)
871 {
872   return(address_space(cell, (t_addr*)NULL));
873 }
874 
875 class cl_address_space *
address_space(class cl_memory_cell * cell,t_addr * addr)876 cl_uc::address_space(class cl_memory_cell *cell, t_addr *addr)
877 {
878   int i;
879 
880   for (i= 0; i < address_spaces->count; i++)
881     {
882       class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
883       if (!m)
884 	continue;
885       if (m->is_owned(cell, addr))
886 	return(m);
887     }
888   return(0);
889 }
890 
891 class cl_memory *
memory(const char * id)892 cl_uc::memory(const char *id)
893 {
894   int i;
895 
896   if (!id ||
897       !(*id))
898     return(0);
899   for (i= 0; i < address_spaces->count; i++)
900     {
901       class cl_base *b= address_spaces->object_at(i);
902       class cl_memory *m= dynamic_cast<cl_memory *>(b);
903       if (!m ||
904 	  !m->have_real_name())
905 	continue;
906       if (m->is_inamed(id))
907 	return(m);
908     }
909   for (i= 0; i < memchips->count; i++)
910     {
911       class cl_memory *m= (cl_memory *)(memchips->at(i));
912       if (!m ||
913 	  !m->have_real_name())
914 	continue;
915       if (m->is_inamed(id))
916 	return(m);
917     }
918   return(0);
919 }
920 
921 
922 static long
ReadInt(cl_f * f,bool * ok,int bytes)923 ReadInt(cl_f *f, bool *ok, int bytes)
924 {
925   char s2[3];
926   long l= 0;
927   int c;
928 
929   *ok= false;
930   while (bytes)
931     {
932       if (f->eof())
933 	return(0);
934       c= f->get_c();
935       if ((c < 0) ||
936 	  (c == 0) ||
937 	  (c > 0xff))
938 	return 0;
939       s2[0]= c;
940       if (f->eof())
941 	return(0);
942       c= f->get_c();
943       if ((c < 0) ||
944 	  (c == 0) ||
945 	  (c > 0xff))
946 	return 0;
947       s2[1]= c;
948       s2[2]= '\0';
949       l= l*256 + strtol(s2, NULL, 16);
950       bytes--;
951     }
952   *ok= true;
953   return(l);
954 }
955 
956 
957 /*
958  * Reading intel hexa file into EROM
959  *____________________________________________________________________________
960  *
961  * If parameter is a NULL pointer, this function reads data from `cmd_in'
962  *
963  */
964 
965 void
set_rom(t_addr addr,t_mem val)966 cl_uc::set_rom(t_addr addr, t_mem val)
967 {
968   //printf("rom[%06lx]=%02x\n", addr, val);
969   t_addr size= rom->get_size();
970   if (addr < size)
971     {
972       rom->download(addr, val);
973       return;
974     }
975   t_addr bank, caddr;
976   bank= addr / size;
977   caddr= addr % size;
978   //printf("getting decoder of %ld/%lx\n", bank, caddr);
979   class cl_banker *d= (class cl_banker *)(rom->get_decoder_of(caddr));
980   if (d)
981     {
982       if (!d->is_banker())
983 	{
984 	  //printf("cell at %lx has no banker\n", caddr);
985 	  return;
986 	}
987       //printf("setting %ld/rom[%lx]=%x\n", bank, caddr, val);
988       d->switch_to(bank, NULL);
989       rom->download(caddr, val);
990       d->activate(NULL);
991     }
992   else
993     ;//printf("no decoder at %lx\n", caddr);
994 }
995 
996 long
read_hex_file(const char * nam)997 cl_uc::read_hex_file(const char *nam)
998 {
999   cl_f *f;
1000 
1001   if (!nam)
1002     {
1003       fprintf(stderr, "cl_uc::read_hex_file File name not specified\n");
1004       return(-1);
1005     }
1006   else
1007     if ((f= /*fopen*/mk_io(nam, "r")) == NULL)
1008       {
1009 	fprintf(stderr, "Can't open `%s': %s\n", nam, strerror(errno));
1010 	return(-1);
1011       }
1012   long l= read_hex_file(f);
1013   delete f;
1014   return l;
1015 }
1016 
1017 long
read_hex_file(cl_console_base * con)1018 cl_uc::read_hex_file(cl_console_base *con)
1019 {
1020   cl_f *f;
1021   if (con == NULL)
1022     return -1;
1023   f= con->get_fin();
1024   if (f == NULL)
1025     return -1;
1026   long l= read_hex_file(f);
1027   return l;
1028 }
1029 
1030 long
read_hex_file(cl_f * f)1031 cl_uc::read_hex_file(cl_f *f)
1032 {
1033   int c;
1034   long written= 0, recnum= 0;
1035 
1036   uint  base= 0;  // extended address, added to every adress
1037   uchar dnum;     // data number
1038   uchar rtyp=0;   // record type
1039   uint  addr= 0;  // address
1040   uchar rec[300]; // data record
1041   uchar sum ;     // checksum
1042   uchar chk ;     // check
1043   int  i;
1044   bool ok, get_low= 1;
1045   uchar low= 0, high;
1046 
1047   if (!rom)
1048     {
1049       sim->app->get_commander()->
1050 	dd_printf("No ROM address space to read in.\n");
1051       return(-1);
1052     }
1053 
1054   //memset(inst_map, '\0', sizeof(inst_map));
1055   ok= true;
1056   while (ok &&
1057 	 rtyp != 1)
1058     {
1059       while (((c= /*getc(f)*/f->get_c()) != ':') &&
1060 	     (/*c != EOF*/!f->eof())) /*printf("search_record=%c\n",c)*/;
1061       if (c != ':')
1062 	{fprintf(stderr, ": not found\n");break;}
1063       recnum++;
1064       dnum= ReadInt(f, &ok, 1);//printf("%ld:dnum=%02x ",recnum,dnum);
1065       chk = dnum;
1066       addr= ReadInt(f, &ok, 2);//printf("%ld:addr=%04x ",recnum,addr);
1067       chk+= (addr & 0xff);
1068       chk+= ((addr >> 8) & 0xff);
1069       rtyp= ReadInt(f, &ok, 1);//printf("%ld:rtyp=%02x ",recnum,rtyp);
1070       chk+= rtyp;
1071       for (i= 0; ok && (i < dnum); i++)
1072 	{
1073 	  rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
1074 	  chk+= rec[i];
1075 	}
1076       if (ok)
1077 	{
1078 	  sum= ReadInt(f, &ok, 1);//printf(" %ld:sum=%02x\n",recnum,sum);
1079 	  if (ok)
1080 	    {
1081 	      if (((sum + chk) & 0xff) == 0)
1082 		{
1083 		  if (rtyp == 0)
1084 		    {
1085 		      if (rom->width > 8)
1086 			addr/= 2;
1087 		      for (i= 0; i < dnum; i++)
1088 			{
1089 			  if (rom->width <= 8)
1090 			    {
1091 			      set_rom(base+addr, rec[i]);
1092 			      addr++;
1093 			      written++;
1094 			    }
1095 			  else if (rom->width <= 16)
1096 			    {
1097 			      if (get_low)
1098 				{
1099 				  low= rec[i];
1100 				  get_low= 0;
1101 				}
1102 			      else
1103 				{
1104 				  high= rec[i];
1105 				  set_rom(base+addr, (high*256)+low);
1106 				  addr++;
1107 				  written++;
1108 				  get_low= 1;
1109 				}
1110 			    }
1111 			}
1112 		    }
1113 		  else if (rtyp == 4)
1114 		    {
1115 		      //printf("hex record type=4\n");
1116 		      if (dnum >= 2)
1117 			{
1118 			  base= (rec[0]*256+rec[1]) << 16;
1119 			  //printf("hex base=%x\n", base);
1120 			}
1121 		    }
1122 		  else
1123 		    if (rtyp != 1)
1124 		      /*application->debug*/fprintf(stderr, "Unknown record type %d(0x%x)\n",
1125 					 rtyp, rtyp);
1126 		}
1127 	      else
1128 		/*application->debug*/fprintf(stderr, "Checksum error (%x instead of %x) in "
1129 				   "record %ld.\n", chk, sum, recnum);
1130 	    }
1131 	  else
1132 	    /*application->debug*/fprintf(stderr, "Read error in record %ld.\n", recnum);
1133 	}
1134     }
1135   if (rom->width > 8 &&
1136       !get_low)
1137     rom->set(addr, low);
1138 
1139   analyze(0);
1140   return(written);
1141 }
1142 
1143 long
read_omf_file(cl_f * f)1144 cl_uc::read_omf_file(cl_f *f)
1145 {
1146   long written= 0;
1147   class cl_omf_rec rec;
1148   while (rec.read(f))
1149     {
1150       if (rec.type == 0x06)
1151 	{
1152 	  // content
1153 	  u16_t addr= rec.pick_word(1);
1154 	  int i= 3;
1155 	  while (i < rec.len)
1156 	    {
1157 	      set_rom(addr+i, rec.rec[i]);
1158 	      written++;
1159 	      i++;
1160 	    }
1161 	}
1162     }
1163   return (written);
1164 }
1165 
1166 long
read_cdb_file(cl_f * f)1167 cl_uc::read_cdb_file(cl_f *f)
1168 {
1169   class cl_cdb_recs *fns= new cl_cdb_recs();
1170   chars ln;
1171   char *lc;
1172   long cnt= 0;
1173   class cl_cdb_rec *r;
1174   class cl_var *v;
1175 
1176   ln= f->get_s();
1177   while (!ln.empty())
1178     {
1179       //printf("CBD LN=%s\n",(char*)ln);
1180       lc= (char*)ln;
1181       if (lc[0] == 'F')
1182 	{
1183 	  if (ln.len() > 5)
1184 	    {
1185 	      if ((lc[1] == ':') &&
1186 		  (lc[2] == 'G'))
1187 		{
1188 		  ln.start_parse(4);
1189 		  chars n= ln.token("$");
1190 		  if ((r= fns->rec(n)) != NULL)
1191 		    {
1192 		      vars->add(v= new cl_var(n, rom, r->addr, ""));
1193 		      v->init();
1194 		      fns->del(n);
1195 		      cnt++;
1196 		    }
1197 		  else
1198 		    fns->add(new cl_cdb_rec(n));
1199 		}
1200 	    }
1201 	}
1202       else if (lc[0] == 'L')
1203 	{
1204 	  if (ln.len() > 5)
1205 	    {
1206 	      if ((ln[1] == ':') &&
1207 		  (lc[2] == 'G'))
1208 		{
1209 		  ln.start_parse(4);
1210 		  chars n= ln.token("$");
1211 		  chars t= ln.token(":");
1212 		  t= ln.token(" ");
1213 		  t_addr a= strtol((char*)t, 0, 16);
1214 		  if ((r= fns->rec(n)) != NULL)
1215 		    {
1216 		      fns->del(n);
1217 		      vars->add(v= new cl_var(n, rom, a, ""));
1218 		      v->init();
1219 		      cnt++;
1220 		    }
1221 		  else
1222 		    fns->add(new cl_cdb_rec(n, a));
1223 		}
1224 	    }
1225 	}
1226       ln= f->get_s();
1227     }
1228   fns->free_all();
1229   delete fns;
1230   return cnt;
1231 }
1232 
1233 cl_f *
find_loadable_file(chars nam)1234 cl_uc::find_loadable_file(chars nam)
1235 {
1236   cl_f *f;
1237   bool o;
1238   chars c;
1239 
1240   f= mk_io(nam, "r");
1241   o= (f->opened());
1242   if (o)
1243     return f;
1244 
1245   c= chars("", "%s.ihx", (char*)nam);
1246   f->open(c, chars("r"));
1247   o= (f->opened());
1248   if (o)
1249     return f;
1250   c= chars("", "%s.hex", (char*)nam);
1251   f->open(c, chars("r"));
1252   o= (f->opened());
1253   if (o)
1254     return f;
1255   c= chars("", "%s.ihex", (char*)nam);
1256   f->open(c, chars("r"));
1257   o= (f->opened());
1258   if (o)
1259     return f;
1260 
1261   c= chars("", "%s.omf", (char*)nam);
1262   f->open(c, chars("r"));
1263   o= (f->opened());
1264   if (o)
1265     return f;
1266 
1267   delete f;
1268   return NULL;
1269 }
1270 
1271 long
read_file(chars nam,class cl_console_base * con)1272 cl_uc::read_file(chars nam, class cl_console_base *con)
1273 {
1274   cl_f *f= find_loadable_file(nam);
1275   long l= 0;
1276 
1277   if (!f)
1278     {
1279       if (con) con->dd_printf("no loadable file found\n");
1280       return 0;
1281     }
1282   /*if (con) con->dd_*/printf("Loading from %s\n", f->get_file_name());
1283   if (is_hex_file(f))
1284     {
1285       l= read_hex_file(f);
1286       printf("%ld words read from %s\n", l, f->get_fname());
1287     }
1288   else if (is_omf_file(f))
1289     {
1290       l= read_omf_file(f);
1291       printf("%ld words read from %s\n", l, f->get_fname());
1292     }
1293   else if (is_cdb_file(f))
1294     {
1295       l= read_cdb_file(f);
1296       printf("%ld symbols read from %s\n", l, f->get_fname());
1297     }
1298   if (strcmp(nam, f->get_fname()) != 0)
1299     {
1300       chars n= nam;
1301       n+= (char*)".cdb";
1302       cl_f *c= mk_io(n, "r");
1303       if (c->opened())
1304 	{
1305 	  l= read_cdb_file(c);
1306 	  printf("%ld symbols read from %s\n", l, c->get_fname());
1307 	}
1308       delete c;
1309     }
1310   delete f;
1311   return l;
1312 }
1313 
1314 
1315 /*
1316  * Handling instruction map
1317  *
1318  * `inst_at' is checking if the specified address is in instruction
1319  * map and `set_inst_at' marks the address in the map and
1320  * `del_inst_at' deletes the mark. `there_is_inst' cheks if there is
1321  * any mark in the map
1322  */
1323 
1324 bool
inst_at(t_addr addr)1325 cl_uc::inst_at(t_addr addr)
1326 {
1327   if (!rom)
1328     return(0);
1329   return(rom->get_cell_flag(addr, CELL_INST));
1330 }
1331 
1332 void
set_inst_at(t_addr addr)1333 cl_uc::set_inst_at(t_addr addr)
1334 {
1335   if (rom)
1336     rom->set_cell_flag(addr, true, CELL_INST);
1337 }
1338 
1339 void
del_inst_at(t_addr addr)1340 cl_uc::del_inst_at(t_addr addr)
1341 {
1342   if (rom)
1343     rom->set_cell_flag(addr, false, CELL_INST);
1344 }
1345 
1346 bool
there_is_inst(void)1347 cl_uc::there_is_inst(void)
1348 {
1349   if (!rom)
1350     return(0);
1351   bool got= false;
1352   t_addr addr;
1353   for (addr= 0; rom->valid_address(addr) && !got; addr++)
1354     got= rom->get_cell_flag(addr, CELL_INST);
1355   return(got);
1356 }
1357 
1358 
1359 /*
1360  * Manipulating HW elements of the CPU
1361  *****************************************************************************
1362  */
1363 
1364 /* Register callback hw objects for mem read/write */
1365 
1366 /*void
1367 cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
1368 {
1369   class cl_m *m;
1370   class cl_memloc *l;
1371 
1372   if ((m= (class cl_m*)mems->at(type)))
1373     {
1374       if ((l= m->read_locs->get_loc(addr)) == 0)
1375 	{
1376 	  l= new cl_memloc(addr);
1377 	  l->init();
1378 	  m->read_locs->add(l);
1379 	}
1380       l->hws->add(hw);
1381     }
1382   else
1383     printf("cl_uc::register_hw_read TROUBLE\n");
1384 }*/
1385 
1386 /*void
1387 cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
1388 {
1389 }*/
1390 
1391 void
add_hw(class cl_hw * hw)1392 cl_uc::add_hw(class cl_hw *hw)
1393 {
1394   int i;
1395   for (i= 0; i < hws->count; i++)
1396     {
1397       class cl_hw *h= (class cl_hw *)(hws->at(i));
1398       h->new_hw_adding(hw);
1399     }
1400   hws->add(hw);
1401   for (i= 0; i < hws->count; i++)
1402     {
1403       class cl_hw *h= (class cl_hw *)(hws->at(i));
1404       if (h != hw)
1405 	h->new_hw_added(hw);
1406     }
1407 }
1408 
1409 int
nuof_hws(void)1410 cl_uc::nuof_hws(void)
1411 {
1412   return hws->count;
1413 }
1414 
1415 /* Looking for a specific HW element */
1416 
1417 class cl_hw *
get_hw(int idx)1418 cl_uc::get_hw(int idx)
1419 {
1420   if (idx >= hws->count)
1421     return NULL;
1422   return (class cl_hw *)(hws->at(idx));
1423 }
1424 
1425 class cl_hw *
get_hw(enum hw_cath cath,int * idx)1426 cl_uc::get_hw(enum hw_cath cath, int *idx)
1427 {
1428   class cl_hw *hw= 0;
1429   int i= 0;
1430 
1431   if (idx)
1432     i= *idx;
1433   for (; i < hws->count; i++)
1434     {
1435       hw= (class cl_hw *)(hws->at(i));
1436       if (hw->cathegory == cath)
1437 	break;
1438     }
1439   if (i >= hws->count)
1440     return(0);
1441   if (idx)
1442     *idx= i;
1443   return(hw);
1444 }
1445 
1446 class cl_hw *
get_hw(char * id_string,int * idx)1447 cl_uc::get_hw(char *id_string, int *idx)
1448 {
1449   class cl_hw *hw= 0;
1450   int i= 0;
1451 
1452   if (idx)
1453     i= *idx;
1454   for (; i < hws->count; i++)
1455     {
1456       hw= (class cl_hw *)(hws->at(i));
1457       if (strstr(hw->id_string, id_string) == hw->id_string)
1458 	break;
1459     }
1460   if (i >= hws->count)
1461     return(0);
1462   if (idx)
1463     *idx= i;
1464   return(hw);
1465 }
1466 
1467 class cl_hw *
get_hw(enum hw_cath cath,int hwid,int * idx)1468 cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
1469 {
1470   class cl_hw *hw;
1471   int i= 0;
1472 
1473   if (idx)
1474     i= *idx;
1475   hw= get_hw(cath, &i);
1476   while (hw &&
1477 	 hw->id != hwid)
1478     {
1479       i++;
1480       hw= get_hw(cath, &i);
1481     }
1482   if (hw &&
1483       idx)
1484     *idx= i;
1485   return(hw);
1486 }
1487 
1488 class cl_hw *
get_hw(char * id_string,int hwid,int * idx)1489 cl_uc::get_hw(char *id_string, int hwid, int *idx)
1490 {
1491   class cl_hw *hw;
1492   int i= 0;
1493 
1494   if (idx)
1495     i= *idx;
1496   hw= get_hw(id_string, &i);
1497   while (hw &&
1498 	 hw->id != hwid)
1499     {
1500       i++;
1501       hw= get_hw(id_string, &i);
1502     }
1503   if (hw &&
1504       idx)
1505     *idx= i;
1506   return(hw);
1507 }
1508 
1509 int
get_max_hw_id(enum hw_cath cath)1510 cl_uc::get_max_hw_id(enum hw_cath cath)
1511 {
1512   class cl_hw *hw;
1513   int i, max= -1;
1514 
1515   for (i= 0; i < hws->count; i++)
1516     {
1517       hw= (class cl_hw *)(hws->at(i));
1518       if (hw->id > max)
1519 	max= hw->id;
1520     }
1521   return max;
1522 }
1523 
1524 /*
1525  * Help of the command interpreter
1526  */
1527 
1528 struct dis_entry *
dis_tbl(void)1529 cl_uc::dis_tbl(void)
1530 {
1531   static struct dis_entry empty= { 0, 0, 0, 0, NULL };
1532   return(&empty);
1533 }
1534 
1535 char *
disass(t_addr addr,const char * sep)1536 cl_uc::disass(t_addr addr, const char *sep)
1537 {
1538   char *buf;
1539 
1540   buf= (char*)malloc(100);
1541   strcpy(buf, "uc::disass() unimplemented\n");
1542   return(buf);
1543 }
1544 
1545 void
print_disass(t_addr addr,class cl_console_base * con)1546 cl_uc::print_disass(t_addr addr, class cl_console_base *con)
1547 {
1548   char *dis;
1549   class cl_brk *b;
1550   int i, l;
1551 
1552   if (!rom)
1553     return;
1554 
1555   t_mem code= rom->get(addr);
1556   b= fbrk_at(addr);
1557   dis= disass(addr, NULL);
1558   if (b)
1559     con->dd_cprintf("answer", "%c", (b->perm == brkFIX)?'F':'D');
1560   else
1561     con->dd_printf(" ");
1562   con->dd_cprintf("answer", "%c ", inst_at(addr)?' ':'?');
1563   con->dd_cprintf("dump_address", rom->addr_format, addr); con->dd_printf(" ");
1564   con->dd_cprintf("dump_number", rom->data_format, code);
1565   l= inst_length(addr);
1566   for (i= 1; i < l; i++)
1567     {
1568       con->dd_printf(" ");
1569       con->dd_cprintf("dump_number", rom->data_format, rom->get(addr+i));
1570     }
1571   int li= longest_inst();
1572   while (i < li)
1573     {
1574       int j;
1575       j= rom->width/4 + ((rom->width%4)?1:0) + 1;
1576       while (j)
1577 	con->dd_printf(" "), j--;
1578       i++;
1579     }
1580   con->dd_cprintf("dump_char", " %s\n", dis);
1581   free((char *)dis);
1582 }
1583 
1584 void
print_regs(class cl_console_base * con)1585 cl_uc::print_regs(class cl_console_base *con)
1586 {
1587   con->dd_printf("No registers\n");
1588 }
1589 
1590 int
inst_length(t_addr addr)1591 cl_uc::inst_length(t_addr addr)
1592 {
1593   struct dis_entry *tabl= dis_tbl();
1594   int i;
1595   t_mem code;
1596 
1597   if (!rom)
1598     return(0);
1599 
1600   code = rom->get(addr);
1601   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
1602   return(tabl[i].mnemonic?tabl[i].length:1);
1603 }
1604 
1605 int
inst_branch(t_addr addr)1606 cl_uc::inst_branch(t_addr addr)
1607 {
1608   struct dis_entry *tabl= dis_tbl();
1609   int i;
1610   t_mem code;
1611 
1612   if (!rom)
1613     return(0);
1614 
1615   code = rom->get(addr);
1616   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
1617     ;
1618   return tabl[i].branch;
1619 }
1620 
1621 bool
is_call(t_addr addr)1622 cl_uc::is_call(t_addr addr)
1623 {
1624   struct dis_entry *tabl= dis_tbl();
1625   int i;
1626   t_mem code;
1627 
1628   if (!rom)
1629     return(0);
1630 
1631   code = rom->get(addr);
1632   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
1633     ;
1634   return tabl[i].is_call;
1635 }
1636 
1637 int
longest_inst(void)1638 cl_uc::longest_inst(void)
1639 {
1640   struct dis_entry *de= dis_tbl();
1641   int max= 0;
1642 
1643   while (de &&
1644 	 de->mnemonic)
1645     {
1646       if (de->length > max)
1647 	max= de->length;
1648       de++;
1649     }
1650   return(max);
1651 }
1652 
1653 bool
addr_name(t_addr addr,class cl_address_space * as,char * buf)1654 cl_uc::addr_name(t_addr addr, class cl_address_space *as, char *buf)
1655 {
1656   t_index i;
1657 
1658   for (i= 0; i < vars->count; i++)
1659     {
1660       class cl_var *v= (cl_var *)(vars->at(i));
1661       if ((v->as == as) &&
1662 	  (v->addr == addr))
1663 	{
1664 	  strcpy(buf, v->get_name());
1665 	  return true;
1666 	}
1667     }
1668   unsigned int a= addr;
1669   sprintf(buf, "%02x", a);
1670   return false;
1671 }
1672 
1673 bool
addr_name(t_addr addr,class cl_address_space * as,int bitnr,char * buf)1674 cl_uc::addr_name(t_addr addr, class cl_address_space *as, int bitnr, char *buf)
1675 {
1676   t_index i;
1677 
1678   for (i= 0; i < vars->count; i++)
1679     {
1680       class cl_var *v= (cl_var *)(vars->at(i));
1681       if ((v->as == as) &&
1682 	  (v->addr == addr) &&
1683 	  (v->bitnr == bitnr))
1684 	{
1685 	  strcpy(buf, v->get_name());
1686 	  return true;
1687 	}
1688     }
1689   unsigned int a= addr;
1690   sprintf(buf, "%02x.%d", a, bitnr);
1691   return false;
1692 }
1693 
1694 bool
symbol2address(char * sym,class cl_address_space ** as,t_addr * addr)1695 cl_uc::symbol2address(char *sym,
1696 		      class cl_address_space **as,
1697 		      t_addr *addr)
1698 {
1699   class cl_var *v;
1700   t_index i;
1701 
1702   if (!sym ||
1703       !*sym)
1704     return false;
1705   if (vars->search(sym, i))
1706     {
1707       v= (class cl_var *)(vars->at(i));
1708       if (v->bitnr >= 0)
1709 	return false;
1710       if (as)
1711 	*as= v->as;
1712       if (addr)
1713 	*addr= v->addr;
1714       return true;
1715     }
1716   return false;
1717 }
1718 
1719 char *
symbolic_bit_name(t_addr bit_address,class cl_memory * mem,t_addr mem_addr,t_mem bit_mask)1720 cl_uc::symbolic_bit_name(t_addr bit_address,
1721 			 class cl_memory *mem,
1722 			 t_addr mem_addr,
1723 			 t_mem bit_mask)
1724 {
1725   //char *sym_name= 0;
1726   int i;
1727   chars c= chars("", mem?(mem->addr_format):"0x%06lx", (unsigned long)mem_addr);
1728   /*if (!sym_name)
1729     {
1730       sym_name= (char *)malloc(16);
1731       sprintf(sym_name, mem?(mem->addr_format):"0x%06lx", (unsigned long)mem_addr);
1732       }*/
1733   /*sym_name= (char *)realloc(sym_name, strlen(sym_name)+2);
1734     strcat(sym_name, ".");*/
1735   c+= cchars(".");
1736   i= 0;
1737   while (bit_mask > 1)
1738     {
1739       bit_mask>>=1;
1740       i++;
1741     }
1742   //char bitnumstr[10];
1743   /*sprintf(bitnumstr, "%1d", i);
1744     strcat(sym_name, bitnumstr);*/
1745   c.append("%d", i);
1746   return(/*sym_name*/strdup((char*)c));
1747 }
1748 
1749 
1750 /*
1751  * Searching for a name in the specified table
1752  */
1753 
1754 struct name_entry *
get_name_entry(struct name_entry tabl[],char * name)1755 cl_uc::get_name_entry(struct name_entry tabl[], char *name)
1756 {
1757   int i= 0;
1758   char *p;
1759 
1760   if (!tabl ||
1761       !name ||
1762       !(*name))
1763     return(0);
1764   for (p= name; *p; *p= toupper(*p), p++);
1765   while (tabl[i].name &&
1766 	 (!(tabl[i].cpu_type & type->type) ||
1767 	 (strcmp(tabl[i].name, name) != 0)))
1768     {
1769       //printf("tabl[%d].name=%s <-> %s\n",i,tabl[i].name,name);
1770       i++;
1771     }
1772   if (tabl[i].name != NULL)
1773     return(&tabl[i]);
1774   else
1775     return(0);
1776 }
1777 
1778 chars
cell_name(class cl_memory_cell * cell)1779 cl_uc::cell_name(class cl_memory_cell *cell)
1780 {
1781   if (cell == NULL)
1782     return chars("");
1783   if (cell->get_flag(CELL_VAR))
1784     {
1785       int i;
1786       for (i= 0; i < vars->count; i++)
1787 	{
1788 	  class cl_var *v= (cl_var*)(vars->at(i));
1789 	  if (v->get_cell() &&
1790 	      (cell == v->get_cell()))
1791 	    return chars(v->get_name());
1792 	}
1793     }
1794   class cl_address_space *as;
1795   t_addr a;
1796   as= address_space(cell, &a);
1797   if (as == NULL)
1798     return chars("");
1799   return chars("", "%s_%06x", as->get_name(), a);
1800 }
1801 
1802 class cl_var *
var(char * nam)1803 cl_uc::var(char *nam)
1804 {
1805   if (!vars)
1806     return NULL;
1807   t_index i;
1808   if (!vars->search(nam, i))
1809     return NULL;
1810   class cl_var *v= (cl_var*)(vars->at(i));
1811   return v;
1812 }
1813 
1814 
1815 /*
1816  * Messages to broadcast
1817  */
1818 
1819 bool
handle_event(class cl_event & event)1820 cl_uc::handle_event(class cl_event &event)
1821 {
1822   switch (event.what)
1823     {
1824     case ev_address_space_added:
1825       {
1826 	try {
1827 	  class cl_event_address_space_added &e=
1828 	    dynamic_cast<class cl_event_address_space_added &>(event);
1829 	  address_space_added(e.as);
1830 	  e.handle();
1831 	}
1832 	catch (...)
1833 	  { break; }
1834 	break;
1835       }
1836     default:
1837       return(pass_event_down(event));
1838       break;
1839     }
1840   return(false);
1841 }
1842 
1843 /*
1844 void
1845 cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
1846 {
1847   if (hws)
1848     hws->mem_cell_changed(mem, addr);
1849   else
1850     printf("JAJ uc\n");//FIXME
1851   if (mems &&
1852       mems->count)
1853     {
1854       int i;
1855       for (i= 0; i < mems->count; i++)
1856 	{
1857 	}
1858     }
1859 }
1860 */
1861 
1862 void
address_space_added(class cl_address_space * as)1863 cl_uc::address_space_added(class cl_address_space *as)
1864 {
1865   /*
1866   if (hws)
1867     hws->address_space_added(as);
1868   else
1869     printf("JAJ uc\n");//FIXME
1870   */
1871 }
1872 
1873 
1874 /*
1875  * Error handling
1876  */
1877 
1878 void
error(class cl_error * error)1879 cl_uc::error(class cl_error *error)
1880 {
1881   //printf("error adding: %s...\n", error->get_class()->get_name());
1882   errors->add(error);
1883   if ((error->inst= inst_exec))
1884     error->PC= instPC;
1885 }
1886 
1887 void
check_errors(void)1888 cl_uc::check_errors(void)
1889 {
1890   int i;
1891   class cl_commander_base *c= sim->app->get_commander();
1892   bool must_stop= false;
1893 
1894   if (c)
1895     {
1896       //printf("error list: %d items\n", errors->count);
1897       for (i= 0; i < errors->count; i++)
1898 	{
1899 	  class cl_error *error= (class cl_error *)(errors->at(i));
1900 	  if (!error->is_on())
1901 	    continue;
1902 	  error->print(c);
1903 	  must_stop= must_stop || (error->get_type() & err_stop);
1904 	  if (error->inst)
1905 	    {
1906 	      class cl_console_base *con;
1907 	      con= c->actual_console;
1908 	      if (!con)
1909 		con= c->frozen_console;
1910 	      if (con)
1911 		{
1912 		  con->dd_printf("Erronouse instruction: ");
1913 		  print_disass(error->PC, con);
1914 		}
1915 	    }
1916 	}
1917       errors->free_all();
1918     }
1919   else
1920     fprintf(stderr, "no actual console, %d errors\n", errors->count);
1921   if (must_stop)
1922     sim->stop(resERROR);
1923 }
1924 
1925 
1926 /*
1927  * Converting bit address into real memory
1928  */
1929 
1930 class cl_address_space *
bit2mem(t_addr bitaddr,t_addr * memaddr,t_mem * bitmask)1931 cl_uc::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
1932 {
1933   if (memaddr)
1934     *memaddr= bitaddr;
1935   if (bitmask)
1936     *bitmask= 1 << (bitaddr & 0x7);
1937   return(0); // abstract...
1938 }
1939 
1940 
1941 /*
1942  * Execution
1943  */
1944 
1945 int
tick_hw(int cycles)1946 cl_uc::tick_hw(int cycles)
1947 {
1948   class cl_hw *hw;
1949   int i;//, cpc= clock_per_cycle();
1950 
1951   // tick hws
1952   for (i= 0; i < hws->count; i++)
1953     {
1954       hw= (class cl_hw *)(hws->at(i));
1955       if ((hw->flags & HWF_INSIDE) &&
1956 	  (hw->on))
1957 	hw->tick(cycles);
1958     }
1959   do_extra_hw(cycles);
1960   return(0);
1961 }
1962 
1963 void
do_extra_hw(int cycles)1964 cl_uc::do_extra_hw(int cycles)
1965 {}
1966 
1967 int
tick(int cycles)1968 cl_uc::tick(int cycles)
1969 {
1970   //class cl_hw *hw;
1971   int i, cpc= clock_per_cycle();
1972 
1973   // increase time
1974   ticks->tick(cycles * cpc);
1975   class it_level *il= (class it_level *)(it_levels->top());
1976   if (il->level >= 0)
1977     isr_ticks->tick(cycles * cpc);
1978   if (state == stIDLE)
1979     idle_ticks->tick(cycles * cpc);
1980   for (i= 0; i < counters->count; i++)
1981     {
1982       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1983       if (t)
1984 	{
1985 	  if ((t->options&TICK_INISR) ||
1986 	      il->level < 0)
1987 	    t->tick(cycles * cpc);
1988 	}
1989     }
1990 
1991   // tick for hardwares
1992   inst_ticks+= cycles;
1993   return(0);
1994 }
1995 
1996 class cl_ticker *
get_counter(int nr)1997 cl_uc::get_counter(int nr)
1998 {
1999   if (nr >= counters->count)
2000     return(0);
2001   return((class cl_ticker *)(counters->at(nr)));
2002 }
2003 
2004 class cl_ticker *
get_counter(const char * nam)2005 cl_uc::get_counter(const char *nam)
2006 {
2007   int i;
2008 
2009   if (!nam)
2010     return(0);
2011   for (i= 0; i < counters->count; i++)
2012     {
2013       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2014       if (t &&
2015 	  t->get_name() &&
2016 	  strcmp(t->get_name(), nam) == 0)
2017 	return(t);
2018     }
2019   return(0);
2020 }
2021 
2022 void
add_counter(class cl_ticker * ticker,int nr)2023 cl_uc::add_counter(class cl_ticker *ticker, int nr)
2024 {
2025   while (counters->count <= nr)
2026     counters->add(0);
2027   counters->put_at(nr, ticker);
2028 }
2029 
2030 void
add_counter(class cl_ticker * ticker,const char *)2031 cl_uc::add_counter(class cl_ticker *ticker, const char */*nam*/)
2032 {
2033   int i;
2034 
2035   if (counters->count < 1)
2036     counters->add(0);
2037   for (i= 1; i < counters->count; i++)
2038     {
2039       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2040       if (!t)
2041 	{
2042 	  counters->put_at(i, ticker);
2043 	  return;
2044 	}
2045     }
2046   counters->add(ticker);
2047 }
2048 
2049 void
del_counter(int nr)2050 cl_uc::del_counter(int nr)
2051 {
2052   class cl_ticker *t;
2053 
2054   if (nr >= counters->count)
2055     return;
2056   if ((t= (class cl_ticker *)(counters->at(0))) != 0)
2057     delete t;
2058   counters->put_at(nr, 0);
2059 }
2060 
2061 void
del_counter(const char * nam)2062 cl_uc::del_counter(const char *nam)
2063 {
2064   int i;
2065 
2066   if (!nam)
2067     return;
2068   for (i= 0; i < counters->count; i++)
2069     {
2070       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
2071       if (t &&
2072 	  t->get_name() &&
2073 	  strcmp(t->get_name(), nam) == 0)
2074 	{
2075 	  delete t;
2076 	  counters->put_at(i, 0);
2077 	  return;
2078 	}
2079     }
2080 }
2081 
2082 /*
2083  * Fetch without checking for breakpoint hit
2084  */
2085 
2086 t_mem
fetch(void)2087 cl_uc::fetch(void)
2088 {
2089   ulong code;
2090 
2091   if (!rom)
2092     return(0);
2093 
2094   code= rom->read(PC);
2095   PC= rom->inc_address(PC);
2096   vc.fetch++;
2097   return(code);
2098 }
2099 
2100 /*
2101  * Fetch but checking for breakpoint hit first, returns TRUE if
2102  * a breakpoint is hit
2103  */
2104 
2105 bool
fetch(t_mem * code)2106 cl_uc::fetch(t_mem *code)
2107 {
2108   class cl_brk *brk;
2109   int idx;
2110 
2111   if (!code)
2112     return(0);
2113   if ((sim->state & SIM_GO) &&
2114       rom &&
2115       (sim->steps_done > 0))
2116     {
2117       if (rom->get_cell_flag(PC, CELL_FETCH_BRK))
2118 	if ((brk= fbrk->get_bp(PC, &idx)))
2119 	  if (brk->do_hit())
2120 	    {
2121 	      if (brk->perm == brkDYNAMIC)
2122 		fbrk->del_bp(PC);
2123 	      return(1);
2124 	    }
2125     }
2126   *code= fetch();
2127   return(0);
2128 }
2129 
2130 int
do_inst(int step)2131 cl_uc::do_inst(int step)
2132 {
2133   t_addr PCsave;
2134   int res= resGO;
2135 
2136   if (step < 0)
2137     step= 1;
2138   while (step-- &&
2139          res == resGO)
2140     {
2141       pre_inst();
2142       PCsave = PC;
2143       res= exec_inst();
2144 
2145       if (res == resINV_INST)
2146 	/* backup to start of instruction */
2147 	PC = PCsave;
2148 
2149       post_inst();
2150 
2151       if ((res == resGO) &&
2152 	  irq)
2153 	{
2154 	  //printf("DO INTERRUPT PC=%lx\n", PC);
2155 	  int r= do_interrupt();
2156 	  if (r != resGO)
2157 	    res= r;
2158 	}
2159 
2160       if (stop_at_time &&
2161 	  stop_at_time->reached())
2162 	{
2163 	  delete stop_at_time;
2164 	  stop_at_time= NULL;
2165 	  res= resBREAKPOINT;
2166 	}
2167     }
2168   if (res != resGO)
2169     sim->stop(res);
2170   return(res);
2171 }
2172 
2173 void
pre_inst(void)2174 cl_uc::pre_inst(void)
2175 {
2176   inst_exec= true;
2177   inst_ticks= 0;
2178   events->disconn_all();
2179   vc.inst++;
2180 }
2181 
2182 int
exec_inst(void)2183 cl_uc::exec_inst(void)
2184 {
2185   instPC= PC;
2186   return(resGO);
2187 }
2188 
2189 int
exec_inst_tab(instruction_wrapper_fn itab[])2190 cl_uc::exec_inst_tab(instruction_wrapper_fn itab[])
2191 {
2192   t_mem c;
2193   int res= resGO;
2194   instPC= PC;
2195   if (fetch(&c))
2196     return resBREAKPOINT;
2197   if (itab[c] == NULL)
2198     {
2199       PC= instPC;
2200       return resNOT_DONE;
2201     }
2202   res= itab[c](this, c);
2203   if (res == resNOT_DONE)
2204     {
2205       PC= instPC;
2206       return res;
2207     }
2208   tick(1);
2209   return res;
2210 }
2211 
2212 
2213 void
post_inst(void)2214 cl_uc::post_inst(void)
2215 {
2216   tick_hw(inst_ticks);
2217   if (errors->count)
2218     check_errors();
2219   if (events->count)
2220     check_events();
2221   inst_exec= false;
2222 }
2223 
2224 
2225 /*
2226  * Interrupt processing
2227  */
2228 
2229 int
do_interrupt(void)2230 cl_uc::do_interrupt(void)
2231 {
2232   int i;
2233   // NMI?
2234 
2235   // Maskable interrupts
2236   if (!it_enabled())
2237     {
2238       //printf("do_interrupt skip (it disabled)\n");
2239       return resGO;
2240     }
2241   class it_level *il= (class it_level *)(it_levels->top()), *IL= 0;
2242   irq= false;
2243   //printf("Checking IRQs...\n");
2244   for (i= 0; i < it_sources->count; i++)
2245     {
2246       class cl_it_src *is= (class cl_it_src *)(it_sources->at(i));
2247        if (is->is_active() &&
2248 	  is->enabled() &&
2249 	  is->pending())
2250 	{
2251 	  int pr= priority_of(is->nuof);
2252 	  int ap;
2253 	  irq= true;
2254 	  if (il &&
2255 	      il->level >= 0)
2256 	    ap= il->level;
2257 	  else
2258 	    ap= priority_main();
2259 	  if (ap >= pr)
2260 	    continue;
2261 	  is->clear();
2262 	  sim->app->get_commander()->
2263 	    debug("%g sec (%d clks): Accepting interrupt `%s' PC= 0x%06x\n",
2264 			  get_rtime(), ticks->ticks, object_name(is), PC);
2265 	  IL= new it_level(pr, is->addr, PC, is);
2266 	  return(accept_it(IL));
2267 	}
2268     }
2269   return resGO;
2270 }
2271 
2272 int
accept_it(class it_level * il)2273 cl_uc::accept_it(class it_level *il)
2274 {
2275   it_levels->push(il);
2276   return resGO;
2277 }
2278 
2279 
2280 /*
2281  * Time related functions
2282  */
2283 
2284 double
get_rtime(void)2285 cl_uc::get_rtime(void)
2286 {
2287   /*  double d;
2288 
2289   d= (double)ticks/xtal;
2290   return(d);*/
2291   return(ticks->get_rtime(xtal));
2292 }
2293 
2294 unsigned long
clocks_of_time(double t)2295 cl_uc::clocks_of_time(double t)
2296 {
2297   return (unsigned long)(t * xtal);
2298 }
2299 
2300 int
clock_per_cycle(void)2301 cl_uc::clock_per_cycle(void)
2302 {
2303   return(1);
2304 }
2305 
2306 void
touch(void)2307 cl_uc::touch(void)
2308 {
2309   class cl_hw *hw;
2310   int i;
2311   for (i= 0; i < hws->count; i++)
2312     {
2313       hw= (class cl_hw *)(hws->at(i));
2314       hw->touch();
2315     }
2316 }
2317 
2318 
2319 /*
2320  * Stack tracking system
2321  */
2322 
2323 void
stack_write(class cl_stack_op * op)2324 cl_uc::stack_write(class cl_stack_op *op)
2325 {
2326   delete op;
2327   return ;
2328   if (op->get_op() & stack_read_operation)
2329     {
2330       class cl_error_stack_tracker_wrong_handle *e= new
2331 	cl_error_stack_tracker_wrong_handle(false);
2332       e->init();
2333       error(e);
2334       return;
2335     }
2336   stack_ops->push(op);
2337 }
2338 
2339 void
stack_read(class cl_stack_op * op)2340 cl_uc::stack_read(class cl_stack_op *op)
2341 {
2342   delete op;
2343   return ;
2344   class cl_stack_op *top= (class cl_stack_op *)(stack_ops->top());
2345 
2346   if (op->get_op() & stack_write_operation)
2347     {
2348       class cl_error_stack_tracker_wrong_handle *e= new
2349 	cl_error_stack_tracker_wrong_handle(true);
2350       e->init();
2351       error(e);
2352       return;
2353     }
2354   if (!top)
2355     {
2356       class cl_error *e= new cl_error_stack_tracker_empty(op);
2357       e->init();
2358       error(e);
2359       return;
2360     }
2361 
2362   if (top)
2363     {
2364       if (!top->match(op))
2365 	{
2366 	  class cl_error *e= new cl_error_stack_tracker_unmatch(top, op);
2367 	  e->init();
2368 	  error(e);
2369 	}
2370       int top_size= top->data_size(), op_size= op->data_size();
2371       if (top_size != op_size)
2372 	{
2373 	  application->debug("0x%06x %d bytes to read out of stack "
2374 			     "but %d was pushed in last operation\n",
2375 			     (int)op->get_pc(), op_size, top_size);
2376 	}
2377     }
2378 
2379   int removed= 0;
2380   while (top &&
2381 	 top->can_removed(op))
2382     {
2383       top= (class cl_stack_op *)stack_ops->pop();
2384       delete top;
2385       top= (class cl_stack_op *)stack_ops->top();
2386       removed++;
2387     }
2388   if (removed != 1)
2389     {
2390       application->debug("0x%06x %d ops removed from stack-tracker "
2391 			 "when %s happened, top pc=0x%06x "
2392 			 "top before=0x%06x op after=0x%06x\n",
2393 			 (int)op->get_pc(), removed, op->get_op_name(),
2394                          top?((int)top->get_pc()):0,
2395 			 top?((int)top->get_before()):0,
2396                          (int)op->get_after());
2397     }
2398 
2399   if (top)
2400     {
2401       int ta= top->get_after(), oa= op->get_after();
2402       if (ta != oa)
2403 	{
2404 	  application->debug("0x%06x stack still inconsistent after %s, "
2405 			     "%d byte(s) should be read out; top after"
2406 			     "=0x%06x op after=0x%06x\n",
2407 			     (int)op->get_pc(),
2408 			     op->get_op_name(),
2409 			     abs(ta-oa),
2410 			     ta, oa);
2411 	  class cl_error *e=
2412 	    new cl_error_stack_tracker_inconsistent(op, abs(ta-oa));
2413 	  e->init();
2414           error(e);
2415         }
2416     }
2417 
2418   delete op;
2419 }
2420 
2421 /*
2422  * Breakpoint handling
2423  */
2424 
2425 class cl_fetch_brk *
fbrk_at(t_addr addr)2426 cl_uc::fbrk_at(t_addr addr)
2427 {
2428   int idx;
2429 
2430   return((class cl_fetch_brk *)(fbrk->get_bp(addr, &idx)));
2431 }
2432 
2433 class cl_ev_brk *
ebrk_at(t_addr addr,char * id)2434 cl_uc::ebrk_at(t_addr addr, char *id)
2435 {
2436   int i;
2437   class cl_ev_brk *eb;
2438 
2439   for (i= 0; i < ebrk->count; i++)
2440     {
2441       eb= (class cl_ev_brk *)(ebrk->at(i));
2442       if (eb->addr == addr &&
2443 	  !strcmp(eb->id, id))
2444 	return(eb);
2445     }
2446   return(0);
2447 }
2448 
2449 /*void
2450 cl_uc::rm_fbrk(long addr)
2451 {
2452   fbrk->del_bp(addr);
2453 }*/
2454 
2455 /* Get a breakpoint specified by its number */
2456 
2457 class cl_brk *
brk_by_nr(int nr)2458 cl_uc::brk_by_nr(int nr)
2459 {
2460   class cl_brk *bp;
2461 
2462   if ((bp= fbrk->get_bp(nr)))
2463     return(bp);
2464   if ((bp= ebrk->get_bp(nr)))
2465     return(bp);
2466   return(0);
2467 }
2468 
2469 /* Get a breakpoint from the specified collection by its number */
2470 
2471 class cl_brk *
brk_by_nr(class brk_coll * bpcoll,int nr)2472 cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
2473 {
2474   class cl_brk *bp;
2475 
2476   if ((bp= bpcoll->get_bp(nr)))
2477     return(bp);
2478   return(0);
2479 }
2480 
2481 /* Remove an event breakpoint specified by its address and id */
2482 
2483 void
rm_ebrk(t_addr addr,char * id)2484 cl_uc::rm_ebrk(t_addr addr, char *id)
2485 {
2486   int i;
2487   class cl_ev_brk *eb;
2488 
2489   for (i= 0; i < ebrk->count; i++)
2490     {
2491       eb= (class cl_ev_brk *)(ebrk->at(i));
2492       if (eb->addr == addr &&
2493 	  !strcmp(eb->id, id))
2494 	ebrk->del_bp(i, 0);
2495     }
2496 }
2497 
2498 /* Remove a breakpoint specified by its number */
2499 
2500 bool
rm_brk(int nr)2501 cl_uc::rm_brk(int nr)
2502 {
2503   class cl_brk *bp;
2504 
2505   if ((bp= brk_by_nr(fbrk, nr)))
2506     {
2507       fbrk->del_bp(bp->addr);
2508       return(true);
2509     }
2510   else if ((bp= brk_by_nr(ebrk, nr)))
2511     {
2512       ebrk->del_bp(ebrk->index_of(bp), 0);
2513       return(true);
2514     }
2515   return(false);
2516 }
2517 
2518 void
put_breaks(void)2519 cl_uc::put_breaks(void)
2520 {}
2521 
2522 /* Remove all fetch and event breakpoints */
2523 
2524 void
remove_all_breaks(void)2525 cl_uc::remove_all_breaks(void)
2526 {
2527   while (fbrk->count)
2528     {
2529       class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
2530       fbrk->del_bp(brk->addr);
2531     }
2532   while (ebrk->count)
2533     ebrk->del_bp(ebrk->count-1, 0);
2534 }
2535 
2536 int
make_new_brknr(void)2537 cl_uc::make_new_brknr(void)
2538 {
2539   if (brk_counter == 0)
2540     return(brk_counter= 1);
2541   if (fbrk->count == 0 &&
2542       ebrk->count == 0)
2543     return(brk_counter= 1);
2544   return(++brk_counter);
2545 }
2546 
2547 class cl_ev_brk *
mk_ebrk(enum brk_perm perm,class cl_address_space * mem,char op,t_addr addr,int hit)2548 cl_uc::mk_ebrk(enum brk_perm perm, class cl_address_space *mem,
2549 	       char op, t_addr addr, int hit)
2550 {
2551   class cl_ev_brk *b;
2552   op= toupper(op);
2553 
2554   b= new cl_ev_brk(mem, make_new_brknr(), addr, perm, hit, op);
2555   b->init();
2556   return(b);
2557 }
2558 
2559 void
check_events(void)2560 cl_uc::check_events(void)
2561 {
2562   int i;
2563   //sim->stop(resEVENTBREAK);
2564   for (i= 0; i < events->count; i++)
2565     {
2566       class cl_ev_brk *brk=
2567 	dynamic_cast<class cl_ev_brk *>(events->object_at(i));
2568       sim->stop(resEVENTBREAK, brk);
2569     }
2570 }
2571 
2572 void
stop_when(class cl_time_measurer * t)2573 cl_uc::stop_when(class cl_time_measurer *t)
2574 {
2575   if (stop_at_time != NULL)
2576     delete stop_at_time;
2577   stop_at_time= t;
2578 }
2579 
2580 
2581 /*
2582  * Errors
2583  *----------------------------------------------------------------------------
2584  */
2585 
cl_error_unknown_code(class cl_uc * the_uc)2586 cl_error_unknown_code::cl_error_unknown_code(class cl_uc *the_uc)
2587 {
2588   uc= the_uc;
2589   classification= uc_error_registry.find("unknown_code");
2590 }
2591 
2592 void
print(class cl_commander_base * c)2593 cl_error_unknown_code::print(class cl_commander_base *c)
2594 {
2595   //FILE *f= c->get_out();
2596   /*cmd_fprintf(f,*/c->dd_printf("%s: unknown instruction code at ", get_type_name());
2597   if (uc->rom)
2598     {
2599       /*cmd_fprintf(f,*/c->dd_printf(uc->rom->addr_format, PC);
2600       /*cmd_fprintf(f,*/c->dd_printf(" (");
2601       /*cmd_fprintf(f,*/c->dd_printf(uc->rom->data_format, uc->rom->get(PC));
2602       /*cmd_fprintf(f,*/c->dd_printf(")");
2603     }
2604   else
2605     /*cmd_fprintf(f,*/c->dd_printf("0x%06x", AU(PC));
2606   /*cmd_fprintf(f,*/c->dd_printf("\n");
2607 }
2608 
2609 
cl_uc_error_registry(void)2610 cl_uc_error_registry::cl_uc_error_registry(void)
2611 {
2612   class cl_error_class *prev = uc_error_registry.find("non-classified");
2613   prev = register_error(new cl_error_class(err_error, "unknown_code", prev, ERROR_OFF));
2614 }
2615 
2616 /* End of uc.cc */
2617