Some fixes towards 0.2.37-pre5
[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(long 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, long addr, ulong *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(long 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  * Memory
132  ******************************************************************************
133  */
134
135 cl_mem::cl_mem(enum mem_class atype, t_addr asize, int awidth):
136   cl_base()
137 {
138   int i;
139
140   type= atype;
141   width= awidth;
142   size= asize;
143   mem= 0;
144   for (i= width, mask= 0; i; i--)
145     mask= (mask<<1) | 1;
146   if (width <= 8)
147     mem= (TYPE_UBYTE *)malloc(size);
148   else if (width <= 16)
149     mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
150   else
151     mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
152   read_locs= new cl_memloc_coll();
153   write_locs= new cl_memloc_coll();
154   dump_finished= 0;
155 }
156
157 cl_mem::~cl_mem(void)
158 {
159   if (mem)
160     free(mem);
161   delete read_locs;
162   delete write_locs;
163 }
164
165 int
166 cl_mem::init(void)
167 {
168   t_addr i;
169
170   for (i= 0; i < size; i++)
171     set(i, (type==MEM_ROM)?(-1):0);
172   return(0);
173 }
174
175 char *
176 cl_mem::id_string(void)
177 {
178   char *s= get_id_string(mem_ids, type);
179
180   return(s?s:(char*)"NONE");
181 }
182
183 ulong
184 cl_mem::read(t_addr addr)
185 {
186   class cl_memloc *loc;
187
188   if (addr >= size)
189     {
190       //FIXME
191       fprintf(stderr, "Address 0x%06lx is over 0x%06lx\n", addr, size);
192       return(0);
193     }
194   if ((loc= read_locs->get_loc(addr)))
195     return(loc->read(this));
196   if (width <= 8)
197     return((((TYPE_UBYTE*)mem)[addr])&mask);
198   else if (width <= 16)
199     return((((TYPE_UWORD*)mem)[addr])&mask);
200   else
201     return((((TYPE_UDWORD*)mem)[addr])&mask);
202 }
203
204 ulong
205 cl_mem::get(t_addr addr)
206 {
207   if (addr >= size)
208     return(0);
209   if (width <= 8)
210     return((((TYPE_UBYTE*)mem)[addr])&mask);
211   else if (width <= 16)
212     return((((TYPE_UWORD*)mem)[addr])&mask);
213   else
214     return((((TYPE_UDWORD*)mem)[addr])&mask);
215 }
216
217
218 /*
219  * Modify memory location
220  */
221
222 /* Write calls callbacks of HW elements */
223
224 void
225 cl_mem::write(t_addr addr, t_mem *val)
226 {
227   class cl_memloc *loc;
228
229   if (addr >= size)
230     return;
231   if ((loc= write_locs->get_loc(addr)))
232     loc->write(this, addr, val);
233   if (width <= 8)
234     ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
235   else if (width <= 16)
236     ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
237   else
238     ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;
239 }
240
241 /* Set doesn't call callbacks */
242
243 void
244 cl_mem::set(t_addr addr, t_mem val)
245 {
246   if (addr >= size)
247     return;
248   if (width <= 8)
249     ((TYPE_UBYTE*)mem)[addr]= val&mask;
250   else if (width <= 16)
251     ((TYPE_UWORD*)mem)[addr]= val&mask;
252   else
253     ((TYPE_UDWORD*)mem)[addr]= val&mask;
254 }
255
256 /* Set or clear bits, without callbacks */
257
258 void
259 cl_mem::set_bit1(t_addr addr, t_mem bits)
260 {
261   if (addr >= size)
262     return;
263   bits&= mask;
264   if (width <= 8)
265     ((TYPE_UBYTE*)mem)[addr]|= bits;
266   else if (width <= 16)
267     ((TYPE_UWORD*)mem)[addr]|= bits;
268   else
269     ((TYPE_UDWORD*)mem)[addr]|= bits;
270 }
271
272 void
273 cl_mem::set_bit0(t_addr addr, t_mem bits)
274 {
275   if (addr >= size)
276     return;
277   bits&= mask;
278   if (width <= 8)
279     ((TYPE_UBYTE*)mem)[addr]&= ~bits;
280   else if (width <= 16)
281     ((TYPE_UWORD*)mem)[addr]&= ~bits;
282   else
283     ((TYPE_UDWORD*)mem)[addr]&= ~bits;
284 }
285
286 void
287 cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
288 {
289   int i;
290
291   if (start < 0)
292     {
293       start= dump_finished;
294       stop= start+stop;
295     }
296   while ((start <= stop) &&
297          (start < size))
298     {
299       con->printf("%06x ", start);
300       for (i= 0; (i < bpl) &&
301              (start+i < size) &&
302              (start+i <= stop);
303            i++)
304         {
305           char format[10];
306           sprintf(format, "%%0%dx ", width/4);
307           con->printf(format/*"%02x "*/, get(start+i));
308         }
309       while (i < bpl)
310         {
311           //FIXME
312           con->printf("   ");
313           i++;
314         }
315       for (i= 0; (i < bpl) &&
316              (start+i < size) &&
317              (start+i <= stop);
318            i++)
319         {
320           long c= get(start+i);
321           con->printf("%c", isprint(255&c)?(255&c):'.');
322           if (width > 8)
323             con->printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
324           if (width > 16)
325             con->printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
326           if (width > 24)
327             con->printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
328         }
329       con->printf("\n");
330       dump_finished= start+i;
331       start+= bpl;
332     }
333 }
334
335
336 /*
337  * Bitmap
338  */
339
340 cl_bitmap::cl_bitmap(long asize):
341   cl_base()
342 {
343   map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
344   memset(map, 0, size);
345 }
346
347 cl_bitmap::~cl_bitmap(void)
348 {
349   free(map);
350 }
351
352 void
353 cl_bitmap::set(long pos)
354 {
355   int i;
356
357   if ((i= pos/(8*SIZEOF_CHAR)) < size)
358     map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
359 }
360
361 void
362 cl_bitmap::clear(long pos)
363 {
364   int i;
365
366   if ((i= pos/(8*SIZEOF_CHAR)) < size)
367     map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
368 }
369
370 bool
371 cl_bitmap::get(long pos)
372 {
373   return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
374 }
375
376 bool
377 cl_bitmap::empty(void)
378 {
379   int i;
380
381   for (i= 0; i < size && map[i] == 0; i++) ;
382   return(i == size);
383 }
384
385 /*
386  * Special memory for code (ROM)
387  */
388
389 cl_rom::cl_rom(long asize, int awidth):
390   cl_mem(MEM_ROM, asize, awidth)
391 {
392   bp_map= new cl_bitmap(asize);
393   inst_map= new cl_bitmap(asize);
394 }
395
396 cl_rom::~cl_rom(void)
397 {
398   delete bp_map;
399   delete inst_map;
400 }
401
402
403 /* End of mem.cc */