fix printf is a macro in gcc 3
[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 // cmd
38 #include "newcmdcl.h"
39
40 // local
41 #include "memcl.h"
42 #include "hwcl.h"
43
44
45 /*
46  * Memory location handled specially by a hw element
47  */
48
49 cl_memloc::cl_memloc(t_addr addr):
50   cl_base()
51 {
52   address= addr;
53   hws= new cl_list(2, 2);
54   hws->init();
55 }
56
57 cl_memloc::~cl_memloc(void)
58 {
59   hws->disconn_all();
60   delete hws;
61 }
62
63 ulong
64 cl_memloc::read(class cl_mem *mem)
65 {
66   uchar ret= 0;
67   class cl_hw *hw;
68
69   if (!hws ||
70       hws->count == 0)
71     return(ret);
72   if ((hw= (class cl_hw *)(hws->at(0))))
73     ret= hw->read(mem, address);
74   return(ret);
75 }
76
77 void
78 cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
79 {
80   class cl_hw *hw;
81   int i;
82
83   if (!hws)
84     return;
85   for (i= 0; i < hws->count; i++)
86     {
87       hw= (class cl_hw *)hws->at(0);
88       hw->write(mem, addr, val);
89     }
90 }
91
92
93 /* Sorted collection of memory locations */
94
95 cl_memloc_coll::cl_memloc_coll(void):
96   cl_sorted_list(2, 2)
97 {
98   Duplicates= DD_FALSE;
99 }
100
101 void *
102 cl_memloc_coll::key_of(void *item)
103 {
104   return(&(((class cl_memloc *)item)->address));
105 }
106
107 int
108 cl_memloc_coll::compare(void *key1, void *key2)
109 {
110   if (*(long*)key1 > *(long*)key2)
111     return(1);
112   else
113     if (*(long*)key1 < *(long*)key2)
114       return(-1);
115     else
116       return(0);
117 }
118
119 class cl_memloc *
120 cl_memloc_coll::get_loc(t_addr address)
121 {
122   t_index i;
123
124   if (search(&address, i))
125     return((class cl_memloc*)(at(i)));
126   return(0);
127 }
128
129
130 /*
131  */
132
133 cl_cell::cl_cell(int awidth):
134   cl_base()
135 {
136   data= 0;
137   mask= 1;
138   for (; awidth; awidth--)
139     {
140       mask<<= 1;
141       mask|= 1;
142     }
143 }
144
145 /*t_mem
146 cl_cell::read(void)
147 {
148   return(data);
149 }*/
150
151 /*t_mem
152 cl_cell::get(void)
153 {
154   return(data);
155 }*/
156
157 /*void
158 cl_cell::write(t_mem *val)
159 {
160   data= *val= (*val & mask);
161 }*/
162
163 /*void
164 cl_cell::set(t_mem val)
165 {
166   data= val & mask;
167 }*/
168
169
170 cl_registered_cell::cl_registered_cell(int awidth):
171   cl_cell(awidth)
172 {
173   hws= new cl_list(1, 1);
174   hardwares= 0;
175   nuof_hws= 0;
176 }
177
178 cl_registered_cell::~cl_registered_cell(void)
179 {
180   hws->disconn_all();
181   delete hws;
182 }
183
184 t_mem
185 cl_registered_cell::read(void)
186 {
187   int i;
188
189   /*if (hws->count)
190     for (i= 0; i < hws->count; i++)
191       {
192         class cl_hw *hw= (class cl_hw *)(hws->at(i));
193         ;
194         }*/
195   if (nuof_hws)
196     for (i= 0; i < nuof_hws; i++)
197       {
198         //hardwares[i];
199         ;
200       }
201   return(data);
202 }
203
204 void
205 cl_registered_cell::write(t_mem *val)
206 {
207   int i;
208
209   /*if (hws->count)
210     for (i= 0; i < hws->count; i++)
211       {
212         class cl_hw *hw= (class cl_hw *)(hws->at(i));
213         ;
214         }*/
215   if (nuof_hws)
216     for (i= 0; i < nuof_hws; i++)
217       {
218         //hardwares[i];
219         ;
220       }
221   data= *val= (*val & mask);
222 }
223
224
225 /* 
226  */
227
228 cl_m::cl_m(t_addr asize, int awidth):
229   cl_mem(MEM_SFR, "sfr", 0, awidth)
230 {
231   t_addr a;
232
233   size= asize;
234   width= awidth;
235   array= (class cl_cell **)malloc(size * sizeof(class cl_cell *));
236   for (a= 0; a < size; a++)
237     array[a]= new cl_registered_cell(width);
238 }
239
240 cl_m::~cl_m(void)
241 {
242   t_addr a;
243
244   for (a= 0; a < size; a++)
245     delete array[a];
246   free(array);
247 }
248
249 t_mem
250 cl_m::read(t_addr addr)
251 {
252   if (addr >= size)
253     return(0);
254   return(array[addr]->read());
255 }
256
257 t_mem
258 cl_m::get(t_addr addr)
259 {
260   if (addr >= size)
261     return(0);
262   return(array[addr]->get());
263 }
264
265 void
266 cl_m::write(t_addr addr, t_mem *val)
267 {
268   if (addr >= size)
269     return;
270   array[addr]->write(val);
271 }
272
273 void
274 cl_m::set(t_addr addr, t_mem val)
275 {
276   if (addr >= size)
277     return;
278   array[addr]->set(val);
279 }
280
281
282 /*
283  * Memory
284  ******************************************************************************
285  */
286
287 cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
288                t_addr asize, int awidth):
289   cl_guiobj()
290 {
291   int i;
292
293   type= atype;
294   class_name= aclass_name;
295   width= awidth;
296   size= asize;
297   mem= 0;
298   for (i= width, mask= 0; i; i--)
299     mask= (mask<<1) | 1;
300   if (width <= 8)
301     mem= (TYPE_UBYTE *)malloc(size);
302   else if (width <= 16)
303     mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
304   else
305     mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
306   read_locs= new cl_memloc_coll();
307   write_locs= new cl_memloc_coll();
308   dump_finished= 0;
309   addr_format= (char *)malloc(10);
310   sprintf(addr_format, "0x%%0%dx",
311           size-1<=0xf?1:
312           (size-1<=0xff?2:
313            (size-1<=0xfff?3:
314             (size-1<=0xffff?4:
315              (size-1<=0xfffff?5:
316               (size-1<=0xffffff?6:12))))));
317   data_format= (char *)malloc(10);
318   sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
319 }
320
321 cl_mem::~cl_mem(void)
322 {
323   if (mem)
324     free(mem);
325   if (addr_format)
326     free(addr_format);
327   if (data_format)
328     free(data_format);
329   delete read_locs;
330   delete write_locs;
331 }
332
333 int
334 cl_mem::init(void)
335 {
336   t_addr i;
337
338   for (i= 0; i < size; i++)
339     set(i, (type==MEM_ROM)?(-1):0);
340   return(0);
341 }
342
343 char *
344 cl_mem::id_string(void)
345 {
346   char *s= get_id_string(mem_ids, type);
347
348   return(s?s:(char*)"NONE");
349 }
350
351 t_mem
352 cl_mem::read(t_addr addr)
353 {
354   class cl_memloc *loc;
355
356   if (addr >= size)
357     {
358       //FIXME
359       fprintf(stderr, "Address 0x%06lx is over 0x%06lx\n", addr, size);
360       return(0);
361     }
362   if ((loc= read_locs->get_loc(addr)))
363     return(loc->read(this));
364   if (width <= 8)
365     return((((TYPE_UBYTE*)mem)[addr])&mask);
366   else if (width <= 16)
367     return((((TYPE_UWORD*)mem)[addr])&mask);
368   else
369     return((((TYPE_UDWORD*)mem)[addr])&mask);
370 }
371
372 t_mem
373 cl_mem::get(t_addr addr)
374 {
375   if (addr >= size)
376     return(0);
377   if (width <= 8)
378     return((((TYPE_UBYTE*)mem)[addr])&mask);
379   else if (width <= 16)
380     return((((TYPE_UWORD*)mem)[addr])&mask);
381   else
382     return((((TYPE_UDWORD*)mem)[addr])&mask);
383 }
384
385
386 /*
387  * Modify memory location
388  */
389
390 /* Write calls callbacks of HW elements */
391
392 void
393 cl_mem::write(t_addr addr, t_mem *val)
394 {
395   class cl_memloc *loc;
396
397   if (addr >= size)
398     return;
399   if ((loc= write_locs->get_loc(addr)))
400     loc->write(this, addr, val);
401   if (width <= 8)
402     ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
403   else if (width <= 16)
404     ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
405   else
406     ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;
407 }
408
409 /* Set doesn't call callbacks */
410
411 void
412 cl_mem::set(t_addr addr, t_mem val)
413 {
414   if (addr >= size)
415     return;
416   if (width <= 8)
417     ((TYPE_UBYTE*)mem)[addr]= val&mask;
418   else if (width <= 16)
419     ((TYPE_UWORD*)mem)[addr]= val&mask;
420   else
421     ((TYPE_UDWORD*)mem)[addr]= val&mask;
422 }
423
424 /* Set or clear bits, without callbacks */
425
426 void
427 cl_mem::set_bit1(t_addr addr, t_mem bits)
428 {
429   if (addr >= size)
430     return;
431   bits&= mask;
432   if (width <= 8)
433     ((TYPE_UBYTE*)mem)[addr]|= bits;
434   else if (width <= 16)
435     ((TYPE_UWORD*)mem)[addr]|= bits;
436   else
437     ((TYPE_UDWORD*)mem)[addr]|= bits;
438 }
439
440 void
441 cl_mem::set_bit0(t_addr addr, t_mem bits)
442 {
443   if (addr >= size)
444     return;
445   bits&= mask;
446   if (width <= 8)
447     ((TYPE_UBYTE*)mem)[addr]&= ~bits;
448   else if (width <= 16)
449     ((TYPE_UWORD*)mem)[addr]&= ~bits;
450   else
451     ((TYPE_UDWORD*)mem)[addr]&= ~bits;
452 }
453
454 t_mem
455 cl_mem::add(t_addr addr, long what)
456 {
457   if (addr >= size)
458     return(0);
459   if (width <= 8)
460     {
461       ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what;
462       return(((TYPE_UBYTE*)mem)[addr]);
463     }
464   else if (width <= 16)
465     {
466       ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what;
467       return(((TYPE_UWORD*)mem)[addr]);
468     }
469   else
470     {
471       ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what;
472       return(((TYPE_UDWORD*)mem)[addr]);
473     }
474 }
475
476 t_addr
477 cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
478 {
479   int i;
480
481   while ((start <= stop) &&
482          (start < size))
483     {
484       con->dd_printf(addr_format, start); con->dd_printf(" ");
485       for (i= 0;
486            (i < bpl) &&
487              (start+i < size) &&
488              (start+i <= stop);
489            i++)
490         {
491           con->dd_printf(data_format, read(start+i)); con->dd_printf(" ");
492         }
493       while (i < bpl)
494         {
495           int j;
496           j= width/4 + ((width%4)?1:0) + 1;
497           while (j)
498             {
499               con->dd_printf(" ");
500               j--;
501             }
502           i++;
503         }
504       for (i= 0; (i < bpl) &&
505              (start+i < size) &&
506              (start+i <= stop);
507            i++)
508         {
509           long c= get(start+i);
510           con->dd_printf("%c", isprint(255&c)?(255&c):'.');
511           if (width > 8)
512             con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
513           if (width > 16)
514             con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
515           if (width > 24)
516             con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
517         }
518       con->dd_printf("\n");
519       dump_finished= start+i;
520       start+= bpl;
521     }
522   return(dump_finished);
523 }
524
525 t_addr
526 cl_mem::dump(class cl_console *con)
527 {
528   return(dump(dump_finished, dump_finished+10*8-1, 8, con));
529 }
530
531 bool
532 cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr)
533 {
534   t_addr a;
535   int i;
536   bool found;
537
538   if (addr == NULL)
539     a= 0;
540   else
541     a= *addr;
542   
543   if (a+len > size)
544     return(DD_FALSE);
545
546   found= DD_FALSE;
547   while (!found &&
548          a+len <= size)
549     {
550       bool match= DD_TRUE;
551       for (i= 0; i < len && match; i++)
552         {
553           t_mem d1, d2;
554           d1= get(a+i);
555           d2= array[i];
556           if (!case_sensitive)
557             {
558               if (/*d1 < 128*/isalpha(d1))
559                 d1= toupper(d1);
560               if (/*d2 < 128*/isalpha(d2))
561                 d2= toupper(d2);
562             }
563           match= d1 == d2;
564         }
565       found= match;
566       if (!found)
567         a++;
568     }
569
570   if (addr)
571     *addr= a;
572   return(found);
573 }
574
575
576 /*
577  * Bitmap
578  */
579
580 cl_bitmap::cl_bitmap(t_addr asize):
581   cl_base()
582 {
583   map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
584   memset(map, 0, size);
585 }
586
587 cl_bitmap::~cl_bitmap(void)
588 {
589   free(map);
590 }
591
592 void
593 cl_bitmap::set(t_addr pos)
594 {
595   int i;
596
597   if ((i= pos/(8*SIZEOF_CHAR)) < size)
598     map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
599 }
600
601 void
602 cl_bitmap::clear(t_addr pos)
603 {
604   int i;
605
606   if ((i= pos/(8*SIZEOF_CHAR)) < size)
607     map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
608 }
609
610 bool
611 cl_bitmap::get(t_addr pos)
612 {
613   return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
614 }
615
616 bool
617 cl_bitmap::empty(void)
618 {
619   int i;
620
621   for (i= 0; i < size && map[i] == 0; i++) ;
622   return(i == size);
623 }
624
625 /*
626  * Special memory for code (ROM)
627  */
628
629 cl_rom::cl_rom(t_addr asize, int awidth):
630   cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth)
631 {
632   bp_map= new cl_bitmap(asize);
633   inst_map= new cl_bitmap(asize);
634 }
635
636 cl_rom::~cl_rom(void)
637 {
638   delete bp_map;
639   delete inst_map;
640 }
641
642
643 /* End of mem.cc */