revision 1195:072131b61d2a
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1195:072131b61d2a |
parent | 1194:ee6ce5804608 |
child | 1196:a14dbddafd13 |
author | nkeynes |
date | Mon Dec 12 21:15:44 2011 +1000 (12 years ago) |
Handle branch delay-slot instruction that falls on the next page correctly.
- Generate the right end PC in the first place (sh4trans.c)
- Allow blocks to be marked as both entry point + continuation, and
specifically handle invalidation when first entry of a page is a continuation ==
flush previous page as well.
- Generate the right end PC in the first place (sh4trans.c)
- Allow blocks to be marked as both entry point + continuation, and
specifically handle invalidation when first entry of a page is a continuation ==
flush previous page as well.
src/sh4/sh4trans.c | view | annotate | diff | log | ||
src/test/testxlt.c | view | annotate | diff | log | ||
src/xlat/xltcache.c | view | annotate | diff | log | ||
src/xlat/xltcache.h | view | annotate | diff | log |
1.1 --- a/src/sh4/sh4trans.c Mon Dec 12 21:13:36 2011 +10001.2 +++ b/src/sh4/sh4trans.c Mon Dec 12 21:15:44 2011 +10001.3 @@ -112,7 +112,7 @@1.4 done = sh4_translate_instruction( pc );1.5 assert( xlat_output <= eob );1.6 pc += 2;1.7 - if ( pc >= lastpc ) {1.8 + if ( pc >= lastpc && done == 0 ) {1.9 done = 2;1.10 }1.11 #ifdef SINGLESTEP1.12 @@ -140,7 +140,7 @@1.13 xlat_current_block->recover_table_offset = xlat_output - (uint8_t *)xlat_current_block->code;1.14 xlat_current_block->recover_table_size = xlat_recovery_posn;1.15 xlat_current_block->xlat_sh4_mode = sh4r.xlat_sh4_mode;1.16 - xlat_commit_block( finalsize, pc-start );1.17 + xlat_commit_block( finalsize, start, pc );1.18 return xlat_current_block->code;1.19 }
2.1 --- a/src/test/testxlt.c Mon Dec 12 21:13:36 2011 +10002.2 +++ b/src/test/testxlt.c Mon Dec 12 21:15:44 2011 +10002.3 @@ -37,7 +37,7 @@2.4 assert( block->active == 1 );2.5 assert( block->size == XLAT_NEW_CACHE_SIZE - (2*sizeof(struct xlat_cache_block)) );2.6 memset( block->code, 0xB5, 8192 );2.7 - xlat_commit_block( 8192, 100 );2.8 + xlat_commit_block( 8192, 0x0C008000, 0x0C008100 );2.9 assert( block->active == 1 );2.10 assert( block->size == 8192 );2.12 @@ -46,7 +46,7 @@2.13 assert( block2->active == 1 );2.14 assert( block2->size == XLAT_NEW_CACHE_SIZE - (3*sizeof(struct xlat_cache_block)) - 8192 );2.15 memset( block2->code, 0x6D, size );2.16 - xlat_commit_block( size, 200 );2.17 + xlat_commit_block( size, 0x0C009000, 0x0C009200 );2.18 assert( block2->active == 1 );2.19 assert( block2->size == size );2.21 @@ -74,7 +74,7 @@2.22 for( i=4096; i<8192; i++ ) {2.23 assert( block3a->code[i] == 0xB5 );2.24 }2.25 - xlat_commit_block(6142, 432);2.26 + xlat_commit_block(6142, 0x0D009800, 0x0D009C32);2.27 addr = xlat_get_code( 0x0D009800 );2.28 assert( addr == &block3a->code );2.29 }
3.1 --- a/src/xlat/xltcache.c Mon Dec 12 21:13:36 2011 +10003.2 +++ b/src/xlat/xltcache.c Mon Dec 12 21:15:44 2011 +10003.3 @@ -43,6 +43,11 @@3.4 #define NEXT(block) ( (xlat_cache_block_t)&((block)->code[(block)->size]))3.5 #define IS_ENTRY_POINT(ent) (ent > XLAT_LUT_ENTRY_USED)3.6 #define IS_ENTRY_USED(ent) (ent != XLAT_LUT_ENTRY_EMPTY)3.7 +#define IS_ENTRY_CONTINUATION(ent) (((uintptr_t)ent) & ((uintptr_t)XLAT_LUT_ENTRY_USED))3.8 +#define IS_FIRST_ENTRY_IN_PAGE(addr) (((addr)&0x1FFE) == 0)3.9 +#define XLAT_CODE_ADDR(ent) ((void *)(((uintptr_t)ent) & (~((uintptr_t)0x03))))3.10 +#define XLAT_BLOCK_FOR_LUT_ENTRY(ent) XLAT_BLOCK_FOR_CODE(XLAT_CODE_ADDR(ent))3.11 +3.13 #define MIN_BLOCK_SIZE 323.14 #define MIN_TOTAL_SIZE (sizeof(struct xlat_cache_block)+MIN_BLOCK_SIZE)3.15 @@ -134,7 +139,7 @@3.16 int i;3.17 for( i=0; i<XLAT_LUT_PAGE_ENTRIES; i++ ) {3.18 if( IS_ENTRY_POINT(page[i]) ) {3.19 - void *p = page[i];3.20 + void *p = XLAT_CODE_ADDR(page[i]);3.21 do {3.22 xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(p);3.23 xlat_delete_block(block);3.24 @@ -150,6 +155,10 @@3.25 void **page = xlat_lut[XLAT_LUT_PAGE(addr)];3.26 if( page != NULL ) {3.27 int entry = XLAT_LUT_ENTRY(addr);3.28 + if( entry == 0 && IS_ENTRY_CONTINUATION(page[entry]) ) {3.29 + /* First entry may be a delay-slot for the previous page */3.30 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(addr-2)]);3.31 + }3.32 if( page[entry] != NULL ) {3.33 xlat_flush_page_by_lut(page);3.34 }3.35 @@ -161,6 +170,10 @@3.36 void **page = xlat_lut[XLAT_LUT_PAGE(addr)];3.37 if( page != NULL ) {3.38 int entry = XLAT_LUT_ENTRY(addr);3.39 + if( entry == 0 && IS_ENTRY_CONTINUATION(page[entry]) ) {3.40 + /* First entry may be a delay-slot for the previous page */3.41 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(addr-2)]);3.42 + }3.43 if( *(uint64_t *)&page[entry] != 0 ) {3.44 xlat_flush_page_by_lut(page);3.45 }3.46 @@ -173,6 +186,11 @@3.47 int entry_count = size >> 1; // words;3.48 uint32_t page_no = XLAT_LUT_PAGE(address);3.49 int entry = XLAT_LUT_ENTRY(address);3.50 +3.51 + if( entry == 0 && xlat_lut[page_no] != NULL && IS_ENTRY_CONTINUATION(xlat_lut[page_no][entry])) {3.52 + /* First entry may be a delay-slot for the previous page */3.53 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(address-2)]);3.54 + }3.55 do {3.56 void **page = xlat_lut[page_no];3.57 int page_entries = XLAT_LUT_PAGE_ENTRIES - entry;3.58 @@ -212,7 +230,7 @@3.59 void *result = NULL;3.60 void **page = xlat_lut[XLAT_LUT_PAGE(address)];3.61 if( page != NULL ) {3.62 - result = (void *)(((uintptr_t)(page[XLAT_LUT_ENTRY(address)])) & (~((uintptr_t)0x03)));3.63 + result = XLAT_CODE_ADDR(page[XLAT_LUT_ENTRY(address)]);3.64 }3.65 return result;3.66 }3.67 @@ -235,18 +253,24 @@3.68 return NULL;3.69 }3.71 -void ** FASTCALL xlat_get_lut_entry( sh4addr_t address )3.72 +static void **xlat_get_lut_page( sh4addr_t address )3.73 {3.74 void **page = xlat_lut[XLAT_LUT_PAGE(address)];3.76 - /* Add the LUT entry for the block */3.77 - if( page == NULL ) {3.78 - xlat_lut[XLAT_LUT_PAGE(address)] = page =3.79 - (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,3.80 - MAP_PRIVATE|MAP_ANON, -1, 0 );3.81 - memset( page, 0, XLAT_LUT_PAGE_SIZE );3.82 - }3.83 + /* Add the LUT entry for the block */3.84 + if( page == NULL ) {3.85 + xlat_lut[XLAT_LUT_PAGE(address)] = page =3.86 + (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,3.87 + MAP_PRIVATE|MAP_ANON, -1, 0 );3.88 + memset( page, 0, XLAT_LUT_PAGE_SIZE );3.89 + }3.91 + return page;3.92 +}3.93 +3.94 +void ** FASTCALL xlat_get_lut_entry( sh4addr_t address )3.95 +{3.96 + void **page = xlat_get_lut_page(address);3.97 return &page[XLAT_LUT_ENTRY(address)];3.98 }3.100 @@ -408,26 +432,22 @@3.101 xlat_new_cache_ptr = NEXT(xlat_new_cache_ptr);3.103 /* Add the LUT entry for the block */3.104 - if( xlat_lut[XLAT_LUT_PAGE(address)] == NULL ) {3.105 - xlat_lut[XLAT_LUT_PAGE(address)] =3.106 - (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,3.107 - MAP_PRIVATE|MAP_ANON, -1, 0 );3.108 - memset( xlat_lut[XLAT_LUT_PAGE(address)], 0, XLAT_LUT_PAGE_SIZE );3.109 - }3.110 -3.111 - if( IS_ENTRY_POINT(xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)]) ) {3.112 - void *p = xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)];3.113 - xlat_cache_block_t oldblock = XLAT_BLOCK_FOR_CODE(p);3.114 + void **p = xlat_get_lut_entry(address);3.115 + void *entry = *p;3.116 + if( IS_ENTRY_POINT(entry) ) {3.117 + xlat_cache_block_t oldblock = XLAT_BLOCK_FOR_LUT_ENTRY(entry);3.118 assert( oldblock->active );3.119 - xlat_new_create_ptr->chain = p;3.120 + xlat_new_create_ptr->chain = XLAT_CODE_ADDR(entry);3.121 } else {3.122 xlat_new_create_ptr->chain = NULL;3.123 }3.124 xlat_new_create_ptr->use_list = NULL;3.126 - xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)] =3.127 - &xlat_new_create_ptr->code;3.128 - xlat_new_create_ptr->lut_entry = xlat_lut[XLAT_LUT_PAGE(address)] + XLAT_LUT_ENTRY(address);3.129 + *p = &xlat_new_create_ptr->code;3.130 + if( IS_ENTRY_CONTINUATION(entry) ) {3.131 + *((uintptr_t *)p) |= (uintptr_t)XLAT_LUT_ENTRY_USED;3.132 + }3.133 + xlat_new_create_ptr->lut_entry = p;3.135 return xlat_new_create_ptr;3.136 }3.137 @@ -473,15 +493,16 @@3.139 }3.141 -void xlat_commit_block( uint32_t destsize, uint32_t srcsize )3.142 +void xlat_commit_block( uint32_t destsize, sh4addr_t startpc, sh4addr_t endpc )3.143 {3.144 - void **ptr = xlat_new_create_ptr->lut_entry;3.145 - void **endptr = ptr + (srcsize>>1);3.146 - while( ptr < endptr ) {3.147 - if( *ptr == NULL ) {3.148 - *ptr = XLAT_LUT_ENTRY_USED;3.149 - }3.150 - ptr++;3.151 + void **entry = xlat_get_lut_entry(startpc+2);3.152 + /* assume main entry has already been set at this point */3.153 +3.154 + for( sh4addr_t pc = startpc+2; pc < endpc; pc += 2 ) {3.155 + if( XLAT_LUT_ENTRY(pc) == 0 )3.156 + entry = xlat_get_lut_entry(pc);3.157 + *((uintptr_t *)entry) |= (uintptr_t)XLAT_LUT_ENTRY_USED;3.158 + entry++;3.159 }3.161 xlat_new_cache_ptr = xlat_cut_block( xlat_new_create_ptr, destsize );3.162 @@ -524,7 +545,7 @@3.163 for( j=0; j<XLAT_LUT_PAGE_ENTRIES; j++ ) {3.164 void *entry = page[j];3.165 if( ((uintptr_t)entry) > (uintptr_t)XLAT_LUT_ENTRY_USED ) {3.166 - xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(entry);3.167 + xlat_cache_block_t block = XLAT_BLOCK_FOR_LUT_ENTRY(entry);3.168 if( ptr >= block->code && ptr < block->code + block->size) {3.169 /* Found it */3.170 return (i<<13) | (j<<1);3.171 @@ -620,7 +641,7 @@3.172 void **page = xlat_lut[i];3.173 if( page != NULL ) {3.174 for( unsigned j=0; j < XLAT_LUT_PAGE_ENTRIES; j++ ) {3.175 - void *code = (void *)(((uintptr_t)(page[j])) & (~((uintptr_t)0x03)));3.176 + void *code = XLAT_CODE_ADDR(page[j]);3.177 if( code != NULL ) {3.178 xlat_cache_block_t ptr = XLAT_BLOCK_FOR_CODE(code);3.179 sh4addr_t pc = XLAT_ADDR_FROM_ENTRY(i,j);
4.1 --- a/src/xlat/xltcache.h Mon Dec 12 21:13:36 2011 +10004.2 +++ b/src/xlat/xltcache.h Mon Dec 12 21:15:44 2011 +10004.3 @@ -78,9 +78,11 @@4.4 /**4.5 * Commit the current translation block4.6 * @param destsize final size of the translation in bytes.4.7 - * @param srcsize size of the original data that was translated in bytes4.8 + * @param startpc PC at the start of the translation block.4.9 + * @param endpc PC at the end of the translation block (i.e. the address of the4.10 + * next instruction after the block).4.11 */4.12 -void xlat_commit_block( uint32_t destsize, uint32_t srcsize );4.13 +void xlat_commit_block( uint32_t destsize, sh4addr_t startpc, sh4addr_t endpc );4.15 /**4.16 * Dump the disassembly of the specified code block to a stream
.