Search
lxdream.org :: lxdream/src/sh4/shadow.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/shadow.c
changeset 1194:ee6ce5804608
prev1191:12fdf3aafcd4
next1198:407659e01ef0
author nkeynes
date Mon Dec 12 21:13:36 2011 +1000 (8 years ago)
permissions -rw-r--r--
last change Handle memory exceptions thrown while in shadow mode
file annotate diff log raw
1.1 --- a/src/sh4/shadow.c Fri Dec 02 18:18:04 2011 +1000
1.2 +++ b/src/sh4/shadow.c Mon Dec 12 21:13:36 2011 +1000
1.3 @@ -24,9 +24,19 @@
1.4 #include "clock.h"
1.5 #include "mem.h"
1.6 #include "sh4/sh4.h"
1.7 +#include "sh4/sh4core.h"
1.8 #include "sh4/sh4trans.h"
1.9 #include "sh4/mmu.h"
1.10
1.11 +#ifdef HAVE_FRAME_ADDRESS
1.12 +static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }
1.13 +#define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:
1.14 +#define EXCEPTION_EXIT(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; } while(0)
1.15 +#else
1.16 +#define INIT_EXCEPTIONS(label)
1.17 +#define EXCEPTION_EXIT() sh4_core_exit(CORE_EXIT_EXCEPTION)
1.18 +#endif
1.19 +
1.20 typedef enum {
1.21 READ_LONG,
1.22 WRITE_LONG,
1.23 @@ -45,6 +55,7 @@
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 @@ -59,7 +70,7 @@
1.32
1.33 #define IS_STORE_QUEUE(X) (((X)&0xFC000000) == 0xE0000000)
1.34
1.35 -static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
1.36 +static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int exception )
1.37 {
1.38 if( mem_log_posn == mem_log_size ) {
1.39 struct mem_log_entry *tmp = realloc(mem_log, mem_log_size * sizeof(struct mem_log_entry) * 2);
1.40 @@ -70,6 +81,11 @@
1.41 mem_log[mem_log_posn].op = op;
1.42 mem_log[mem_log_posn].addr = addr;
1.43 mem_log[mem_log_posn].value = value;
1.44 + if( exception ) {
1.45 + mem_log[mem_log_posn].exception_pc = sh4r.pc;
1.46 + } else {
1.47 + mem_log[mem_log_posn].exception_pc = -1;
1.48 + }
1.49 mem_log_posn++;
1.50 }
1.51
1.52 @@ -89,7 +105,7 @@
1.53 }
1.54 }
1.55
1.56 -static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value )
1.57 +static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int *exception )
1.58 {
1.59 if( mem_check_posn >= mem_log_posn ) {
1.60 fprintf( stderr, "Unexpected interpreter memory operation: " );
1.61 @@ -107,6 +123,14 @@
1.62 print_mem_op(stderr, op, addr, value );
1.63 abort();
1.64 }
1.65 +
1.66 + if( mem_log[mem_check_posn].exception_pc != -1 ) {
1.67 + sh4_reraise_exception(mem_log[mem_check_posn].exception_pc);
1.68 + *exception = 1;
1.69 + } else {
1.70 + *exception = 0;
1.71 + }
1.72 +
1.73 return mem_log[mem_check_posn++].value;
1.74 }
1.75
1.76 @@ -172,120 +196,206 @@
1.77 if( memcmp( xsh4r->store_queue, esh4r->store_queue, sizeof(xsh4r->store_queue) ) != 0 ) {
1.78 isgood = FALSE;
1.79 fprintf( stderr, "Store queue Xlt =\n" );
1.80 - fwrite_dump( xsh4r->store_queue, sizeof(xsh4r->store_queue), stderr );
1.81 + fwrite_dump( (unsigned char *)xsh4r->store_queue, sizeof(xsh4r->store_queue), stderr );
1.82 fprintf( stderr, " Emu =\n" );
1.83 - fwrite_dump( esh4r->store_queue, sizeof(esh4r->store_queue), stderr );
1.84 + fwrite_dump( (unsigned char *)esh4r->store_queue, sizeof(esh4r->store_queue), stderr );
1.85 }
1.86 return isgood;
1.87 }
1.88
1.89 -static FASTCALL int32_t log_read_long( sh4addr_t addr )
1.90 +static FASTCALL int32_t log_read_long( sh4addr_t addr, void *exc )
1.91 {
1.92 - int32_t rv = real_address_space[addr>>12]->read_long(addr);
1.93 - log_mem_op( READ_LONG, addr, rv );
1.94 + INIT_EXCEPTIONS(except);
1.95 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_long)(addr, &&except);
1.96 + log_mem_op( READ_LONG, addr, rv, 0 );
1.97 return rv;
1.98 +except:
1.99 + log_mem_op( READ_LONG, addr, rv, 1 );
1.100 + EXCEPTION_EXIT(exc);
1.101 }
1.102
1.103 -static FASTCALL int32_t log_read_word( sh4addr_t addr )
1.104 +static FASTCALL int32_t log_read_word( sh4addr_t addr, void *exc )
1.105 {
1.106 - int32_t rv = real_address_space[addr>>12]->read_word(addr);
1.107 - log_mem_op( READ_WORD, addr, rv );
1.108 + INIT_EXCEPTIONS(except);
1.109 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_word)(addr, &&except);
1.110 + log_mem_op( READ_WORD, addr, rv, 0 );
1.111 return rv;
1.112 +except:
1.113 + log_mem_op( READ_WORD, addr, rv, 1 );
1.114 + EXCEPTION_EXIT(exc);
1.115 }
1.116
1.117 -static FASTCALL int32_t log_read_byte( sh4addr_t addr )
1.118 +static FASTCALL int32_t log_read_byte( sh4addr_t addr, void *exc )
1.119 {
1.120 - int32_t rv = real_address_space[addr>>12]->read_byte(addr);
1.121 - log_mem_op( READ_BYTE, addr, rv );
1.122 + INIT_EXCEPTIONS(except);
1.123 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte)(addr, &&except);
1.124 + log_mem_op( READ_BYTE, addr, rv, 0 );
1.125 return rv;
1.126 +except:
1.127 + log_mem_op( READ_BYTE, addr, rv, 1 );
1.128 + EXCEPTION_EXIT(exc);
1.129 }
1.130
1.131 -static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr )
1.132 +static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr, void *exc )
1.133 {
1.134 - int32_t rv = real_address_space[addr>>12]->read_byte_for_write(addr);
1.135 - log_mem_op( READ_BYTE_FOR_WRITE, addr, rv );
1.136 + INIT_EXCEPTIONS(except);
1.137 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte_for_write)(addr, &&except);
1.138 + log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 0 );
1.139 return rv;
1.140 +except:
1.141 + log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 1 );
1.142 + EXCEPTION_EXIT(exc);
1.143 }
1.144
1.145 -static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val )
1.146 +static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val, void *exc )
1.147 {
1.148 + INIT_EXCEPTIONS(except);
1.149 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_long)(addr, val, &&except);
1.150 if( !IS_STORE_QUEUE(addr) )
1.151 - log_mem_op( WRITE_LONG, addr, val );
1.152 - real_address_space[addr>>12]->write_long(addr, val);
1.153 + log_mem_op( WRITE_LONG, addr, val, 0 );
1.154 + return;
1.155 +except:
1.156 + if( !IS_STORE_QUEUE(addr) )
1.157 + log_mem_op( WRITE_LONG, addr, val, 1 );
1.158 + EXCEPTION_EXIT(exc);
1.159 }
1.160
1.161 -static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val )
1.162 +static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val, void *exc )
1.163 {
1.164 + INIT_EXCEPTIONS(except);
1.165 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_word)(addr, val, &&except);
1.166 if( !IS_STORE_QUEUE(addr) )
1.167 - log_mem_op( WRITE_WORD, addr, val );
1.168 - real_address_space[addr>>12]->write_word(addr, val);
1.169 + log_mem_op( WRITE_WORD, addr, val, 0 );
1.170 + return;
1.171 +except:
1.172 + if( !IS_STORE_QUEUE(addr) )
1.173 + log_mem_op( WRITE_WORD, addr, val, 1 );
1.174 + EXCEPTION_EXIT(exc);
1.175 }
1.176
1.177 -static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val )
1.178 +static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val, void *exc )
1.179 {
1.180 + INIT_EXCEPTIONS(except);
1.181 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_byte)(addr, val, &&except);
1.182 if( !IS_STORE_QUEUE(addr) )
1.183 - log_mem_op( WRITE_BYTE, addr, val );
1.184 - real_address_space[addr>>12]->write_byte(addr, val);
1.185 + log_mem_op( WRITE_BYTE, addr, val, 0 );
1.186 + return;
1.187 +except:
1.188 + if( !IS_STORE_QUEUE(addr) )
1.189 + log_mem_op( WRITE_BYTE, addr, val, 1 );
1.190 + EXCEPTION_EXIT(exc);
1.191 }
1.192
1.193 -static FASTCALL void log_prefetch( sh4addr_t addr )
1.194 +static FASTCALL void log_prefetch( sh4addr_t addr, void *exc )
1.195 {
1.196 - log_mem_op( PREFETCH, addr, 0 );
1.197 - real_address_space[addr>>12]->prefetch(addr);
1.198 + INIT_EXCEPTIONS(except);
1.199 + ((mem_prefetch_exc_fn_t)real_address_space[addr>>12]->prefetch)(addr, &&except);
1.200 + log_mem_op( PREFETCH, addr, 0, 0 );
1.201 + return;
1.202 +except:
1.203 + log_mem_op( PREFETCH, addr, 0, 1 );
1.204 + EXCEPTION_EXIT(exc);
1.205 }
1.206
1.207 -static FASTCALL int32_t check_read_long( sh4addr_t addr )
1.208 +static FASTCALL int32_t check_read_long( sh4addr_t addr, void *exc )
1.209 {
1.210 - return check_mem_op( READ_LONG, addr, 0 );
1.211 + int except;
1.212 + int32_t value = check_mem_op( READ_LONG, addr, 0, &except );
1.213 + if( except ) {
1.214 + EXCEPTION_EXIT(exc);
1.215 + }
1.216 + return value;
1.217 }
1.218
1.219 -static FASTCALL int32_t check_read_word( sh4addr_t addr )
1.220 +static FASTCALL int32_t check_read_word( sh4addr_t addr, void *exc )
1.221 {
1.222 - return check_mem_op( READ_WORD, addr, 0 );
1.223 + int except;
1.224 + int32_t value = check_mem_op( READ_WORD, addr, 0, &except );
1.225 + if( except ) {
1.226 + EXCEPTION_EXIT(exc);
1.227 + }
1.228 + return value;
1.229 }
1.230
1.231 -static FASTCALL int32_t check_read_byte( sh4addr_t addr )
1.232 +static FASTCALL int32_t check_read_byte( sh4addr_t addr, void *exc )
1.233 {
1.234 - return check_mem_op( READ_BYTE, addr, 0 );
1.235 + int except;
1.236 + int32_t value = check_mem_op( READ_BYTE, addr, 0, &except );
1.237 + if( except ) {
1.238 + EXCEPTION_EXIT(exc);
1.239 + }
1.240 + return value;
1.241 }
1.242
1.243 -static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr )
1.244 +static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr, void *exc )
1.245 {
1.246 - return check_mem_op( READ_BYTE_FOR_WRITE, addr, 0 );
1.247 + int except;
1.248 + int32_t value = check_mem_op( READ_BYTE_FOR_WRITE, addr, 0, &except );
1.249 + if( except ) {
1.250 + EXCEPTION_EXIT(exc);
1.251 + }
1.252 + return value;
1.253 }
1.254
1.255 -static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value )
1.256 +static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value, void *exc )
1.257 {
1.258 - if( !IS_STORE_QUEUE(addr) )
1.259 - check_mem_op( WRITE_LONG, addr, value );
1.260 + if( !IS_STORE_QUEUE(addr) ) {
1.261 + int except;
1.262 + check_mem_op( WRITE_LONG, addr, value, &except );
1.263 + if( except ) {
1.264 + EXCEPTION_EXIT(exc);
1.265 + }
1.266 + } else {
1.267 + real_address_space[addr>>12]->write_long(addr, value);
1.268 + }
1.269 }
1.270
1.271 -static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value )
1.272 +static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value, void *exc )
1.273 {
1.274 - if( !IS_STORE_QUEUE(addr) )
1.275 - check_mem_op( WRITE_WORD, addr, value );
1.276 + if( !IS_STORE_QUEUE(addr) ) {
1.277 + int except;
1.278 + check_mem_op( WRITE_WORD, addr, value, &except );
1.279 + if( except ) {
1.280 + EXCEPTION_EXIT(exc);
1.281 + }
1.282 + } else {
1.283 + real_address_space[addr>>12]->write_word(addr, value);
1.284 + }
1.285 }
1.286
1.287 -static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value )
1.288 +static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value, void *exc )
1.289 {
1.290 - if( !IS_STORE_QUEUE(addr) )
1.291 - check_mem_op( WRITE_BYTE, addr, value );
1.292 + if( !IS_STORE_QUEUE(addr) ){
1.293 + int except;
1.294 + check_mem_op( WRITE_BYTE, addr, value, &except );
1.295 + if( except ) {
1.296 + EXCEPTION_EXIT(exc);
1.297 + }
1.298 + } else {
1.299 + real_address_space[addr>>12]->write_byte(addr, value);
1.300 + }
1.301 }
1.302
1.303 -static FASTCALL void check_prefetch( sh4addr_t addr )
1.304 +static FASTCALL void check_prefetch( sh4addr_t addr, void *exc )
1.305 {
1.306 - check_mem_op( PREFETCH, addr, 0 );
1.307 + int except;
1.308 + check_mem_op( PREFETCH, addr, 0, &except );
1.309 + if( except ) {
1.310 + EXCEPTION_EXIT(exc);
1.311 + }
1.312 }
1.313
1.314 -struct mem_region_fn log_fns = { log_read_long, log_write_long,
1.315 - log_read_word, log_write_word,
1.316 - log_read_byte, log_write_byte,
1.317 - NULL, NULL, log_prefetch, log_read_byte_for_write };
1.318 +struct mem_region_fn log_fns = {
1.319 + (mem_read_fn_t)log_read_long, (mem_write_fn_t)log_write_long,
1.320 + (mem_read_fn_t)log_read_word, (mem_write_fn_t)log_write_word,
1.321 + (mem_read_fn_t)log_read_byte, (mem_write_fn_t)log_write_byte,
1.322 + NULL, NULL, (mem_prefetch_fn_t)log_prefetch, (mem_read_fn_t)log_read_byte_for_write };
1.323
1.324 -struct mem_region_fn check_fns = { check_read_long, check_write_long,
1.325 - check_read_word, check_write_word,
1.326 - check_read_byte, check_write_byte,
1.327 - NULL, NULL, check_prefetch, check_read_byte_for_write };
1.328 +struct mem_region_fn check_fns = {
1.329 + (mem_read_fn_t)check_read_long, (mem_write_fn_t)check_write_long,
1.330 + (mem_read_fn_t)check_read_word, (mem_write_fn_t)check_write_word,
1.331 + (mem_read_fn_t)check_read_byte, (mem_write_fn_t)check_write_byte,
1.332 + NULL, NULL, (mem_prefetch_fn_t)check_prefetch, (mem_read_fn_t)check_read_byte_for_write };
1.333
1.334
1.335
.