Search
lxdream.org :: lxdream/src/xlat/xltcache.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/xltcache.c
changeset 1195:072131b61d2a
prev1189:1540105786c8
next1214:49152b3d8b75
author nkeynes
date Mon Dec 12 21:15:44 2011 +1000 (10 years ago)
permissions -rw-r--r--
last change 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.
file annotate diff log raw
1.1 --- a/src/xlat/xltcache.c Thu Dec 01 08:02:13 2011 +1000
1.2 +++ b/src/xlat/xltcache.c Mon Dec 12 21:15:44 2011 +1000
1.3 @@ -43,6 +43,11 @@
1.4 #define NEXT(block) ( (xlat_cache_block_t)&((block)->code[(block)->size]))
1.5 #define IS_ENTRY_POINT(ent) (ent > XLAT_LUT_ENTRY_USED)
1.6 #define IS_ENTRY_USED(ent) (ent != XLAT_LUT_ENTRY_EMPTY)
1.7 +#define IS_ENTRY_CONTINUATION(ent) (((uintptr_t)ent) & ((uintptr_t)XLAT_LUT_ENTRY_USED))
1.8 +#define IS_FIRST_ENTRY_IN_PAGE(addr) (((addr)&0x1FFE) == 0)
1.9 +#define XLAT_CODE_ADDR(ent) ((void *)(((uintptr_t)ent) & (~((uintptr_t)0x03))))
1.10 +#define XLAT_BLOCK_FOR_LUT_ENTRY(ent) XLAT_BLOCK_FOR_CODE(XLAT_CODE_ADDR(ent))
1.11 +
1.12
1.13 #define MIN_BLOCK_SIZE 32
1.14 #define MIN_TOTAL_SIZE (sizeof(struct xlat_cache_block)+MIN_BLOCK_SIZE)
1.15 @@ -134,7 +139,7 @@
1.16 int i;
1.17 for( i=0; i<XLAT_LUT_PAGE_ENTRIES; i++ ) {
1.18 if( IS_ENTRY_POINT(page[i]) ) {
1.19 - void *p = page[i];
1.20 + void *p = XLAT_CODE_ADDR(page[i]);
1.21 do {
1.22 xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(p);
1.23 xlat_delete_block(block);
1.24 @@ -150,6 +155,10 @@
1.25 void **page = xlat_lut[XLAT_LUT_PAGE(addr)];
1.26 if( page != NULL ) {
1.27 int entry = XLAT_LUT_ENTRY(addr);
1.28 + if( entry == 0 && IS_ENTRY_CONTINUATION(page[entry]) ) {
1.29 + /* First entry may be a delay-slot for the previous page */
1.30 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(addr-2)]);
1.31 + }
1.32 if( page[entry] != NULL ) {
1.33 xlat_flush_page_by_lut(page);
1.34 }
1.35 @@ -161,6 +170,10 @@
1.36 void **page = xlat_lut[XLAT_LUT_PAGE(addr)];
1.37 if( page != NULL ) {
1.38 int entry = XLAT_LUT_ENTRY(addr);
1.39 + if( entry == 0 && IS_ENTRY_CONTINUATION(page[entry]) ) {
1.40 + /* First entry may be a delay-slot for the previous page */
1.41 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(addr-2)]);
1.42 + }
1.43 if( *(uint64_t *)&page[entry] != 0 ) {
1.44 xlat_flush_page_by_lut(page);
1.45 }
1.46 @@ -173,6 +186,11 @@
1.47 int entry_count = size >> 1; // words;
1.48 uint32_t page_no = XLAT_LUT_PAGE(address);
1.49 int entry = XLAT_LUT_ENTRY(address);
1.50 +
1.51 + if( entry == 0 && xlat_lut[page_no] != NULL && IS_ENTRY_CONTINUATION(xlat_lut[page_no][entry])) {
1.52 + /* First entry may be a delay-slot for the previous page */
1.53 + xlat_flush_page_by_lut(xlat_lut[XLAT_LUT_PAGE(address-2)]);
1.54 + }
1.55 do {
1.56 void **page = xlat_lut[page_no];
1.57 int page_entries = XLAT_LUT_PAGE_ENTRIES - entry;
1.58 @@ -212,7 +230,7 @@
1.59 void *result = NULL;
1.60 void **page = xlat_lut[XLAT_LUT_PAGE(address)];
1.61 if( page != NULL ) {
1.62 - result = (void *)(((uintptr_t)(page[XLAT_LUT_ENTRY(address)])) & (~((uintptr_t)0x03)));
1.63 + result = XLAT_CODE_ADDR(page[XLAT_LUT_ENTRY(address)]);
1.64 }
1.65 return result;
1.66 }
1.67 @@ -235,18 +253,24 @@
1.68 return NULL;
1.69 }
1.70
1.71 -void ** FASTCALL xlat_get_lut_entry( sh4addr_t address )
1.72 +static void **xlat_get_lut_page( sh4addr_t address )
1.73 {
1.74 void **page = xlat_lut[XLAT_LUT_PAGE(address)];
1.75
1.76 - /* Add the LUT entry for the block */
1.77 - if( page == NULL ) {
1.78 - xlat_lut[XLAT_LUT_PAGE(address)] = page =
1.79 - (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,
1.80 - MAP_PRIVATE|MAP_ANON, -1, 0 );
1.81 - memset( page, 0, XLAT_LUT_PAGE_SIZE );
1.82 - }
1.83 + /* Add the LUT entry for the block */
1.84 + if( page == NULL ) {
1.85 + xlat_lut[XLAT_LUT_PAGE(address)] = page =
1.86 + (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,
1.87 + MAP_PRIVATE|MAP_ANON, -1, 0 );
1.88 + memset( page, 0, XLAT_LUT_PAGE_SIZE );
1.89 + }
1.90
1.91 + return page;
1.92 +}
1.93 +
1.94 +void ** FASTCALL xlat_get_lut_entry( sh4addr_t address )
1.95 +{
1.96 + void **page = xlat_get_lut_page(address);
1.97 return &page[XLAT_LUT_ENTRY(address)];
1.98 }
1.99
1.100 @@ -408,26 +432,22 @@
1.101 xlat_new_cache_ptr = NEXT(xlat_new_cache_ptr);
1.102
1.103 /* Add the LUT entry for the block */
1.104 - if( xlat_lut[XLAT_LUT_PAGE(address)] == NULL ) {
1.105 - xlat_lut[XLAT_LUT_PAGE(address)] =
1.106 - (void **)mmap( NULL, XLAT_LUT_PAGE_SIZE, PROT_READ|PROT_WRITE,
1.107 - MAP_PRIVATE|MAP_ANON, -1, 0 );
1.108 - memset( xlat_lut[XLAT_LUT_PAGE(address)], 0, XLAT_LUT_PAGE_SIZE );
1.109 - }
1.110 -
1.111 - if( IS_ENTRY_POINT(xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)]) ) {
1.112 - void *p = xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)];
1.113 - xlat_cache_block_t oldblock = XLAT_BLOCK_FOR_CODE(p);
1.114 + void **p = xlat_get_lut_entry(address);
1.115 + void *entry = *p;
1.116 + if( IS_ENTRY_POINT(entry) ) {
1.117 + xlat_cache_block_t oldblock = XLAT_BLOCK_FOR_LUT_ENTRY(entry);
1.118 assert( oldblock->active );
1.119 - xlat_new_create_ptr->chain = p;
1.120 + xlat_new_create_ptr->chain = XLAT_CODE_ADDR(entry);
1.121 } else {
1.122 xlat_new_create_ptr->chain = NULL;
1.123 }
1.124 xlat_new_create_ptr->use_list = NULL;
1.125
1.126 - xlat_lut[XLAT_LUT_PAGE(address)][XLAT_LUT_ENTRY(address)] =
1.127 - &xlat_new_create_ptr->code;
1.128 - xlat_new_create_ptr->lut_entry = xlat_lut[XLAT_LUT_PAGE(address)] + XLAT_LUT_ENTRY(address);
1.129 + *p = &xlat_new_create_ptr->code;
1.130 + if( IS_ENTRY_CONTINUATION(entry) ) {
1.131 + *((uintptr_t *)p) |= (uintptr_t)XLAT_LUT_ENTRY_USED;
1.132 + }
1.133 + xlat_new_create_ptr->lut_entry = p;
1.134
1.135 return xlat_new_create_ptr;
1.136 }
1.137 @@ -473,15 +493,16 @@
1.138
1.139 }
1.140
1.141 -void xlat_commit_block( uint32_t destsize, uint32_t srcsize )
1.142 +void xlat_commit_block( uint32_t destsize, sh4addr_t startpc, sh4addr_t endpc )
1.143 {
1.144 - void **ptr = xlat_new_create_ptr->lut_entry;
1.145 - void **endptr = ptr + (srcsize>>1);
1.146 - while( ptr < endptr ) {
1.147 - if( *ptr == NULL ) {
1.148 - *ptr = XLAT_LUT_ENTRY_USED;
1.149 - }
1.150 - ptr++;
1.151 + void **entry = xlat_get_lut_entry(startpc+2);
1.152 + /* assume main entry has already been set at this point */
1.153 +
1.154 + for( sh4addr_t pc = startpc+2; pc < endpc; pc += 2 ) {
1.155 + if( XLAT_LUT_ENTRY(pc) == 0 )
1.156 + entry = xlat_get_lut_entry(pc);
1.157 + *((uintptr_t *)entry) |= (uintptr_t)XLAT_LUT_ENTRY_USED;
1.158 + entry++;
1.159 }
1.160
1.161 xlat_new_cache_ptr = xlat_cut_block( xlat_new_create_ptr, destsize );
1.162 @@ -524,7 +545,7 @@
1.163 for( j=0; j<XLAT_LUT_PAGE_ENTRIES; j++ ) {
1.164 void *entry = page[j];
1.165 if( ((uintptr_t)entry) > (uintptr_t)XLAT_LUT_ENTRY_USED ) {
1.166 - xlat_cache_block_t block = XLAT_BLOCK_FOR_CODE(entry);
1.167 + xlat_cache_block_t block = XLAT_BLOCK_FOR_LUT_ENTRY(entry);
1.168 if( ptr >= block->code && ptr < block->code + block->size) {
1.169 /* Found it */
1.170 return (i<<13) | (j<<1);
1.171 @@ -620,7 +641,7 @@
1.172 void **page = xlat_lut[i];
1.173 if( page != NULL ) {
1.174 for( unsigned j=0; j < XLAT_LUT_PAGE_ENTRIES; j++ ) {
1.175 - void *code = (void *)(((uintptr_t)(page[j])) & (~((uintptr_t)0x03)));
1.176 + void *code = XLAT_CODE_ADDR(page[j]);
1.177 if( code != NULL ) {
1.178 xlat_cache_block_t ptr = XLAT_BLOCK_FOR_CODE(code);
1.179 sh4addr_t pc = XLAT_ADDR_FROM_ENTRY(i,j);
.