version 0.5.2
[fw/sdcc] / sim / ucsim / sim.src / uc.cc
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 "cmduccl.h"
43 #include "bpcl.h"
44 #include "getcl.h"
45 #include "setcl.h"
46 #include "infocl.h"
47 #include "timercl.h"
48 #include "cmdstatcl.h"
49 #include "cmdmemcl.h"
50
51 // local, sim.src
52 #include "uccl.h"
53 #include "hwcl.h"
54 #include "memcl.h"
55 #include "simcl.h"
56 #include "itsrccl.h"
57
58
59 /*
60  * Clock counter
61  */
62
63 cl_ticker::cl_ticker(int adir, int in_isr, char *aname)
64 {
65   options= TICK_RUN;
66   if (in_isr)
67     options|= TICK_INISR;
68   dir= adir;
69   ticks= 0;
70   set_name(aname);
71 }
72
73 cl_ticker::~cl_ticker(void) {}
74
75 int
76 cl_ticker::tick(int nr)
77 {
78   if (options&TICK_RUN)
79     ticks+= dir*nr;
80   return(ticks);
81 }
82
83 double
84 cl_ticker::get_rtime(double xtal)
85 {
86   double d;
87
88   d= (double)ticks/xtal;
89   return(d);
90 }
91
92 void
93 cl_ticker::dump(int nr, double xtal, class cl_console *con)
94 {
95   con->dd_printf("timer #%d(\"%s\") %s%s: %g sec (%lu clks)\n",
96                  nr, get_name("unnamed"),
97                  (options&TICK_RUN)?"ON":"OFF",
98                  (options&TICK_INISR)?",ISR":"",
99                  get_rtime(xtal), ticks);
100 }
101
102
103 /*
104  * Options of uc
105  */
106
107 cl_xtal_option::cl_xtal_option(class cl_uc *the_uc):
108   cl_optref(the_uc)
109 {
110   uc= the_uc;
111 }
112
113 void
114 cl_xtal_option::option_changed(void)
115 {
116   if (!uc)
117     return;
118   double d;
119   option->get_value(&d);
120   uc->xtal= d;
121 }
122
123
124 /*
125  * Abstract microcontroller
126  ******************************************************************************
127  */
128
129 cl_uc::cl_uc(class cl_sim *asim):
130   cl_base()
131 {
132   //int i;
133   sim = asim;
134   //mems= new cl_list(MEM_TYPES, 1);
135   memchips= new cl_list(2, 2, "memchips");
136   address_spaces= new cl_address_space_list(this);
137   //address_decoders= new cl_list(2, 2);
138   rom= 0;
139
140   hws = new cl_hws();
141   //options= new cl_list(2, 2);
142   //for (i= MEM_ROM; i < MEM_TYPES; i++) mems->add(0);
143   xtal_option= new cl_xtal_option(this);
144   xtal_option->init();
145   ticks= new cl_ticker(+1, 0, "time");
146   isr_ticks= new cl_ticker(+1, TICK_INISR, "isr");
147   idle_ticks= new cl_ticker(+1, TICK_IDLE, "idle");
148   counters= new cl_list(2, 2, "counters");
149   it_levels= new cl_list(2, 2, "it levels");
150   it_sources= new cl_irqs(2, 2);
151   class it_level *il= new it_level(-1, 0, 0, 0);
152   it_levels->push(il);
153   stack_ops= new cl_list(2, 2, "stack operations");
154   errors= new cl_list(2, 2, "errors in uc");
155   events= new cl_list(2, 2, "events in uc");
156   sp_max= 0;
157   sp_avg= 0;
158   inst_exec= DD_FALSE;
159 }
160
161
162 cl_uc::~cl_uc(void)
163 {
164   //delete mems;
165   delete hws;
166   //delete options;
167   delete ticks;
168   delete isr_ticks;
169   delete idle_ticks;
170   delete counters;
171   events->disconn_all();
172   delete events;
173   delete fbrk;
174   delete ebrk;
175   delete it_levels;
176   delete it_sources;
177   delete stack_ops;
178   errors->free_all();
179   delete errors;
180   delete xtal_option;
181   delete address_spaces;
182   delete memchips;
183   //delete address_decoders;
184 }
185
186
187 int
188 cl_uc::init(void)
189 {
190   int i;
191
192   set_name("controller");
193   cl_base::init();
194   if (xtal_option->use("xtal"))
195     xtal= xtal_option->get_value(xtal);
196   else
197     xtal= 11059200;
198   make_memories();
199   rom= address_space(MEM_ROM_ID);
200   ebrk= new brk_coll(2, 2, rom);
201   fbrk= new brk_coll(2, 2, rom);
202   fbrk->Duplicates= DD_FALSE;
203   brk_counter= 0;
204   mk_hw_elements();
205   reset();
206   class cl_cmdset *cs= sim->app->get_commander()->cmdset;
207   build_cmdset(cs);
208
209   for (i= 0; i < sim->app->in_files->count; i++)
210     {
211       char *fname= (char *)(sim->app->in_files->at(i));
212       long l;
213       if ((l= read_hex_file(fname)) >= 0)
214         {
215           sim->app->get_commander()->all_printf("%ld words read from %s\n",
216                                                 l, fname);
217         }
218     }
219   return(0);
220 }
221
222 char *
223 cl_uc::id_string(void)
224 {
225   return("unknown microcontroller");
226 }
227
228 void
229 cl_uc::reset(void)
230 {
231   class it_level *il;
232
233   instPC= PC= 0;
234   state = stGO;
235   ticks->ticks= 0;
236   isr_ticks->ticks= 0;
237   idle_ticks->ticks= 0;
238   /*FIXME should we clear user counters?*/
239   il= (class it_level *)(it_levels->top());
240   while (il &&
241          il->level >= 0)
242     {
243       il= (class it_level *)(it_levels->pop());
244       delete il;
245       il= (class it_level *)(it_levels->top());
246     }
247   sp_max= 0;
248   sp_avg= 0;
249   
250   stack_ops->free_all();
251
252   int i;
253   for (i= 0; i < hws->count; i++)
254     {
255       class cl_hw *hw= (class cl_hw *)(hws->at(i));
256       hw->reset();
257     }
258 }
259
260 /*
261  * Making elements
262  */
263
264 void
265 cl_uc::make_memories(void)
266 {}
267
268 /*t_addr
269 cl_uc::get_mem_size(char *id)
270 {
271   class cl_memory *m= memory(id);
272   return(m?(m->get_size()):0);
273 }
274
275 int
276 cl_uc::get_mem_width(char *id)
277 {
278   class cl_memory *m= memory(id);
279   return(m?(m->width):8);
280 }
281 */
282 void
283 cl_uc::mk_hw_elements(void)
284 {
285 }
286
287 void
288 cl_uc::build_cmdset(class cl_cmdset *cmdset)
289 {
290   class cl_cmd *cmd;
291   class cl_super_cmd *super_cmd;
292   class cl_cmdset *cset;
293
294   cmdset->add(cmd= new cl_state_cmd("state", 0,
295 "state              State of microcontroller",
296 "long help of state"));
297   cmd->init();
298
299 #ifdef STATISTIC
300   cmdset->add(cmd= new cl_statistic_cmd("statistic", 0,
301 "statistic [mem [startaddr [endaddr]]]\n"
302 "                   Statistic of memory accesses",
303 "long help of statistic"));
304   cmd->init();
305 #endif
306
307   cmdset->add(cmd= new cl_file_cmd("file", 0,
308 "file \"FILE\"        Load FILE into ROM",
309 "long help of file"));
310   cmd->init();
311   cmd->add_name("load");
312
313   cmdset->add(cmd= new cl_dl_cmd("download", 0,
314 "download           Load (intel.hex) data",
315 "long help of download"));
316   cmd->init();
317   cmd->add_name("dl");
318
319   cmdset->add(cmd= new cl_pc_cmd("pc", 0,
320 "pc [addr]          Set/get PC",
321 "long help of pc"));
322   cmd->init();
323
324   cmdset->add(cmd= new cl_reset_cmd("reset", 0,
325 "reset              Reset",
326 "long help of reset"));
327   cmd->init();
328
329   cmdset->add(cmd= new cl_dump_cmd("dump", DD_TRUE,
330 "dump memory_type [start [stop [bytes_per_line]]]\n"
331 "                   Dump memory of specified type\n"
332 "dump bit...        Dump bits",
333 "long help of dump"));
334   cmd->init();
335
336   cmdset->add(cmd= new cl_dch_cmd("dch", DD_TRUE,
337 "dch [start [stop]] Dump code in hex form",
338 "long help of dch"));
339   cmd->init();
340
341   cmdset->add(cmd= new cl_dc_cmd("dc", DD_TRUE,
342 "dc [start [stop]]  Dump code in disass form",
343 "long help of dc"));
344   cmd->init();
345
346   cmdset->add(cmd= new cl_disassemble_cmd("disassemble", DD_TRUE,
347 "disassemble [start [offset [lines]]]\n"
348 "                   Disassemble code",
349 "long help of disassemble"));
350   cmd->init();
351
352   cmdset->add(cmd= new cl_fill_cmd("fill", 0,
353 "fill memory_type start end data\n"
354 "                   Fill memory region with data",
355 "long help of fill"));
356   cmd->init();
357
358   cmdset->add(cmd= new cl_where_cmd("where", 0,
359 "where memory_type data...\n"
360 "                   Case unsensitive search for data",
361 "long help of where"));
362   cmd->init();
363
364   cmdset->add(cmd= new cl_Where_cmd("Where", 0,
365 "Where memory_type data...\n"
366 "                   Case sensitive search for data",
367 "long help of Where"));
368   cmd->init();
369
370   cmdset->add(cmd= new cl_break_cmd("break", 0,
371 "break addr [hit]   Set fix breakpoint\n"
372 "break mem_type r|w addr [hit]\n"
373 "                   Set fix event breakpoint",
374 "long help of break"));
375   cmd->init();
376
377   cmdset->add(cmd= new cl_tbreak_cmd("tbreak", 0,
378 "tbreak addr [hit]  Set temporary breakpoint\n"
379 "tbreak mem_type r|w addr [hit]\n"
380 "                   Set temporary event breakpoint",
381 "long help of tbreak"));
382   cmd->init();
383
384   cmdset->add(cmd= new cl_clear_cmd("clear", 0,
385 "clear [addr...]    Clear fix breakpoint",
386 "long help of clear"));
387   cmd->init();
388
389   cmdset->add(cmd= new cl_delete_cmd("delete", 0,
390 "delete [nr...]     Delete breakpoint(s)",
391 "long help of clear"));
392   cmd->init();
393
394   {
395     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("get"));
396     if (super_cmd)
397       cset= super_cmd->commands;
398     else {
399       cset= new cl_cmdset();
400       cset->init();
401     }
402     cset->add(cmd= new cl_get_sfr_cmd("sfr", 0,
403 "get sfr address...\n"
404 "                   Get value of addressed SFRs",
405 "long help of get sfr"));
406     cmd->init();
407     /*cset->add(cmd= new cl_get_option_cmd("option", 0,
408 "get option name\n"
409 "                   Get value of an option",
410 "long help of get option"));
411 cmd->init();*/
412   }
413   if (!super_cmd)
414     {
415       cmdset->add(cmd= new cl_super_cmd("get", 0,
416 "get subcommand     Get, see `get' command for more help",
417 "long help of get", cset));
418       cmd->init();
419     }
420
421   {
422     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("set"));
423     if (super_cmd)
424       cset= super_cmd->commands;
425     else {
426       cset= new cl_cmdset();
427       cset->init();
428     }
429     cset->add(cmd= new cl_set_mem_cmd("memory", 0,
430 "set memory memory_type address data...\n"
431 "                   Place list of data into memory",
432 "long help of set memory"));
433     cmd->init();
434     cset->add(cmd= new cl_set_bit_cmd("bit", 0,
435 "set bit addr 0|1   Set specified bit to 0 or 1",
436 "long help of set bit"));
437     cmd->init();
438     cset->add(cmd= new cl_set_hw_cmd("hardware", 0,
439 "set hardware cathegory params...\n"
440 "                   Set parameters of specified hardware element",
441 "long help of set hardware"));
442     cmd->add_name("hw");
443     cmd->init();
444   }
445   if (!super_cmd)
446     {
447       cmdset->add(cmd= new cl_super_cmd("set", 0,
448 "set subcommand     Set, see `set' command for more help",
449 "long help of set", cset));
450       cmd->init();
451     }
452
453   { // info
454     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("info"));
455     if (super_cmd)
456       cset= super_cmd->get_subcommands();
457     else {
458       cset= new cl_cmdset();
459       cset->init();
460     }
461     cset->add(cmd= new cl_info_bp_cmd("breakpoints", 0, 
462 "info breakpoints   Status of user-settable breakpoints",
463 "long help of info breakpoints"));
464     cmd->add_name("bp");
465     cmd->init();
466     cset->add(cmd= new cl_info_reg_cmd("registers", 0, 
467 "info registers     List of integer registers and their contents",
468 "long help of info registers"));
469     cmd->init();
470     cset->add(cmd= new cl_info_hw_cmd("hardware", 0, 
471 "info hardware cathegory\n"
472 "                   Status of hardware elements of the CPU",
473 "long help of info hardware"));
474     cmd->add_name("hw");
475     cmd->init();
476     cset->add(cmd= new cl_info_stack_cmd("stack", 0, 
477 "info stack         Status of stack of the CPU",
478 "long help of info stack"));
479     cmd->init();
480     cset->add(cmd= new cl_info_memory_cmd("memory", 0,
481 "info memory        Information about memory system",
482 "long help of info memory"));
483     cmd->init();
484   }
485   if (!super_cmd) {
486     cmdset->add(cmd= new cl_super_cmd("info", 0,
487 "info subcommand    Information, see `info' command for more help",
488 "long help of info", cset));
489     cmd->init();
490   }
491
492   {
493     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("timer"));
494     if (super_cmd)
495       cset= super_cmd->get_subcommands();
496     else {
497       cset= new cl_cmdset();
498       cset->init();
499     }
500     cset->add(cmd= new cl_timer_add_cmd("add", 0,
501 "timer add id [direction [in_isr]]\n"
502 "                   Create a clock counter (timer)",
503 "log help of timer add"));
504     cmd->init();
505     cmd->add_name("create");
506     cmd->add_name("make");
507     cset->add(cmd= new cl_timer_delete_cmd("delete", 0,
508 "timer delete id    Delete a timer",
509 "long help of timer delete"));
510     cmd->init();
511     cmd->add_name("remove");
512     cset->add(cmd= new cl_timer_get_cmd("get", 0,
513 "timer get [id]     Get value of a timer, or all",
514 "long help of timer get"));
515     cmd->init();
516     cset->add(cmd= new cl_timer_run_cmd("run", 0,
517 "timer start id     Start a timer",
518 "long help of timer run"));
519     cmd->init();
520     cmd->add_name("start");
521     cset->add(cmd= new cl_timer_stop_cmd("stop", 0,
522 "timer stop id      Stop a timer",
523 "long help of timer stop"));
524     cmd->init();
525     cset->add(cmd= new cl_timer_value_cmd("set", 0,
526 "timer set id value\n"
527 "                   Set a timer value",
528 "long help of timer set"));
529     cmd->init();
530     cmd->add_name("value");
531   }
532   if (!super_cmd) {
533     cmdset->add(cmd= new cl_super_cmd("timer", 0,
534 "timer subcommand   Manage timers",
535 "long help of timer", cset));
536     cmd->init();
537   }
538
539   {
540     super_cmd= (class cl_super_cmd *)(cmdset->get_cmd("memory"));
541     if (super_cmd)
542       cset= super_cmd->get_subcommands();
543     else {
544       cset= new cl_cmdset();
545       cset->init();
546     }
547     /*
548     cset->add(cmd= new cl_memory_cmd("_no_parameters_", 0,
549 "memory             Information about memory system",
550 "long help of memory"));
551     cmd->init();
552     */
553     cset->add(cmd= new cl_memory_createchip_cmd("createchip", 0,
554 "memory createchip id size cellsize\n"
555 "                   Create a new memory chip",
556 "long help of memory createchip"));
557     cmd->init();
558     cmd->add_name("cchip");
559     cset->add(cmd= new cl_memory_createaddressspace_cmd("createaddressspace", 0,
560 "memory createaddressspace id startaddr size\n"
561 "                   Create address space",
562 "long help of memory createaddressspace"));
563     cmd->init();
564     cmd->add_name("createaddrspace");
565     cmd->add_name("createaspace");
566     cmd->add_name("caddressspace");
567     cmd->add_name("caddrspace");
568     cmd->add_name("caspace");
569     cset->add(cmd= new cl_memory_createaddressdecoder_cmd("createaddressdecoder", 0,
570 "memory createaddressdecoder addressspace begin end chip begin\n"
571 "                   Create address decoder",
572 "long help of memory createaddressdecoder"));
573     cmd->init();
574     cmd->add_name("createaddrdecoder");
575     cmd->add_name("createadecoder");
576     cmd->add_name("caddressdecoder");
577     cmd->add_name("caddrdecoder");
578     cmd->add_name("cadecoder");
579   }
580   if (!super_cmd) {
581     cmdset->add(cmd= new cl_super_cmd("memory", 0,
582 "memory subcommand  Manage memory chips and address spaces",
583 "long help of memory", cset));
584     cmd->init();
585   }
586 }
587
588
589 /*
590  * Read/write simulated memory
591  */
592
593 t_mem
594 cl_uc::read_mem(char *id, t_addr addr)
595 {
596   class cl_address_space *m= address_space(id);
597
598   return(m?(m->read(addr)):0);
599 }
600
601 t_mem
602 cl_uc::get_mem(char *id, t_addr addr)
603 {
604   class cl_address_space *m= address_space(id);
605
606   return(m?(m->get(addr)):0);
607 }
608
609 void
610 cl_uc::write_mem(char *id, t_addr addr, t_mem val)
611 {
612   class cl_address_space *m= address_space(id);
613
614   if (m)
615     m->write(addr, val);
616 }
617
618 void
619 cl_uc::set_mem(char *id, t_addr addr, t_mem val)
620 {
621   class cl_address_space *m= address_space(id);
622
623   if(m)
624     m->set(addr, val);
625 }
626
627
628 /*
629 class cl_memory *
630 cl_uc::mem(enum mem_class type)
631 {
632   class cl_m *m;
633     
634   if (mems->count < type)
635     m= (class cl_m *)(mems->at(MEM_DUMMY));
636   else
637     m= (class cl_m *)(mems->at(type));
638   return(m);
639 }
640 */
641
642 class cl_address_space *
643 cl_uc::address_space(char *id)
644 {
645   int i;
646
647   if (!id ||
648       !(*id))
649     return(0);
650   for (i= 0; i < address_spaces->count; i++)
651     {
652       class cl_address_space *m= (cl_address_space *)(address_spaces->at(i));
653       if (!m ||
654           !m->have_real_name())
655         continue;
656       if (m->is_inamed(id))
657         return(m);
658     }
659   return(0);
660 }
661
662 class cl_memory *
663 cl_uc::memory(char *id)
664 {
665   int i;
666
667   if (!id ||
668       !(*id))
669     return(0);
670   for (i= 0; i < address_spaces->count; i++)
671     {
672       class cl_memory *m= (cl_memory *)(address_spaces->at(i));
673       if (!m ||
674           !m->have_real_name())
675         continue;
676       if (m->is_inamed(id))
677         return(m);
678     }
679   for (i= 0; i < memchips->count; i++)
680     {
681       class cl_memory *m= (cl_memory *)(memchips->at(i));
682       if (!m ||
683           !m->have_real_name())
684         continue;
685       if (m->is_inamed(id))
686         return(m);
687     }
688   return(0);
689 }
690
691
692 static long
693 ReadInt(FILE *f, bool *ok, int bytes)
694 {
695   char s2[3];
696   long l= 0;
697
698   *ok= DD_FALSE;
699   while (bytes)
700     {
701       if (fscanf(f, "%2c", &s2[0]) == EOF)
702         return(0);
703       s2[2]= '\0';
704       l= l*256 + strtol(s2, NULL, 16);
705       bytes--;
706     }
707   *ok= DD_TRUE;
708   return(l);
709 }
710
711
712 /* 
713  * Reading intel hexa file into EROM
714  *____________________________________________________________________________
715  *
716  * If parameter is a NULL pointer, this function reads data from `cmd_in'
717  *
718  */
719
720 long
721 cl_uc::read_hex_file(const char *nam)
722 {
723   FILE *f;
724   int c;
725   long written= 0, recnum= 0;
726
727   uchar dnum;     // data number
728   uchar rtyp=0;   // record type
729   uint  addr= 0;  // address
730   uchar rec[300]; // data record
731   uchar sum ;     // checksum
732   uchar chk ;     // check
733   int  i;
734   bool ok, get_low= 1;
735   uchar low= 0, high;
736
737   if (!rom)
738     {
739       sim->app->get_commander()->
740         dd_printf("No ROM address space to read in.\n");
741       return(-1);
742     }
743
744   if (!nam)
745     {
746       sim->app->get_commander()->
747         dd_printf("cl_uc::read_hex_file File name not specified\n");
748       return(-1);
749     }
750   else
751     if ((f= fopen(nam, "r")) == NULL)
752       {
753         fprintf(stderr, "Can't open `%s': %s\n", nam, strerror(errno));
754         return(-1);
755       }
756
757   //memset(inst_map, '\0', sizeof(inst_map));
758   ok= DD_TRUE;
759   while (ok &&
760          rtyp != 1)
761     {
762       while (((c= getc(f)) != ':') &&
763              (c != EOF)) ;
764       if (c != ':')
765         {fprintf(stderr, ": not found\n");break;}
766       recnum++;
767       dnum= ReadInt(f, &ok, 1);//printf("dnum=%02x",dnum);
768       chk = dnum;
769       addr= ReadInt(f, &ok, 2);//printf("addr=%04x",addr);
770       chk+= (addr & 0xff);
771       chk+= ((addr >> 8) & 0xff);
772       rtyp= ReadInt(f, &ok, 1);//printf("rtyp=%02x ",rtyp);
773       chk+= rtyp;
774       for (i= 0; ok && (i < dnum); i++)
775         {
776           rec[i]= ReadInt(f, &ok, 1);//printf("%02x",rec[i]);
777           chk+= rec[i];
778         }
779       if (ok)
780         {
781           sum= ReadInt(f, &ok, 1);//printf(" sum=%02x\n",sum);
782           if (ok)
783             {
784               if (((sum + chk) & 0xff) == 0)
785                 {
786                   if (rtyp == 0)
787                     {
788                       if (rom->width > 8)
789                         addr/= 2;
790                       for (i= 0; i < dnum; i++)
791                         {
792                           if (rom->width <= 8)
793                             {
794                               rom->set(addr, rec[i]);
795                               addr++;
796                               written++;
797                             }
798                           else if (rom->width <= 16)
799                             {
800                               if (get_low)
801                                 {
802                                   low= rec[i];
803                                   get_low= 0;
804                                 }
805                               else
806                                 {
807                                   high= rec[i];
808                                   rom->set(addr, (high*256)+low);
809                                   addr++;
810                                   written++;
811                                   get_low= 1;
812                                 }
813                             }
814                         }
815                     }
816                   else
817                     if (rtyp != 1)
818                       application->debug("Unknown record type %d(0x%x)\n",
819                                          rtyp, rtyp);
820                 }
821               else
822                 application->debug("Checksum error (%x instead of %x) in "
823                                    "record %ld.\n", chk, sum, recnum);
824             }
825           else
826             application->debug("Read error in record %ld.\n", recnum);
827         }
828     }
829   if (rom->width > 8 &&
830       !get_low)
831     rom->set(addr, low);
832
833   if (nam)
834     fclose(f);
835   application->debug("%ld records have been read\n", recnum);
836   analyze(0);
837   return(written);
838 }
839
840
841 /*
842  * Handling instruction map
843  *
844  * `inst_at' is checking if the specified address is in instruction
845  * map and `set_inst_at' marks the address in the map and
846  * `del_inst_at' deletes the mark. `there_is_inst' cheks if there is
847  * any mark in the map
848  */
849
850 bool
851 cl_uc::inst_at(t_addr addr)
852 {
853   if (!rom)
854     return(0);
855   return(rom->get_cell_flag(addr, CELL_INST));
856 }
857
858 void
859 cl_uc::set_inst_at(t_addr addr)
860 {
861   if (rom)
862     rom->set_cell_flag(addr, DD_TRUE, CELL_INST);
863 }
864
865 void
866 cl_uc::del_inst_at(t_addr addr)
867 {
868   if (rom)
869     rom->set_cell_flag(addr, DD_FALSE, CELL_INST);
870 }
871
872 bool
873 cl_uc::there_is_inst(void)
874 {
875   if (!rom)
876     return(0);
877   bool got= DD_FALSE;
878   t_addr addr;
879   for (addr= 0; rom->valid_address(addr) && !got; addr++)
880     got= rom->get_cell_flag(addr, CELL_INST);
881   return(got);
882 }
883
884
885 /*
886  * Manipulating HW elements of the CPU
887  *****************************************************************************
888  */
889
890 /* Register callback hw objects for mem read/write */
891
892 /*void
893 cl_uc::register_hw_read(enum mem_class type, t_addr addr, class cl_hw *hw)
894 {
895   class cl_m *m;
896   class cl_memloc *l;
897
898   if ((m= (class cl_m*)mems->at(type)))
899     {
900       if ((l= m->read_locs->get_loc(addr)) == 0)
901         {
902           l= new cl_memloc(addr);
903           l->init();
904           m->read_locs->add(l);
905         }
906       l->hws->add(hw);
907     }
908   else
909     printf("cl_uc::register_hw_read TROUBLE\n");
910 }*/
911
912 /*void
913 cl_uc::register_hw_write(enum mem_class type, t_addr addr, class cl_hw *hw)
914 {
915 }*/
916
917 /* Looking for a specific HW element */
918
919 class cl_hw *
920 cl_uc::get_hw(enum hw_cath cath, int *idx)
921 {
922   class cl_hw *hw= 0;
923   int i= 0;
924
925   if (idx)
926     i= *idx;
927   for (; i < hws->count; i++)
928     {
929       hw= (class cl_hw *)(hws->at(i));
930       if (hw->cathegory == cath)
931         break;
932     }
933   if (i >= hws->count)
934     return(0);
935   if (idx)
936     *idx= i;
937   return(hw);
938 }
939
940 class cl_hw *
941 cl_uc::get_hw(char *id_string, int *idx)
942 {
943   class cl_hw *hw= 0;
944   int i= 0;
945
946   if (idx)
947     i= *idx;
948   for (; i < hws->count; i++)
949     {
950       hw= (class cl_hw *)(hws->at(i));
951       if (strstr(hw->id_string, id_string) == hw->id_string)
952         break;
953     }
954   if (i >= hws->count)
955     return(0);
956   if (idx)
957     *idx= i;
958   return(hw);
959 }
960
961 class cl_hw *
962 cl_uc::get_hw(enum hw_cath cath, int hwid, int *idx)
963 {
964   class cl_hw *hw;
965   int i= 0;
966
967   if (idx)
968     i= *idx;
969   hw= get_hw(cath, &i);
970   while (hw &&
971          hw->id != hwid)
972     {
973       i++;
974       hw= get_hw(cath, &i);
975     }
976   if (hw && 
977       idx)
978     *idx= i;
979   return(hw);
980 }
981
982 class cl_hw *
983 cl_uc::get_hw(char *id_string, int hwid, int *idx)
984 {
985   class cl_hw *hw;
986   int i= 0;
987
988   if (idx)
989     i= *idx;
990   hw= get_hw(id_string, &i);
991   while (hw &&
992          hw->id != hwid)
993     {
994       i++;
995       hw= get_hw(id_string, &i);
996     }
997   if (hw && 
998       idx)
999     *idx= i;
1000   return(hw);
1001 }
1002
1003
1004 /*
1005  * Help of the command interpreter
1006  */
1007
1008 struct dis_entry *
1009 cl_uc::dis_tbl(void)
1010 {
1011   static struct dis_entry empty= { 0, 0, 0, 0, NULL };
1012   return(&empty);
1013 }
1014
1015 struct name_entry *
1016 cl_uc::sfr_tbl(void)
1017 {
1018   static struct name_entry empty= { 0, 0 };
1019   return(&empty);
1020 }
1021
1022 struct name_entry *
1023 cl_uc::bit_tbl(void)
1024 {
1025   static struct name_entry empty= { 0, 0 };
1026   return(&empty);
1027 }
1028
1029 char *
1030 cl_uc::disass(t_addr addr, char *sep)
1031 {
1032   char *buf;
1033
1034   buf= (char*)malloc(100);
1035   strcpy(buf, "uc::disass() unimplemented\n");
1036   return(buf);
1037 }
1038
1039 void
1040 cl_uc::print_disass(t_addr addr, class cl_console *con)
1041 {
1042   char *dis;
1043   class cl_brk *b;
1044   int i;
1045
1046   if (!rom)
1047     return;
1048
1049   t_mem code= rom->get(addr);
1050   b= fbrk_at(addr);
1051   dis= disass(addr, NULL);
1052   if (b)
1053     con->dd_printf("%c", (b->perm == brkFIX)?'F':'D');
1054   else
1055     con->dd_printf(" ");
1056   con->dd_printf("%c ", inst_at(addr)?' ':'?');
1057   con->dd_printf(rom->addr_format, addr); con->dd_printf(" ");
1058   con->dd_printf(rom->data_format, code);
1059   for (i= 1; i < inst_length(addr); i++)
1060     {
1061       con->dd_printf(" ");
1062       con->dd_printf(rom->data_format, rom->get(addr+i));
1063     }
1064   int li= longest_inst();
1065   while (i < li)
1066     {
1067       int j;
1068       j= rom->width/4 + ((rom->width%4)?1:0) + 1;
1069       while (j)
1070         con->dd_printf(" "), j--;
1071       i++;
1072     }
1073   con->dd_printf(" %s\n", dis);
1074   free(dis);
1075 }
1076
1077 void
1078 cl_uc::print_regs(class cl_console *con)
1079 {
1080   con->dd_printf("No registers\n");
1081 }
1082
1083 int
1084 cl_uc::inst_length(t_addr addr)
1085 {
1086   struct dis_entry *tabl= dis_tbl();
1087   int i;
1088   t_mem code;
1089
1090   if (!rom)
1091     return(0);
1092
1093   code = rom->get(addr);
1094   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++) ;
1095   return(tabl[i].mnemonic?tabl[i].length:1);
1096 }
1097
1098 int
1099 cl_uc::inst_branch(t_addr addr)
1100 {
1101   struct dis_entry *tabl= dis_tbl();
1102   int i;
1103   t_mem code;
1104
1105   if (!rom)
1106     return(0);
1107
1108   code = rom->get(addr);
1109   for (i= 0; tabl[i].mnemonic && (code & tabl[i].mask) != tabl[i].code; i++)
1110     ;
1111   return tabl[i].branch;
1112 }
1113
1114 int
1115 cl_uc::longest_inst(void)
1116 {
1117   struct dis_entry *de= dis_tbl();
1118   int max= 0;
1119
1120   while (de &&
1121          de->mnemonic)
1122     {
1123       if (de->length > max)
1124         max= de->length;
1125       de++;
1126     }
1127   return(max);
1128 }
1129
1130 bool
1131 cl_uc::get_name(t_addr addr, struct name_entry tab[], char *buf)
1132 {
1133   int i;
1134
1135   i= 0;
1136   while (tab[i].name &&
1137          (!(tab[i].cpu_type & type) ||
1138          (tab[i].addr != addr)))
1139     i++;
1140   if (tab[i].name)
1141     strcpy(buf, tab[i].name);
1142   return(tab[i].name != NULL);
1143 }
1144
1145 bool
1146 cl_uc::symbol2address(char *sym, struct name_entry tab[],
1147                       t_addr *addr)
1148 {
1149   int i;
1150
1151   if (!sym ||
1152       !*sym)
1153     return(DD_FALSE);
1154   i= 0;
1155   while (tab[i].name &&
1156          (!(tab[i].cpu_type & type) ||
1157           strcasecmp(sym, tab[i].name) != 0))
1158     i++;
1159   if (tab[i].name)
1160     {
1161       if (addr)
1162         *addr= tab[i].addr;
1163       return(DD_TRUE);
1164     }
1165   return(DD_FALSE);
1166 }
1167
1168 char *
1169 cl_uc::symbolic_bit_name(t_addr bit_address,
1170                          class cl_memory *mem,
1171                          t_addr mem_addr,
1172                          t_mem bit_mask)
1173 {
1174   char *sym_name= 0;
1175   int i;
1176
1177   i= 0;
1178   while (bit_tbl()[i].name &&
1179          (bit_tbl()[i].addr != bit_address))
1180     i++;
1181   if (bit_tbl()[i].name)
1182     {
1183       sym_name= strdup(bit_tbl()[i].name);
1184       return(sym_name);
1185     }
1186
1187   if (mem &&
1188       mem->have_real_name() &&
1189       strstr(mem->get_name(), "sfr") == mem->get_name())
1190     {
1191       i= 0;
1192       while (sfr_tbl()[i].name &&
1193              (sfr_tbl()[i].addr != mem_addr))
1194         i++;
1195       if (sfr_tbl()[i].name)
1196         sym_name= strdup(sfr_tbl()[i].name);
1197       else
1198         sym_name= 0;
1199     }
1200   if (!sym_name)
1201     {
1202       sym_name= (char *)malloc(16);
1203       sprintf(sym_name, mem?(mem->addr_format):"0x%06x", mem_addr);
1204     }
1205   sym_name= (char *)realloc(sym_name, strlen(sym_name)+2);
1206   strcat(sym_name, ".");
1207   i= 0;
1208   while (bit_mask > 1)
1209     {
1210       bit_mask>>=1;
1211       i++;
1212     }
1213   char bitnumstr[10];
1214   sprintf(bitnumstr, "%1d", i);
1215   strcat(sym_name, bitnumstr);
1216   return(sym_name);
1217 }
1218
1219
1220 /*
1221  * Messages to broadcast
1222  */
1223
1224 bool
1225 cl_uc::handle_event(class cl_event &event)
1226 {
1227   switch (event.what)
1228     {
1229     case ev_address_space_added:
1230       {
1231         try {
1232           class cl_event_address_space_added &e=
1233             dynamic_cast<class cl_event_address_space_added &>(event);
1234           address_space_added(e.as);
1235           e.handle();
1236         }
1237         catch (...)
1238           { break; }
1239         break;
1240       }
1241     default:
1242       return(pass_event_down(event));
1243       break;
1244     }
1245   return(DD_FALSE);
1246 }
1247
1248 /*
1249 void
1250 cl_uc::mem_cell_changed(class cl_address_space *mem, t_addr addr)
1251 {
1252   if (hws)
1253     hws->mem_cell_changed(mem, addr);
1254   else
1255     printf("JAJ uc\n");//FIXME
1256   if (mems &&
1257       mems->count)
1258     {
1259       int i;
1260       for (i= 0; i < mems->count; i++)
1261         {
1262         }
1263     }
1264 }
1265 */
1266
1267 void
1268 cl_uc::address_space_added(class cl_address_space *as)
1269 {
1270   if (hws)
1271     hws->address_space_added(as);
1272   else
1273     printf("JAJ uc\n");//FIXME
1274 }
1275
1276
1277 /*
1278  * Error handling
1279  */
1280
1281 void
1282 cl_uc::error(class cl_error *error)
1283 {
1284   errors->add(error);
1285   if ((error->inst= inst_exec))
1286     error->PC= instPC;
1287 }
1288
1289 void
1290 cl_uc::check_errors(void)
1291 {
1292   int i;
1293   class cl_commander *c= sim->app->get_commander();
1294   bool must_stop= DD_FALSE;
1295
1296   if (c)
1297     {
1298       for (i= 0; i < errors->count; i++)
1299         {
1300           class cl_error *error= (class cl_error *)(errors->at(i));
1301           if (!error->is_on())
1302             continue;
1303           error->print(c);
1304           must_stop= must_stop || (error->get_type() & err_stop);
1305           if (error->inst)
1306             {
1307               class cl_console *con;
1308               con= c->actual_console;
1309               if (!con)
1310                 con= c->frozen_console;
1311               if (con)
1312                 {
1313                   con->dd_printf("Erronouse instruction: ");
1314                   print_disass(error->PC, con);
1315                 }
1316             }
1317         }
1318       errors->free_all();
1319     }
1320   else
1321     fprintf(stderr, "no actual console, %d errors\n", errors->count);
1322   if (must_stop)
1323     sim->stop(resERROR);
1324 }
1325
1326
1327 /*
1328  * Converting bit address into real memory
1329  */
1330
1331 class cl_address_space *
1332 cl_uc::bit2mem(t_addr bitaddr, t_addr *memaddr, t_mem *bitmask)
1333 {
1334   if (memaddr)
1335     *memaddr= bitaddr;
1336   if (bitmask)
1337     *bitmask= 1 << (bitaddr & 0x7);
1338   return(0); // abstract...
1339 }
1340
1341
1342 /*
1343  * Execution
1344  */
1345
1346 int
1347 cl_uc::tick_hw(int cycles)
1348 {
1349   class cl_hw *hw;
1350   int i;//, cpc= clock_per_cycle();
1351
1352   // tick hws
1353   for (i= 0; i < hws->count; i++)
1354     {
1355       hw= (class cl_hw *)(hws->at(i));
1356       if (hw->flags & HWF_INSIDE)
1357         hw->tick(cycles);
1358     }
1359   do_extra_hw(cycles);
1360   return(0);
1361 }
1362
1363 void
1364 cl_uc::do_extra_hw(int cycles)
1365 {}
1366
1367 int
1368 cl_uc::tick(int cycles)
1369 {
1370   //class cl_hw *hw;
1371   int i, cpc= clock_per_cycle();
1372
1373   // increase time
1374   ticks->tick(cycles * cpc);
1375   class it_level *il= (class it_level *)(it_levels->top());
1376   if (il->level >= 0)
1377     isr_ticks->tick(cycles * cpc);
1378   if (state == stIDLE)
1379     idle_ticks->tick(cycles * cpc);
1380   for (i= 0; i < counters->count; i++)
1381     {
1382       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1383       if (t)
1384         {
1385           if ((t->options&TICK_INISR) ||
1386               il->level < 0)
1387             t->tick(cycles * cpc);
1388         }
1389     }
1390
1391   // tick for hardwares
1392   inst_ticks+= cycles;
1393   return(0);
1394 }
1395
1396 class cl_ticker *
1397 cl_uc::get_counter(int nr)
1398 {
1399   if (nr >= counters->count)
1400     return(0);
1401   return((class cl_ticker *)(counters->at(nr)));
1402 }
1403
1404 class cl_ticker *
1405 cl_uc::get_counter(char *nam)
1406 {
1407   int i;
1408
1409   if (!nam)
1410     return(0);
1411   for (i= 0; i < counters->count; i++)
1412     {
1413       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1414       if (t &&
1415           t->get_name() &&
1416           strcmp(t->get_name(), nam) == 0)
1417         return(t);
1418     }
1419   return(0);
1420 }
1421
1422 void
1423 cl_uc::add_counter(class cl_ticker *ticker, int nr)
1424 {
1425   while (counters->count <= nr)
1426     counters->add(0);
1427   counters->put_at(nr, ticker);
1428 }
1429
1430 void
1431 cl_uc::add_counter(class cl_ticker *ticker, char */*nam*/)
1432 {
1433   int i;
1434
1435   if (counters->count < 1)
1436     counters->add(0);
1437   for (i= 1; i < counters->count; i++)
1438     {
1439       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1440       if (!t)
1441         {
1442           counters->put_at(i, ticker);
1443           return;
1444         }
1445     }
1446   counters->add(ticker);
1447 }
1448
1449 void
1450 cl_uc::del_counter(int nr)
1451 {
1452   class cl_ticker *t;
1453
1454   if (nr >= counters->count)
1455     return;
1456   if ((t= (class cl_ticker *)(counters->at(0))) != 0)
1457     delete t;
1458   counters->put_at(nr, 0);
1459 }
1460
1461 void
1462 cl_uc::del_counter(char *nam)
1463 {
1464   int i;
1465   
1466   if (!nam)
1467     return;
1468   for (i= 0; i < counters->count; i++)
1469     {
1470       class cl_ticker *t= (class cl_ticker *)(counters->at(i));
1471       if (t &&
1472           t->get_name() &&
1473           strcmp(t->get_name(), nam) == 0)
1474         {
1475           delete t;
1476           counters->put_at(i, 0);
1477           return;
1478         }
1479     }
1480 }
1481
1482 /*
1483  * Fetch without checking for breakpoint hit
1484  */
1485
1486 t_mem
1487 cl_uc::fetch(void)
1488 {
1489   ulong code;
1490   
1491   if (!rom)
1492     return(0);
1493
1494   code= rom->read(PC);
1495   PC= rom->inc_address(PC);
1496   return(code);
1497 }
1498
1499 /*
1500  * Fetch but checking for breakpoint hit first, returns TRUE if
1501  * a breakpoint is hit
1502  */
1503
1504 bool
1505 cl_uc::fetch(t_mem *code)
1506 {
1507   class cl_brk *brk;
1508   int idx;
1509
1510   if (!code)
1511     return(0);
1512   if ((sim->state & SIM_GO) &&
1513       rom)
1514     {
1515       if (rom->get_cell_flag(PC, CELL_FETCH_BRK) &&
1516           (brk= fbrk->get_bp(PC, &idx)) &&
1517           (brk->do_hit()))
1518         {
1519           if (brk->perm == brkDYNAMIC)
1520             fbrk->del_bp(PC);
1521           return(1);
1522         }
1523     }
1524   *code= fetch();
1525   return(0);
1526 }
1527
1528 int
1529 cl_uc::do_inst(int step)
1530 {
1531   int res= resGO;
1532
1533   if (step < 0)
1534     step= 1;
1535   while (step-- &&
1536          res == resGO)
1537     {
1538       pre_inst();
1539       res= exec_inst();
1540       post_inst();
1541     }
1542   if (res != resGO)
1543     sim->stop(res);
1544   return(res);
1545 }
1546
1547 void
1548 cl_uc::pre_inst(void)
1549 {
1550   inst_exec= DD_TRUE;
1551   inst_ticks= 0;
1552   events->disconn_all();
1553 }
1554
1555 int
1556 cl_uc::exec_inst(void)
1557 {
1558   instPC= PC;
1559   return(resGO);
1560 }
1561
1562 void
1563 cl_uc::post_inst(void)
1564 {
1565   tick_hw(inst_ticks);
1566   if (errors->count)
1567     check_errors();
1568   if (events->count)
1569     check_events();
1570   inst_exec= DD_FALSE;
1571 }
1572
1573
1574 /*
1575  * Time related functions
1576  */
1577
1578 double
1579 cl_uc::get_rtime(void)
1580 {
1581   /*  double d;
1582
1583   d= (double)ticks/xtal;
1584   return(d);*/
1585   return(ticks->get_rtime(xtal));
1586 }
1587
1588 int
1589 cl_uc::clock_per_cycle(void)
1590 {
1591   return(1);
1592 }
1593
1594
1595 /*
1596  * Stack tracking system
1597  */
1598
1599 void
1600 cl_uc::stack_write(class cl_stack_op *op)
1601 {
1602   if (op->get_op() & stack_read_operation)
1603     {
1604       class cl_error_stack_tracker_wrong_handle *e= new
1605         cl_error_stack_tracker_wrong_handle(DD_FALSE);
1606       //fprintf(stderr, "%06"_A_"x cl_uc::stack_read() should be called for "
1607       //"%s\n", op->get_pc(), op->get_op_name());
1608       e->init();
1609       error(e);
1610       return;
1611     }
1612   stack_ops->push(op);
1613 }
1614
1615 void
1616 cl_uc::stack_read(class cl_stack_op *op)
1617 {
1618   class cl_stack_op *top= (class cl_stack_op *)(stack_ops->top());
1619   
1620   if (op->get_op() & stack_write_operation)
1621     {
1622       class cl_error_stack_tracker_wrong_handle *e= new
1623         cl_error_stack_tracker_wrong_handle(DD_TRUE);
1624       e->init();
1625       error(e);
1626       //fprintf(stderr, "%06"_A_"x cl_uc::stack_write() should be called for "
1627       //"%s\n", op->get_pc(), op->get_op_name());
1628       return;
1629     }
1630   if (!top)
1631     {
1632       class cl_error *e= new cl_error_stack_tracker_empty(op);
1633       /*printf("0x%06"_A_"x %s operation on stack but no operation was before\n
1634         ",
1635         op->get_pc(), op->get_op_name());*/
1636       e->init();
1637       error(e);
1638       return;
1639     }
1640
1641   if (top)
1642     {
1643       if (!top->match(op))
1644         {
1645           class cl_error *e= new cl_error_stack_tracker_unmatch(top, op);
1646           e->init();
1647           error(e);
1648           /*printf("0x%06"_A_"x %s operation on stack but last was %s\n",
1649             op->get_pc(), op->get_op_name(), top->get_op_name());*/
1650         }
1651       int top_size= top->data_size(), op_size= op->data_size();
1652       if (top_size != op_size)
1653         {
1654           application->debug("0x%06"_A_"x %d bytes to read out of stack "
1655                              "but %d was pushed in last operation\n",
1656                              op->get_pc(), op_size, top_size);
1657         }
1658     }
1659
1660   int removed= 0;
1661   while (top &&
1662          top->can_removed(op))
1663     {
1664       top= (class cl_stack_op *)stack_ops->pop();
1665       delete top;
1666       top= (class cl_stack_op *)stack_ops->top();
1667       removed++;
1668     }
1669   if (removed != 1)
1670     {
1671       application->debug("0x%06"_A_"x %d ops removed from stack-tracker "
1672                          "when %s happened, top pc=0x%06"_A_"x "
1673                          "top before=0x%06"_A_"x op after=0x%06"_A_"x\n",
1674                          op->get_pc(), removed, op->get_op_name(),
1675                          top?(top->get_pc()):0, top?(top->get_before()):0,
1676                          op->get_after());
1677     }
1678   
1679   if (top)
1680     {
1681       int ta= top->get_after(), oa= op->get_after();
1682       if (ta != oa)
1683         {
1684           application->debug("0x%06"_A_"x stack still inconsistent after %s, "
1685                              "%d byte(s) should be read out; top after"
1686                              "=0x%06"_A_"x op after=0x%06"_A_"x\n",
1687                              op->get_pc(), op->get_op_name(), abs(ta-oa),
1688                              ta, oa);
1689           class cl_error *e=
1690             new cl_error_stack_tracker_inconsistent(op, abs(ta-oa));
1691           e->init();
1692           error(e);
1693         }
1694     }
1695   
1696   delete op;
1697 }
1698
1699
1700 /*
1701  * Breakpoint handling
1702  */
1703
1704 class cl_fetch_brk *
1705 cl_uc::fbrk_at(t_addr addr)
1706 {
1707   int idx;
1708   
1709   return((class cl_fetch_brk *)(fbrk->get_bp(addr, &idx)));
1710 }
1711
1712 class cl_ev_brk *
1713 cl_uc::ebrk_at(t_addr addr, char *id)
1714 {
1715   int i;
1716   class cl_ev_brk *eb;
1717
1718   for (i= 0; i < ebrk->count; i++)
1719     {
1720       eb= (class cl_ev_brk *)(ebrk->at(i));
1721       if (eb->addr == addr &&
1722           !strcmp(eb->id, id))
1723         return(eb);
1724     }
1725   return(0);
1726 }
1727
1728 /*void
1729 cl_uc::rm_fbrk(long addr)
1730 {
1731   fbrk->del_bp(addr);
1732 }*/
1733
1734 /* Get a breakpoint specified by its number */
1735
1736 class cl_brk *
1737 cl_uc::brk_by_nr(int nr)
1738 {
1739   class cl_brk *bp;
1740
1741   if ((bp= fbrk->get_bp(nr)))
1742     return(bp);
1743   if ((bp= ebrk->get_bp(nr)))
1744     return(bp);
1745   return(0);
1746 }
1747
1748 /* Get a breakpoint from the specified collection by its number */
1749
1750 class cl_brk *
1751 cl_uc::brk_by_nr(class brk_coll *bpcoll, int nr)
1752 {
1753   class cl_brk *bp;
1754
1755   if ((bp= bpcoll->get_bp(nr)))
1756     return(bp);
1757   return(0);
1758 }
1759
1760 /* Remove an event breakpoint specified by its address and id */
1761
1762 void
1763 cl_uc::rm_ebrk(t_addr addr, char *id)
1764 {
1765   int i;
1766   class cl_ev_brk *eb;
1767
1768   for (i= 0; i < ebrk->count; i++)
1769     {
1770       eb= (class cl_ev_brk *)(ebrk->at(i));
1771       if (eb->addr == addr &&
1772           !strcmp(eb->id, id))
1773         ebrk->del_bp(i, 0);
1774     }
1775 }
1776
1777 /* Remove a breakpoint specified by its number */
1778
1779 bool
1780 cl_uc::rm_brk(int nr)
1781 {
1782   class cl_brk *bp;
1783
1784   if ((bp= brk_by_nr(fbrk, nr)))
1785     {
1786       fbrk->del_bp(bp->addr);
1787       return(DD_TRUE);
1788     }
1789   else if ((bp= brk_by_nr(ebrk, nr)))
1790     {
1791       ebrk->del_bp(ebrk->index_of(bp), 0);
1792       return(DD_TRUE);
1793     }
1794   return(DD_FALSE);
1795 }
1796
1797 void
1798 cl_uc::put_breaks(void)
1799 {}
1800
1801 /* Remove all fetch and event breakpoints */
1802
1803 void
1804 cl_uc::remove_all_breaks(void)
1805 {
1806   while (fbrk->count)
1807     {
1808       class cl_brk *brk= (class cl_brk *)(fbrk->at(0));
1809       fbrk->del_bp(brk->addr);
1810     }
1811   while (ebrk->count)
1812     ebrk->del_bp(ebrk->count-1, 0);
1813 }
1814
1815 int
1816 cl_uc::make_new_brknr(void)
1817 {
1818   if (brk_counter == 0)
1819     return(brk_counter= 1);
1820   if (fbrk->count == 0 &&
1821       ebrk->count == 0)
1822     return(brk_counter= 1);
1823   return(++brk_counter);
1824 }
1825
1826 class cl_ev_brk *
1827 cl_uc::mk_ebrk(enum brk_perm perm, class cl_address_space *mem,
1828                char op, t_addr addr, int hit)
1829 {
1830   class cl_ev_brk *b;
1831   op= toupper(op);
1832
1833   b= new cl_ev_brk(mem, make_new_brknr(), addr, perm, hit, op);
1834   b->init();
1835   return(b);
1836 }
1837
1838 void
1839 cl_uc::check_events(void)
1840 {
1841   int i;
1842   for (i= 0; i < events->count; i++)
1843     {
1844       class cl_ev_brk *brk=
1845         dynamic_cast<class cl_ev_brk *>(events->object_at(i));
1846       sim->stop(brk);
1847     }
1848   sim->stop(resBREAKPOINT);
1849 }
1850
1851
1852 /*
1853  * Errors
1854  *----------------------------------------------------------------------------
1855  */
1856
1857 ERROR_CLASS_DEF_PARENT_ON(err_error, unknown_code, "unknown_code",
1858                           error_class_base, ERROR_ON);
1859
1860 cl_error_unknown_code::cl_error_unknown_code(class cl_uc *the_uc)
1861 {
1862   uc= the_uc;
1863   classification= &error_unknown_code_class;
1864 }
1865
1866 void
1867 cl_error_unknown_code::print(class cl_commander *c)
1868 {
1869   c->dd_printf(get_type_name());
1870   c->dd_printf(": unknown instruction code at ");
1871   if (uc->rom)
1872     {
1873       c->dd_printf(uc->rom->addr_format, PC);
1874       c->dd_printf(" (");
1875       c->dd_printf(uc->rom->data_format, uc->rom->get(PC));
1876       c->dd_printf(")");
1877     }
1878   else
1879     c->dd_printf("0x%06x", PC);
1880   c->dd_printf("\n");
1881 }
1882
1883
1884 /* End of uc.cc */