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