#include "mmu.h" // internal function to get segment at offset // @returns 0 on success, nonzero on error int getSegment(mmu_t *mmu, int offset, memory_map_t *segment) { int i; for(i=0; ilength; i++) { *segment=mmu->segments[i]; if(segment->pos<=offset&&segment->pos+segment->len>offset) return 0; } return 1; } int Mmu_checkAccess(mmu_t *mmu, int offset) { memory_map_t segment; if(getSegment(mmu, offset, &segment)) { return 0; } return segment.access; } void Mmu_readByte(mmu_t *mmu, char *byte, int offset) { memory_map_t segment; if(getSegment(mmu, offset, &segment)) { if(mmu->onError==MMU_ONERROR_ZERO) *byte=0; return; } if(segment.access&MMU_ACCESS_r) { if(segment.access&&MMU_ACCESS_absent) { segment.getter(offset-segment.pos, byte, segment.opaque); } else { *byte=segment.pointer[offset-segment.pos]; } } else { if(mmu->onError==MMU_ONERROR_ZERO) *byte=0; } } void Mmu_writeByte(mmu_t *mmu, char byte, int offset) { memory_map_t segment; if(getSegment(mmu, offset, &segment)) { return; } if(segment.access&MMU_ACCESS_w) { if(segment.access&&MMU_ACCESS_absent) { segment.setter(offset-segment.pos, byte, segment.opaque); } else { segment.pointer[offset-segment.pos]=byte; } } } void Mmu_readHalfWord(mmu_t *mmu, half_word_t *half, int offset) { for(int i=0; i<2; i++) { Mmu_readByte(mmu, &half->bytes[i], offset+i); } } void Mmu_writeHalfWord(mmu_t *mmu, half_word_t half, int offset) { for(int i=0; i<2; i++) { Mmu_writeByte(mmu, half.bytes[i], offset+i); } } void Mmu_readWord(mmu_t *mmu, word_t *half, int offset) { for(int i=0; i<4; i++) { Mmu_readByte(mmu, &half->bytes[i], offset+i); } } void Mmu_writeWord(mmu_t *mmu, word_t half, int offset) { for(int i=0; i<4; i++) { Mmu_writeByte(mmu, half.bytes[i], offset+i); } } void Mmu_readBlock(mmu_t *mmu, void* data, int offset, int length) { //get a char pointer on the data char* ptr=(char*) data; //get the segment memory_map_t segment; if(getSegment(mmu, offset, &segment)) { //clear the buffer for(int i=0; ionError==MMU_ONERROR_ZERO) { //clear the buffer for(int i=0; ilength=0; mmu->onError=0; } int Mmu_addSegment(mmu_t *mmu, int pos, int len, char* pointer, char access, char info) { if(mmu->length==32||(access&MMU_ACCESS_absent)) return 0; if(!pointer) return 1; mmu->segments[mmu->length].pos=pos; mmu->segments[mmu->length].len=len; mmu->segments[mmu->length].pointer=pointer; mmu->segments[mmu->length].access=access; mmu->segments[mmu->length].info=info; mmu->length++; return 1; } int Mmu_addAbsentSegment(mmu_t *mmu, int pos, int len, mmu_getter_t getter, mmu_setter_t setter, void* opaque, char access, char info) { if(mmu->length==32) return 0; if((!getter)||(!setter)) return 0; mmu->segments[mmu->length].pos=pos; mmu->segments[mmu->length].len=len; mmu->segments[mmu->length].opaque=opaque; mmu->segments[mmu->length].getter=getter; mmu->segments[mmu->length].setter=setter; mmu->segments[mmu->length].access=access|MMU_ACCESS_absent; mmu->segments[mmu->length].info=info; mmu->length++; return 1; } int Mmu_removeSegment(mmu_t *mmu, int pos) { for(int i=0; ilength; i++) { if(mmu->segments[i].pos==pos) { if(i!=mmu->length-1) { mmu->segments[i]=mmu->segments[mmu->length-1]; } mmu->length--; return 1; } } return 0; }