📄 mem.cc
字号:
/* * Simulator of microcontrollers (mem.cc) * * Copyright (C) 1999,99 Drotos Daniel, Talker Bt. * * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu * *//* This file is part of microcontroller simulator: ucsim. UCSIM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. UCSIM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with UCSIM; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//*@1@*/#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include "i_string.h"// prj#include "utils.h"#include "globals.h"// sim#include "simcl.h"// cmd#include "newcmdcl.h"#include "cmdutil.h"// local#include "memcl.h"#include "hwcl.h"static class cl_mem_error_registry mem_error_registry;/* * 3rd version of memory system */cl_memory::cl_memory(char *id, t_addr asize, int awidth): cl_base(){ size= asize; set_name(id); addr_format= data_format= 0; width= awidth; start_address= 0; uc= 0;}cl_memory::~cl_memory(void){ if (addr_format) free(addr_format); if (data_format) free(data_format);}intcl_memory::init(void){ 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)); data_mask= 1; int w= width; for (--w; w; w--) { data_mask<<= 1; data_mask|= 1; } dump_finished= start_address; return(0);}boolcl_memory::valid_address(t_addr addr){ return(addr >= start_address && addr < start_address+size);}t_addrcl_memory::inc_address(t_addr addr, int val){ if (!start_address) return(((signed)addr+val)%size); addr-= start_address; addr+= val; addr%= size; addr+= start_address; return(addr);}t_addrcl_memory::inc_address(t_addr addr){ if (!start_address) return(((signed)addr+1)%size); addr-= start_address; addr++; addr%= size; addr+= start_address; return(addr);}t_addrcl_memory::validate_address(t_addr addr){ while (addr < start_address) addr+= size; if (addr > start_address+size) { addr-= start_address; addr%= size; addr+= start_address; } return(addr);}voidcl_memory::err_inv_addr(t_addr addr){ if (!uc) return; class cl_error *e= new cl_error_mem_invalid_address(this, addr); uc->error(e);}voidcl_memory::err_non_decoded(t_addr addr){ if (!uc) return; class cl_error *e= new cl_error_mem_non_decoded(this, addr); uc->error(e);}t_addrcl_memory::dump(t_addr start, t_addr stop, int bpl, class cl_console *con){ int i; t_addr lva= lowest_valid_address(); t_addr hva= highest_valid_address(); if (start < lva) start= lva; if (stop > hva) stop= hva; while ((start <= stop) && (start < hva)) { con->dd_printf(addr_format, start); con->dd_printf(" "); for (i= 0; (i < bpl) && (start+i < hva) && (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 < hva) && (start+i <= stop); i++) { long c= read(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_addrcl_memory::dump(class cl_console *con){ return(dump(dump_finished, dump_finished+10*8-1, 8, con));}boolcl_memory::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);}/* * Memory operators */cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell, t_addr addr): cl_base(){ cell= acell; data= 0; mask= ~0; next_operator= 0; address= addr;}cl_memory_operator::cl_memory_operator(class cl_memory_cell *acell, t_addr addr, t_mem *data_place, t_mem the_mask): cl_base(){ cell= acell; data= data_place; mask= the_mask; next_operator= 0; address= addr;}voidcl_memory_operator::set_data(t_mem *data_place, t_mem the_mask){ data= data_place; mask= the_mask;}t_memcl_memory_operator::read(void){ if (next_operator) return(next_operator->read()); else return(*data);}t_memcl_memory_operator::write(t_mem val){ if (next_operator) return(next_operator->write(val)); else return(*data= (val & mask));}/* Memory operator for hw callbacks */cl_hw_operator::cl_hw_operator(class cl_memory_cell *acell, t_addr addr, t_mem *data_place, t_mem the_mask, class cl_hw *ahw): cl_memory_operator(acell, addr, data_place, the_mask){ hw= ahw;}t_memcl_hw_operator::read(void){ t_mem d= 0; if (hw) d= hw->read(cell); if (next_operator) next_operator->read(); return(d);}t_memcl_hw_operator::read(enum hw_cath skip){ t_mem d= *data; if (hw && hw->cathegory != skip) d= hw->read(cell); if (next_operator) next_operator->read(); return(d); }t_memcl_hw_operator::write(t_mem val){ if (hw) hw->write(cell, &val); if (next_operator) val= next_operator->write(val); return(*data= (val & mask));}/* Write event break on cell */cl_write_operator::cl_write_operator(class cl_memory_cell *acell, t_addr addr, t_mem *data_place, t_mem the_mask, class cl_uc *auc, class cl_brk *the_bp): cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp){ uc= auc; bp= the_bp;}t_memcl_write_operator::write(t_mem val){ //printf("write event at 0x%x bp=%p\n",address,bp); uc->events->add(bp); if (next_operator) return(next_operator->write(val)); else return(*data= (val & mask));}/* Read event break on cell */cl_read_operator::cl_read_operator(class cl_memory_cell *acell, t_addr addr, t_mem *data_place, t_mem the_mask, class cl_uc *auc, class cl_brk *the_bp): cl_event_break_operator(acell, addr, data_place, the_mask, auc, the_bp){ uc= auc; bp= the_bp;}t_memcl_read_operator::read(void){ //printf("read event at 0x%x bp=%p\n",address,bp); uc->events->add(bp); if (next_operator) return(next_operator->read()); else return(*data);}/* * Memory cell */cl_memory_cell::cl_memory_cell(void): cl_base(){ data= (t_mem *)malloc(sizeof(t_mem)); flags= CELL_NON_DECODED; width= 8; *data= 0; operators= NULL;#ifdef STATISTIC nuof_writes= nuof_reads= 0;#endif mask= 1; int w= width; for (--w; w; w--) { mask<<= 1; mask|= 1; }}cl_memory_cell::~cl_memory_cell(void){ if ((flags & CELL_NON_DECODED) && data) free(data);}intcl_memory_cell::init(void){ cl_base::init(); set(0/*rand()*/); return(0);}TYPE_UBYTEcl_memory_cell::get_flags(void){ return(flags);}boolcl_memory_cell::get_flag(enum cell_flag flag){ return(flags & flag);}voidcl_memory_cell::set_flags(TYPE_UBYTE what){ flags= what;}voidcl_memory_cell::set_flag(enum cell_flag flag, bool val){ if (val) flags|= flag; else flags&= ~(flag);}voidcl_memory_cell::un_decode(void){ if ((flags & CELL_NON_DECODED) == 0) { data= (t_mem *)malloc(sizeof(t_mem)); flags|= CELL_NON_DECODED; }}voidcl_memory_cell::decode(class cl_memory_chip *chip, t_addr addr){ if (flags & CELL_NON_DECODED) free(data); data= chip->get_slot(addr); if (!data) { data= (t_mem *)malloc(sizeof(t_mem)); flags|= CELL_NON_DECODED; } else flags&= ~(CELL_NON_DECODED);}t_memcl_memory_cell::read(void){#ifdef STATISTIC nuof_reads++;#endif if (operators) return(operators->read()); return(*data);}t_memcl_memory_cell::read(enum hw_cath skip){#ifdef STATISTIC nuof_reads++;#endif if (operators) return(operators->read(skip)); return(*data);} t_memcl_memory_cell::get(void) { return(*data);}t_memcl_memory_cell::write(t_mem val){#ifdef STATISTIC nuof_writes++;#endif if (operators) return(operators->write(val)); *data= val & mask; return(*data);}t_memcl_memory_cell::set(t_mem val){ *data= val & mask; return(*data);}t_memcl_memory_cell::add(long what){ *data= (*data + what) & mask; return(*data);}t_memcl_memory_cell::wadd(long what){ t_mem d= (*data + what) & mask; return(write(d));}voidcl_memory_cell::set_bit1(t_mem bits){ bits&= mask; (*data)|= bits;}voidcl_memory_cell::set_bit0(t_mem bits){ bits&= mask; (*data)&= ~bits;}voidcl_memory_cell::append_operator(class cl_memory_operator *op){ if (!operators) operators= op; else { class cl_memory_operator *o= operators, *n; n= o->get_next(); while (n) { o= n; n= o->get_next(); } o->set_next(op); }}voidcl_memory_cell::prepend_operator(class cl_memory_operator *op){ if (op) { op->set_next(operators); operators= op; }}voidcl_memory_cell::del_operator(class cl_brk *brk){ if (!operators) return; class cl_memory_operator *op= operators; if (operators->match(brk)) { operators= op->get_next(); delete op; } else { while (op->get_next() && !op->get_next()->match(brk)) op= op->get_next(); if (op->get_next()) { class cl_memory_operator *m= op->get_next(); op->set_next(m->get_next());; delete m; } }}class cl_memory_cell *cl_memory_cell::add_hw(class cl_hw *hw, int *ith, t_addr addr){ class cl_hw_operator *o= new cl_hw_operator(this, addr, data, mask, hw); append_operator(o); return(this);}/*class cl_hw *cl_memory_cell::get_hw(int ith){ return(0);}*/class cl_event_handler *cl_memory_cell::get_event_handler(void){ return(0);}/* * Dummy cell for non-existent addresses */t_memcl_dummy_cell::write(t_mem val){#ifdef STATISTIC nuof_writes++;#endif *data= rand() & mask; return(*data);}t_memcl_dummy_cell::set(t_mem val){ *data= rand() & mask; return(*data);}/* * Address space */cl_address_space::cl_address_space(char *id,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -