f47137aaeab01df75949ba0cf10b83f657e58a86
[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_cell::cl_cell(void):
508   cl_base()
509 {
510 #ifdef STATISTIC
511   nuof_writes= nuof_reads= 0;
512 #endif
513 }
514
515
516 cl_normal_cell::cl_normal_cell(uchar awidth):
517   cl_cell()
518 {
519   type= CELL_NORMAL;
520   data= 0;
521   mask= 1;
522   width= awidth;
523   for (--awidth; awidth; awidth--)
524     {
525       mask<<= 1;
526       mask|= 1;
527     }
528 }
529
530 t_mem
531 cl_normal_cell::add(long what)
532 {
533   t_mem d;
534   
535   if (width <= 8)
536     d= TYPE_BYTE(data) + what;
537   else if (width <= 16)
538     d= TYPE_WORD(data) + what;
539   else
540     d= TYPE_DWORD(data) + what;
541   return(data= d & mask);
542 }
543
544 t_mem
545 cl_normal_cell::wadd(long what)
546 {
547   t_mem d;
548   
549   if (width <= 8)
550     d= TYPE_BYTE(data) + what;
551   else if (width <= 16)
552     d= TYPE_WORD(data) + what;
553   else
554     d= TYPE_DWORD(data) + what;
555   return(write(d));
556 }
557
558 void
559 cl_normal_cell::set_bit1(t_mem bits)
560 {
561   bits&= mask;
562   data|= bits;
563 }
564
565 void
566 cl_normal_cell::set_bit0(t_mem bits)
567 {
568   bits&= mask;
569   data&= ~bits;
570 }
571
572
573 /*
574  */
575
576 cl_registered_cell::cl_registered_cell(uchar awidth):
577   cl_normal_cell(awidth)
578 {
579   type= CELL_HW_READ | CELL_HW_WRITE;
580   //hws= new cl_list(1, 1);
581   hardwares= 0;
582   nuof_hws= 0;
583 }
584
585 cl_registered_cell::~cl_registered_cell(void)
586 {
587   if (hardwares)
588     free(hardwares);
589 }
590
591 /*void
592 cl_registered_cell::destroy(void)
593 {
594   hardwares= 0;
595   nuof_hws= 0;
596 }*/
597
598 t_mem
599 cl_registered_cell::read(void)
600 {
601   int i;
602   t_mem d= data;
603
604   if (nuof_hws)
605     for (i= 0; i < nuof_hws; i++)
606       {
607         d= hardwares[i]->read(this);
608         ;
609       }
610 #ifdef STATISTIC
611   nuof_reads++;
612 #endif
613   return(d & mask);
614 }
615
616 t_mem
617 cl_registered_cell::read(enum hw_cath skip)
618 {
619   int i;
620   t_mem d= data;
621
622   if (nuof_hws)
623     for (i= 0; i < nuof_hws; i++)
624       {
625         if ((skip & hardwares[i]->cathegory) == 0)
626           d= hardwares[i]->read(this);
627         ;
628       }
629 #ifdef STATISTIC
630   nuof_reads++;
631 #endif
632   return(d & mask);
633 }
634
635 t_mem
636 cl_registered_cell::write(t_mem val)
637 {
638   int i;
639
640   val&= mask;
641   if (nuof_hws)
642     for (i= 0; i < nuof_hws; i++)
643       {
644         hardwares[i]->write(this, &val);
645         ;
646       }
647 #ifdef STATISTIC
648   nuof_writes++;
649 #endif
650   return(data= val & mask);
651 }
652
653 class cl_cell *
654 cl_registered_cell::add_hw(class cl_hw *hw, int *ith)
655 {
656   if (!hw)
657     {
658       /* Whatta hell!? */
659       return(0);
660     }
661   if (!hardwares)
662     hardwares= (class cl_hw **)malloc(sizeof(class cl_hw *));
663   else
664     hardwares= (class cl_hw **)realloc(hardwares,
665                                        sizeof(class c_hw *) * (nuof_hws+1));
666   hardwares[nuof_hws]= hw;
667   nuof_hws++;
668   if (ith)
669     *ith= nuof_hws-1;
670   return(this);
671 }
672
673 class cl_hw *
674 cl_registered_cell::get_hw(int ith)
675 {
676   if (ith >= nuof_hws)
677     return(0);
678   return(hardwares[ith]);
679 }
680
681
682 /*
683  */
684
685 cl_event_handler::cl_event_handler(class cl_uc *auc):
686   cl_base()
687 {
688   uc= auc;
689   read_bps= new cl_list(1, 1);
690   write_bps= new cl_list(1, 1);
691 }
692
693 cl_event_handler::~cl_event_handler(void)
694 {
695   read_bps->disconn_all();
696   write_bps->disconn_all();
697   delete read_bps;
698   delete write_bps;
699 }
700
701 void
702 cl_event_handler::write(void)
703 {
704   int i;
705
706   for (i= 0; i < write_bps->count; i++)
707     {
708       class cl_brk *bp= (class cl_brk *)(write_bps->at(i));
709       uc->events->add(bp);
710     }
711 }
712
713 void
714 cl_event_handler::read(void)
715 {
716   int i;
717
718   for (i= 0; i < read_bps->count; i++)
719     {
720       class cl_brk *bp= (class cl_brk *)(read_bps->at(i));
721       uc->events->add(bp);
722     }
723 }
724
725 int
726 cl_event_handler::add_bp(class cl_brk *bp)
727 {
728   int t= CELL_NORMAL;
729
730   if (!bp)
731     return(CELL_NORMAL);
732   switch (bp->get_event())
733     {
734     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
735       t|= CELL_WRITE_BRK;
736       write_bps->add(bp);
737       break;
738     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
739       t|= CELL_READ_BRK;
740       read_bps->add(bp);
741       break;
742     default:
743       t|= CELL_READ_BRK | CELL_WRITE_BRK;
744       read_bps->add(bp);
745       write_bps->add(bp);
746       break;
747     }
748   return(t);
749 }
750
751 int
752 cl_event_handler::copy_from(class cl_event_handler *eh)
753 {
754   int i, t= CELL_NORMAL;
755   
756   if (!eh)
757     return(t);
758   for (i= 0; i < eh->read_bps->count; i++)
759     {
760       class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i));
761       t|= add_bp(bp);
762     }
763   for (i= 0; i < eh->write_bps->count; i++)
764     {
765       class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i));
766       t|= add_bp(bp);
767     }
768   return(t);
769 }
770
771 int
772 cl_event_handler::del_bp(class cl_brk *bp)
773 {
774   int t= CELL_NORMAL;
775
776   write_bps->disconn(bp);
777   read_bps->disconn(bp);
778   if (write_bps->count)
779     t|= CELL_WRITE_BRK;
780   if (read_bps->count)
781     t|= CELL_READ_BRK;
782   return(t);
783 }
784
785
786 /*
787  */
788
789 cl_event_cell::cl_event_cell(uchar awidth, class cl_uc *auc):
790   cl_normal_cell(awidth)
791 {
792   eh= new cl_event_handler(auc);
793 }
794
795 cl_event_cell::~cl_event_cell(void)
796 {
797   delete eh;
798 }
799
800 t_mem
801 cl_event_cell::read(void)
802 {
803   if (type & CELL_READ_BRK)
804     eh->read();
805   return(cl_normal_cell::read());
806 }
807
808 t_mem
809 cl_event_cell::write(t_mem val)
810 {
811   if (type & CELL_WRITE_BRK)
812     eh->write();
813   return(cl_normal_cell::write(val));
814 }
815
816
817 /*
818  */
819
820 cl_ev_reg_cell::cl_ev_reg_cell(uchar awidth, class cl_uc *auc):
821   cl_registered_cell(awidth)
822 {
823   eh= new cl_event_handler(auc);
824 }
825
826 cl_ev_reg_cell::~cl_ev_reg_cell(void)
827 {}
828
829 t_mem
830 cl_ev_reg_cell::read(void)
831 {
832   if (type & CELL_READ_BRK)
833     eh->read();
834   return(cl_registered_cell::read());
835 }
836
837 t_mem
838 cl_ev_reg_cell::write(t_mem val)
839 {
840   if (type & CELL_WRITE_BRK)
841     eh->write();
842   return(cl_registered_cell::write(val));
843 }
844
845
846 /*
847  */
848
849 cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell)
850 {
851   real_cell= realcell;
852 }
853
854 cl_mapped_cell::~cl_mapped_cell(void)
855 {}
856
857 t_mem
858 cl_mapped_cell::read(void)
859 {
860   return(real_cell->read());
861 }
862
863 t_mem
864 cl_mapped_cell::read(enum hw_cath skip)
865 {
866   return(real_cell->read(skip));
867 }
868
869 t_mem
870 cl_mapped_cell::get(void)
871 {
872   return(real_cell->get());
873 }
874
875 t_mem
876 cl_mapped_cell::write(t_mem val)
877 {
878   return(real_cell->write(val));
879 }
880
881 t_mem
882 cl_mapped_cell::set(t_mem val)
883 {
884   return(real_cell->set(val));
885 }
886
887 t_mem
888 cl_mapped_cell::add(long what)
889 {
890   return(real_cell->add(what));
891 }
892
893 t_mem
894 cl_mapped_cell::wadd(long what)
895 {
896   return(real_cell->wadd(what));
897 }
898
899 void
900 cl_mapped_cell::set_bit1(t_mem bits)
901 {
902   return(real_cell->set_bit1(bits));
903 }
904
905 void
906 cl_mapped_cell::set_bit0(t_mem bits)
907 {
908   return(real_cell->set_bit0(bits));
909 }
910
911 class cl_cell *
912 cl_mapped_cell::add_hw(class cl_hw *hw, int *ith)
913 {
914   return(real_cell->add_hw(hw, ith));
915 }
916
917 class cl_hw *
918 cl_mapped_cell::get_hw(int ith)
919 {
920   return(real_cell->get_hw(ith));
921 }
922
923 class cl_event_handler *
924 cl_mapped_cell::get_event_handler(void)
925 {
926   return(real_cell->get_event_handler());
927 }
928
929
930 /*
931  */
932
933 cl_m::cl_m(enum mem_class atype, char *aclass_name, t_addr asize, int awidth,
934            class cl_uc *auc):
935   cl_mem(atype, aclass_name, 0, awidth, auc)
936 {
937   t_addr a;
938
939   size= asize;
940   width= awidth;
941   array= (class cl_cell **)calloc(size, sizeof(class cl_cell *));
942   for (a= 0; a < size; a++)
943     array[a]= new cl_normal_cell(width);
944   bus_mask= 0;
945   t_addr i;
946   for (i= 1; i < size; i<<=1)
947     bus_mask= (bus_mask<<1)|1;
948   dummy= new cl_normal_cell(width);
949   //mk_cell(size, 0);
950 }
951
952 cl_m::~cl_m(void)
953 {
954   t_addr a;
955
956   for (a= 0; a < size; a++)
957     delete array[a];
958   free(array);
959   delete dummy;
960 }
961
962 void
963 cl_m::err_inv_addr(t_addr addr)
964 {
965   if (!uc)
966     return;
967   class cl_error *e= new cl_err_inv_addr(this, addr);
968   uc->error(e);
969 }
970
971 /*void
972 cl_m::mk_cell(t_addr addr, class cl_cell *cell)
973 {
974   if (!cell)
975     cell= new cl_cell(width);
976   class cl_cell *p;
977   if (addr >= size)
978     p= dummy;
979   else
980     p= array[addr];
981   if (p == 0)
982     {
983       p= (class cl_cell *)calloc(1, sizeof(*cell));
984     }
985   else
986     {
987       p->destroy();
988       p= (class cl_cell *)realloc(p, sizeof(cell));
989     }
990   memcpy(p, cell, sizeof(*cell));
991   cell->destroy();
992   delete cell;
993 }*/
994
995 int
996 cl_m::get_cell_flag(t_addr addr)
997 {
998   if (addr >= size)
999     {
1000       return(dummy->get_type());
1001     }
1002   return(array[addr]->get_type());
1003 }
1004
1005 bool
1006 cl_m::get_cell_flag(t_addr addr, int flag)
1007 {
1008   if (addr >= size)
1009     {
1010       return(dummy->get_type() & flag);
1011     }
1012   return(array[addr]->get_type() & flag);
1013 }
1014
1015 void
1016 cl_m::set_cell_flag(t_addr addr, bool set_to, int flag)
1017 {
1018   class cl_cell *cell;
1019   
1020   if (addr >= size)
1021     {
1022       cell= dummy;
1023     }
1024   else
1025     cell= array[addr];
1026   if (set_to)
1027     cell->set_type(cell->get_type() | flag);
1028   else
1029     cell->set_type(cell->get_type() & ~flag);
1030 }
1031
1032 t_mem
1033 cl_m::read(t_addr addr)
1034 {
1035   //addr&= bus_mask;
1036   if (addr >= size)
1037     {
1038       err_inv_addr(addr);
1039       return(dummy->read());
1040     }
1041   return(array[addr]->read());
1042 }
1043
1044 t_mem
1045 cl_m::read(t_addr addr, enum hw_cath skip)
1046 {
1047   //addr&= bus_mask;
1048   if (addr >= size)
1049     {
1050       err_inv_addr(addr);
1051       return(dummy->read(skip));
1052     }
1053   return(array[addr]->read(skip));
1054 }
1055
1056 t_mem
1057 cl_m::get(t_addr addr)
1058 {
1059   addr&= bus_mask;
1060   if (addr >= size)
1061     {
1062       err_inv_addr(addr);
1063       return(dummy->get());
1064     }
1065   return(array[addr]->get());
1066 }
1067
1068 t_mem
1069 cl_m::write(t_addr addr, t_mem val)
1070 {
1071   //addr&= bus_mask;
1072   if (addr >= size)
1073     {
1074       err_inv_addr(addr);
1075       return(dummy->write(val));
1076     }
1077   return(array[addr]->write(val));
1078 }
1079
1080 void
1081 cl_m::set(t_addr addr, t_mem val)
1082 {
1083   if (addr >= size)
1084     {
1085       err_inv_addr(addr);
1086       //addr&= bus_mask;
1087       dummy->set(val);
1088       return;
1089     }
1090   //addr&= bus_mask;
1091   array[addr]->set(val);
1092 }
1093
1094 class cl_cell *
1095 cl_m::get_cell(t_addr addr)
1096 {
1097   //addr&= bus_mask;
1098   if (addr >= size)
1099     {
1100       err_inv_addr(addr);
1101       return(dummy);
1102     }
1103   return(array[addr]);
1104 }
1105
1106
1107 /* Set or clear bits, without callbacks */
1108
1109 void
1110 cl_m::set_bit1(t_addr addr, t_mem bits)
1111 {
1112   class cl_cell *cell;
1113
1114   addr&= bus_mask;
1115   if (addr >= size)
1116     {
1117       err_inv_addr(addr);
1118       cell= dummy;
1119     }
1120   else
1121     cell= array[addr];
1122   bits&= cell->get_mask();
1123   cell->set(cell->get() | bits);
1124 }
1125
1126 void
1127 cl_m::write_bit1(t_addr addr, t_mem bits)
1128 {
1129   class cl_cell *cell;
1130
1131   addr&= bus_mask;
1132   if (addr >= size)
1133     {
1134       err_inv_addr(addr);
1135       cell= dummy;
1136     }
1137   else
1138     cell= array[addr];
1139   bits&= cell->get_mask();
1140   cell->write(cell->get() | bits);
1141 }
1142
1143 void
1144 cl_m::set_bit0(t_addr addr, t_mem bits)
1145 {
1146   class cl_cell *cell;
1147
1148   addr&= bus_mask;
1149   if (addr >= size)
1150     {
1151       err_inv_addr(addr);
1152       cell= dummy;
1153     }
1154   else
1155     cell= array[addr];
1156   bits&= cell->get_mask();
1157   cell->set(cell->get() & ~bits);
1158 }
1159
1160 void
1161 cl_m::write_bit0(t_addr addr, t_mem bits)
1162 {
1163   class cl_cell *cell;
1164
1165   addr&= bus_mask;
1166   if (addr >= size)
1167     {
1168       err_inv_addr(addr);
1169       cell =dummy;
1170     }
1171   else
1172     cell= array[addr];
1173   bits&= cell->get_mask();
1174   cell->write(cell->get() & ~bits);
1175 }
1176
1177 t_mem
1178 cl_m::add(t_addr addr, long what)
1179 {
1180   addr&= bus_mask;
1181   if (addr >= size)
1182     {
1183       err_inv_addr(addr);
1184       return(dummy->add(what));
1185     }
1186   return(array[addr]->add(what));
1187 }
1188
1189 t_mem
1190 cl_m::wadd(t_addr addr, long what)
1191 {
1192   addr&= bus_mask;
1193   if (addr >= size)
1194     {
1195       err_inv_addr(addr);
1196       return(dummy->wadd(what));
1197     }
1198   return(array[addr]->wadd(what));
1199 }
1200
1201 class cl_cell *
1202 cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce)
1203 {
1204   class cl_cell *cell, *nc;
1205
1206   addr&= bus_mask;
1207   if (addr >= size)
1208     cell= dummy;
1209   else
1210     cell= array[addr];
1211
1212   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1213     {
1214       /* Already registered */
1215       return(cell->add_hw(hw, ith));
1216     }
1217   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1218     {
1219       /* Event break is set on it, now register hw */
1220       nc= new cl_ev_reg_cell(width, uc);
1221       nc->set(cell->get());
1222       nc->set_type(nc->get_type() &
1223                    ~(CELL_GENERAL|CELL_READ_BRK|CELL_WRITE_BRK));
1224       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1225       class cl_event_handler *eh= nc->get_event_handler();
1226       if (eh)
1227         nc->set_type(nc->get_type() | eh->copy_from(cell->get_event_handler()));
1228       nc->add_hw(hw, ith);
1229     }
1230   else
1231     {
1232       /* Normal cell, register hw */
1233       nc= new cl_registered_cell(width);
1234       nc->set(cell->get());
1235       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1236       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1237       nc->add_hw(hw, ith);
1238     }
1239
1240   if (addr >= size)
1241     {
1242       delete dummy;
1243       dummy= nc;  
1244     }
1245   else
1246     {
1247       delete array[addr];
1248       array[addr]= nc;
1249     }
1250   if (announce)
1251     uc->sim->/*app->*/mem_cell_changed(this, addr);
1252   return(nc);
1253 }
1254
1255 void
1256 cl_m::set_brk(t_addr addr, class cl_brk *brk)
1257 {
1258   class cl_cell *cell, *nc;
1259   char e= '_';
1260
1261   addr&= bus_mask;
1262   if (addr >= size)
1263     cell= dummy;
1264   else
1265     cell= array[addr];
1266
1267   switch (brk->get_event())
1268     {
1269     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1270       e= 'W';
1271       break;
1272     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1273       e= 'R';
1274       break;
1275     case brkNONE:
1276       set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
1277       return;
1278       break;
1279     default: e= '.'; break;       
1280     }
1281   
1282   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1283     {
1284       /* Hw is registered on it, now set event break */
1285       nc= new cl_ev_reg_cell(width, uc);
1286       nc->set(cell->get());
1287       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1288       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1289       int i= 0;
1290       class cl_hw *hw;
1291       while ((hw= cell->get_hw(i)) != 0)
1292         {
1293           nc->add_hw(hw, 0);
1294           i++;
1295         }
1296       if (((class cl_registered_cell *)cell)->hardwares)
1297         {
1298           free(((class cl_registered_cell *)cell)->hardwares);
1299           ((class cl_registered_cell *)cell)->hardwares= 0;
1300         }
1301       class cl_event_handler *eh;
1302       if ((eh= nc->get_event_handler()))
1303         nc->set_type(nc->get_type() | eh->add_bp(brk));
1304     }
1305   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1306     {
1307       /* Break is already set on it */
1308       class cl_event_handler *eh;
1309       if ((eh= cell->get_event_handler()))
1310         cell->set_type(cell->get_type() | eh->add_bp(brk));
1311       return;
1312     }
1313   else
1314     {
1315       /* Normal cell, set event break */
1316       nc= new cl_event_cell(width, uc);
1317       nc->set(cell->get());
1318       nc->set_type(nc->get_type() & ~CELL_GENERAL);
1319       nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1320       class cl_event_handler *eh;
1321       if ((eh= nc->get_event_handler()))
1322         nc->set_type(nc->get_type() | eh->add_bp(brk));
1323     }
1324
1325   if (addr >= size)
1326     {
1327       delete dummy;
1328       dummy= nc;
1329     }
1330   else
1331     {
1332       delete array[addr];
1333       array[addr]= nc;
1334     }
1335   uc->sim->/*app->*/mem_cell_changed(this, addr);
1336 }
1337
1338 void
1339 cl_m::del_brk(t_addr addr, class cl_brk *brk)
1340 {
1341   class cl_cell *cell, *nc;
1342   char e= '_';
1343
1344   addr&= bus_mask;
1345   if (addr >= size)
1346     cell= dummy;
1347   else
1348     cell= array[addr];
1349
1350   switch (brk->get_event())
1351     {
1352     case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: e= 'W'; break;
1353     case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1354       e= 'R';
1355       break;
1356     case brkNONE:
1357       set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
1358       return;
1359       break;
1360     default: e= '.'; break;
1361     }
1362   
1363   if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1364     {
1365       /* Hw is registered on it, delete event break */
1366       class cl_event_handler *eh;
1367       int t= CELL_NORMAL;
1368       if ((eh= cell->get_event_handler()))
1369         t= eh->del_bp(brk);
1370       if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1371         {
1372           cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1373           cell->set_type(cell->get_type() | t);
1374           return;
1375         }
1376       nc= new cl_registered_cell(width);
1377       nc->set(cell->get());
1378       nc->set_type(cell->get_type() & ~CELL_GENERAL);
1379       nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1380       int i= 0;
1381       class cl_hw *hw;
1382       while ((hw= cell->get_hw(i)) != 0)
1383         {
1384           nc->add_hw(hw, 0);
1385           i++;
1386         }
1387       if (((class cl_registered_cell *)cell)->hardwares)
1388         free(((class cl_registered_cell *)cell)->hardwares);
1389     }
1390   else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1391     {
1392       /* Break already set on it, delete brk */
1393       class cl_event_handler *eh;
1394       int t= CELL_NORMAL;
1395       if ((eh= cell->get_event_handler()))
1396         t= eh->del_bp(brk);
1397       if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1398         {
1399           cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1400           cell->set_type(cell->get_type() | t);
1401           return;
1402         }
1403       nc= new cl_normal_cell(width);
1404       nc->set(cell->get());
1405       nc->set_type(cell->get_type() & ~CELL_GENERAL);
1406       nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1407       return;
1408     }
1409   else
1410     {
1411       /* Normal cell */
1412       return;
1413     }
1414
1415   if (addr >= size)
1416     {
1417       delete dummy;
1418       dummy= nc;
1419     }
1420   else
1421     {
1422       delete array[addr];
1423       array[addr]= nc;
1424     }
1425   uc->sim->/*app->*/mem_cell_changed(this, addr);
1426 }
1427
1428
1429 #ifdef STATISTIC
1430 unsigned long
1431 cl_m::get_nuof_reads(void)
1432 {
1433   unsigned long res= 0;
1434   t_addr i;
1435   for (i= 0; i < size; i++)
1436     res+= array[i]->nuof_reads;
1437   return(res);
1438 }
1439
1440 unsigned long
1441 cl_m::get_nuof_writes(void)
1442 {
1443   unsigned long res= 0;
1444   t_addr i;
1445   for (i= 0; i < size; i++)
1446     res+= array[i]->nuof_writes;
1447   return(res);
1448 }
1449
1450 void
1451 cl_m::set_nuof_reads(unsigned long value)
1452 {
1453   t_addr i;
1454   for (i= 0; i < size; i++)
1455     array[i]->nuof_reads= value;
1456   dummy->nuof_reads= value;
1457 }
1458
1459 void
1460 cl_m::set_nuof_writes(unsigned long value)
1461 {
1462   t_addr i;
1463   for (i= 0; i < size; i++)
1464     array[i]->nuof_writes= value;
1465   dummy->nuof_writes= value;
1466 }
1467 #endif
1468
1469
1470 /*
1471  * Errors in memory handling
1472  */
1473
1474 cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr):
1475   cl_error()
1476 {
1477   mem= amem;
1478   addr= aaddr;
1479 }
1480
1481 void
1482 cl_err_inv_addr::print(class cl_commander *c)
1483 {
1484   c->dd_printf("Error: invalid address ");
1485   c->dd_printf(mem->addr_format, addr);
1486   c->dd_printf(" in memory %s.\n", mem->class_name);
1487 }
1488
1489
1490 /* End of mem.cc */