Search
lxdream.org :: lxdream :: r1194:ee6ce5804608
lxdream 0.9.1
released Jun 29
Download Now
changeset1194:ee6ce5804608
parent1193:dff55bdc4f46
child1195:072131b61d2a
authornkeynes
dateMon Dec 12 21:13:36 2011 +1000 (12 years ago)
Handle memory exceptions thrown while in shadow mode
src/sh4/sh4.c
src/sh4/sh4core.h
src/sh4/sh4x86.in
src/sh4/shadow.c
1.1 --- a/src/sh4/sh4.c Mon Dec 12 21:10:04 2011 +1000
1.2 +++ b/src/sh4/sh4.c Mon Dec 12 21:13:36 2011 +1000
1.3 @@ -550,6 +550,17 @@
1.4 sh4r.in_delay_slot = 0;
1.5 }
1.6
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 +1000
2.2 +++ b/src/sh4/sh4core.h Mon Dec 12 21:13:36 2011 +1000
2.3 @@ -243,6 +243,11 @@
2.4 void FASTCALL sh4_accept_interrupt( void );
2.5
2.6 /**
2.7 + * Helper method to update the SH4 registers for an exception, without
2.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 the
2.13 * system from being left in an inconsistent state when an exit is
2.14 * triggered during a memory write.
3.1 --- a/src/sh4/sh4x86.in Mon Dec 12 21:10:04 2011 +1000
3.2 +++ b/src/sh4/sh4x86.in Mon Dec 12 21:13:36 2011 +1000
3.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 the
3.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 to
3.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 M2
3.23 MOVAPS_rbpdisp_xmm( REG_OFFSET(fr[1][4]), 0 ); // M5 M4 M7 M6
3.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 +1000
4.2 +++ b/src/sh4/shadow.c Mon Dec 12 21:13:36 2011 +1000
4.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.10
4.11 +#ifdef HAVE_FRAME_ADDRESS
4.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 +#else
4.16 +#define INIT_EXCEPTIONS(label)
4.17 +#define EXCEPTION_EXIT() sh4_core_exit(CORE_EXIT_EXCEPTION)
4.18 +#endif
4.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.29
4.30 static struct sh4_registers shadow_sh4r;
4.31 @@ -59,7 +70,7 @@
4.32
4.33 #define IS_STORE_QUEUE(X) (((X)&0xFC000000) == 0xE0000000)
4.34
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.51
4.52 @@ -89,7 +105,7 @@
4.53 }
4.54 }
4.55
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.75
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.88
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.102
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.116
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.130
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.144
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.160
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.176
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.192
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.206
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.218
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.230
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.242
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.254
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.270
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.286
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.302
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.313
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.323
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 };
4.333
4.334
4.335
.