Search
lxdream.org :: lxdream :: r1195:072131b61d2a
lxdream 0.9.1
released Jun 29
Download Now
changeset1195:072131b61d2a
parent1194:ee6ce5804608
child1196:a14dbddafd13
authornkeynes
dateMon Dec 12 21:15:44 2011 +1000 (7 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.
src/sh4/sh4trans.c
src/test/testxlt.c
src/xlat/xltcache.c
src/xlat/xltcache.h
1.1 --- a/src/sh4/sh4trans.c Mon Dec 12 21:13:36 2011 +1000
1.2 +++ b/src/sh4/sh4trans.c Mon Dec 12 21:15:44 2011 +1000
1.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 SINGLESTEP
1.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 }
1.20
2.1 --- a/src/test/testxlt.c Mon Dec 12 21:13:36 2011 +1000
2.2 +++ b/src/test/testxlt.c Mon Dec 12 21:15:44 2011 +1000
2.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.11
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.20
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 +1000
3.2 +++ b/src/xlat/xltcache.c Mon Dec 12 21:15:44 2011 +1000
3.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.12
3.13 #define MIN_BLOCK_SIZE 32
3.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.70
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.75
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.90
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.99
3.100 @@ -408,26 +432,22 @@
3.101 xlat_new_cache_ptr = NEXT(xlat_new_cache_ptr);
3.102
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.125
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.134
3.135 return xlat_new_create_ptr;
3.136 }
3.137 @@ -473,15 +493,16 @@
3.138
3.139 }
3.140
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.160
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 +1000
4.2 +++ b/src/xlat/xltcache.h Mon Dec 12 21:15:44 2011 +1000
4.3 @@ -78,9 +78,11 @@
4.4 /**
4.5 * Commit the current translation block
4.6 * @param destsize final size of the translation in bytes.
4.7 - * @param srcsize size of the original data that was translated in bytes
4.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 the
4.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.14
4.15 /**
4.16 * Dump the disassembly of the specified code block to a stream
.