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