revision 400:049d72a7a229
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 400:049d72a7a229 |
parent | 399:23e51a2b4f99 |
child | 401:f79327f39818 |
author | nkeynes |
date | Thu Sep 20 08:35:04 2007 +0000 (13 years ago) |
Add translation cache invalidation
![]() | src/sh4/sh4mem.c | view | annotate | diff | log | |
![]() | src/sh4/xltcache.c | view | annotate | diff | log | |
![]() | src/sh4/xltcache.h | view | annotate | diff | log |
1.1 --- a/src/sh4/sh4mem.c Thu Sep 20 08:34:23 2007 +00001.2 +++ b/src/sh4/sh4mem.c Thu Sep 20 08:35:04 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: sh4mem.c,v 1.22 2007-09-08 04:38:11 nkeynes Exp $1.6 + * $Id: sh4mem.c,v 1.23 2007-09-20 08:35:04 nkeynes Exp $1.7 * sh4mem.c is responsible for the SH4's access to memory (including memory1.8 * mapped I/O), using the page maps created in mem.c1.9 *1.10 @@ -152,6 +152,7 @@1.11 TRACE_IO( "Long read %08X <= %08X", page, (addr&0xFFF), val, addr );1.12 return val;1.13 } else {1.14 + // fprintf( stderr, "MOV.L %08X <= %08X\n",*(int32_t *)(page+(addr&0xFFF)), addr );1.15 return *(int32_t *)(page+(addr&0xFFF));1.16 }1.17 }1.18 @@ -227,6 +228,7 @@1.19 TRACE_IO( "Byte read %02X <= %08X", page, (addr&0xFFF), val&0xFF, addr );1.20 return val;1.21 } else {1.22 + // fprintf( stderr, "MOV.B %02X <= %08X\n",(uint32_t)*(uint8_t *)(page+(addr&0xFFF)), addr );1.23 return SIGNEXT8(*(int8_t *)(page+(addr&0xFFF)));1.24 }1.25 }1.26 @@ -234,7 +236,8 @@1.27 void sh4_write_long( uint32_t addr, uint32_t val )1.28 {1.29 char *page;1.30 -1.31 +1.32 + // fprintf( stderr, "MOV.L %08X => %08X\n", val, addr );1.33 CHECK_WRITE_WATCH(addr,4,val);1.35 if( addr >= 0xE0000000 ) {1.36 @@ -275,6 +278,7 @@1.37 TRACE_IO( "Long write %08X => %08X", page, (addr&0xFFF), val, addr );1.38 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);1.39 } else {1.40 + xlat_invalidate_long(addr);1.41 *(uint32_t *)(page+(addr&0xFFF)) = val;1.42 }1.43 }1.44 @@ -283,6 +287,7 @@1.45 {1.46 char *page;1.48 + // fprintf( stderr, "MOV.W %04X => %08X\n", val, addr );1.49 CHECK_WRITE_WATCH(addr,2,val);1.51 if( addr >= 0xE0000000 ) {1.52 @@ -302,6 +307,11 @@1.53 sh4_stop();1.54 return;1.55 }1.56 + if( (addr&0x1FFFFFFF) < 0x200000 ) {1.57 + ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);1.58 + sh4_stop();1.59 + return;1.60 + }1.61 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];1.62 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */1.63 if( page == NULL ) {1.64 @@ -311,6 +321,7 @@1.65 TRACE_IO( "Word write %04X => %08X", page, (addr&0xFFF), val&0xFFFF, addr );1.66 io_rgn[(uint32_t)page]->io_write(addr&0xFFF, val);1.67 } else {1.68 + xlat_invalidate_word(addr);1.69 *(uint16_t *)(page+(addr&0xFFF)) = val;1.70 }1.71 }1.72 @@ -319,6 +330,7 @@1.73 {1.74 char *page;1.76 + // fprintf( stderr, "MOV.B %02X => %08X\n", val, addr );1.77 CHECK_WRITE_WATCH(addr,1,val);1.79 if( addr >= 0xE0000000 ) {1.80 @@ -339,6 +351,11 @@1.81 sh4_stop();1.82 return;1.83 }1.84 + if( (addr&0x1FFFFFFF) < 0x200000 ) {1.85 + ERROR( "Attempted write to read-only memory: %08X => %08X", val, addr);1.86 + sh4_stop();1.87 + return;1.88 + }1.89 page = page_map[ (addr & 0x1FFFFFFF) >> 12 ];1.90 if( ((uint32_t)page) < MAX_IO_REGIONS ) { /* IO Region */1.91 if( page == NULL ) {1.92 @@ -348,6 +365,7 @@1.93 TRACE_IO( "Byte write %02X => %08X", page, (addr&0xFFF), val&0xFF, addr );1.94 io_rgn[(uint32_t)page]->io_write( (addr&0xFFF), val);1.95 } else {1.96 + xlat_invalidate_word(addr);1.97 *(uint8_t *)(page+(addr&0xFFF)) = val;1.98 }1.99 }1.100 @@ -355,7 +373,7 @@1.103 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly1.104 - * into the same memory black1.105 + * into the same memory block1.106 */1.107 void mem_copy_from_sh4( char *dest, uint32_t srcaddr, size_t count ) {1.108 if( srcaddr >= 0x04000000 && srcaddr < 0x05000000 ) {1.109 @@ -386,6 +404,7 @@1.110 if( dest == NULL )1.111 ERROR( "Attempted block write to unknown address %08X", destaddr );1.112 else {1.113 + xlat_invalidate_block( destaddr, count );1.114 memcpy( dest, src, count );1.115 }1.116 }
2.1 --- a/src/sh4/xltcache.c Thu Sep 20 08:34:23 2007 +00002.2 +++ b/src/sh4/xltcache.c Thu Sep 20 08:35:04 2007 +00002.3 @@ -1,5 +1,5 @@2.4 /**2.5 - * $Id: xltcache.c,v 1.4 2007-09-16 06:59:47 nkeynes Exp $2.6 + * $Id: xltcache.c,v 1.5 2007-09-20 08:35:04 nkeynes Exp $2.7 *2.8 * Translation cache management. This part is architecture independent.2.9 *2.10 @@ -78,6 +78,12 @@2.11 xlat_flush_cache();2.12 }2.14 +void xlat_print_free( FILE *out )2.15 +{2.16 + fprintf( out, "New space: %d\nTemp space: %d\nOld space: %d\n",2.17 + xlat_new_cache_ptr->size, xlat_temp_cache_ptr->size, xlat_old_cache_ptr->size );2.18 +}2.19 +2.20 /**2.21 * Reset the cache structure to its default state2.22 */2.23 @@ -110,10 +116,9 @@2.24 }2.25 }2.27 -void xlat_flush_page( sh4addr_t address )2.28 +static void xlat_flush_page_by_lut( void **page )2.29 {2.30 int i;2.31 - void **page = xlat_lut[XLAT_LUT_PAGE(address)];2.32 for( i=0; i<XLAT_LUT_PAGE_ENTRIES; i++ ) {2.33 if( IS_ENTRY_POINT(page[i]) ) {2.34 BLOCK_FOR_CODE(page[i])->active = 0;2.35 @@ -122,6 +127,74 @@2.36 }2.37 }2.39 +void xlat_invalidate_word( sh4addr_t addr )2.40 +{2.41 + if( xlat_lut ) {2.42 + void **page = xlat_lut[XLAT_LUT_PAGE(addr)];2.43 + if( page != NULL ) {2.44 + int entry = XLAT_LUT_ENTRY(addr);2.45 + if( page[entry] != NULL ) {2.46 + xlat_flush_page_by_lut(page);2.47 + }2.48 + }2.49 + }2.50 +}2.51 +2.52 +void xlat_invalidate_long( sh4addr_t addr )2.53 +{2.54 + if( xlat_lut ) {2.55 + void **page = xlat_lut[XLAT_LUT_PAGE(addr)];2.56 + if( page != NULL ) {2.57 + int entry = XLAT_LUT_ENTRY(addr);2.58 + if( page[entry] != NULL || page[entry+1] != NULL ) {2.59 + xlat_flush_page_by_lut(page);2.60 + }2.61 + }2.62 + }2.63 +}2.64 +2.65 +void xlat_invalidate_block( sh4addr_t address, size_t size )2.66 +{2.67 + int i;2.68 + int entry_count = size >> 1; // words;2.69 + uint32_t page_no = XLAT_LUT_PAGE(address);2.70 + int entry = XLAT_LUT_ENTRY(address);2.71 + if( xlat_lut ) {2.72 + do {2.73 + void **page = xlat_lut[page_no];2.74 + int page_entries = XLAT_LUT_PAGE_ENTRIES - entry;2.75 + if( entry_count < page_entries ) {2.76 + page_entries = entry_count;2.77 + }2.78 + if( page != NULL ) {2.79 + if( page_entries == XLAT_LUT_PAGE_ENTRIES ) {2.80 + /* Overwriting the entire page anyway */2.81 + xlat_flush_page_by_lut(page);2.82 + } else {2.83 + for( i=entry; i<entry+page_entries; i++ ) {2.84 + if( page[i] != NULL ) {2.85 + xlat_flush_page_by_lut(page);2.86 + break;2.87 + }2.88 + }2.89 + }2.90 + entry_count -= page_entries;2.91 + }2.92 + page_no ++;2.93 + entry_count -= page_entries;2.94 + entry = 0;2.95 + } while( entry_count > 0 );2.96 + }2.97 +}2.98 +2.99 +void xlat_flush_page( sh4addr_t address )2.100 +{2.101 + void **page = xlat_lut[XLAT_LUT_PAGE(address)];2.102 + if( page != NULL ) {2.103 + xlat_flush_page_by_lut(page);2.104 + }2.105 +}2.106 +2.107 void *xlat_get_code( sh4addr_t address )2.108 {2.109 void **page = xlat_lut[XLAT_LUT_PAGE(address)];
3.1 --- a/src/sh4/xltcache.h Thu Sep 20 08:34:23 2007 +00003.2 +++ b/src/sh4/xltcache.h Thu Sep 20 08:35:04 2007 +00003.3 @@ -1,5 +1,5 @@3.4 /**3.5 - * $Id: xltcache.h,v 1.3 2007-09-12 09:16:47 nkeynes Exp $3.6 + * $Id: xltcache.h,v 1.4 2007-09-20 08:35:04 nkeynes Exp $3.7 *3.8 * Translation cache support (architecture independent)3.9 *3.10 @@ -79,6 +79,15 @@3.11 */3.12 void xlat_flush_page( sh4addr_t address );3.14 +void xlat_invalidate_word( sh4addr_t address );3.15 +void xlat_invalidate_long( sh4addr_t address );3.16 +3.17 +3.18 +/**3.19 + * Invalidate the code cache for a memory region3.20 + */3.21 +void xlat_invalidate_block( sh4addr_t address, size_t bytes );3.22 +3.23 /**3.24 * Flush the entire code cache. This isn't as cheap as one might like3.25 */
.