--- /dev/null
+/*
+ * Memory location handled specially by a hw element
+ */
+
+/*cl_memloc::cl_memloc(t_addr addr):
+ cl_base()
+{
+ address= addr;
+ hws= new cl_list(2, 2);
+ hws->init();
+}*/
+
+/*cl_memloc::~cl_memloc(void)
+{
+ hws->disconn_all();
+ delete hws;
+}*/
+
+/*ulong
+cl_memloc::read(class cl_mem *mem)
+{
+ uchar ret= 0;
+ class cl_hw *hw;
+
+ if (!hws ||
+ hws->count == 0)
+ return(ret);
+ if ((hw= (class cl_hw *)(hws->at(0))))
+ ret= hw->read(mem, address);
+ return(ret);
+}*/
+
+/*void
+cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
+{
+ class cl_hw *hw;
+ int i;
+
+ if (!hws)
+ return;
+ for (i= 0; i < hws->count; i++)
+ {
+ hw= (class cl_hw *)hws->at(0);
+ hw->write(mem, addr, val);
+ }
+}*/
+
+
+/* Sorted collection of memory locations */
+
+/*cl_memloc_coll::cl_memloc_coll(void):
+ cl_sorted_list(2, 2)
+{
+ Duplicates= DD_FALSE;
+}*/
+
+/*void *
+cl_memloc_coll::key_of(void *item)
+{
+ return(&(((class cl_memloc *)item)->address));
+}*/
+
+/*int
+cl_memloc_coll::compare(void *key1, void *key2)
+{
+ if (*(long*)key1 > *(long*)key2)
+ return(1);
+ else
+ if (*(long*)key1 < *(long*)key2)
+ return(-1);
+ else
+ return(0);
+}*/
+
+/*class cl_memloc *
+cl_memloc_coll::get_loc(t_addr address)
+{
+ t_index i;
+
+ if (search(&address, i))
+ return((class cl_memloc*)(at(i)));
+ return(0);
+}*/
+
+
+/*
+ * Memory
+ ******************************************************************************
+ */
+
+/*
+ * Bitmap
+ */
+
+/*cl_bitmap::cl_bitmap(t_addr asize):
+ cl_base()
+{
+ map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
+ memset(map, 0, size);
+}
+
+cl_bitmap::~cl_bitmap(void)
+{
+ free(map);
+}
+
+void
+cl_bitmap::set(t_addr pos)
+{
+ int i;
+
+ if ((i= pos/(8*SIZEOF_CHAR)) < size)
+ map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
+}
+
+void
+cl_bitmap::clear(t_addr pos)
+{
+ int i;
+
+ if ((i= pos/(8*SIZEOF_CHAR)) < size)
+ map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
+}
+
+bool
+cl_bitmap::get(t_addr pos)
+{
+ return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
+}
+
+bool
+cl_bitmap::empty(void)
+{
+ int i;
+
+ for (i= 0; i < size && map[i] == 0; i++) ;
+ return(i == size);
+}*/
+
+/*
+ * Special memory for code (ROM)
+ */
+
+/*cl_rom::cl_rom(t_addr asize, int awidth, class cl_uc *auc):
+ cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth, auc)
+{
+ bp_map= new cl_bitmap(asize);
+ inst_map= new cl_bitmap(asize);
+}
+
+cl_rom::~cl_rom(void)
+{
+ delete bp_map;
+ delete inst_map;
+}*/
+
+
+cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
+ t_addr asize, int awidth, class cl_uc *auc):
+ cl_guiobj()
+{
+ int i;
+
+ uc= auc;
+ type= atype;
+ class_name= aclass_name;
+ width= awidth;
+ size= asize;
+ mem= 0;
+ for (i= width, mask= 0; i; i--)
+ mask= (mask<<1) | 1;
+ if (width == 0 ||
+ size == 0)
+ mem= 0;
+ else if (width <= 8)
+ mem= (TYPE_UBYTE *)malloc(size);
+ else if (width <= 16)
+ mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
+ else
+ mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
+ //read_locs= new cl_memloc_coll();
+ //write_locs= new cl_memloc_coll();
+ dump_finished= 0;
+ addr_format= data_format= 0;
+}
+
+cl_mem::~cl_mem(void)
+{
+ if (mem)
+ free(mem);
+ if (addr_format)
+ free(addr_format);
+ if (data_format)
+ free(data_format);
+ //delete read_locs;
+ //delete write_locs;
+}
+
+int
+cl_mem::init(void)
+{
+ t_addr i;
+
+ addr_format= (char *)malloc(10);
+ sprintf(addr_format, "0x%%0%dx",
+ size-1<=0xf?1:
+ (size-1<=0xff?2:
+ (size-1<=0xfff?3:
+ (size-1<=0xffff?4:
+ (size-1<=0xfffff?5:
+ (size-1<=0xffffff?6:12))))));
+ data_format= (char *)malloc(10);
+ sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
+
+ for (i= 0; i < size; i++)
+ set(i, (type==MEM_ROM)?(-1):0);
+ return(0);
+}
+
+char *
+cl_mem::id_string(void)
+{
+ char *s= get_id_string(mem_ids, type);
+
+ return(s?s:(char*)"NONE");
+}
+
+t_mem
+cl_mem::read(t_addr addr)
+{
+ //class cl_memloc *loc;
+
+ if (addr >= size)
+ {
+ //FIXME
+ fprintf(stderr, "Address 0x%06"_A_"x is over 0x%06"_A_"x\n", addr, size);
+ return(0);
+ }
+ /*if ((loc= read_locs->get_loc(addr)))
+ return(loc->read(this));*/
+ if (width <= 8)
+ return((((TYPE_UBYTE*)mem)[addr])&mask);
+ else if (width <= 16)
+ return((((TYPE_UWORD*)mem)[addr])&mask);
+ else
+ return((((TYPE_UDWORD*)mem)[addr])&mask);
+}
+
+t_mem
+cl_mem::get(t_addr addr)
+{
+ if (addr >= size)
+ return(0);
+ if (width <= 8)
+ return((((TYPE_UBYTE*)mem)[addr])&mask);
+ else if (width <= 16)
+ return((((TYPE_UWORD*)mem)[addr])&mask);
+ else
+ return((((TYPE_UDWORD*)mem)[addr])&mask);
+}
+
+
+/*
+ * Modify memory location
+ */
+
+/* Write calls callbacks of HW elements */
+
+t_mem
+cl_mem::write(t_addr addr, t_mem val)
+{
+ /* class cl_memloc *loc;
+
+ if (addr >= size)
+ return;
+ if ((loc= write_locs->get_loc(addr)))
+ loc->write(this, addr, val);
+ if (width <= 8)
+ ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
+ else if (width <= 16)
+ ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
+ else
+ ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;*/
+ fprintf(stderr, "FIXME cl_mem::write(0x%06"_A_"x, 0x%04"_M_"x)\n",
+ addr, val);
+ return(0);
+}
+
+/* Set doesn't call callbacks */
+
+void
+cl_mem::set(t_addr addr, t_mem val)
+{
+ if (addr >= size)
+ return;
+ if (width <= 8)
+ ((TYPE_UBYTE*)mem)[addr]= val&mask;
+ else if (width <= 16)
+ ((TYPE_UWORD*)mem)[addr]= val&mask;
+ else
+ ((TYPE_UDWORD*)mem)[addr]= val&mask;
+}
+
+t_mem
+cl_mem::add(t_addr addr, long what)
+{
+ if (addr >= size)
+ return(0);
+ if (width <= 8)
+ {
+ ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what;
+ return(((TYPE_UBYTE*)mem)[addr]);
+ }
+ else if (width <= 16)
+ {
+ ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what;
+ return(((TYPE_UWORD*)mem)[addr]);
+ }
+ else
+ {
+ ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what;
+ return(((TYPE_UDWORD*)mem)[addr]);
+ }
+}
+
+t_addr
+cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
+{
+ int i;
+
+ while ((start <= stop) &&
+ (start < size))
+ {
+ con->dd_printf(addr_format, start); con->dd_printf(" ");
+ for (i= 0;
+ (i < bpl) &&
+ (start+i < size) &&
+ (start+i <= stop);
+ i++)
+ {
+ con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
+ }
+ while (i < bpl)
+ {
+ int j;
+ j= width/4 + ((width%4)?1:0) + 1;
+ while (j)
+ {
+ con->dd_printf(" ");
+ j--;
+ }
+ i++;
+ }
+ for (i= 0; (i < bpl) &&
+ (start+i < size) &&
+ (start+i <= stop);
+ i++)
+ {
+ long c= get(start+i);
+ con->dd_printf("%c", isprint(255&c)?(255&c):'.');
+ if (width > 8)
+ con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
+ if (width > 16)
+ con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
+ if (width > 24)
+ con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
+ }
+ con->dd_printf("\n");
+ dump_finished= start+i;
+ start+= bpl;
+ }
+ return(dump_finished);
+}
+
+t_addr
+cl_mem::dump(class cl_console *con)
+{
+ return(dump(dump_finished, dump_finished+10*8-1, 8, con));
+}
+
+
+
+/*
+ */
+/*
+cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell)
+{
+ real_cell= realcell;
+}
+
+cl_mapped_cell::~cl_mapped_cell(void)
+{}
+
+t_mem
+cl_mapped_cell::read(void)
+{
+ return(real_cell->read());
+}
+
+t_mem
+cl_mapped_cell::read(enum hw_cath skip)
+{
+ return(real_cell->read(skip));
+}
+
+t_mem
+cl_mapped_cell::get(void)
+{
+ return(real_cell->get());
+}
+
+t_mem
+cl_mapped_cell::write(t_mem val)
+{
+ return(real_cell->write(val));
+}
+
+t_mem
+cl_mapped_cell::set(t_mem val)
+{
+ return(real_cell->set(val));
+}
+
+t_mem
+cl_mapped_cell::add(long what)
+{
+ return(real_cell->add(what));
+}
+
+t_mem
+cl_mapped_cell::wadd(long what)
+{
+ return(real_cell->wadd(what));
+}
+
+void
+cl_mapped_cell::set_bit1(t_mem bits)
+{
+ return(real_cell->set_bit1(bits));
+}
+
+void
+cl_mapped_cell::set_bit0(t_mem bits)
+{
+ return(real_cell->set_bit0(bits));
+}
+
+class cl_cell *
+cl_mapped_cell::add_hw(class cl_hw *hw, int *ith)
+{
+ return(real_cell->add_hw(hw, ith));
+}
+
+class cl_hw *
+cl_mapped_cell::get_hw(int ith)
+{
+ return(real_cell->get_hw(ith));
+}
+
+class cl_event_handler *
+cl_mapped_cell::get_event_handler(void)
+{
+ return(real_cell->get_event_handler());
+}
+*/
+
+/*
+ */
+
+cl_m::cl_m(enum mem_class atype, char *aclass_name, t_addr asize, int awidth,
+ class cl_uc *auc):
+ cl_memory(aclass_name, asize, awidth)
+ //cl_mem(atype, aclass_name, 0, awidth, auc)
+{
+ t_addr a;
+
+ //size= asize;
+ width= awidth;
+ set_name(aclass_name);
+ uc= auc;
+ type= atype;
+
+ array= (class cl_cell **)calloc(size, sizeof(class cl_cell *));
+ for (a= 0; a < size; a++)
+ array[a]= new cl_normal_cell(width);
+ bus_mask= 0;
+ t_addr i;
+ for (i= 1; i < size; i<<=1)
+ bus_mask= (bus_mask<<1)|1;
+ dummy= new cl_normal_cell(width);
+ //mk_cell(size, 0);
+}
+
+cl_m::~cl_m(void)
+{
+ t_addr a;
+
+ for (a= 0; a < size; a++)
+ delete array[a];
+ free(array);
+ delete dummy;
+}
+
+int
+cl_m::init(void)
+{
+ t_addr i;
+
+ cl_memory::init();
+
+ for (i= 0; i < size; i++)
+ set(i, (type==MEM_ROM)?(-1):0);
+ return(0);
+}
+
+char *
+cl_m::id_string(void)
+{
+ char *s= get_id_string(mem_ids, type);
+
+ return(s?s:(char*)"NONE");
+}
+
+/*void
+cl_m::mk_cell(t_addr addr, class cl_cell *cell)
+{
+ if (!cell)
+ cell= new cl_cell(width);
+ class cl_cell *p;
+ if (addr >= size)
+ p= dummy;
+ else
+ p= array[addr];
+ if (p == 0)
+ {
+ p= (class cl_cell *)calloc(1, sizeof(*cell));
+ }
+ else
+ {
+ p->destroy();
+ p= (class cl_cell *)realloc(p, sizeof(cell));
+ }
+ memcpy(p, cell, sizeof(*cell));
+ cell->destroy();
+ delete cell;
+}*/
+
+t_mem
+cl_m::read(t_addr addr)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->read());
+ }
+ return(array[addr]->read());
+}
+
+t_mem
+cl_m::read(t_addr addr, enum hw_cath skip)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->read(skip));
+ }
+ return(array[addr]->read(skip));
+}
+
+t_mem
+cl_m::get(t_addr addr)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->get());
+ }
+ return(array[addr]->get());
+}
+
+t_mem
+cl_m::write(t_addr addr, t_mem val)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->write(val));
+ }
+ return(array[addr]->write(val));
+}
+
+void
+cl_m::set(t_addr addr, t_mem val)
+{
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ //addr&= bus_mask;
+ dummy->set(val);
+ return;
+ }
+ //addr&= bus_mask;
+ array[addr]->set(val);
+}
+
+class cl_cell *
+cl_m::get_cell(t_addr addr)
+{
+ //addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy);
+ }
+ return(array[addr]);
+}
+
+
+/* Set or clear bits, without callbacks */
+
+void
+cl_m::set_bit1(t_addr addr, t_mem bits)
+{
+ class cl_cell *cell;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ cell= dummy;
+ }
+ else
+ cell= array[addr];
+ bits&= cell->get_mask();
+ cell->set(cell->get() | bits);
+}
+
+void
+cl_m::write_bit1(t_addr addr, t_mem bits)
+{
+ class cl_cell *cell;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ cell= dummy;
+ }
+ else
+ cell= array[addr];
+ bits&= cell->get_mask();
+ cell->write(cell->get() | bits);
+}
+
+void
+cl_m::set_bit0(t_addr addr, t_mem bits)
+{
+ class cl_cell *cell;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ cell= dummy;
+ }
+ else
+ cell= array[addr];
+ bits&= cell->get_mask();
+ cell->set(cell->get() & ~bits);
+}
+
+void
+cl_m::write_bit0(t_addr addr, t_mem bits)
+{
+ class cl_cell *cell;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ cell =dummy;
+ }
+ else
+ cell= array[addr];
+ bits&= cell->get_mask();
+ cell->write(cell->get() & ~bits);
+}
+
+t_mem
+cl_m::add(t_addr addr, long what)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->add(what));
+ }
+ return(array[addr]->add(what));
+}
+
+t_mem
+cl_m::wadd(t_addr addr, long what)
+{
+ addr&= bus_mask;
+ if (addr >= size)
+ {
+ err_inv_addr(addr);
+ return(dummy->wadd(what));
+ }
+ return(array[addr]->wadd(what));
+}
+
+bool
+cl_m::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr)
+{
+ t_addr a;
+ int i;
+ bool found;
+
+ if (addr == NULL)
+ a= 0;
+ else
+ a= *addr;
+
+ if (a+len > size)
+ return(DD_FALSE);
+
+ found= DD_FALSE;
+ while (!found &&
+ a+len <= size)
+ {
+ bool match= DD_TRUE;
+ for (i= 0; i < len && match; i++)
+ {
+ t_mem d1, d2;
+ d1= get(a+i);
+ d2= array[i];
+ if (!case_sensitive)
+ {
+ if (/*d1 < 128*/isalpha(d1))
+ d1= toupper(d1);
+ if (/*d2 < 128*/isalpha(d2))
+ d2= toupper(d2);
+ }
+ match= d1 == d2;
+ }
+ found= match;
+ if (!found)
+ a++;
+ }
+
+ if (addr)
+ *addr= a;
+ return(found);
+}
+
+class cl_cell *
+cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce)
+{
+ class cl_cell *cell, *nc;
+
+ addr&= bus_mask;
+ if (addr >= size)
+ cell= dummy;
+ else
+ cell= array[addr];
+
+ if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
+ {
+ /* Already registered */
+ return(cell->add_hw(hw, ith));
+ }
+ else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
+ {
+ /* Event break is set on it, now register hw */
+ nc= new cl_ev_reg_cell(width, uc);
+ nc->set(cell->get());
+ nc->set_type(nc->get_type() &
+ ~(CELL_GENERAL|CELL_READ_BRK|CELL_WRITE_BRK));
+ nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
+ class cl_event_handler *eh= nc->get_event_handler();
+ if (eh)
+ nc->set_type(nc->get_type() | eh->copy_from(cell->get_event_handler()));
+ nc->add_hw(hw, ith);
+ }
+ else
+ {
+ /* Normal cell, register hw */
+ nc= new cl_registered_cell(width);
+ nc->set(cell->get());
+ nc->set_type(nc->get_type() & ~CELL_GENERAL);
+ nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
+ nc->add_hw(hw, ith);
+ }
+
+ if (addr >= size)
+ {
+ delete dummy;
+ dummy= nc;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ if (announce)
+ uc->sim->/*app->*/mem_cell_changed(this, addr);
+ return(nc);
+}
+
+void
+cl_m::set_brk(t_addr addr, class cl_brk *brk)
+{
+ class cl_cell *cell, *nc;
+ char e= '_';
+
+ addr&= bus_mask;
+ if (addr >= size)
+ cell= dummy;
+ else
+ cell= array[addr];
+
+ switch (brk->get_event())
+ {
+ case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
+ e= 'W';
+ break;
+ case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
+ e= 'R';
+ break;
+ case brkNONE:
+ set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
+ return;
+ break;
+ default: e= '.'; break;
+ }
+
+ if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
+ {
+ /* Hw is registered on it, now set event break */
+ nc= new cl_ev_reg_cell(width, uc);
+ nc->set(cell->get());
+ nc->set_type(nc->get_type() & ~CELL_GENERAL);
+ nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
+ int i= 0;
+ class cl_hw *hw;
+ while ((hw= cell->get_hw(i)) != 0)
+ {
+ nc->add_hw(hw, 0);
+ i++;
+ }
+ if (((class cl_registered_cell *)cell)->hardwares)
+ {
+ free(((class cl_registered_cell *)cell)->hardwares);
+ ((class cl_registered_cell *)cell)->hardwares= 0;
+ }
+ class cl_event_handler *eh;
+ if ((eh= nc->get_event_handler()))
+ nc->set_type(nc->get_type() | eh->add_bp(brk));
+ }
+ else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
+ {
+ /* Break is already set on it */
+ class cl_event_handler *eh;
+ if ((eh= cell->get_event_handler()))
+ cell->set_type(cell->get_type() | eh->add_bp(brk));
+ return;
+ }
+ else
+ {
+ /* Normal cell, set event break */
+ nc= new cl_event_cell(width, uc);
+ nc->set(cell->get());
+ nc->set_type(nc->get_type() & ~CELL_GENERAL);
+ nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
+ class cl_event_handler *eh;
+ if ((eh= nc->get_event_handler()))
+ nc->set_type(nc->get_type() | eh->add_bp(brk));
+ }
+
+ if (addr >= size)
+ {
+ delete dummy;
+ dummy= nc;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ uc->sim->/*app->*/mem_cell_changed(this, addr);
+}
+
+void
+cl_m::del_brk(t_addr addr, class cl_brk *brk)
+{
+ class cl_cell *cell, *nc;
+ char e= '_';
+
+ addr&= bus_mask;
+ if (addr >= size)
+ cell= dummy;
+ else
+ cell= array[addr];
+
+ switch (brk->get_event())
+ {
+ case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: e= 'W'; break;
+ case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
+ e= 'R';
+ break;
+ case brkNONE:
+ set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
+ return;
+ break;
+ default: e= '.'; break;
+ }
+
+ if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
+ {
+ /* Hw is registered on it, delete event break */
+ class cl_event_handler *eh;
+ int t= CELL_NORMAL;
+ if ((eh= cell->get_event_handler()))
+ t= eh->del_bp(brk);
+ if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
+ {
+ cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
+ cell->set_type(cell->get_type() | t);
+ return;
+ }
+ nc= new cl_registered_cell(width);
+ nc->set(cell->get());
+ nc->set_type(cell->get_type() & ~CELL_GENERAL);
+ nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
+ int i= 0;
+ class cl_hw *hw;
+ while ((hw= cell->get_hw(i)) != 0)
+ {
+ nc->add_hw(hw, 0);
+ i++;
+ }
+ if (((class cl_registered_cell *)cell)->hardwares)
+ free(((class cl_registered_cell *)cell)->hardwares);
+ }
+ else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
+ {
+ /* Break already set on it, delete brk */
+ class cl_event_handler *eh;
+ int t= CELL_NORMAL;
+ if ((eh= cell->get_event_handler()))
+ t= eh->del_bp(brk);
+ if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
+ {
+ cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
+ cell->set_type(cell->get_type() | t);
+ return;
+ }
+ nc= new cl_normal_cell(width);
+ nc->set(cell->get());
+ nc->set_type(cell->get_type() & ~CELL_GENERAL);
+ nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
+ return;
+ }
+ else
+ {
+ /* Normal cell */
+ return;
+ }
+
+ if (addr >= size)
+ {
+ delete dummy;
+ dummy= nc;
+ }
+ else
+ {
+ delete array[addr];
+ array[addr]= nc;
+ }
+ uc->sim->/*app->*/mem_cell_changed(this, addr);
+}
+
+
+#ifdef STATISTIC
+unsigned long
+cl_m::get_nuof_reads(void)
+{
+ unsigned long res= 0;
+ t_addr i;
+ for (i= 0; i < size; i++)
+ res+= array[i]->nuof_reads;
+ return(res);
+}
+
+unsigned long
+cl_m::get_nuof_writes(void)
+{
+ unsigned long res= 0;
+ t_addr i;
+ for (i= 0; i < size; i++)
+ res+= array[i]->nuof_writes;
+ return(res);
+}
+
+void
+cl_m::set_nuof_reads(unsigned long value)
+{
+ t_addr i;
+ for (i= 0; i < size; i++)
+ array[i]->nuof_reads= value;
+ dummy->nuof_reads= value;
+}
+
+void
+cl_m::set_nuof_writes(unsigned long value)
+{
+ t_addr i;
+ for (i= 0; i < size; i++)
+ array[i]->nuof_writes= value;
+ dummy->nuof_writes= value;
+}
+#endif
+
+
+cl_normal_cell::cl_normal_cell(uchar awidth):
+ cl_cell()
+{
+ type= CELL_NORMAL;
+ data= 0;
+ mask= 1;
+ width= awidth;
+ for (--awidth; awidth; awidth--)
+ {
+ mask<<= 1;
+ mask|= 1;
+ }
+}
+
+t_mem
+cl_normal_cell::add(long what)
+{
+ t_mem d;
+
+ if (width <= 8)
+ d= TYPE_BYTE(data) + what;
+ else if (width <= 16)
+ d= TYPE_WORD(data) + what;
+ else
+ d= TYPE_DWORD(data) + what;
+ return(data= d & mask);
+}
+
+t_mem
+cl_normal_cell::wadd(long what)
+{
+ t_mem d;
+
+ if (width <= 8)
+ d= TYPE_BYTE(data) + what;
+ else if (width <= 16)
+ d= TYPE_WORD(data) + what;
+ else
+ d= TYPE_DWORD(data) + what;
+ return(write(d));
+}
+
+void
+cl_normal_cell::set_bit1(t_mem bits)
+{
+ bits&= mask;
+ data|= bits;
+}
+
+void
+cl_normal_cell::set_bit0(t_mem bits)
+{
+ bits&= mask;
+ data&= ~bits;
+}
+
+
+/*
+ */
+
+cl_registered_cell::cl_registered_cell(uchar awidth):
+ cl_normal_cell(awidth)
+{
+ type= CELL_HW_READ | CELL_HW_WRITE;
+ //hws= new cl_list(1, 1);
+ hardwares= 0;
+ nuof_hws= 0;
+}
+
+cl_registered_cell::~cl_registered_cell(void)
+{
+ if (hardwares)
+ free(hardwares);
+}
+
+/*void
+cl_registered_cell::destroy(void)
+{
+ hardwares= 0;
+ nuof_hws= 0;
+}*/
+
+t_mem
+cl_registered_cell::read(void)
+{
+ int i;
+ t_mem d= data;
+
+ if (nuof_hws)
+ for (i= 0; i < nuof_hws; i++)
+ {
+ d= hardwares[i]->read(this);
+ ;
+ }
+#ifdef STATISTIC
+ nuof_reads++;
+#endif
+ return(d & mask);
+}
+
+t_mem
+cl_registered_cell::read(enum hw_cath skip)
+{
+ int i;
+ t_mem d= data;
+
+ if (nuof_hws)
+ for (i= 0; i < nuof_hws; i++)
+ {
+ if ((skip & hardwares[i]->cathegory) == 0)
+ d= hardwares[i]->read(this);
+ ;
+ }
+#ifdef STATISTIC
+ nuof_reads++;
+#endif
+ return(d & mask);
+}
+
+t_mem
+cl_registered_cell::write(t_mem val)
+{
+ int i;
+
+ val&= mask;
+ if (nuof_hws)
+ for (i= 0; i < nuof_hws; i++)
+ {
+ hardwares[i]->write(this, &val);
+ ;
+ }
+#ifdef STATISTIC
+ nuof_writes++;
+#endif
+ return(data= val & mask);
+}
+
+class cl_cell *
+cl_registered_cell::add_hw(class cl_hw *hw, int *ith)
+{
+ if (!hw)
+ {
+ /* Whatta hell!? */
+ return(0);
+ }
+ if (!hardwares)
+ hardwares= (class cl_hw **)malloc(sizeof(class cl_hw *));
+ else
+ hardwares= (class cl_hw **)realloc(hardwares,
+ sizeof(class c_hw *) * (nuof_hws+1));
+ hardwares[nuof_hws]= hw;
+ nuof_hws++;
+ if (ith)
+ *ith= nuof_hws-1;
+ return(this);
+}
+
+class cl_hw *
+cl_registered_cell::get_hw(int ith)
+{
+ if (ith >= nuof_hws)
+ return(0);
+ return(hardwares[ith]);
+}
+
+
+/*
+ */
+
+cl_event_cell::cl_event_cell(uchar awidth, class cl_uc *auc):
+ cl_normal_cell(awidth)
+{
+ eh= new cl_event_handler(auc);
+}
+
+cl_event_cell::~cl_event_cell(void)
+{
+ delete eh;
+}
+
+t_mem
+cl_event_cell::read(void)
+{
+ if (type & CELL_READ_BRK)
+ eh->read();
+ return(cl_normal_cell::read());
+}
+
+t_mem
+cl_event_cell::write(t_mem val)
+{
+ if (type & CELL_WRITE_BRK)
+ eh->write();
+ return(cl_normal_cell::write(val));
+}
+
+
+/*
+ */
+
+cl_ev_reg_cell::cl_ev_reg_cell(uchar awidth, class cl_uc *auc):
+ cl_registered_cell(awidth)
+{
+ eh= new cl_event_handler(auc);
+}
+
+cl_ev_reg_cell::~cl_ev_reg_cell(void)
+{}
+
+t_mem
+cl_ev_reg_cell::read(void)
+{
+ if (type & CELL_READ_BRK)
+ eh->read();
+ return(cl_registered_cell::read());
+}
+
+t_mem
+cl_ev_reg_cell::write(t_mem val)
+{
+ if (type & CELL_WRITE_BRK)
+ eh->write();
+ return(cl_registered_cell::write(val));
+}
+
+
+/*
+ */
+
+cl_event_handler::cl_event_handler(class cl_uc *auc):
+ cl_base()
+{
+ uc= auc;
+ read_bps= new cl_list(1, 1);
+ write_bps= new cl_list(1, 1);
+}
+
+cl_event_handler::~cl_event_handler(void)
+{
+ read_bps->disconn_all();
+ write_bps->disconn_all();
+ delete read_bps;
+ delete write_bps;
+}
+
+void
+cl_event_handler::write(void)
+{
+ int i;
+
+ for (i= 0; i < write_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(write_bps->at(i));
+ uc->events->add(bp);
+ }
+}
+
+void
+cl_event_handler::read(void)
+{
+ int i;
+
+ for (i= 0; i < read_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(read_bps->at(i));
+ uc->events->add(bp);
+ }
+}
+
+int
+cl_event_handler::add_bp(class cl_brk *bp)
+{
+ int t= CELL_NORMAL;
+
+ if (!bp)
+ return(CELL_NORMAL);
+ switch (bp->get_event())
+ {
+ case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
+ t|= CELL_WRITE_BRK;
+ write_bps->add(bp);
+ break;
+ case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
+ t|= CELL_READ_BRK;
+ read_bps->add(bp);
+ break;
+ default:
+ t|= CELL_READ_BRK | CELL_WRITE_BRK;
+ read_bps->add(bp);
+ write_bps->add(bp);
+ break;
+ }
+ return(t);
+}
+
+int
+cl_event_handler::copy_from(class cl_event_handler *eh)
+{
+ int i, t= CELL_NORMAL;
+
+ if (!eh)
+ return(t);
+ for (i= 0; i < eh->read_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i));
+ t|= add_bp(bp);
+ }
+ for (i= 0; i < eh->write_bps->count; i++)
+ {
+ class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i));
+ t|= add_bp(bp);
+ }
+ return(t);
+}
+
+int
+cl_event_handler::del_bp(class cl_brk *bp)
+{
+ int t= CELL_NORMAL;
+
+ write_bps->disconn(bp);
+ read_bps->disconn(bp);
+ if (write_bps->count)
+ t|= CELL_WRITE_BRK;
+ if (read_bps->count)
+ t|= CELL_READ_BRK;
+ return(t);
+}
+
+