2 * Simulator of microcontrollers (mem.cc)
4 * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
6 * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
10 /* This file is part of microcontroller simulator: ucsim.
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.
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.
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
46 * Memory location handled specially by a hw element
49 cl_memloc::cl_memloc(t_addr addr):
53 hws= new cl_list(2, 2);
57 cl_memloc::~cl_memloc(void)
64 cl_memloc::read(class cl_mem *mem)
72 if ((hw= (class cl_hw *)(hws->at(0))))
73 ret= hw->read(mem, address);
78 cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
85 for (i= 0; i < hws->count; i++)
87 hw= (class cl_hw *)hws->at(0);
88 hw->write(mem, addr, val);
93 /* Sorted collection of memory locations */
95 cl_memloc_coll::cl_memloc_coll(void):
102 cl_memloc_coll::key_of(void *item)
104 return(&(((class cl_memloc *)item)->address));
108 cl_memloc_coll::compare(void *key1, void *key2)
110 if (*(long*)key1 > *(long*)key2)
113 if (*(long*)key1 < *(long*)key2)
120 cl_memloc_coll::get_loc(t_addr address)
124 if (search(&address, i))
125 return((class cl_memloc*)(at(i)));
133 cl_cell::cl_cell(int awidth):
138 for (; awidth; awidth--)
158 cl_cell::write(t_mem *val)
160 data= *val= (*val & mask);
164 cl_cell::set(t_mem val)
170 cl_registered_cell::cl_registered_cell(int awidth):
173 hws= new cl_list(1, 1);
178 cl_registered_cell::~cl_registered_cell(void)
185 cl_registered_cell::read(void)
190 for (i= 0; i < hws->count; i++)
192 class cl_hw *hw= (class cl_hw *)(hws->at(i));
196 for (i= 0; i < nuof_hws; i++)
205 cl_registered_cell::write(t_mem *val)
210 for (i= 0; i < hws->count; i++)
212 class cl_hw *hw= (class cl_hw *)(hws->at(i));
216 for (i= 0; i < nuof_hws; i++)
221 data= *val= (*val & mask);
228 cl_m::cl_m(t_addr asize, int awidth):
229 cl_mem(MEM_SFR, "sfr", 0, 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);
244 for (a= 0; a < size; a++)
250 cl_m::read(t_addr addr)
254 return(array[addr]->read());
258 cl_m::get(t_addr addr)
262 return(array[addr]->get());
266 cl_m::write(t_addr addr, t_mem *val)
270 array[addr]->write(val);
274 cl_m::set(t_addr addr, t_mem val)
278 array[addr]->set(val);
284 ******************************************************************************
287 cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
288 t_addr asize, int awidth):
294 class_name= aclass_name;
298 for (i= width, mask= 0; i; i--)
301 mem= (TYPE_UBYTE *)malloc(size);
302 else if (width <= 16)
303 mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
305 mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
306 read_locs= new cl_memloc_coll();
307 write_locs= new cl_memloc_coll();
309 addr_format= (char *)malloc(10);
310 sprintf(addr_format, "0x%%0%dx",
316 (size-1<=0xffffff?6:12))))));
317 data_format= (char *)malloc(10);
318 sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
321 cl_mem::~cl_mem(void)
338 for (i= 0; i < size; i++)
339 set(i, (type==MEM_ROM)?(-1):0);
344 cl_mem::id_string(void)
346 char *s= get_id_string(mem_ids, type);
348 return(s?s:(char*)"NONE");
352 cl_mem::read(t_addr addr)
354 class cl_memloc *loc;
359 fprintf(stderr, "Address 0x%06lx is over 0x%06lx\n", addr, size);
362 if ((loc= read_locs->get_loc(addr)))
363 return(loc->read(this));
365 return((((TYPE_UBYTE*)mem)[addr])&mask);
366 else if (width <= 16)
367 return((((TYPE_UWORD*)mem)[addr])&mask);
369 return((((TYPE_UDWORD*)mem)[addr])&mask);
373 cl_mem::get(t_addr addr)
378 return((((TYPE_UBYTE*)mem)[addr])&mask);
379 else if (width <= 16)
380 return((((TYPE_UWORD*)mem)[addr])&mask);
382 return((((TYPE_UDWORD*)mem)[addr])&mask);
387 * Modify memory location
390 /* Write calls callbacks of HW elements */
393 cl_mem::write(t_addr addr, t_mem *val)
395 class cl_memloc *loc;
399 if ((loc= write_locs->get_loc(addr)))
400 loc->write(this, addr, val);
402 ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
403 else if (width <= 16)
404 ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
406 ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;
409 /* Set doesn't call callbacks */
412 cl_mem::set(t_addr addr, t_mem val)
417 ((TYPE_UBYTE*)mem)[addr]= val&mask;
418 else if (width <= 16)
419 ((TYPE_UWORD*)mem)[addr]= val&mask;
421 ((TYPE_UDWORD*)mem)[addr]= val&mask;
424 /* Set or clear bits, without callbacks */
427 cl_mem::set_bit1(t_addr addr, t_mem bits)
433 ((TYPE_UBYTE*)mem)[addr]|= bits;
434 else if (width <= 16)
435 ((TYPE_UWORD*)mem)[addr]|= bits;
437 ((TYPE_UDWORD*)mem)[addr]|= bits;
441 cl_mem::set_bit0(t_addr addr, t_mem bits)
447 ((TYPE_UBYTE*)mem)[addr]&= ~bits;
448 else if (width <= 16)
449 ((TYPE_UWORD*)mem)[addr]&= ~bits;
451 ((TYPE_UDWORD*)mem)[addr]&= ~bits;
455 cl_mem::add(t_addr addr, long what)
461 ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what;
462 return(((TYPE_UBYTE*)mem)[addr]);
464 else if (width <= 16)
466 ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what;
467 return(((TYPE_UWORD*)mem)[addr]);
471 ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what;
472 return(((TYPE_UDWORD*)mem)[addr]);
477 cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
481 while ((start <= stop) &&
484 con->dd_printf(addr_format, start); con->dd_printf(" ");
491 con->dd_printf(data_format, read(start+i)); con->dd_printf(" ");
496 j= width/4 + ((width%4)?1:0) + 1;
504 for (i= 0; (i < bpl) &&
509 long c= get(start+i);
510 con->dd_printf("%c", isprint(255&c)?(255&c):'.');
512 con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
514 con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
516 con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
518 con->dd_printf("\n");
519 dump_finished= start+i;
522 return(dump_finished);
526 cl_mem::dump(class cl_console *con)
528 return(dump(dump_finished, dump_finished+10*8-1, 8, con));
532 cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr)
551 for (i= 0; i < len && match; i++)
558 if (/*d1 < 128*/isalpha(d1))
560 if (/*d2 < 128*/isalpha(d2))
580 cl_bitmap::cl_bitmap(t_addr asize):
583 map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
584 memset(map, 0, size);
587 cl_bitmap::~cl_bitmap(void)
593 cl_bitmap::set(t_addr pos)
597 if ((i= pos/(8*SIZEOF_CHAR)) < size)
598 map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
602 cl_bitmap::clear(t_addr pos)
606 if ((i= pos/(8*SIZEOF_CHAR)) < size)
607 map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
611 cl_bitmap::get(t_addr pos)
613 return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
617 cl_bitmap::empty(void)
621 for (i= 0; i < size && map[i] == 0; i++) ;
626 * Special memory for code (ROM)
629 cl_rom::cl_rom(t_addr asize, int awidth):
630 cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth)
632 bp_map= new cl_bitmap(asize);
633 inst_map= new cl_bitmap(asize);
636 cl_rom::~cl_rom(void)