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