+}*/
+
+
+/*
+ * New type of memory simulation
+ */
+
+cl_cell::cl_cell(void):
+ cl_base()
+{
+#ifdef STATISTIC
+ nuof_writes= nuof_reads= 0;
+#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_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);
+}
+
+
+/*
+ */
+
+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_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_mem(atype, aclass_name, 0, awidth, auc)
+{
+ t_addr a;
+
+ size= asize;
+ width= awidth;
+ 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;
+}
+
+void
+cl_m::err_inv_addr(t_addr addr)
+{
+ if (!uc)
+ return;
+ class cl_error *e= new cl_err_inv_addr(this, addr);
+ uc->error(e);
+}
+
+/*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;
+}*/
+
+int
+cl_m::get_cell_flag(t_addr addr)
+{
+ if (addr >= size)
+ {
+ return(dummy->get_type());
+ }
+ return(array[addr]->get_type());
+}
+
+bool
+cl_m::get_cell_flag(t_addr addr, int flag)
+{
+ if (addr >= size)
+ {
+ return(dummy->get_type() & flag);
+ }
+ return(array[addr]->get_type() & flag);
+}
+
+void
+cl_m::set_cell_flag(t_addr addr, bool set_to, int flag)
+{
+ class cl_cell *cell;
+
+ if (addr >= size)
+ {
+ cell= dummy;
+ }
+ else
+ cell= array[addr];
+ if (set_to)
+ cell->set_type(cell->get_type() | flag);
+ else
+ cell->set_type(cell->get_type() & ~flag);
+}
+
+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));
+}
+
+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
+
+
+/*
+ * Errors in memory handling
+ */
+
+cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr):
+ cl_error()
+{
+ mem= amem;
+ addr= aaddr;
+}
+
+void
+cl_err_inv_addr::print(class cl_commander *c)
+{
+ c->dd_printf("Error: invalid address ");
+ c->dd_printf(mem->addr_format, addr);
+ c->dd_printf(" in memory %s.\n", mem->class_name);