/* * memory.c * $Id: memory.c,v 1.10 2004/11/11 09:02:51 mah Exp $ * Christoph Berg * Mark Hillebrand */ #include #include #include "help.h" #include "dlx.h" #include "memory.h" void init_memory(int size) { // TODO what about non-zero memory initialization? static int is_initialized = 0; if(is_initialized) { free(state.memory); } if ((state.memory = calloc(1, size)) == NULL) { die("cannot allocate 0x%x bytes (%d MB) memory", size, size >> 20); } state.memorysize = size; is_initialized = 1; printf("allocated 0x%x bytes (%d MB) memory\n", size, size >> 20); } void fill_memory(char *memory, int start, int length, char c) { int pos; for(pos = start; pos < start + length; pos++) { memory[pos] = c; } } void count_memory(char *memory, int start, int length) { int pos; for(pos = start; pos < start + length; pos++) { memory[pos] = pos & 0xff; } } void poke(char *memory, int pos, int data) { int *mempos = (int *)(memory+pos); *mempos = data; } int usermode() { return state.spr[SPR_MODE] & 1; } int systemmode() { return !usermode(); } int buserror(int ea) { if( ea < 0 || ea >= state.memorysize ) { STEP_TRACE("bus error at address 0x%x",ea); return 1; } return 0; } int physicaladdress( int ea ) { // (no error checks) if( !(arch & ARCH_VM) || systemmode() ) { return ea; } else { return (*((int*)(state.memory + (state.spr[SPR_PTO] << 12) + (PX(ea)<<2)))& PTE_PPX_MASK) | BX(ea); } } int pagefault( int mw, int ea ) { int excp = 0; int ptea, pte; if( !(arch & ARCH_VM) || systemmode() ) { excp = buserror(ea); } else if( PX(ea) > state.spr[SPR_PTL] ) { excp = 1; } else { ptea = (state.spr[SPR_PTO] << 12) + (PX(ea)<<2); excp = buserror(ptea); if( excp ) { STEP_TRACE("page table access out of allocated memory (PX=0x%x)",PX(ea)); } else { pte = *((int*)(state.memory + ptea)); excp = !PTE_V(pte) || (mw && PTE_P(pte)); if( !excp ) { excp = buserror((pte&PTE_PPX_MASK) | BX(ea)); } } } return excp; } int memop_fetch(unsigned pc,void *data) { int excp = 0; if( pc & 0x3 ) { STEP_TRACE("misalignment at dpc=0x%x", pc); excp = CA_mal; } else if( pagefault(0,pc) ) { excp = CA_ipf; } else { pc = physicaladdress(pc); } *((int*)data) = excp ? 0 : *((int*)(state.memory+pc)); return excp; } // TODO why ea int, not unsigned? int memop_load(int ea,int d,int sign,void *data) { int excp = 0; if(ea == 0) STEP_WARNING("NULL pointer load at dpc=0x%x", state.dpc); if( ea % d ) { STEP_TRACE("misalignment at dpc=0x%x, access width d=%d, effective address 0x%x", state.dpc, d, ea); excp = CA_mal; } else if( pagefault(0,ea) ) { excp = CA_dpf; } else { ea = physicaladdress(ea); switch( d ) { case 1: if( sign ) { *((int*)data) = *((char*)(state.memory+ea)); } else { *((unsigned*)data) = *((unsigned char*)(state.memory+ea)); } break; case 2: if( sign ) { *((int*)data) = *((short int*)(state.memory+ea)); } else { *((unsigned*)data) = *((unsigned short int*)(state.memory+ea)); } break; case 4: *((int*)data) = *((int*)(state.memory+ea)); break; case 8: *((double*)data) = *((double*)(state.memory+ea)); break; } } if ( excp ) { // make sure to return zero data *((int*)data) = 0; if( d==8 ) *(((int*)data)+1) = 0; } return excp; } int memop_store(int ea,int d,void *data) { int excp = 0; if(ea == 0) STEP_WARNING("NULL pointer store at dpc=0x%x", state.dpc); if( ea % d ) { STEP_TRACE("misalignment at dpc=0x%x, access width d=%d, effective address 0x%x", state.dpc, d, ea); excp = CA_mal; } else if( pagefault(1,ea) ) { excp = CA_dpf; } else { ea = physicaladdress(ea); switch( d ) { case 1: *((char*)(state.memory+ea)) = *((char*)data); break; case 2: *((short int*)(state.memory+ea)) = *((short int*)data); break; case 4: *((int*)(state.memory+ea)) = *((int*)data); break; case 8: *((double*)(state.memory+ea)) = *((double*)data); break; } } return excp; }