Search
lxdream.org :: lxdream/src/sh4/shadow.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/shadow.c
changeset 1217:677b1d85f1b4
prev1202:01ae5cbad4c8
next1298:d0eb2307b847
author nkeynes
date Sat Mar 03 15:52:59 2012 +1000 (12 years ago)
permissions -rw-r--r--
last change Swap between run + pause icons when pressed
file annotate diff log raw
1.1 --- a/src/sh4/shadow.c Fri Dec 23 08:20:17 2011 +1000
1.2 +++ b/src/sh4/shadow.c Sat Mar 03 15:52:59 2012 +1000
1.3 @@ -23,18 +23,12 @@
1.4
1.5 #include "clock.h"
1.6 #include "mem.h"
1.7 +#include "mmio.h"
1.8 #include "sh4/sh4.h"
1.9 #include "sh4/sh4core.h"
1.10 #include "sh4/sh4trans.h"
1.11 #include "sh4/mmu.h"
1.12
1.13 -#ifdef HAVE_FRAME_ADDRESS
1.14 -static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
1.15 -#define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
1.16 -#else
1.17 -#define INIT_EXCEPTIONS(label)
1.18 -#endif
1.19 -
1.20 typedef enum {
1.21 READ_LONG,
1.22 WRITE_LONG,
1.23 @@ -53,13 +47,17 @@
1.24 MemOp op;
1.25 sh4addr_t addr;
1.26 uint32_t value;
1.27 - sh4addr_t exception_pc;
1.28 };
1.29
1.30 static struct sh4_registers shadow_sh4r;
1.31 -static struct mem_region_fn **log_address_space;
1.32 -static struct mem_region_fn **check_address_space;
1.33 -static struct mem_region_fn **real_address_space;
1.34 +static struct mem_region_fn **shadow_address_space;
1.35 +static struct mem_region_fn **p4_address_space;
1.36 +
1.37 +typedef enum {
1.38 + SHADOW_LOG,
1.39 + SHADOW_CHECK
1.40 +} shadow_mode_t;
1.41 +static shadow_mode_t shadow_address_mode = SHADOW_LOG;
1.42
1.43 #define MEM_LOG_SIZE 4096
1.44 static struct mem_log_entry *mem_log;
1.45 @@ -68,7 +66,7 @@
1.46
1.47 #define IS_STORE_QUEUE(X) (((X)&0xFC000000) == 0xE0000000)
1.48
1.49 -static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int exception )
1.50 +static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
1.51 {
1.52 if( mem_log_posn == mem_log_size ) {
1.53 struct mem_log_entry *tmp = realloc(mem_log, mem_log_size * sizeof(struct mem_log_entry) * 2);
1.54 @@ -79,11 +77,6 @@
1.55 mem_log[mem_log_posn].op = op;
1.56 mem_log[mem_log_posn].addr = addr;
1.57 mem_log[mem_log_posn].value = value;
1.58 - if( exception ) {
1.59 - mem_log[mem_log_posn].exception_pc = sh4r.pc;
1.60 - } else {
1.61 - mem_log[mem_log_posn].exception_pc = -1;
1.62 - }
1.63 mem_log_posn++;
1.64 }
1.65
1.66 @@ -103,7 +96,7 @@
1.67 }
1.68 }
1.69
1.70 -static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int *exception )
1.71 +static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
1.72 {
1.73 if( mem_check_posn >= mem_log_posn ) {
1.74 fprintf( stderr, "Unexpected interpreter memory operation: " );
1.75 @@ -121,14 +114,6 @@
1.76 print_mem_op(stderr, op, addr, value );
1.77 abort();
1.78 }
1.79 -
1.80 - if( mem_log[mem_check_posn].exception_pc != -1 ) {
1.81 - sh4_reraise_exception(mem_log[mem_check_posn].exception_pc);
1.82 - *exception = 1;
1.83 - } else {
1.84 - *exception = 0;
1.85 - }
1.86 -
1.87 return mem_log[mem_check_posn++].value;
1.88 }
1.89
1.90 @@ -201,202 +186,117 @@
1.91 return isgood;
1.92 }
1.93
1.94 -static FASTCALL int32_t log_read_long( sh4addr_t addr, void *exc )
1.95 +static mem_region_fn_t real_region( sh4addr_t addr )
1.96 {
1.97 - INIT_EXCEPTIONS(except);
1.98 - int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_long)(addr, &&except);
1.99 - log_mem_op( READ_LONG, addr, rv, 0 );
1.100 - return rv;
1.101 -except:
1.102 - log_mem_op( READ_LONG, addr, rv, 1 );
1.103 - SH4_EXCEPTION_EXIT();
1.104 + if( addr >= 0xE0000000 )
1.105 + return p4_address_space[VMA_TO_EXT_ADDR(addr)>>12];
1.106 + else
1.107 + return ext_address_space[VMA_TO_EXT_ADDR(addr)>>12];
1.108 }
1.109
1.110 -static FASTCALL int32_t log_read_word( sh4addr_t addr, void *exc )
1.111 +static FASTCALL int32_t shadow_read_long( sh4addr_t addr )
1.112 {
1.113 - INIT_EXCEPTIONS(except);
1.114 - int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_word)(addr, &&except);
1.115 - log_mem_op( READ_WORD, addr, rv, 0 );
1.116 - return rv;
1.117 -except:
1.118 - log_mem_op( READ_WORD, addr, rv, 1 );
1.119 - SH4_EXCEPTION_EXIT();
1.120 -}
1.121 -
1.122 -static FASTCALL int32_t log_read_byte( sh4addr_t addr, void *exc )
1.123 -{
1.124 - INIT_EXCEPTIONS(except);
1.125 - int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte)(addr, &&except);
1.126 - log_mem_op( READ_BYTE, addr, rv, 0 );
1.127 - return rv;
1.128 -except:
1.129 - log_mem_op( READ_BYTE, addr, rv, 1 );
1.130 - SH4_EXCEPTION_EXIT();
1.131 -}
1.132 -
1.133 -static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr, void *exc )
1.134 -{
1.135 - INIT_EXCEPTIONS(except);
1.136 - int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte_for_write)(addr, &&except);
1.137 - log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 0 );
1.138 - return rv;
1.139 -except:
1.140 - log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 1 );
1.141 - SH4_EXCEPTION_EXIT();
1.142 -}
1.143 -
1.144 -static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val, void *exc )
1.145 -{
1.146 - INIT_EXCEPTIONS(except);
1.147 - ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_long)(addr, val, &&except);
1.148 - if( !IS_STORE_QUEUE(addr) )
1.149 - log_mem_op( WRITE_LONG, addr, val, 0 );
1.150 - return;
1.151 -except:
1.152 - if( !IS_STORE_QUEUE(addr) )
1.153 - log_mem_op( WRITE_LONG, addr, val, 1 );
1.154 - SH4_EXCEPTION_EXIT();
1.155 -}
1.156 -
1.157 -static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val, void *exc )
1.158 -{
1.159 - INIT_EXCEPTIONS(except);
1.160 - ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_word)(addr, val, &&except);
1.161 - if( !IS_STORE_QUEUE(addr) )
1.162 - log_mem_op( WRITE_WORD, addr, val, 0 );
1.163 - return;
1.164 -except:
1.165 - if( !IS_STORE_QUEUE(addr) )
1.166 - log_mem_op( WRITE_WORD, addr, val, 1 );
1.167 - SH4_EXCEPTION_EXIT();
1.168 -}
1.169 -
1.170 -static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val, void *exc )
1.171 -{
1.172 - INIT_EXCEPTIONS(except);
1.173 - ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_byte)(addr, val, &&except);
1.174 - if( !IS_STORE_QUEUE(addr) )
1.175 - log_mem_op( WRITE_BYTE, addr, val, 0 );
1.176 - return;
1.177 -except:
1.178 - if( !IS_STORE_QUEUE(addr) )
1.179 - log_mem_op( WRITE_BYTE, addr, val, 1 );
1.180 - SH4_EXCEPTION_EXIT();
1.181 -}
1.182 -
1.183 -static FASTCALL void log_prefetch( sh4addr_t addr, void *exc )
1.184 -{
1.185 - INIT_EXCEPTIONS(except);
1.186 - ((mem_prefetch_exc_fn_t)real_address_space[addr>>12]->prefetch)(addr, &&except);
1.187 - log_mem_op( PREFETCH, addr, 0, 0 );
1.188 - return;
1.189 -except:
1.190 - log_mem_op( PREFETCH, addr, 0, 1 );
1.191 - SH4_EXCEPTION_EXIT();
1.192 -}
1.193 -
1.194 -static FASTCALL int32_t check_read_long( sh4addr_t addr, void *exc )
1.195 -{
1.196 - int except;
1.197 - int32_t value = check_mem_op( READ_LONG, addr, 0, &except );
1.198 - if( except ) {
1.199 - SH4_EXCEPTION_EXIT();
1.200 - }
1.201 - return value;
1.202 -}
1.203 -
1.204 -static FASTCALL int32_t check_read_word( sh4addr_t addr, void *exc )
1.205 -{
1.206 - int except;
1.207 - int32_t value = check_mem_op( READ_WORD, addr, 0, &except );
1.208 - if( except ) {
1.209 - SH4_EXCEPTION_EXIT();
1.210 - }
1.211 - return value;
1.212 -}
1.213 -
1.214 -static FASTCALL int32_t check_read_byte( sh4addr_t addr, void *exc )
1.215 -{
1.216 - int except;
1.217 - int32_t value = check_mem_op( READ_BYTE, addr, 0, &except );
1.218 - if( except ) {
1.219 - SH4_EXCEPTION_EXIT();
1.220 - }
1.221 - return value;
1.222 -}
1.223 -
1.224 -static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr, void *exc )
1.225 -{
1.226 - int except;
1.227 - int32_t value = check_mem_op( READ_BYTE_FOR_WRITE, addr, 0, &except );
1.228 - if( except ) {
1.229 - SH4_EXCEPTION_EXIT();
1.230 - }
1.231 - return value;
1.232 -}
1.233 -
1.234 -static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value, void *exc )
1.235 -{
1.236 - if( !IS_STORE_QUEUE(addr) ) {
1.237 - int except;
1.238 - check_mem_op( WRITE_LONG, addr, value, &except );
1.239 - if( except ) {
1.240 - SH4_EXCEPTION_EXIT();
1.241 - }
1.242 + if( shadow_address_mode == SHADOW_LOG ) {
1.243 + int32_t rv = real_region(addr)->read_long(addr);
1.244 + log_mem_op( READ_LONG, addr, rv );
1.245 + return rv;
1.246 } else {
1.247 - real_address_space[addr>>12]->write_long(addr, value);
1.248 + return check_mem_op( READ_LONG, addr, 0 );
1.249 }
1.250 }
1.251
1.252 -static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value, void *exc )
1.253 +static FASTCALL int32_t shadow_read_word( sh4addr_t addr )
1.254 {
1.255 - if( !IS_STORE_QUEUE(addr) ) {
1.256 - int except;
1.257 - check_mem_op( WRITE_WORD, addr, value, &except );
1.258 - if( except ) {
1.259 - SH4_EXCEPTION_EXIT();
1.260 - }
1.261 + if( shadow_address_mode == SHADOW_LOG ) {
1.262 + int32_t rv = real_region(addr)->read_word(addr);
1.263 + log_mem_op( READ_WORD, addr, rv );
1.264 + return rv;
1.265 } else {
1.266 - real_address_space[addr>>12]->write_word(addr, value);
1.267 + return check_mem_op( READ_WORD, addr, 0 );
1.268 }
1.269 }
1.270
1.271 -static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value, void *exc )
1.272 +static FASTCALL int32_t shadow_read_byte( sh4addr_t addr )
1.273 {
1.274 - if( !IS_STORE_QUEUE(addr) ){
1.275 - int except;
1.276 - check_mem_op( WRITE_BYTE, addr, value, &except );
1.277 - if( except ) {
1.278 - SH4_EXCEPTION_EXIT();
1.279 - }
1.280 + if( shadow_address_mode == SHADOW_LOG ) {
1.281 + int32_t rv = real_region(addr)->read_byte(addr);
1.282 + log_mem_op( READ_BYTE, addr, rv );
1.283 + return rv;
1.284 } else {
1.285 - real_address_space[addr>>12]->write_byte(addr, value);
1.286 + return check_mem_op( READ_BYTE, addr, 0 );
1.287 }
1.288 }
1.289
1.290 -static FASTCALL void check_prefetch( sh4addr_t addr, void *exc )
1.291 +static FASTCALL int32_t shadow_read_byte_for_write( sh4addr_t addr )
1.292 {
1.293 - int except;
1.294 - check_mem_op( PREFETCH, addr, 0, &except );
1.295 - if( except ) {
1.296 - SH4_EXCEPTION_EXIT();
1.297 + if( shadow_address_mode == SHADOW_LOG ) {
1.298 + int32_t rv = real_region(addr)->read_byte_for_write(addr);
1.299 + log_mem_op( READ_BYTE_FOR_WRITE, addr, rv );
1.300 + return rv;
1.301 + } else {
1.302 + return check_mem_op( READ_BYTE_FOR_WRITE, addr, 0 );
1.303 }
1.304 }
1.305
1.306 -struct mem_region_fn log_fns = {
1.307 - (mem_read_fn_t)log_read_long, (mem_write_fn_t)log_write_long,
1.308 - (mem_read_fn_t)log_read_word, (mem_write_fn_t)log_write_word,
1.309 - (mem_read_fn_t)log_read_byte, (mem_write_fn_t)log_write_byte,
1.310 - NULL, NULL, (mem_prefetch_fn_t)log_prefetch, (mem_read_fn_t)log_read_byte_for_write };
1.311 +static FASTCALL void shadow_write_long( sh4addr_t addr, uint32_t val )
1.312 +{
1.313 + if( shadow_address_mode == SHADOW_LOG ) {
1.314 + real_region(addr)->write_long(addr, val);
1.315 + if( !IS_STORE_QUEUE(addr) )
1.316 + log_mem_op( WRITE_LONG, addr, val );
1.317 + } else {
1.318 + if( !IS_STORE_QUEUE(addr) ) {
1.319 + check_mem_op( WRITE_LONG, addr, val );
1.320 + } else {
1.321 + real_region(addr)->write_long(addr, val);
1.322 + }
1.323 + }
1.324 +}
1.325
1.326 -struct mem_region_fn check_fns = {
1.327 - (mem_read_fn_t)check_read_long, (mem_write_fn_t)check_write_long,
1.328 - (mem_read_fn_t)check_read_word, (mem_write_fn_t)check_write_word,
1.329 - (mem_read_fn_t)check_read_byte, (mem_write_fn_t)check_write_byte,
1.330 - NULL, NULL, (mem_prefetch_fn_t)check_prefetch, (mem_read_fn_t)check_read_byte_for_write };
1.331 +static FASTCALL void shadow_write_word( sh4addr_t addr, uint32_t val )
1.332 +{
1.333 + if( shadow_address_mode == SHADOW_LOG ) {
1.334 + real_region(addr)->write_word(addr, val);
1.335 + if( !IS_STORE_QUEUE(addr) )
1.336 + log_mem_op( WRITE_WORD, addr, val );
1.337 + } else {
1.338 + if( !IS_STORE_QUEUE(addr) ) {
1.339 + check_mem_op( WRITE_WORD, addr, val );
1.340 + } else {
1.341 + real_region(addr)->write_word(addr, val);
1.342 + }
1.343 + }
1.344 +}
1.345
1.346 +static FASTCALL void shadow_write_byte( sh4addr_t addr, uint32_t val )
1.347 +{
1.348 + if( shadow_address_mode == SHADOW_LOG ) {
1.349 + real_region(addr)->write_byte(addr, val);
1.350 + if( !IS_STORE_QUEUE(addr) )
1.351 + log_mem_op( WRITE_BYTE, addr, val );
1.352 + } else {
1.353 + if( !IS_STORE_QUEUE(addr) ) {
1.354 + check_mem_op( WRITE_BYTE, addr, val );
1.355 + } else {
1.356 + real_region(addr)->write_byte(addr, val);
1.357 + }
1.358 + }
1.359 +}
1.360
1.361 -
1.362 +static FASTCALL void shadow_prefetch( sh4addr_t addr )
1.363 +{
1.364 + if( shadow_address_mode == SHADOW_LOG ) {
1.365 + real_region(addr)->prefetch(addr);
1.366 + log_mem_op( PREFETCH, addr, 0 );
1.367 + } else {
1.368 + check_mem_op( PREFETCH, addr, 0 );
1.369 + }
1.370 +}
1.371 +struct mem_region_fn shadow_fns = {
1.372 + shadow_read_long, shadow_write_long,
1.373 + shadow_read_word, shadow_write_word,
1.374 + shadow_read_byte, shadow_write_byte,
1.375 + NULL, NULL, shadow_prefetch, shadow_read_byte_for_write };
1.376
1.377 void sh4_shadow_block_begin()
1.378 {
1.379 @@ -412,7 +312,7 @@
1.380 memcpy( &temp_sh4r, &sh4r, sizeof(struct sh4_registers) );
1.381 memcpy( &sh4r, &shadow_sh4r, sizeof(struct sh4_registers) );
1.382
1.383 - sh4_address_space = check_address_space;
1.384 + shadow_address_mode = SHADOW_CHECK;
1.385 mem_check_posn = 0;
1.386 sh4r.new_pc = sh4r.pc + 2;
1.387 while( sh4r.slice_cycle < temp_sh4r.slice_cycle ) {
1.388 @@ -434,18 +334,17 @@
1.389 }
1.390 abort();
1.391 }
1.392 - sh4_address_space = real_address_space;
1.393 + shadow_address_mode = SHADOW_LOG;
1.394 }
1.395
1.396
1.397 void sh4_shadow_init()
1.398 {
1.399 - real_address_space = sh4_address_space;
1.400 - log_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
1.401 - check_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 256 );
1.402 - for( unsigned i=0; i < (256 * 4096); i++ ) {
1.403 - log_address_space[i] = &log_fns;
1.404 - check_address_space[i] = &check_fns;
1.405 + shadow_address_mode = SHADOW_LOG;
1.406 + p4_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 32 );
1.407 + shadow_address_space = mem_alloc_pages( sizeof(mem_region_fn_t) * 32 );
1.408 + for( unsigned i=0; i < (32 * 4096); i++ ) {
1.409 + shadow_address_space[i] = &shadow_fns;
1.410 }
1.411
1.412 mem_log_size = MEM_LOG_SIZE;
1.413 @@ -454,6 +353,10 @@
1.414
1.415 sh4_translate_set_callbacks( sh4_shadow_block_begin, sh4_shadow_block_end );
1.416 sh4_translate_set_fastmem( FALSE );
1.417 - sh4_translate_set_address_space( log_address_space, log_address_space );
1.418 + memcpy( p4_address_space, sh4_address_space + (0xE0000000>>LXDREAM_PAGE_BITS),
1.419 + sizeof(mem_region_fn_t) * (0x20000000>>LXDREAM_PAGE_BITS) );
1.420 + memcpy( sh4_address_space + (0xE0000000>>LXDREAM_PAGE_BITS), shadow_address_space,
1.421 + sizeof(mem_region_fn_t) * (0x20000000>>LXDREAM_PAGE_BITS) );
1.422 + mmu_set_ext_address_space(shadow_address_space);
1.423 }
1.424
.