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
49 * Memory location handled specially by a hw element
52 /*cl_memloc::cl_memloc(t_addr addr):
56 hws= new cl_list(2, 2);
60 /*cl_memloc::~cl_memloc(void)
67 cl_memloc::read(class cl_mem *mem)
75 if ((hw= (class cl_hw *)(hws->at(0))))
76 ret= hw->read(mem, address);
81 cl_memloc::write(class cl_mem *mem, t_addr addr, t_mem *val)
88 for (i= 0; i < hws->count; i++)
90 hw= (class cl_hw *)hws->at(0);
91 hw->write(mem, addr, val);
96 /* Sorted collection of memory locations */
98 /*cl_memloc_coll::cl_memloc_coll(void):
101 Duplicates= DD_FALSE;
105 cl_memloc_coll::key_of(void *item)
107 return(&(((class cl_memloc *)item)->address));
111 cl_memloc_coll::compare(void *key1, void *key2)
113 if (*(long*)key1 > *(long*)key2)
116 if (*(long*)key1 < *(long*)key2)
123 cl_memloc_coll::get_loc(t_addr address)
127 if (search(&address, i))
128 return((class cl_memloc*)(at(i)));
135 ******************************************************************************
138 cl_mem::cl_mem(enum mem_class atype, char *aclass_name,
139 t_addr asize, int awidth, class cl_uc *auc):
146 class_name= aclass_name;
150 for (i= width, mask= 0; i; i--)
156 mem= (TYPE_UBYTE *)malloc(size);
157 else if (width <= 16)
158 mem= (TYPE_UWORD *)malloc(size*sizeof(TYPE_WORD));
160 mem= (TYPE_UDWORD *)malloc(size*sizeof(TYPE_DWORD));
161 //read_locs= new cl_memloc_coll();
162 //write_locs= new cl_memloc_coll();
164 addr_format= data_format= 0;
167 cl_mem::~cl_mem(void)
184 addr_format= (char *)malloc(10);
185 sprintf(addr_format, "0x%%0%dx",
191 (size-1<=0xffffff?6:12))))));
192 data_format= (char *)malloc(10);
193 sprintf(data_format, "%%0%dx", width/4+((width%4)?1:0));
195 for (i= 0; i < size; i++)
196 set(i, (type==MEM_ROM)?(-1):0);
201 cl_mem::id_string(void)
203 char *s= get_id_string(mem_ids, type);
205 return(s?s:(char*)"NONE");
209 cl_mem::read(t_addr addr)
211 //class cl_memloc *loc;
216 fprintf(stderr, "Address 0x%06"_A_"x is over 0x%06"_A_"x\n", addr, size);
219 /*if ((loc= read_locs->get_loc(addr)))
220 return(loc->read(this));*/
222 return((((TYPE_UBYTE*)mem)[addr])&mask);
223 else if (width <= 16)
224 return((((TYPE_UWORD*)mem)[addr])&mask);
226 return((((TYPE_UDWORD*)mem)[addr])&mask);
230 cl_mem::get(t_addr addr)
235 return((((TYPE_UBYTE*)mem)[addr])&mask);
236 else if (width <= 16)
237 return((((TYPE_UWORD*)mem)[addr])&mask);
239 return((((TYPE_UDWORD*)mem)[addr])&mask);
244 * Modify memory location
247 /* Write calls callbacks of HW elements */
250 cl_mem::write(t_addr addr, t_mem val)
252 /* class cl_memloc *loc;
256 if ((loc= write_locs->get_loc(addr)))
257 loc->write(this, addr, val);
259 ((TYPE_UBYTE*)mem)[addr]= (*val)&mask;
260 else if (width <= 16)
261 ((TYPE_UWORD*)mem)[addr]= (*val)&mask;
263 ((TYPE_UDWORD*)mem)[addr]= (*val)&mask;*/
264 fprintf(stderr, "FIXME cl_mem::write(0x%06"_A_"x, 0x%04"_M_"x)\n",
269 /* Set doesn't call callbacks */
272 cl_mem::set(t_addr addr, t_mem val)
277 ((TYPE_UBYTE*)mem)[addr]= val&mask;
278 else if (width <= 16)
279 ((TYPE_UWORD*)mem)[addr]= val&mask;
281 ((TYPE_UDWORD*)mem)[addr]= val&mask;
284 /* Set or clear bits, without callbacks */
287 cl_mem::set_bit1(t_addr addr, t_mem bits)
293 ((TYPE_UBYTE*)mem)[addr]|= bits;
294 else if (width <= 16)
295 ((TYPE_UWORD*)mem)[addr]|= bits;
297 ((TYPE_UDWORD*)mem)[addr]|= bits;
301 cl_mem::set_bit0(t_addr addr, t_mem bits)
307 ((TYPE_UBYTE*)mem)[addr]&= ~bits;
308 else if (width <= 16)
309 ((TYPE_UWORD*)mem)[addr]&= ~bits;
311 ((TYPE_UDWORD*)mem)[addr]&= ~bits;
315 cl_mem::add(t_addr addr, long what)
321 ((TYPE_UBYTE*)mem)[addr]= ((TYPE_UBYTE*)mem)[addr] + what;
322 return(((TYPE_UBYTE*)mem)[addr]);
324 else if (width <= 16)
326 ((TYPE_UWORD*)mem)[addr]= ((TYPE_UWORD*)mem)[addr] + what;
327 return(((TYPE_UWORD*)mem)[addr]);
331 ((TYPE_UDWORD*)mem)[addr]= ((TYPE_UDWORD*)mem)[addr] + what;
332 return(((TYPE_UDWORD*)mem)[addr]);
337 cl_mem::dump(t_addr start, t_addr stop, int bpl, class cl_console *con)
341 while ((start <= stop) &&
344 con->dd_printf(addr_format, start); con->dd_printf(" ");
351 con->dd_printf(data_format, /*read*/get(start+i)); con->dd_printf(" ");
356 j= width/4 + ((width%4)?1:0) + 1;
364 for (i= 0; (i < bpl) &&
369 long c= get(start+i);
370 con->dd_printf("%c", isprint(255&c)?(255&c):'.');
372 con->dd_printf("%c", isprint(255&(c>>8))?(255&(c>>8)):'.');
374 con->dd_printf("%c", isprint(255&(c>>16))?(255&(c>>16)):'.');
376 con->dd_printf("%c", isprint(255&(c>>24))?(255&(c>>24)):'.');
378 con->dd_printf("\n");
379 dump_finished= start+i;
382 return(dump_finished);
386 cl_mem::dump(class cl_console *con)
388 return(dump(dump_finished, dump_finished+10*8-1, 8, con));
392 cl_mem::search_next(bool case_sensitive, t_mem *array, int len, t_addr *addr)
411 for (i= 0; i < len && match; i++)
418 if (/*d1 < 128*/isalpha(d1))
420 if (/*d2 < 128*/isalpha(d2))
440 /*cl_bitmap::cl_bitmap(t_addr asize):
443 map= (uchar*)malloc(size= asize/(8*SIZEOF_CHAR));
444 memset(map, 0, size);
447 cl_bitmap::~cl_bitmap(void)
453 cl_bitmap::set(t_addr pos)
457 if ((i= pos/(8*SIZEOF_CHAR)) < size)
458 map[i]|= (1 << (pos & ((8*SIZEOF_CHAR)-1)));
462 cl_bitmap::clear(t_addr pos)
466 if ((i= pos/(8*SIZEOF_CHAR)) < size)
467 map[i]&= ~(1 << (pos & ((8*SIZEOF_CHAR)-1)));
471 cl_bitmap::get(t_addr pos)
473 return(map[pos/(8*SIZEOF_CHAR)] & (1 << (pos & ((8*SIZEOF_CHAR)-1))));
477 cl_bitmap::empty(void)
481 for (i= 0; i < size && map[i] == 0; i++) ;
486 * Special memory for code (ROM)
489 /*cl_rom::cl_rom(t_addr asize, int awidth, class cl_uc *auc):
490 cl_mem(MEM_ROM, get_id_string(mem_classes, MEM_ROM), asize, awidth, auc)
492 bp_map= new cl_bitmap(asize);
493 inst_map= new cl_bitmap(asize);
496 cl_rom::~cl_rom(void)
504 * New type of memory simulation
507 cl_cell::cl_cell(void):
511 nuof_writes= nuof_reads= 0;
516 cl_normal_cell::cl_normal_cell(uchar awidth):
523 for (--awidth; awidth; awidth--)
531 cl_normal_cell::add(long what)
536 d= TYPE_BYTE(data) + what;
537 else if (width <= 16)
538 d= TYPE_WORD(data) + what;
540 d= TYPE_DWORD(data) + what;
541 return(data= d & mask);
545 cl_normal_cell::wadd(long what)
550 d= TYPE_BYTE(data) + what;
551 else if (width <= 16)
552 d= TYPE_WORD(data) + what;
554 d= TYPE_DWORD(data) + what;
559 cl_normal_cell::set_bit1(t_mem bits)
566 cl_normal_cell::set_bit0(t_mem bits)
576 cl_registered_cell::cl_registered_cell(uchar awidth):
577 cl_normal_cell(awidth)
579 type= CELL_HW_READ | CELL_HW_WRITE;
580 //hws= new cl_list(1, 1);
585 cl_registered_cell::~cl_registered_cell(void)
592 cl_registered_cell::destroy(void)
599 cl_registered_cell::read(void)
605 for (i= 0; i < nuof_hws; i++)
607 d= hardwares[i]->read(this);
617 cl_registered_cell::read(enum hw_cath skip)
623 for (i= 0; i < nuof_hws; i++)
625 if ((skip & hardwares[i]->cathegory) == 0)
626 d= hardwares[i]->read(this);
636 cl_registered_cell::write(t_mem val)
642 for (i= 0; i < nuof_hws; i++)
644 hardwares[i]->write(this, &val);
650 return(data= val & mask);
654 cl_registered_cell::add_hw(class cl_hw *hw, int *ith)
662 hardwares= (class cl_hw **)malloc(sizeof(class cl_hw *));
664 hardwares= (class cl_hw **)realloc(hardwares,
665 sizeof(class c_hw *) * (nuof_hws+1));
666 hardwares[nuof_hws]= hw;
674 cl_registered_cell::get_hw(int ith)
678 return(hardwares[ith]);
685 cl_event_handler::cl_event_handler(class cl_uc *auc):
689 read_bps= new cl_list(1, 1);
690 write_bps= new cl_list(1, 1);
693 cl_event_handler::~cl_event_handler(void)
695 read_bps->disconn_all();
696 write_bps->disconn_all();
702 cl_event_handler::write(void)
706 for (i= 0; i < write_bps->count; i++)
708 class cl_brk *bp= (class cl_brk *)(write_bps->at(i));
714 cl_event_handler::read(void)
718 for (i= 0; i < read_bps->count; i++)
720 class cl_brk *bp= (class cl_brk *)(read_bps->at(i));
726 cl_event_handler::add_bp(class cl_brk *bp)
732 switch (bp->get_event())
734 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
738 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
743 t|= CELL_READ_BRK | CELL_WRITE_BRK;
752 cl_event_handler::copy_from(class cl_event_handler *eh)
754 int i, t= CELL_NORMAL;
758 for (i= 0; i < eh->read_bps->count; i++)
760 class cl_brk *bp= (class cl_brk *)(eh->read_bps->at(i));
763 for (i= 0; i < eh->write_bps->count; i++)
765 class cl_brk *bp= (class cl_brk *)(eh->write_bps->at(i));
772 cl_event_handler::del_bp(class cl_brk *bp)
776 write_bps->disconn(bp);
777 read_bps->disconn(bp);
778 if (write_bps->count)
789 cl_event_cell::cl_event_cell(uchar awidth, class cl_uc *auc):
790 cl_normal_cell(awidth)
792 eh= new cl_event_handler(auc);
795 cl_event_cell::~cl_event_cell(void)
801 cl_event_cell::read(void)
803 if (type & CELL_READ_BRK)
805 return(cl_normal_cell::read());
809 cl_event_cell::write(t_mem val)
811 if (type & CELL_WRITE_BRK)
813 return(cl_normal_cell::write(val));
820 cl_ev_reg_cell::cl_ev_reg_cell(uchar awidth, class cl_uc *auc):
821 cl_registered_cell(awidth)
823 eh= new cl_event_handler(auc);
826 cl_ev_reg_cell::~cl_ev_reg_cell(void)
830 cl_ev_reg_cell::read(void)
832 if (type & CELL_READ_BRK)
834 return(cl_registered_cell::read());
838 cl_ev_reg_cell::write(t_mem val)
840 if (type & CELL_WRITE_BRK)
842 return(cl_registered_cell::write(val));
849 cl_mapped_cell::cl_mapped_cell(class cl_cell *realcell)
854 cl_mapped_cell::~cl_mapped_cell(void)
858 cl_mapped_cell::read(void)
860 return(real_cell->read());
864 cl_mapped_cell::read(enum hw_cath skip)
866 return(real_cell->read(skip));
870 cl_mapped_cell::get(void)
872 return(real_cell->get());
876 cl_mapped_cell::write(t_mem val)
878 return(real_cell->write(val));
882 cl_mapped_cell::set(t_mem val)
884 return(real_cell->set(val));
888 cl_mapped_cell::add(long what)
890 return(real_cell->add(what));
894 cl_mapped_cell::wadd(long what)
896 return(real_cell->wadd(what));
900 cl_mapped_cell::set_bit1(t_mem bits)
902 return(real_cell->set_bit1(bits));
906 cl_mapped_cell::set_bit0(t_mem bits)
908 return(real_cell->set_bit0(bits));
912 cl_mapped_cell::add_hw(class cl_hw *hw, int *ith)
914 return(real_cell->add_hw(hw, ith));
918 cl_mapped_cell::get_hw(int ith)
920 return(real_cell->get_hw(ith));
923 class cl_event_handler *
924 cl_mapped_cell::get_event_handler(void)
926 return(real_cell->get_event_handler());
933 cl_m::cl_m(enum mem_class atype, char *aclass_name, t_addr asize, int awidth,
935 cl_mem(atype, aclass_name, 0, awidth, auc)
941 array= (class cl_cell **)calloc(size, sizeof(class cl_cell *));
942 for (a= 0; a < size; a++)
943 array[a]= new cl_normal_cell(width);
946 for (i= 1; i < size; i<<=1)
947 bus_mask= (bus_mask<<1)|1;
948 dummy= new cl_normal_cell(width);
956 for (a= 0; a < size; a++)
963 cl_m::err_inv_addr(t_addr addr)
967 class cl_error *e= new cl_err_inv_addr(this, addr);
972 cl_m::mk_cell(t_addr addr, class cl_cell *cell)
975 cell= new cl_cell(width);
983 p= (class cl_cell *)calloc(1, sizeof(*cell));
988 p= (class cl_cell *)realloc(p, sizeof(cell));
990 memcpy(p, cell, sizeof(*cell));
996 cl_m::get_cell_flag(t_addr addr)
1000 return(dummy->get_type());
1002 return(array[addr]->get_type());
1006 cl_m::get_cell_flag(t_addr addr, int flag)
1010 return(dummy->get_type() & flag);
1012 return(array[addr]->get_type() & flag);
1016 cl_m::set_cell_flag(t_addr addr, bool set_to, int flag)
1018 class cl_cell *cell;
1027 cell->set_type(cell->get_type() | flag);
1029 cell->set_type(cell->get_type() & ~flag);
1033 cl_m::read(t_addr addr)
1039 return(dummy->read());
1041 return(array[addr]->read());
1045 cl_m::read(t_addr addr, enum hw_cath skip)
1051 return(dummy->read(skip));
1053 return(array[addr]->read(skip));
1057 cl_m::get(t_addr addr)
1063 return(dummy->get());
1065 return(array[addr]->get());
1069 cl_m::write(t_addr addr, t_mem val)
1075 return(dummy->write(val));
1077 return(array[addr]->write(val));
1081 cl_m::set(t_addr addr, t_mem val)
1091 array[addr]->set(val);
1095 cl_m::get_cell(t_addr addr)
1103 return(array[addr]);
1107 /* Set or clear bits, without callbacks */
1110 cl_m::set_bit1(t_addr addr, t_mem bits)
1112 class cl_cell *cell;
1122 bits&= cell->get_mask();
1123 cell->set(cell->get() | bits);
1127 cl_m::write_bit1(t_addr addr, t_mem bits)
1129 class cl_cell *cell;
1139 bits&= cell->get_mask();
1140 cell->write(cell->get() | bits);
1144 cl_m::set_bit0(t_addr addr, t_mem bits)
1146 class cl_cell *cell;
1156 bits&= cell->get_mask();
1157 cell->set(cell->get() & ~bits);
1161 cl_m::write_bit0(t_addr addr, t_mem bits)
1163 class cl_cell *cell;
1173 bits&= cell->get_mask();
1174 cell->write(cell->get() & ~bits);
1178 cl_m::add(t_addr addr, long what)
1184 return(dummy->add(what));
1186 return(array[addr]->add(what));
1190 cl_m::wadd(t_addr addr, long what)
1196 return(dummy->wadd(what));
1198 return(array[addr]->wadd(what));
1202 cl_m::register_hw(t_addr addr, class cl_hw *hw, int *ith, bool announce)
1204 class cl_cell *cell, *nc;
1212 if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1214 /* Already registered */
1215 return(cell->add_hw(hw, ith));
1217 else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1219 /* Event break is set on it, now register hw */
1220 nc= new cl_ev_reg_cell(width, uc);
1221 nc->set(cell->get());
1222 nc->set_type(nc->get_type() &
1223 ~(CELL_GENERAL|CELL_READ_BRK|CELL_WRITE_BRK));
1224 nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1225 class cl_event_handler *eh= nc->get_event_handler();
1227 nc->set_type(nc->get_type() | eh->copy_from(cell->get_event_handler()));
1228 nc->add_hw(hw, ith);
1232 /* Normal cell, register hw */
1233 nc= new cl_registered_cell(width);
1234 nc->set(cell->get());
1235 nc->set_type(nc->get_type() & ~CELL_GENERAL);
1236 nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1237 nc->add_hw(hw, ith);
1251 uc->sim->/*app->*/mem_cell_changed(this, addr);
1256 cl_m::set_brk(t_addr addr, class cl_brk *brk)
1258 class cl_cell *cell, *nc;
1267 switch (brk->get_event())
1269 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR:
1272 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1276 set_cell_flag(addr, DD_TRUE, CELL_FETCH_BRK);
1279 default: e= '.'; break;
1282 if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1284 /* Hw is registered on it, now set event break */
1285 nc= new cl_ev_reg_cell(width, uc);
1286 nc->set(cell->get());
1287 nc->set_type(nc->get_type() & ~CELL_GENERAL);
1288 nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1291 while ((hw= cell->get_hw(i)) != 0)
1296 if (((class cl_registered_cell *)cell)->hardwares)
1298 free(((class cl_registered_cell *)cell)->hardwares);
1299 ((class cl_registered_cell *)cell)->hardwares= 0;
1301 class cl_event_handler *eh;
1302 if ((eh= nc->get_event_handler()))
1303 nc->set_type(nc->get_type() | eh->add_bp(brk));
1305 else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1307 /* Break is already set on it */
1308 class cl_event_handler *eh;
1309 if ((eh= cell->get_event_handler()))
1310 cell->set_type(cell->get_type() | eh->add_bp(brk));
1315 /* Normal cell, set event break */
1316 nc= new cl_event_cell(width, uc);
1317 nc->set(cell->get());
1318 nc->set_type(nc->get_type() & ~CELL_GENERAL);
1319 nc->set_type(nc->get_type() | (cell->get_type() & CELL_GENERAL));
1320 class cl_event_handler *eh;
1321 if ((eh= nc->get_event_handler()))
1322 nc->set_type(nc->get_type() | eh->add_bp(brk));
1335 uc->sim->/*app->*/mem_cell_changed(this, addr);
1339 cl_m::del_brk(t_addr addr, class cl_brk *brk)
1341 class cl_cell *cell, *nc;
1350 switch (brk->get_event())
1352 case brkWRITE: case brkWXRAM: case brkWIRAM: case brkWSFR: e= 'W'; break;
1353 case brkREAD: case brkRXRAM: case brkRCODE: case brkRIRAM: case brkRSFR:
1357 set_cell_flag(addr, DD_FALSE, CELL_FETCH_BRK);
1360 default: e= '.'; break;
1363 if (cell->get_type() & (CELL_HW_READ | CELL_HW_WRITE))
1365 /* Hw is registered on it, delete event break */
1366 class cl_event_handler *eh;
1368 if ((eh= cell->get_event_handler()))
1370 if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1372 cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1373 cell->set_type(cell->get_type() | t);
1376 nc= new cl_registered_cell(width);
1377 nc->set(cell->get());
1378 nc->set_type(cell->get_type() & ~CELL_GENERAL);
1379 nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1382 while ((hw= cell->get_hw(i)) != 0)
1387 if (((class cl_registered_cell *)cell)->hardwares)
1388 free(((class cl_registered_cell *)cell)->hardwares);
1390 else if (cell->get_type() & (CELL_READ_BRK | CELL_WRITE_BRK))
1392 /* Break already set on it, delete brk */
1393 class cl_event_handler *eh;
1395 if ((eh= cell->get_event_handler()))
1397 if (t & (CELL_READ_BRK|CELL_WRITE_BRK))
1399 cell->set_type(cell->get_type() & ~(CELL_READ_BRK|CELL_WRITE_BRK));
1400 cell->set_type(cell->get_type() | t);
1403 nc= new cl_normal_cell(width);
1404 nc->set(cell->get());
1405 nc->set_type(cell->get_type() & ~CELL_GENERAL);
1406 nc->set_type(cell->get_type() | (cell->get_type() & CELL_GENERAL));
1425 uc->sim->/*app->*/mem_cell_changed(this, addr);
1431 cl_m::get_nuof_reads(void)
1433 unsigned long res= 0;
1435 for (i= 0; i < size; i++)
1436 res+= array[i]->nuof_reads;
1441 cl_m::get_nuof_writes(void)
1443 unsigned long res= 0;
1445 for (i= 0; i < size; i++)
1446 res+= array[i]->nuof_writes;
1451 cl_m::set_nuof_reads(unsigned long value)
1454 for (i= 0; i < size; i++)
1455 array[i]->nuof_reads= value;
1456 dummy->nuof_reads= value;
1460 cl_m::set_nuof_writes(unsigned long value)
1463 for (i= 0; i < size; i++)
1464 array[i]->nuof_writes= value;
1465 dummy->nuof_writes= value;
1471 * Errors in memory handling
1474 cl_err_inv_addr::cl_err_inv_addr(class cl_mem *amem, t_addr aaddr):
1482 cl_err_inv_addr::print(class cl_commander *c)
1484 c->dd_printf("Error: invalid address ");
1485 c->dd_printf(mem->addr_format, addr);
1486 c->dd_printf(" in memory %s.\n", mem->class_name);