Search
lxdream.org :: lxdream/src/mem.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/mem.c
changeset 934:3acd3b3ee6d1
prev932:2602c5603ce2
next939:6f2302afeb89
author nkeynes
date Fri Dec 26 14:25:23 2008 +0000 (11 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Change RAM regions to use static arrays rather than mmap regions, for a 2-3% performance gain.
General mem cleanups, including some save state fixes that break states again.
file annotate diff log raw
1.1 --- a/src/mem.c Wed Dec 24 06:05:42 2008 +0000
1.2 +++ b/src/mem.c Fri Dec 26 14:25:23 2008 +0000
1.3 @@ -131,19 +131,25 @@
1.4
1.5 void mem_save( FILE *f )
1.6 {
1.7 - int i;
1.8 + int i, num_ram_regions = 0;
1.9 uint32_t len;
1.10
1.11 - /* All memory regions */
1.12 - fwrite( &num_mem_rgns, sizeof(num_mem_rgns), 1, f );
1.13 + /* All RAM regions (ROM and non-memory regions don't need to be saved)
1.14 + * Flash is questionable - for now we save it too */
1.15 for( i=0; i<num_mem_rgns; i++ ) {
1.16 - if( mem_rgn[i].mem != NULL ) {
1.17 + if( mem_rgn[i].flags == MEM_FLAG_RAM ) {
1.18 + num_ram_regions++;
1.19 + }
1.20 + }
1.21 + fwrite( &num_ram_regions, sizeof(num_ram_regions), 1, f );
1.22 +
1.23 + for( i=0; i<num_mem_rgns; i++ ) {
1.24 + if( mem_rgn[i].flags == MEM_FLAG_RAM ) {
1.25 fwrite_string( mem_rgn[i].name, f );
1.26 fwrite( &mem_rgn[i].base, sizeof(uint32_t), 1, f );
1.27 fwrite( &mem_rgn[i].flags, sizeof(uint32_t), 1, f );
1.28 fwrite( &mem_rgn[i].size, sizeof(uint32_t), 1, f );
1.29 - if( mem_rgn[i].flags != MEM_FLAG_ROM )
1.30 - fwrite_gzip( mem_rgn[i].mem, mem_rgn[i].size, 1, f );
1.31 + fwrite_gzip( mem_rgn[i].mem, mem_rgn[i].size, 1, f );
1.32 }
1.33 }
1.34
1.35 @@ -164,34 +170,51 @@
1.36 uint32_t len;
1.37 uint32_t base, size;
1.38 uint32_t flags;
1.39 - int i;
1.40 + int i, j;
1.41 + int mem_region_loaded[MAX_MEM_REGIONS];
1.42
1.43 - /* All memory regions */
1.44 + /* All RAM regions */
1.45 + memset( mem_region_loaded, 0, sizeof(mem_region_loaded) );
1.46 fread( &len, sizeof(len), 1, f );
1.47 - if( len != num_mem_rgns )
1.48 - return -1;
1.49 for( i=0; i<len; i++ ) {
1.50 - if( mem_rgn[i].mem != NULL ) {
1.51 - fread_string( tmp, sizeof(tmp), f );
1.52 - fread( &base, sizeof(base), 1, f );
1.53 - fread( &flags, sizeof(flags), 1, f );
1.54 - fread( &size, sizeof(size), 1, f );
1.55 - if( strcmp( mem_rgn[i].name, tmp ) != 0 ||
1.56 - base != mem_rgn[i].base ||
1.57 - flags != mem_rgn[i].flags ||
1.58 - size != mem_rgn[i].size ) {
1.59 - ERROR( "Bad memory region %d %s", i, tmp );
1.60 - return -1;
1.61 + fread_string( tmp, sizeof(tmp), f );
1.62 +
1.63 + for( j=0; j<num_mem_rgns; j++ ) {
1.64 + if( strcasecmp( mem_rgn[j].name, tmp ) == 0 ) {
1.65 + fread( &base, sizeof(base), 1, f );
1.66 + fread( &flags, sizeof(flags), 1, f );
1.67 + fread( &size, sizeof(size), 1, f );
1.68 + if( base != mem_rgn[j].base ||
1.69 + flags != mem_rgn[j].flags ||
1.70 + size != mem_rgn[j].size ) {
1.71 + ERROR( "Bad memory block %d %s (not mapped to expected region)", i, tmp );
1.72 + return -1;
1.73 + }
1.74 + if( flags != MEM_FLAG_RAM ) {
1.75 + ERROR( "Unexpected memory block %d %s (Not a RAM region)", i, tmp );
1.76 + return -1;
1.77 + }
1.78 + fread_gzip( mem_rgn[j].mem, size, 1, f );
1.79 + mem_region_loaded[j] = 1;
1.80 }
1.81 - if( flags != MEM_FLAG_ROM )
1.82 - fread_gzip( mem_rgn[i].mem, size, 1, f );
1.83 + }
1.84 + }
1.85 + /* Make sure we got all the memory regions we expected */
1.86 + for( i=0; i<num_mem_rgns; i++ ) {
1.87 + if( mem_rgn[i].flags == MEM_FLAG_RAM &&
1.88 + mem_region_loaded[i] == 0 ) {
1.89 + ERROR( "Missing memory block %s (not found in save state)", mem_rgn[i].name );
1.90 + return -1;
1.91 }
1.92 }
1.93
1.94 /* All MMIO regions */
1.95 fread( &len, sizeof(len), 1, f );
1.96 - if( len != num_io_rgns )
1.97 + if( len != num_io_rgns ) {
1.98 + ERROR( "Unexpected IO region count %d (expected %d)", len, num_io_rgns );
1.99 return -1;
1.100 + }
1.101 +
1.102 for( i=0; i<len; i++ ) {
1.103 fread_string( tmp, sizeof(tmp), f );
1.104 fread( &base, sizeof(base), 1, f );
1.105 @@ -270,8 +293,8 @@
1.106 }
1.107
1.108 struct mem_region *mem_map_region( void *mem, uint32_t base, uint32_t size,
1.109 - const char *name, mem_region_fn_t fn, int flags, uint32_t repeat_offset,
1.110 - uint32_t repeat_until )
1.111 + const char *name, mem_region_fn_t fn, int flags,
1.112 + uint32_t repeat_offset, uint32_t repeat_until )
1.113 {
1.114 int i;
1.115 mem_rgn[num_mem_rgns].base = base;
1.116 @@ -284,7 +307,9 @@
1.117
1.118 do {
1.119 for( i=0; i<size>>LXDREAM_PAGE_BITS; i++ ) {
1.120 - page_map[(base>>LXDREAM_PAGE_BITS)+i] = mem + (i<<LXDREAM_PAGE_BITS);
1.121 + if( mem != NULL ) {
1.122 + page_map[(base>>LXDREAM_PAGE_BITS)+i] = mem + (i<<LXDREAM_PAGE_BITS);
1.123 + }
1.124 ext_address_space[(base>>LXDREAM_PAGE_BITS)+i] = fn;
1.125 mem_page_remapped( base + (i<<LXDREAM_PAGE_BITS), fn );
1.126 }
1.127 @@ -294,78 +319,39 @@
1.128 return &mem_rgn[num_mem_rgns-1];
1.129 }
1.130
1.131 -void register_misc_region( uint32_t base, uint32_t size, const char *name, mem_region_fn_t fn )
1.132 +gboolean mem_load_rom( void *output, const gchar *file, uint32_t size, uint32_t crc )
1.133 {
1.134 - mem_rgn[num_mem_rgns].base = base;
1.135 - mem_rgn[num_mem_rgns].size = size;
1.136 - mem_rgn[num_mem_rgns].flags = 0;
1.137 - mem_rgn[num_mem_rgns].name = name;
1.138 - mem_rgn[num_mem_rgns].mem = NULL;
1.139 - mem_rgn[num_mem_rgns].fn = fn;
1.140 - num_mem_rgns++;
1.141 + if( file != NULL && file[0] != '\0' ) {
1.142 + FILE *f = fopen(file,"r");
1.143 + struct stat st;
1.144 + uint32_t calc_crc;
1.145
1.146 - int count = size >> 12;
1.147 - mem_region_fn_t *ptr = &ext_address_space[base>>12];
1.148 - while( count-- > 0 ) {
1.149 - *ptr++ = fn;
1.150 - }
1.151 -}
1.152 -
1.153 -void *mem_create_ram_region( uint32_t base, uint32_t size, const char *name, mem_region_fn_t fn )
1.154 -{
1.155 - return mem_create_repeating_ram_region( base, size, name, fn, size, base );
1.156 -}
1.157 -
1.158 -void *mem_create_repeating_ram_region( uint32_t base, uint32_t size, const char *name,
1.159 - mem_region_fn_t fn,
1.160 - uint32_t repeat_offset, uint32_t repeat_until )
1.161 -{
1.162 - char *mem;
1.163 -
1.164 - assert( (base&0xFFFFF000) == base ); /* must be page aligned */
1.165 - assert( (size&0x00000FFF) == 0 );
1.166 - assert( num_mem_rgns < MAX_MEM_REGIONS );
1.167 - assert( page_map != NULL );
1.168 -
1.169 - mem = mem_alloc_pages( size>>LXDREAM_PAGE_BITS );
1.170 -
1.171 - mem_map_region( mem, base, size, name, fn, MEM_FLAG_RAM, repeat_offset, repeat_until );
1.172 -
1.173 - return mem;
1.174 -}
1.175 -
1.176 -gboolean mem_load_rom( const gchar *file, uint32_t base, uint32_t size, uint32_t crc,
1.177 - const gchar *region_name, mem_region_fn_t fn )
1.178 -{
1.179 - sh4ptr_t mem;
1.180 - uint32_t calc_crc;
1.181 - int status;
1.182 -
1.183 - mem = mem_get_region(base);
1.184 - if( mem == NULL ) {
1.185 - mem = mmap( NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0 );
1.186 - if( mem == MAP_FAILED ) {
1.187 - ERROR( "Unable to allocate ROM memory: %s (%s)", file, strerror(errno) );
1.188 + if( f == NULL ) {
1.189 + ERROR( "Unable to load file '%s': %s", file, strerror(errno) );
1.190 return FALSE;
1.191 }
1.192 - mem_map_region( mem, base, size, region_name, fn, MEM_FLAG_ROM, size, base );
1.193 - } else {
1.194 - mprotect( mem, size, PROT_READ|PROT_WRITE );
1.195 - }
1.196
1.197 - if( file != NULL && file[0] != '\0' ) {
1.198 - status = mem_load_block( file, base, size );
1.199 - mprotect( mem, size, PROT_READ );
1.200 + fstat( fileno(f), &st );
1.201 + if( st.st_size != size ) {
1.202 + ERROR( "File '%s' is invalid, expected %d bytes but was %d bytes long.", file, size, st.st_size );
1.203 + fclose(f);
1.204 + return FALSE;
1.205 + }
1.206 +
1.207 + if( fread( output, 1, size, f ) != size ) {
1.208 + ERROR( "Failed to load file '%s': %s", file, strerror(errno) );
1.209 + fclose(f);
1.210 + return FALSE;
1.211 + }
1.212
1.213 - if( status == 0 ) {
1.214 - /* CRC check only if we loaded something */
1.215 - calc_crc = crc32(0L, (sh4ptr_t)mem, size);
1.216 - if( calc_crc != crc ) {
1.217 - WARN( "Bios CRC Mismatch in %s: %08X (expected %08X)",
1.218 - file, calc_crc, crc);
1.219 - }
1.220 - return TRUE;
1.221 + /* CRC check only if we loaded something */
1.222 + calc_crc = crc32(0L, output, size);
1.223 + if( calc_crc != crc ) {
1.224 + WARN( "Bios CRC Mismatch in %s: %08X (expected %08X)",
1.225 + file, calc_crc, crc);
1.226 }
1.227 + /* Even if the CRC fails, continue normally */
1.228 + return TRUE;
1.229 }
1.230 return FALSE;
1.231 }
1.232 @@ -413,16 +399,9 @@
1.233 while( *io ) register_io_region( *io++ );
1.234 }
1.235
1.236 -int mem_has_page( uint32_t addr )
1.237 +gboolean mem_has_page( uint32_t addr )
1.238 {
1.239 - sh4ptr_t page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.240 - return page != NULL;
1.241 -}
1.242 -
1.243 -sh4ptr_t mem_get_page( uint32_t addr )
1.244 -{
1.245 - sh4ptr_t page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];
1.246 - return page;
1.247 + return ext_address_space[ (addr&0x1FFFFFFF)>>12 ] != &mem_region_unmapped;
1.248 }
1.249
1.250 sh4ptr_t mem_get_region( uint32_t addr )
1.251 @@ -437,22 +416,7 @@
1.252
1.253 void mem_write_long( sh4addr_t addr, uint32_t value )
1.254 {
1.255 - sh4ptr_t ptr = mem_get_region(addr);
1.256 - assert(ptr != NULL);
1.257 - *((uint32_t *)ptr) = value;
1.258 -}
1.259 -
1.260 -struct mmio_region *mem_get_io_region( uint32_t addr )
1.261 -{
1.262 - if( addr > 0xFF000000 ) {
1.263 - return P4_io[(addr&0x00FFFFFF)>>12];
1.264 - }
1.265 - sh4ptr_t page = page_map[(addr&0x1FFFFFFF)>>12];
1.266 - if( ((uintptr_t)page) < MAX_IO_REGIONS ) {
1.267 - return io_rgn[(uintptr_t)page];
1.268 - } else {
1.269 - return NULL;
1.270 - }
1.271 + ext_address_space[(addr&0x1FFFFFFF)>>12]->write_long(addr, value);
1.272 }
1.273
1.274 struct mmio_region *mem_get_io_region_by_name( const gchar *name )
.