Search
lxdream.org :: lxdream :: r400:049d72a7a229
lxdream 0.9.1
released Jun 29
Download Now
changeset400:049d72a7a229
parent399:23e51a2b4f99
child401:f79327f39818
authornkeynes
dateThu Sep 20 08:35:04 2007 +0000 (12 years ago)
Add translation cache invalidation
src/sh4/sh4mem.c
src/sh4/xltcache.c
src/sh4/xltcache.h
1.1 --- a/src/sh4/sh4mem.c Thu Sep 20 08:34:23 2007 +0000
1.2 +++ b/src/sh4/sh4mem.c Thu Sep 20 08:35:04 2007 +0000
1.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 memory
1.8 * mapped I/O), using the page maps created in mem.c
1.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.34
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.47
1.48 + // fprintf( stderr, "MOV.W %04X => %08X\n", val, addr );
1.49 CHECK_WRITE_WATCH(addr,2,val);
1.50
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.75
1.76 + // fprintf( stderr, "MOV.B %02X => %08X\n", val, addr );
1.77 CHECK_WRITE_WATCH(addr,1,val);
1.78
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.101
1.102
1.103 /* FIXME: Handle all the many special cases when the range doesn't fall cleanly
1.104 - * into the same memory black
1.105 + * into the same memory block
1.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 +0000
2.2 +++ b/src/sh4/xltcache.c Thu Sep 20 08:35:04 2007 +0000
2.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.13
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 state
2.22 */
2.23 @@ -110,10 +116,9 @@
2.24 }
2.25 }
2.26
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.38
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 +0000
3.2 +++ b/src/sh4/xltcache.h Thu Sep 20 08:35:04 2007 +0000
3.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.13
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 region
3.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 like
3.25 */
.