12d168692a2fd52df261819a886a8a0f137c45dc
[fw/sdcc] / sim / ucsim / sim.src / mem.cc
1 /*
2  * Simulator of microcontrollers (mem.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 <stdio.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include "i_string.h"
32
33 // prj
34 #include "utils.h"
35 #include "globals.h"
36
37 // sim
38 #include "simcl.h"
39
40 // cmd
41 #include "newcmdcl.h"
42
43 // local
44 #include "memcl.h"
45 #include "hwcl.h"
46
47
48 /*
49  * Memory location handled specially by a hw element
50  */
51
52 /*cl_memloc::cl_memloc(t_addr addr):
53   cl_base()
54 {
55   address= addr;
56   hws= new cl_list(2, 2);
57   hws->init();
58 }*/
59
60 /*cl_memloc::~cl_memloc(void)
61 {
62   hws->disconn_all();
63   delete hws;
64 }*/
65
66 /*ulong
67 cl_memloc::read(class cl_mem *mem)
68 {
69   uchar ret= 0;
70   class cl_hw *hw;
71
72   if (!hws ||
73       hws->count == 0)
74     return(ret);
75   if ((hw= (class cl_hw *)(hws->at(0))))
76     ret= hw->read(mem, address);
77   return(ret);
78 }*/
79
80 /*void
81 cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
82 {
83   class cl_hw *hw;
84   int i;
85
86   if (!hws)
87     return;
88   for (i= 0; i < hws->count; i++)
89     {
90       hw= (class cl_hw *)hws->at(0);
91       hw->write(mem, addr, val);
92     }
93 }*/
94
95
96 /* Sorted collection of memory locations */
97
98 /*cl_memloc_coll::cl_memloc_coll(void):
99   cl_sorted_list(2, 2)
100 {
101   Duplicates= DD_FALSE;
102 }*/
103
104 /*void *
105 cl_memloc_coll::key_of(void *item)
106 {
107   return(&(((class cl_memloc *)item)->address));
108 }*/
109
110 /*int
111 cl_memloc_coll::compare(void *key1, void *key2)
112 {
113   if (*(long*)key1 > *(long*)key2)
114     return(1);
115   else
116     if (*(long*)key1 < *(long*)key2)
117       return(-1);
118     else
119       return(0);
120 }*/
121
122 /*class cl_memloc *
123 cl_memloc_coll::get_loc(t_addr address)
124 {
125   t_index i;
126
127   if (search(&address, i))
128     return((class cl_memloc*)(at(i)));
129   return(0);
130 }*/
131
132
133 /*
134  * Memory
135  ******************************************************************************
136  */
137
138 cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
139                t_addr asize, int awidth, class cl_uc *auc):
140   cl_guiobj()
141 {
142   int i;
143   
144   uc= auc;
145   type= atype;
146   class_name= aclass_name;
147   width= awidth;
148   size= asize;
149   mem= 0;
150   for (i= width, mask= 0; i; i--)
151     mask= (mask<<1) | 1;
152   if (width == 0 ||
153       size == 0)
154     mem= 0;
155   else if (width <= 8)
156     mem= (TYPE_UBYTE *)malloc(size);
157   else if (width <= 16)
158     mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
159   else
160     mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
161   //read_locs= new cl_memloc_coll();
162   //write_locs= new cl_memloc_coll();
163   dump_finished= 0;
164   addr_format= data_format= 0;
165 }
166
167 cl_mem::~cl_mem(void)
168 {
169   if (mem)
170     free(mem);
171   if (addr_format)
172     free(addr_format);
173   if (data_format)
174     free(data_format);
175   //delete read_locs;
176   //delete write_locs;
177 }
178
179 int
180 cl_mem::init(void)
181 {
182   t_addr i;
183
184   addr_format= (char *)malloc(10);
185   sprintf(addr_format, "0x%%0%dx",
186           size-1<=0xf?1:
187           (size-1<=0xff?2:
188            (size-1<=0xfff?3:
189             (size-1<=0xffff?4:
190              (size-1<=0xfffff?5:
191               (size-1<=0xffffff?6:12))))));
192   data_format= (char *)malloc(10);
193   sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
194
195   for (i= 0; i < size; i++)
196     set(i, (type==MEM_ROM)?(-1):0);
197   return(0);
198 }
199
200 char *
201 cl_mem::id_string(void)
202 {
203   char *s= get_id_string(mem_ids, type);
204
205   return(s?s:(char*)"NONE");
206 }
207
208 t_mem
209 cl_mem::read(t_addr addr)
210 {
211   //class cl_memloc *loc;
212
213   if (addr >= size)
214     {
215       //FIXME
216       fprintf(stderr, "Address 0x%06"_A_"x is over 0x%06"_A_"x\n", addr, size);
217       return(0);
218     }
219   /*if ((loc= read_locs->get_loc(addr)))
220     return(loc->read(this));*/
221   if (width <= 8)
222     return((((TYPE_UBYTE*)mem)[addr])&mask);
223   else if (width <= 16)
224     return((((TYPE_UWORD*)mem)[addr])&mask);
225   else
226     return((((TYPE_UDWORD*)mem)[addr])&mask);
227 }
228
229 t_mem
230 cl_mem::get(t_addr addr)
231 {
232   if (addr >= size)
233     return(0);
234   if (width <= 8)
235     return((((TYPE_UBYTE*)mem)[addr])&mask);
236   else if (width <= 16)
237     return((((TYPE_UWORD*)mem)[addr])&mask);
238   else
239     return((((TYPE_UDWORD*)mem)[addr])&mask);
240 }
241
242
243 /*
244  * Modify memory location
245  */
246
247 /* Write calls callbacks of HW elements */
248
249 t_mem
250 cl_mem::write(t_addr addr, t_mem val)
251 {
252   /*  class cl_memloc *loc;
253
254   if (addr >= size)
255     return;
256   if ((loc= write_locs->get_loc(addr)))
257     loc->write(this, addr, val);
258   if (width <= 8)
259     ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
260   else if (width <= 16)
261     ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
262   else
263   ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;*/
264   fprintf(stderr, "FIXME cl_mem::write(0x%06"_A_"x, 0x%04"_M_"x)\n",
265           addr, val);
266   return(0);
267 }
268
269 /* Set doesn't call callbacks */
270
271 void
272 cl_mem::set(t_addr addr, t_mem val)
273 {
274   if (addr >= size)
275     return;
276   if (width <= 8)
277     ((TYPE_UBYTE*)mem)[addr]= val&mask;
278   else if (width <= 16)
279     ((TYPE_UWORD*)mem)[addr]= val&mask;
280   else
281     ((TYPE_UDWORD*)mem)[addr]= val&mask;
282 }
283
284 /* Set or clear bits, without callbacks */
285
286 void
287 cl_mem::set_bit1(t_addr addr, t_mem bits)
288 {
289   if (addr >= size)
290     return;
291   bits&= mask;
292   if (width <= 8)
293     ((TYPE_UBYTE*)mem)[addr]|= bits;
294   else if (width <= 16)
295     ((TYPE_UWORD*)mem)[addr]|= bits;
296   else
297     ((TYPE_UDWORD*)mem)[addr]|= bits;
298 }
299
300 void
301 cl_mem::set_bit0(t_addr addr, t_mem bits)
302 {
303   if (addr >= size)
304     return;
305   bits&= mask;
306   if (width <= 8)
307     ((TYPE_UBYTE*)mem)[addr]&= ~bits;
308   else if (width <= 16)
309     ((TYPE_UWORD*)mem)[addr]&= ~bits;
310   else
311     ((TYPE_UDWORD*)mem)[addr]&= ~bits;
312 }
313
314 t_mem
315 cl_mem::add(t_addr addr, long what)
316 {
317   if (addr >= size)
318     return(0);
319   if (width <= 8)
320     {
321       ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what;
322       return(((TYPE_UBYTE*)mem)[addr]);
323     }
324   else if (width <= 16)
325     {
326       ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what;
327       return(((TYPE_UWORD*)mem)[addr]);
328     }
329   else
330     {
331       ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what;
332       return(((TYPE_UDWORD*)mem)[addr]);
333     }
334 }
335
336 t_addr
337 cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
338 {
339   int i;
340
341   while ((start <= stop) &&
342          (start < size))
343     {
344       con->dd_printf(addr_format, start); con->dd_printf(" ");
345       for (i= 0;
346            (i < bpl) &&
347              (start+i < size) &&
348              (start+i <= stop);
349            i++)
350         {
351           con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
352         }
353       while (i < bpl)
354         {
355           int j;
356           j= width/4 + ((width%4)?1:0) + 1;
357           while (j)
358             {
359               con->dd_printf(" ");
360               j--;
361             }
362           i++;
363         }
364       for (i= 0; (i < bpl) &&
365              (start+i < size) &&
366              (start+i <= stop);
367            i++)
368         {
369           long c= get(start+i);
370           con->dd_printf("%c", isprint(255&c)?(255&c):'.');
371           if (width > 8)
372             con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
373           if (width > 16)
374             con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
375           if (width > 24)
376             con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
377         }
378       con->dd_printf("\n");
379       dump_finished= start+i;
380       start+= bpl;
381     }
382   return(dump_finished);
383 }
384
385 t_addr
386 cl_mem::dump(class cl_console *con)
387 {
388   return(dump(dump_finished, dump_finished+10*8-1, 8, con));
389 }
390
391 bool
392 cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr)
393 {
394   t_addr a;
395   int i;
396   bool found;
397
398   if (addr == NULL)
399     a= 0;
400   else
401     a= *addr;
402   
403   if (a+len > size)
404     return(DD_FALSE);
405
406   found= DD_FALSE;
407   while (!found &&
408          a+len <= size)
409     {
410       bool match= DD_TRUE;
411       for (i= 0; i < len && match; i++)
412         {
413           t_mem d1, d2;
414           d1= get(a+i);
415           d2= array[i];
416           if (!case_sensitive)
417             {
418               if (/*d1 < 128*/isalpha(d1))
419                 d1= toupper(d1);
420               if (/*d2 < 128*/isalpha(d2))
421                 d2= toupper(d2);
422             }
423           match= d1 == d2;
424         }
425       found= match;
426       if (!found)
427         a++;
428     }
429
430   if (addr)
431     *addr= a;
432   return(found);
433 }
434
435
436 /*
437  * Bitmap
438  */
439
440 /*cl_bitmap::cl_bitmap(t_addr asize):
441   cl_base()
442 {
443   map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
444   memset(map, 0, size);
445 }
446
447 cl_bitmap::~cl_bitmap(void)
448 {
449   free(map);
450 }
451
452 void
453 cl_bitmap::set(t_addr pos)
454 {
455   int i;
456
457   if ((i= pos/(8*SIZEOF_CHAR)) < size)
458     map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
459 }
460
461 void
462 cl_bitmap::clear(t_addr pos)
463 {
464   int i;
465
466   if ((i= pos/(8*SIZEOF_CHAR)) < size)
467     map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
468 }
469
470 bool
471 cl_bitmap::get(t_addr pos)
472 {
473   return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
474 }
475
476 bool
477 cl_bitmap::empty(void)
478 {
479   int i;
480
481   for (i= 0; i < size && map[i] == 0; i++) ;
482   return(i == size);
483 }*/
484
485 /*
486  * Special memory for code (ROM)
487  */
488
489 /*cl_rom::cl_rom(t_addr asize, int awidth, class cl_uc *auc):
490   cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth, auc)
491 {
492   bp_map= new cl_bitmap(asize);
493   inst_map= new cl_bitmap(asize);
494 }
495
496 cl_rom::~cl_rom(void)
497 {
498   delete bp_map;
499   delete inst_map;
500 }*/
501
502
503 /*
504  * New type of memory simulation
505  */
506
507 cl_normal_cell::cl_normal_cell(uchar awidth):
508   cl_cell()
509 {
510   type= CELL_NORMAL;
511   data= 0;
512   mask= 1;
513   width= awidth;
514   for (--awidth; awidth; awidth--)
515     {
516       mask<<= 1;
517       mask|= 1;
518     }
519 }
520
521 t_mem
522 cl_normal_cell::add(long what)
523 {
524   t_mem d;
525   
526   if (width <= 8)
527     d= TYPE_BYTE(data) + what;
528   else if (width <= 16)
529     d= TYPE_WORD(data) + what;
530   else
531     d= TYPE_DWORD(data) + what;
532   return(data= d & mask);
533 }
534
535 t_mem
536 cl_normal_cell::wadd(long what)
537 {
538   t_mem d;
539   
540   if (width <= 8)
541     d= TYPE_BYTE(data) + what;
542   else if (width <= 16)
543     d= TYPE_WORD(data) + what;
544   else
545     d= TYPE_DWORD(data) + what;
546   return(write(d));
547 }
548
549 void
550 cl_normal_cell::set_bit1(t_mem bits)
551 {
552   bits&= mask;
553   data|= bits;
554 }
555
556 void
557 cl_normal_cell::set_bit0(t_mem bits)
558 {
559   bits&= mask;
560   data&= ~bits;
561 }
562
563
564 /*
565  */
566
567 cl_registered_cell::cl_registered_cell(uchar awidth):
568   cl_normal_cell(awidth)
569 {
570   type= CELL_HW_READ | CELL_HW_WRITE;
571   //hws= new cl_list(1, 1);
572   hardwares= 0;
573   nuof_hws= 0;
574 }
575
576 cl_registered_cell::~cl_registered_cell(void)
577 {
578   if (hardwares)
579     free(hardwares);
580 }
581
582 /*void
583 cl_registered_cell::destroy(void)
584 {
585   hardwares= 0;
586   nuof_hws= 0;
587 }*/
588
589 t_mem
590 cl_registered_cell::read(void)
591 {
592   int i;
593   t_mem d= data;
594
595   if (nuof_hws)
596     for (i= 0; i < nuof_hws; i++)
597       {
598         d= hardwares[i]->read(this);
599         ;
600       }
601   return(d & mask);
602 }
603
604 t_mem
605 cl_registered_cell::read(enum hw_cath skip)
606 {
607   int i;
608   t_mem d= data;
609
610   if (nuof_hws)
611     for (i= 0; i < nuof_hws; i++)
612       {
613         if ((skip & hardwares[i]->cathegory) == 0)
614           d= hardwares[i]->read(this);
615         ;
616       }
617   return(d & mask);
618 }
619
620 t_mem
621 cl_registered_cell::write(t_mem val)
622 {
623   int i;
624
625   val&= mask;
626   if (nuof_hws)
627     for (i= 0; i < nuof_hws; i++)
628       {
629         hardwares[i]->write(this, &val);
630         ;
631       }
632   return(data= val & mask);
633 }
634
635 class cl_cell *
636 cl_registered_cell::add_hw(class cl_hw *hw, int *ith)
637 {
638   if (!hw)
639     {
640       /* Whatta hell!? */
641       return(0);
642     }
643   if (!hardwares)
644     hardwares= (class cl_hw **)malloc(sizeof(class cl_hw *));
645   else
646     hardwares= (class cl_hw **)realloc(hardwares,
647                                        sizeof(class c_hw *) * (nuof_hws+1));
648   hardwares[nuof_hws]= hw;
649   nuof_hws++;
650   if (ith)
651     *ith= nuof_hws-1;
652   return(this);
653 }
654
655 class cl_hw *
656 cl_registered_cell::get_hw(int ith)
657 {
658   if (ith >= nuof_hws)
659     return(0);
660   return(hardwares[ith]);
661 }
662
663
664 /*
665  */
666
667 cl_event_handler::cl_event_handler(class cl_uc *auc):
668   cl_base()
669 {
670   uc= auc;
671   read_bps= new cl_list(1, 1);
672   write_bps= new cl_list(1, 1);
673 }
674
675 cl_event_handler::~cl_event_handler(void)
676 {
677   read_bps->disconn_all();
678   write_bps->disconn_all();
679   delete read_bps;
680   delete write_bps;
681 }
682
683 void
684 cl_event_handler::write(void)
685 {
686   int i;
687
688   for (i= 0; i < write_bps->count; i++)
689     {
690       class cl_brk *bp= (class cl_brk *)(write_bps->at(i));
691       uc->events->add(bp);
692     }
693 }
694
695 void
696 cl_event_handler::read(void)
697 {
698   int i;
699
700   for (i= 0; i < read_bps->count; i++)
701     {
702       class cl_brk *bp= (class cl_brk *)(read_bps->at(i));
703       uc->events->add(bp);
704     }
705 }
706
707 int
708 cl_event_handler::add_bp(class cl_brk *bp)
709 {
710   int t= CELL_NORMAL;
711
712   if (!bp)
713     return(CELL_NORMAL);
714   switch (bp->get_event())
715     {
716     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
717       t|= CELL_WRITE_BRK;
718       write_bps->add(bp);
719       break;
720     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
721       t|= CELL_READ_BRK;
722       read_bps->add(bp);
723       break;
724     default:
725       t|= CELL_READ_BRK | CELL_WRITE_BRK;
726       read_bps->add(bp);
727       write_bps->add(bp);
728       break;
729     }
730   return(t);
731 }
732
733 int
734 cl_event_handler::copy_from(class cl_event_handler *eh)
735 {
736   int i, t= CELL_NORMAL;
737   
738   if (!eh)
739     return(t);
740   for (i= 0; i < eh->read_bps->count; i++)
741     {
742       class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i));
743       t|= add_bp(bp);
744     }
745   for (i= 0; i < eh->write_bps->count; i++)
746     {
747       class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i));
748       t|= add_bp(bp);
749     }
750   return(t);
751 }
752
753 int
754 cl_event_handler::del_bp(class cl_brk *bp)
755 {
756   int t= CELL_NORMAL;
757
758   write_bps->disconn(bp);
759   read_bps->disconn(bp);
760   if (write_bps->count)
761     t|= CELL_WRITE_BRK;
762   if (read_bps->count)
763     t|= CELL_READ_BRK;
764   return(t);
765 }
766
767
768 /*
769  */
770
771 cl_event_cell::cl_event_cell(uchar awidth, class cl_uc *auc):
772   cl_normal_cell(awidth)
773 {
774   eh= new cl_event_handler(auc);
775 }
776
777 cl_event_cell::~cl_event_cell(void)
778 {
779   delete eh;
780 }
781
782 t_mem
783 cl_event_cell::read(void)
784 {
785   if (type & CELL_READ_BRK)
786     eh->read();
787   return(cl_normal_cell::read());
788 }
789
790 t_mem
791 cl_event_cell::write(t_mem val)
792 {
793   if (type & CELL_WRITE_BRK)
794     eh->write();
795   return(cl_normal_cell::write(val));
796 }
797
798
799 /*
800  */
801
802 cl_ev_reg_cell::cl_ev_reg_cell(uchar awidth, class cl_uc *auc):
803   cl_registered_cell(awidth)
804 {
805   eh= new cl_event_handler(auc);
806 }
807
808 cl_ev_reg_cell::~cl_ev_reg_cell(void)
809 {}
810
811 t_mem
812 cl_ev_reg_cell::read(void)
813 {
814   if (type & CELL_READ_BRK)
815     eh->read();
816   return(cl_registered_cell::read());
817 }
818
819 t_mem
820 cl_ev_reg_cell::write(t_mem val)
821 {
822   if (type & CELL_WRITE_BRK)
823     eh->write();
824   return(cl_registered_cell::write(val));
825 }
826
827
828 /*
829  */
830
831 cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell)
832 {
833   real_cell= realcell;
834 }
835
836 cl_mapped_cell::~cl_mapped_cell(void)
837 {}
838
839 t_mem
840 cl_mapped_cell::read(void)
841 {
842   return(real_cell->read());
843 }
844
845 t_mem
846 cl_mapped_cell::read(enum hw_cath skip)
847 {
848   return(real_cell->read(skip));
849 }
850
851 t_mem
852 cl_mapped_cell::get(void)
853 {
854   return(real_cell->get());
855 }
856
857 t_mem
858 cl_mapped_cell::write(t_mem val)
859 {
860   return(real_cell->write(val));
861 }
862
863 t_mem
864 cl_mapped_cell::set(t_mem val)
865 {
866   return(real_cell->set(val));
867 }
868
869 t_mem
870 cl_mapped_cell::add(long what)
871 {
872   return(real_cell->add(what));
873 }
874
875 t_mem
876 cl_mapped_cell::wadd(long what)
877 {
878   return(real_cell->wadd(what));
879 }
880
881 void
882 cl_mapped_cell::set_bit1(t_mem bits)
883 {
884   return(real_cell->set_bit1(bits));
885 }
886
887 void
888 cl_mapped_cell::set_bit0(t_mem bits)
889 {
890   return(real_cell->set_bit0(bits));
891 }
892
893 class cl_cell *
894 cl_mapped_cell::add_hw(class cl_hw *hw, int *ith)
895 {
896   return(real_cell->add_hw(hw, ith));
897 }
898
899 class cl_hw *
900 cl_mapped_cell::get_hw(int ith)
901 {
902   return(real_cell->get_hw(ith));
903 }
904
905 class cl_event_handler *
906 cl_mapped_cell::get_event_handler(void)
907 {
908   return(real_cell->get_event_handler());
909 }
910
911
912 /*
913  */
914
915 cl_m::cl_m(enum mem_class atype, char *aclass_name, t_addr asize, int awidth,
916            class cl_uc *auc):
917   cl_mem(atype, aclass_name, 0, awidth, auc)
918 {
919   t_addr a;
920
921   size= asize;
922   width= awidth;
923   array= (class cl_cell **)calloc(size, sizeof(class cl_cell *));
924   for (a= 0; a < size; a++)
925     array[a]= new cl_normal_cell(width);
926   bus_mask= 0;
927   t_addr i;
928   for (i= 1; i < size; i<<=1)
929     bus_mask= (bus_mask<<1)|1;
930   dummy= new cl_normal_cell(width);
931   //mk_cell(size, 0);
932 }
933
934 cl_m::~cl_m(void)
935 {
936   t_addr a;
937
938   for (a= 0; a < size; a++)
939     delete array[a];
940   free(array);
941   delete dummy;
942 }
943
944 void
945 cl_m::err_inv_addr(t_addr addr)
946 {
947   if (!uc)
948     return;
949   class cl_error *e= new cl_err_inv_addr(this, addr);
950   uc->error(e);
951 }
952
953 /*void
954 cl_m::mk_cell(t_addr addr, class cl_cell *cell)
955 {
956   if (!cell)
957     cell= new cl_cell(width);
958   class cl_cell *p;
959   if (addr >= size)
960     p= dummy;
961   else
962     p= array[addr];
963   if (p == 0)
964     {
965       p= (class cl_cell *)calloc(1, sizeof(*cell));
966     }
967   else
968     {
969       p->destroy();
970       p= (class cl_cell *)realloc(p, sizeof(cell));
971     }
972   memcpy(p, cell, sizeof(*cell));
973   cell->destroy();
974   delete cell;
975 }*/
976
977 int
978 cl_m::get_cell_flag(t_addr addr)
979 {
980   if (addr >= size)
981     {
982       return(dummy->get_type());
983     }
984   return(array[addr]->get_type());
985 }
986
987 bool
988 cl_m::get_cell_flag(t_addr addr, int flag)
989 {
990   if (addr >= size)
991     {
992       return(dummy->get_type() & flag);
993     }
994   return(array[addr]->get_type() & flag);
995 }
996
997 void
998 cl_m::set_cell_flag(t_addr addr, bool set_to, int flag)
999 {
1000   class cl_cell *cell;
1001   
1002   if (addr >= size)
1003     {
1004       cell= dummy;
1005     }
1006   else
1007     cell= array[addr];
1008   if (set_to)
1009     cell->set_type(cell->get_type() | flag);
1010   else
1011     cell->set_type(cell->get_type() & ~flag);
1012 }
1013
1014 t_mem
1015 cl_m::read(t_addr addr)
1016 {
1017   //addr&= bus_mask;
1018   if (addr >= size)
1019     {
1020       err_inv_addr(addr);
1021       return(dummy->read());
1022     }
1023   return(array[addr]->read());
1024 }
1025
1026 t_mem
1027 cl_m::read(t_addr addr, enum hw_cath skip)
1028 {
1029   //addr&= bus_mask;
1030   if (addr >= size)
1031     {
1032       err_inv_addr(addr);
1033       return(dummy->read(skip));
1034     }
1035   return(array[addr]->read(skip));
1036 }
1037
1038 t_mem
1039 cl_m::get(t_addr addr)
1040 {
1041   addr&= bus_mask;
1042   if (addr >= size)
1043     {
1044       err_inv_addr(addr);
1045       return(dummy->get());
1046     }
1047   return(array[addr]->get());
1048 }
1049
1050 t_mem
1051 cl_m::write(t_addr addr, t_mem val)
1052 {
1053   //addr&= bus_mask;
1054   if (addr >= size)
1055     {
1056       err_inv_addr(addr);
1057       return(dummy->write(val));
1058     }
1059   return(array[addr]->write(val));
1060 }
1061
1062 void
1063 cl_m::set(t_addr addr, t_mem val)
1064 {
1065   if (addr >= size)
1066     {
1067       err_inv_addr(addr);
1068       //addr&= bus_mask;
1069       dummy->set(val);
1070       return;
1071     }
1072   //addr&= bus_mask;
1073   array[addr]->set(val);
1074 }
1075
1076 class cl_cell *
1077 cl_m::get_cell(t_addr addr)
1078 {
1079   //addr&= bus_mask;
1080   if (addr >= size)
1081     {
1082       err_inv_addr(addr);
1083       return(dummy);
1084     }
1085   return(array[addr]);
1086 }
1087
1088
1089 /* Set or clear bits, without callbacks */
1090
1091 void
1092 cl_m::set_bit1(t_addr addr, t_mem bits)
1093 {
1094   class cl_cell *cell;
1095
1096   addr&= bus_mask;
1097   if (addr >= size)
1098     {
1099       err_inv_addr(addr);
1100       cell= dummy;
1101     }
1102   else
1103     cell= array[addr];
1104   bits&= cell->get_mask();
1105   cell->set(cell->get() | bits);
1106 }
1107
1108 void
1109 cl_m::write_bit1(t_addr addr, t_mem bits)
1110 {
1111   class cl_cell *cell;
1112
1113   addr&= bus_mask;
1114   if (addr >= size)
1115     {
1116       err_inv_addr(addr);
1117       cell= dummy;
1118     }
1119   else
1120     cell= array[addr];
1121   bits&= cell->get_mask();
1122   cell->write(cell->get() | bits);
1123 }
1124
1125 void
1126 cl_m::set_bit0(t_addr addr, t_mem bits)
1127 {
1128   class cl_cell *cell;
1129
1130   addr&= bus_mask;
1131   if (addr >= size)
1132     {
1133       err_inv_addr(addr);
1134       cell= dummy;
1135     }
1136   else
1137     cell= array[addr];
1138   bits&= cell->get_mask();
1139   cell->set(cell->get() & ~bits);
1140 }
1141
1142 void
1143 cl_m::write_bit0(t_addr addr, t_mem bits)
1144 {
1145   class cl_cell *cell;
1146
1147   addr&= bus_mask;
1148   if (addr >= size)
1149     {
1150       err_inv_addr(addr);
1151       cell =dummy;
1152     }
1153   else
1154     cell= array[addr];
1155   bits&= cell->get_mask();
1156   cell->write(cell->get() & ~bits);
1157 }
1158
1159 t_mem
1160 cl_m::add(t_addr addr, long what)
1161 {
1162   addr&= bus_mask;
1163   if (addr >= size)
1164     {
1165       err_inv_addr(addr);
1166       return(dummy->add(what));
1167     }
1168   return(array[addr]->add(what));
1169 }
1170
1171 t_mem
1172 cl_m::wadd(t_addr addr, long what)
1173 {
1174   addr&= bus_mask;
1175   if (addr >= size)
1176     {
1177       err_inv_addr(addr);
1178       return(dummy->wadd(what));
1179     }
1180   return(array[addr]->wadd(what));
1181 }
1182
1183 class cl_cell *
1184 cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce)
1185 {
1186   class cl_cell *cell, *nc;
1187
1188   addr&= bus_mask;
1189   if (addr >= size)
1190     cell= dummy;
1191   else
1192     cell= array[addr];
1193
1194   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1195     {
1196       /* Already registered */
1197       return(cell->add_hw(hw, ith));
1198     }
1199   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1200     {
1201       /* Event break is set on it, now register hw */
1202       nc= new cl_ev_reg_cell(width, uc);
1203       nc->set(cell->get());
1204       nc->set_type(nc->get_type() &
1205                    ~(CELL_GENERAL|CELL_READ_BRK|CELL_WRITE_BRK));
1206       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1207       class cl_event_handler *eh= nc->get_event_handler();
1208       if (eh)
1209         nc->set_type(nc->get_type() | eh->copy_from(cell->get_event_handler()));
1210       nc->add_hw(hw, ith);
1211     }
1212   else
1213     {
1214       /* Normal cell, register hw */
1215       nc= new cl_registered_cell(width);
1216       nc->set(cell->get());
1217       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1218       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1219       nc->add_hw(hw, ith);
1220     }
1221
1222   if (addr >= size)
1223     {
1224       delete dummy;
1225       dummy= nc;  
1226     }
1227   else
1228     {
1229       delete array[addr];
1230       array[addr]= nc;
1231     }
1232   if (announce)
1233     uc->sim->/*app->*/mem_cell_changed(this, addr);
1234   return(nc);
1235 }
1236
1237 void
1238 cl_m::set_brk(t_addr addr, class cl_brk *brk)
1239 {
1240   class cl_cell *cell, *nc;
1241   char e= '_';
1242
1243   addr&= bus_mask;
1244   if (addr >= size)
1245     cell= dummy;
1246   else
1247     cell= array[addr];
1248
1249   switch (brk->get_event())
1250     {
1251     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1252       e= 'W';
1253       break;
1254     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1255       e= 'R';
1256       break;
1257     case brkNONE:
1258       set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
1259       return;
1260       break;
1261     default: e= '.'; break;       
1262     }
1263   
1264   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1265     {
1266       /* Hw is registered on it, now set event break */
1267       nc= new cl_ev_reg_cell(width, uc);
1268       nc->set(cell->get());
1269       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1270       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1271       int i= 0;
1272       class cl_hw *hw;
1273       while ((hw= cell->get_hw(i)) != 0)
1274         {
1275           nc->add_hw(hw, 0);
1276           i++;
1277         }
1278       if (((class cl_registered_cell *)cell)->hardwares)
1279         {
1280           free(((class cl_registered_cell *)cell)->hardwares);
1281           ((class cl_registered_cell *)cell)->hardwares= 0;
1282         }
1283       class cl_event_handler *eh;
1284       if ((eh= nc->get_event_handler()))
1285         nc->set_type(nc->get_type() | eh->add_bp(brk));
1286     }
1287   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1288     {
1289       /* Break is already set on it */
1290       class cl_event_handler *eh;
1291       if ((eh= cell->get_event_handler()))
1292         cell->set_type(cell->get_type() | eh->add_bp(brk));
1293       return;
1294     }
1295   else
1296     {
1297       /* Normal cell, set event break */
1298       nc= new cl_event_cell(width, uc);
1299       nc->set(cell->get());
1300       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1301       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1302       class cl_event_handler *eh;
1303       if ((eh= nc->get_event_handler()))
1304         nc->set_type(nc->get_type() | eh->add_bp(brk));
1305     }
1306
1307   if (addr >= size)
1308     {
1309       delete dummy;
1310       dummy= nc;
1311     }
1312   else
1313     {
1314       delete array[addr];
1315       array[addr]= nc;
1316     }
1317   uc->sim->/*app->*/mem_cell_changed(this, addr);
1318 }
1319
1320 void
1321 cl_m::del_brk(t_addr addr, class cl_brk *brk)
1322 {
1323   class cl_cell *cell, *nc;
1324   char e= '_';
1325
1326   addr&= bus_mask;
1327   if (addr >= size)
1328     cell= dummy;
1329   else
1330     cell= array[addr];
1331
1332   switch (brk->get_event())
1333     {
1334     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: e= 'W'; break;
1335     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1336       e= 'R';
1337       break;
1338     case brkNONE:
1339       set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
1340       return;
1341       break;
1342     default: e= '.'; break;
1343     }
1344   
1345   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1346     {
1347       /* Hw is registered on it, delete event break */
1348       class cl_event_handler *eh;
1349       int t= CELL_NORMAL;
1350       if ((eh= cell->get_event_handler()))
1351         t= eh->del_bp(brk);
1352       if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1353         {
1354           cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1355           cell->set_type(cell->get_type() | t);
1356           return;
1357         }
1358       nc= new cl_registered_cell(width);
1359       nc->set(cell->get());
1360       nc->set_type(cell->get_type() & ~CELL_GENERAL);
1361       nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1362       int i= 0;
1363       class cl_hw *hw;
1364       while ((hw= cell->get_hw(i)) != 0)
1365         {
1366           nc->add_hw(hw, 0);
1367           i++;
1368         }
1369       if (((class cl_registered_cell *)cell)->hardwares)
1370         free(((class cl_registered_cell *)cell)->hardwares);
1371     }
1372   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1373     {
1374       /* Break already set on it, delete brk */
1375       class cl_event_handler *eh;
1376       int t= CELL_NORMAL;
1377       if ((eh= cell->get_event_handler()))
1378         t= eh->del_bp(brk);
1379       if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1380         {
1381           cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1382           cell->set_type(cell->get_type() | t);
1383           return;
1384         }
1385       nc= new cl_normal_cell(width);
1386       nc->set(cell->get());
1387       nc->set_type(cell->get_type() & ~CELL_GENERAL);
1388       nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1389       return;
1390     }
1391   else
1392     {
1393       /* Normal cell */
1394       return;
1395     }
1396
1397   if (addr >= size)
1398     {
1399       delete dummy;
1400       dummy= nc;
1401     }
1402   else
1403     {
1404       delete array[addr];
1405       array[addr]= nc;
1406     }
1407   uc->sim->/*app->*/mem_cell_changed(this, addr);
1408 }
1409
1410
1411 /*
1412  * Errors in memory handling
1413  */
1414
1415 cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr):
1416   cl_error()
1417 {
1418   mem= amem;
1419   addr= aaddr;
1420 }
1421
1422 void
1423 cl_err_inv_addr::print(class cl_commander *c)
1424 {
1425   c->dd_printf("Error: invalid address ");
1426   c->dd_printf(mem->addr_format, addr);
1427   c->dd_printf(" in memory %s.\n", mem->class_name);
1428 }
1429
1430
1431 /* End of mem.cc */