revision 1194:ee6ce5804608
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1194:ee6ce5804608 |
parent | 1193:dff55bdc4f46 |
child | 1195:072131b61d2a |
author | nkeynes |
date | Mon Dec 12 21:13:36 2011 +1000 (12 years ago) |
Handle memory exceptions thrown while in shadow mode
src/sh4/sh4.c | view | annotate | diff | log | ||
src/sh4/sh4core.h | view | annotate | diff | log | ||
src/sh4/sh4x86.in | view | annotate | diff | log | ||
src/sh4/shadow.c | view | annotate | diff | log |
1.1 --- a/src/sh4/sh4.c Mon Dec 12 21:10:04 2011 +10001.2 +++ b/src/sh4/sh4.c Mon Dec 12 21:13:36 2011 +10001.3 @@ -550,6 +550,17 @@1.4 sh4r.in_delay_slot = 0;1.5 }1.7 +void FASTCALL sh4_reraise_exception( sh4addr_t exception_pc )1.8 +{1.9 + sh4r.spc = sh4r.pc;1.10 + sh4r.ssr = sh4_read_sr();1.11 + sh4r.sgr = sh4r.r[15];1.12 + sh4r.pc = exception_pc;1.13 + sh4r.new_pc = sh4r.pc + 2;1.14 + sh4_write_sr( sh4r.ssr |SR_MD|SR_BL|SR_RB );1.15 + sh4r.in_delay_slot = 0;1.16 +}1.17 +1.18 void FASTCALL sh4_accept_interrupt( void )1.19 {1.20 uint32_t code = intc_accept_interrupt();
2.1 --- a/src/sh4/sh4core.h Mon Dec 12 21:10:04 2011 +10002.2 +++ b/src/sh4/sh4core.h Mon Dec 12 21:13:36 2011 +10002.3 @@ -243,6 +243,11 @@2.4 void FASTCALL sh4_accept_interrupt( void );2.6 /**2.7 + * Helper method to update the SH4 registers for an exception, without2.8 + * touching the MMU registers. Mainly for use in shadow mode.2.9 + */2.10 +void FASTCALL sh4_reraise_exception( sh4addr_t exception_pc );2.11 +/**2.12 * Complete the current instruction as part of a core exit. Prevents the2.13 * system from being left in an inconsistent state when an exit is2.14 * triggered during a memory write.
3.1 --- a/src/sh4/sh4x86.in Mon Dec 12 21:10:04 2011 +10003.2 +++ b/src/sh4/sh4x86.in Mon Dec 12 21:13:36 2011 +10003.3 @@ -623,7 +623,7 @@3.4 static void jump_next_block_fixed_pc( sh4addr_t pc )3.5 {3.6 if( IS_IN_ICACHE(pc) ) {3.7 - if( sh4_x86.sh4_mode != SH4_MODE_UNKNOWN ) {3.8 + if( sh4_x86.sh4_mode != SH4_MODE_UNKNOWN && sh4_x86.end_callback == NULL ) {3.9 /* Fixed address, in cache, and fixed SH4 mode - generate a call to the3.10 * fetch-and-backpatch routine, which will replace the call with a branch */3.11 emit_translate_and_backpatch();3.12 @@ -2683,7 +2683,11 @@3.13 COUNT_INST(I_FTRV);3.14 check_fpuen();3.15 if( sh4_x86.double_prec == 0 ) {3.16 - if( sh4_x86.sse3_enabled ) {3.17 + if( sh4_x86.sse3_enabled && sh4_x86.begin_callback == NULL ) {3.18 + /* FIXME: For now, disable this inlining when we're running in shadow mode -3.19 + * it gives slightly different results from the emu core. Need to3.20 + * fix the precision so both give the right results.3.21 + */3.22 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][0]), 1 ); // M1 M0 M3 M23.23 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][4]), 0 ); // M5 M4 M7 M63.24 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][8]), 3 ); // M9 M8 M11 M10
4.1 --- a/src/sh4/shadow.c Mon Dec 12 21:10:04 2011 +10004.2 +++ b/src/sh4/shadow.c Mon Dec 12 21:13:36 2011 +10004.3 @@ -24,9 +24,19 @@4.4 #include "clock.h"4.5 #include "mem.h"4.6 #include "sh4/sh4.h"4.7 +#include "sh4/sh4core.h"4.8 #include "sh4/sh4trans.h"4.9 #include "sh4/mmu.h"4.11 +#ifdef HAVE_FRAME_ADDRESS4.12 +static FASTCALL __attribute__((noinline)) void *__first_arg(void *a, void *b) { return a; }4.13 +#define INIT_EXCEPTIONS(label) goto *__first_arg(&&fnstart,&&label); fnstart:4.14 +#define EXCEPTION_EXIT(exc) do{ *(((void **)__builtin_frame_address(0))+1) = exc; } while(0)4.15 +#else4.16 +#define INIT_EXCEPTIONS(label)4.17 +#define EXCEPTION_EXIT() sh4_core_exit(CORE_EXIT_EXCEPTION)4.18 +#endif4.19 +4.20 typedef enum {4.21 READ_LONG,4.22 WRITE_LONG,4.23 @@ -45,6 +55,7 @@4.24 MemOp op;4.25 sh4addr_t addr;4.26 uint32_t value;4.27 + sh4addr_t exception_pc;4.28 };4.30 static struct sh4_registers shadow_sh4r;4.31 @@ -59,7 +70,7 @@4.33 #define IS_STORE_QUEUE(X) (((X)&0xFC000000) == 0xE0000000)4.35 -static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value )4.36 +static void log_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int exception )4.37 {4.38 if( mem_log_posn == mem_log_size ) {4.39 struct mem_log_entry *tmp = realloc(mem_log, mem_log_size * sizeof(struct mem_log_entry) * 2);4.40 @@ -70,6 +81,11 @@4.41 mem_log[mem_log_posn].op = op;4.42 mem_log[mem_log_posn].addr = addr;4.43 mem_log[mem_log_posn].value = value;4.44 + if( exception ) {4.45 + mem_log[mem_log_posn].exception_pc = sh4r.pc;4.46 + } else {4.47 + mem_log[mem_log_posn].exception_pc = -1;4.48 + }4.49 mem_log_posn++;4.50 }4.52 @@ -89,7 +105,7 @@4.53 }4.54 }4.56 -static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value )4.57 +static int32_t check_mem_op( MemOp op, sh4addr_t addr, uint32_t value, int *exception )4.58 {4.59 if( mem_check_posn >= mem_log_posn ) {4.60 fprintf( stderr, "Unexpected interpreter memory operation: " );4.61 @@ -107,6 +123,14 @@4.62 print_mem_op(stderr, op, addr, value );4.63 abort();4.64 }4.65 +4.66 + if( mem_log[mem_check_posn].exception_pc != -1 ) {4.67 + sh4_reraise_exception(mem_log[mem_check_posn].exception_pc);4.68 + *exception = 1;4.69 + } else {4.70 + *exception = 0;4.71 + }4.72 +4.73 return mem_log[mem_check_posn++].value;4.74 }4.76 @@ -172,120 +196,206 @@4.77 if( memcmp( xsh4r->store_queue, esh4r->store_queue, sizeof(xsh4r->store_queue) ) != 0 ) {4.78 isgood = FALSE;4.79 fprintf( stderr, "Store queue Xlt =\n" );4.80 - fwrite_dump( xsh4r->store_queue, sizeof(xsh4r->store_queue), stderr );4.81 + fwrite_dump( (unsigned char *)xsh4r->store_queue, sizeof(xsh4r->store_queue), stderr );4.82 fprintf( stderr, " Emu =\n" );4.83 - fwrite_dump( esh4r->store_queue, sizeof(esh4r->store_queue), stderr );4.84 + fwrite_dump( (unsigned char *)esh4r->store_queue, sizeof(esh4r->store_queue), stderr );4.85 }4.86 return isgood;4.87 }4.89 -static FASTCALL int32_t log_read_long( sh4addr_t addr )4.90 +static FASTCALL int32_t log_read_long( sh4addr_t addr, void *exc )4.91 {4.92 - int32_t rv = real_address_space[addr>>12]->read_long(addr);4.93 - log_mem_op( READ_LONG, addr, rv );4.94 + INIT_EXCEPTIONS(except);4.95 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_long)(addr, &&except);4.96 + log_mem_op( READ_LONG, addr, rv, 0 );4.97 return rv;4.98 +except:4.99 + log_mem_op( READ_LONG, addr, rv, 1 );4.100 + EXCEPTION_EXIT(exc);4.101 }4.103 -static FASTCALL int32_t log_read_word( sh4addr_t addr )4.104 +static FASTCALL int32_t log_read_word( sh4addr_t addr, void *exc )4.105 {4.106 - int32_t rv = real_address_space[addr>>12]->read_word(addr);4.107 - log_mem_op( READ_WORD, addr, rv );4.108 + INIT_EXCEPTIONS(except);4.109 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_word)(addr, &&except);4.110 + log_mem_op( READ_WORD, addr, rv, 0 );4.111 return rv;4.112 +except:4.113 + log_mem_op( READ_WORD, addr, rv, 1 );4.114 + EXCEPTION_EXIT(exc);4.115 }4.117 -static FASTCALL int32_t log_read_byte( sh4addr_t addr )4.118 +static FASTCALL int32_t log_read_byte( sh4addr_t addr, void *exc )4.119 {4.120 - int32_t rv = real_address_space[addr>>12]->read_byte(addr);4.121 - log_mem_op( READ_BYTE, addr, rv );4.122 + INIT_EXCEPTIONS(except);4.123 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte)(addr, &&except);4.124 + log_mem_op( READ_BYTE, addr, rv, 0 );4.125 return rv;4.126 +except:4.127 + log_mem_op( READ_BYTE, addr, rv, 1 );4.128 + EXCEPTION_EXIT(exc);4.129 }4.131 -static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr )4.132 +static FASTCALL int32_t log_read_byte_for_write( sh4addr_t addr, void *exc )4.133 {4.134 - int32_t rv = real_address_space[addr>>12]->read_byte_for_write(addr);4.135 - log_mem_op( READ_BYTE_FOR_WRITE, addr, rv );4.136 + INIT_EXCEPTIONS(except);4.137 + int32_t rv = ((mem_read_exc_fn_t)real_address_space[addr>>12]->read_byte_for_write)(addr, &&except);4.138 + log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 0 );4.139 return rv;4.140 +except:4.141 + log_mem_op( READ_BYTE_FOR_WRITE, addr, rv, 1 );4.142 + EXCEPTION_EXIT(exc);4.143 }4.145 -static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val )4.146 +static FASTCALL void log_write_long( sh4addr_t addr, uint32_t val, void *exc )4.147 {4.148 + INIT_EXCEPTIONS(except);4.149 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_long)(addr, val, &&except);4.150 if( !IS_STORE_QUEUE(addr) )4.151 - log_mem_op( WRITE_LONG, addr, val );4.152 - real_address_space[addr>>12]->write_long(addr, val);4.153 + log_mem_op( WRITE_LONG, addr, val, 0 );4.154 + return;4.155 +except:4.156 + if( !IS_STORE_QUEUE(addr) )4.157 + log_mem_op( WRITE_LONG, addr, val, 1 );4.158 + EXCEPTION_EXIT(exc);4.159 }4.161 -static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val )4.162 +static FASTCALL void log_write_word( sh4addr_t addr, uint32_t val, void *exc )4.163 {4.164 + INIT_EXCEPTIONS(except);4.165 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_word)(addr, val, &&except);4.166 if( !IS_STORE_QUEUE(addr) )4.167 - log_mem_op( WRITE_WORD, addr, val );4.168 - real_address_space[addr>>12]->write_word(addr, val);4.169 + log_mem_op( WRITE_WORD, addr, val, 0 );4.170 + return;4.171 +except:4.172 + if( !IS_STORE_QUEUE(addr) )4.173 + log_mem_op( WRITE_WORD, addr, val, 1 );4.174 + EXCEPTION_EXIT(exc);4.175 }4.177 -static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val )4.178 +static FASTCALL void log_write_byte( sh4addr_t addr, uint32_t val, void *exc )4.179 {4.180 + INIT_EXCEPTIONS(except);4.181 + ((mem_write_exc_fn_t)real_address_space[addr>>12]->write_byte)(addr, val, &&except);4.182 if( !IS_STORE_QUEUE(addr) )4.183 - log_mem_op( WRITE_BYTE, addr, val );4.184 - real_address_space[addr>>12]->write_byte(addr, val);4.185 + log_mem_op( WRITE_BYTE, addr, val, 0 );4.186 + return;4.187 +except:4.188 + if( !IS_STORE_QUEUE(addr) )4.189 + log_mem_op( WRITE_BYTE, addr, val, 1 );4.190 + EXCEPTION_EXIT(exc);4.191 }4.193 -static FASTCALL void log_prefetch( sh4addr_t addr )4.194 +static FASTCALL void log_prefetch( sh4addr_t addr, void *exc )4.195 {4.196 - log_mem_op( PREFETCH, addr, 0 );4.197 - real_address_space[addr>>12]->prefetch(addr);4.198 + INIT_EXCEPTIONS(except);4.199 + ((mem_prefetch_exc_fn_t)real_address_space[addr>>12]->prefetch)(addr, &&except);4.200 + log_mem_op( PREFETCH, addr, 0, 0 );4.201 + return;4.202 +except:4.203 + log_mem_op( PREFETCH, addr, 0, 1 );4.204 + EXCEPTION_EXIT(exc);4.205 }4.207 -static FASTCALL int32_t check_read_long( sh4addr_t addr )4.208 +static FASTCALL int32_t check_read_long( sh4addr_t addr, void *exc )4.209 {4.210 - return check_mem_op( READ_LONG, addr, 0 );4.211 + int except;4.212 + int32_t value = check_mem_op( READ_LONG, addr, 0, &except );4.213 + if( except ) {4.214 + EXCEPTION_EXIT(exc);4.215 + }4.216 + return value;4.217 }4.219 -static FASTCALL int32_t check_read_word( sh4addr_t addr )4.220 +static FASTCALL int32_t check_read_word( sh4addr_t addr, void *exc )4.221 {4.222 - return check_mem_op( READ_WORD, addr, 0 );4.223 + int except;4.224 + int32_t value = check_mem_op( READ_WORD, addr, 0, &except );4.225 + if( except ) {4.226 + EXCEPTION_EXIT(exc);4.227 + }4.228 + return value;4.229 }4.231 -static FASTCALL int32_t check_read_byte( sh4addr_t addr )4.232 +static FASTCALL int32_t check_read_byte( sh4addr_t addr, void *exc )4.233 {4.234 - return check_mem_op( READ_BYTE, addr, 0 );4.235 + int except;4.236 + int32_t value = check_mem_op( READ_BYTE, addr, 0, &except );4.237 + if( except ) {4.238 + EXCEPTION_EXIT(exc);4.239 + }4.240 + return value;4.241 }4.243 -static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr )4.244 +static FASTCALL int32_t check_read_byte_for_write( sh4addr_t addr, void *exc )4.245 {4.246 - return check_mem_op( READ_BYTE_FOR_WRITE, addr, 0 );4.247 + int except;4.248 + int32_t value = check_mem_op( READ_BYTE_FOR_WRITE, addr, 0, &except );4.249 + if( except ) {4.250 + EXCEPTION_EXIT(exc);4.251 + }4.252 + return value;4.253 }4.255 -static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value )4.256 +static FASTCALL void check_write_long( sh4addr_t addr, uint32_t value, void *exc )4.257 {4.258 - if( !IS_STORE_QUEUE(addr) )4.259 - check_mem_op( WRITE_LONG, addr, value );4.260 + if( !IS_STORE_QUEUE(addr) ) {4.261 + int except;4.262 + check_mem_op( WRITE_LONG, addr, value, &except );4.263 + if( except ) {4.264 + EXCEPTION_EXIT(exc);4.265 + }4.266 + } else {4.267 + real_address_space[addr>>12]->write_long(addr, value);4.268 + }4.269 }4.271 -static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value )4.272 +static FASTCALL void check_write_word( sh4addr_t addr, uint32_t value, void *exc )4.273 {4.274 - if( !IS_STORE_QUEUE(addr) )4.275 - check_mem_op( WRITE_WORD, addr, value );4.276 + if( !IS_STORE_QUEUE(addr) ) {4.277 + int except;4.278 + check_mem_op( WRITE_WORD, addr, value, &except );4.279 + if( except ) {4.280 + EXCEPTION_EXIT(exc);4.281 + }4.282 + } else {4.283 + real_address_space[addr>>12]->write_word(addr, value);4.284 + }4.285 }4.287 -static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value )4.288 +static FASTCALL void check_write_byte( sh4addr_t addr, uint32_t value, void *exc )4.289 {4.290 - if( !IS_STORE_QUEUE(addr) )4.291 - check_mem_op( WRITE_BYTE, addr, value );4.292 + if( !IS_STORE_QUEUE(addr) ){4.293 + int except;4.294 + check_mem_op( WRITE_BYTE, addr, value, &except );4.295 + if( except ) {4.296 + EXCEPTION_EXIT(exc);4.297 + }4.298 + } else {4.299 + real_address_space[addr>>12]->write_byte(addr, value);4.300 + }4.301 }4.303 -static FASTCALL void check_prefetch( sh4addr_t addr )4.304 +static FASTCALL void check_prefetch( sh4addr_t addr, void *exc )4.305 {4.306 - check_mem_op( PREFETCH, addr, 0 );4.307 + int except;4.308 + check_mem_op( PREFETCH, addr, 0, &except );4.309 + if( except ) {4.310 + EXCEPTION_EXIT(exc);4.311 + }4.312 }4.314 -struct mem_region_fn log_fns = { log_read_long, log_write_long,4.315 - log_read_word, log_write_word,4.316 - log_read_byte, log_write_byte,4.317 - NULL, NULL, log_prefetch, log_read_byte_for_write };4.318 +struct mem_region_fn log_fns = {4.319 + (mem_read_fn_t)log_read_long, (mem_write_fn_t)log_write_long,4.320 + (mem_read_fn_t)log_read_word, (mem_write_fn_t)log_write_word,4.321 + (mem_read_fn_t)log_read_byte, (mem_write_fn_t)log_write_byte,4.322 + NULL, NULL, (mem_prefetch_fn_t)log_prefetch, (mem_read_fn_t)log_read_byte_for_write };4.324 -struct mem_region_fn check_fns = { check_read_long, check_write_long,4.325 - check_read_word, check_write_word,4.326 - check_read_byte, check_write_byte,4.327 - NULL, NULL, check_prefetch, check_read_byte_for_write };4.328 +struct mem_region_fn check_fns = {4.329 + (mem_read_fn_t)check_read_long, (mem_write_fn_t)check_write_long,4.330 + (mem_read_fn_t)check_read_word, (mem_write_fn_t)check_write_word,4.331 + (mem_read_fn_t)check_read_byte, (mem_write_fn_t)check_write_byte,4.332 + NULL, NULL, (mem_prefetch_fn_t)check_prefetch, (mem_read_fn_t)check_read_byte_for_write };
.