Search
lxdream.org :: lxdream/src/sh4/sh4x86.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.c
changeset 586:2a3ba82cf243
prev553:4e6166258c22
next590:4db6a084ca3c
author nkeynes
date Tue Jan 15 20:50:23 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Merged lxdream-mmu r570:596 to trunk
file annotate diff log raw
1.1 --- a/src/sh4/sh4x86.c Thu Dec 20 09:56:07 2007 +0000
1.2 +++ b/src/sh4/sh4x86.c Tue Jan 15 20:50:23 2008 +0000
1.3 @@ -1,5 +1,5 @@
1.4 /**
1.5 - * $Id: sh4x86.in,v 1.20 2007-11-08 11:54:16 nkeynes Exp $
1.6 + * $Id$
1.7 *
1.8 * SH4 => x86 translation. This version does no real optimization, it just
1.9 * outputs straight-line x86 code - it mainly exists to provide a baseline
1.10 @@ -34,6 +34,14 @@
1.11
1.12 #define DEFAULT_BACKPATCH_SIZE 4096
1.13
1.14 +struct backpatch_record {
1.15 + uint32_t *fixup_addr;
1.16 + uint32_t fixup_icount;
1.17 + uint32_t exc_code;
1.18 +};
1.19 +
1.20 +#define MAX_RECOVERY_SIZE 2048
1.21 +
1.22 /**
1.23 * Struct to manage internal translation state. This state is not saved -
1.24 * it is only valid between calls to sh4_translate_begin_block() and
1.25 @@ -48,10 +56,15 @@
1.26 uint32_t stack_posn; /* Trace stack height for alignment purposes */
1.27 int tstate;
1.28
1.29 + /* mode flags */
1.30 + gboolean tlb_on; /* True if tlb translation is active */
1.31 +
1.32 /* Allocated memory for the (block-wide) back-patch list */
1.33 - uint32_t **backpatch_list;
1.34 + struct backpatch_record *backpatch_list;
1.35 uint32_t backpatch_posn;
1.36 uint32_t backpatch_size;
1.37 + struct xlat_recovery_record recovery_list[MAX_RECOVERY_SIZE];
1.38 + uint32_t recovery_posn;
1.39 };
1.40
1.41 #define TSTATE_NONE -1
1.42 @@ -75,14 +88,6 @@
1.43 OP(0x70+ (sh4_x86.tstate^1)); OP(rel8); \
1.44 MARK_JMP(rel8, label)
1.45
1.46 -
1.47 -#define EXIT_DATA_ADDR_READ 0
1.48 -#define EXIT_DATA_ADDR_WRITE 7
1.49 -#define EXIT_ILLEGAL 14
1.50 -#define EXIT_SLOT_ILLEGAL 21
1.51 -#define EXIT_FPU_DISABLED 28
1.52 -#define EXIT_SLOT_FPU_DISABLED 35
1.53 -
1.54 static struct sh4_x86_state sh4_x86;
1.55
1.56 static uint32_t max_int = 0x7FFFFFFF;
1.57 @@ -93,26 +98,32 @@
1.58 void sh4_x86_init()
1.59 {
1.60 sh4_x86.backpatch_list = malloc(DEFAULT_BACKPATCH_SIZE);
1.61 - sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(uint32_t *);
1.62 + sh4_x86.backpatch_size = DEFAULT_BACKPATCH_SIZE / sizeof(struct backpatch_record);
1.63 }
1.64
1.65
1.66 -static void sh4_x86_add_backpatch( uint8_t *ptr )
1.67 +static void sh4_x86_add_backpatch( uint8_t *fixup_addr, uint32_t fixup_pc, uint32_t exc_code )
1.68 {
1.69 if( sh4_x86.backpatch_posn == sh4_x86.backpatch_size ) {
1.70 sh4_x86.backpatch_size <<= 1;
1.71 - sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list, sh4_x86.backpatch_size * sizeof(uint32_t *) );
1.72 + sh4_x86.backpatch_list = realloc( sh4_x86.backpatch_list,
1.73 + sh4_x86.backpatch_size * sizeof(struct backpatch_record));
1.74 assert( sh4_x86.backpatch_list != NULL );
1.75 }
1.76 - sh4_x86.backpatch_list[sh4_x86.backpatch_posn++] = (uint32_t *)ptr;
1.77 + if( sh4_x86.in_delay_slot ) {
1.78 + fixup_pc -= 2;
1.79 + }
1.80 + sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_addr = (uint32_t *)fixup_addr;
1.81 + sh4_x86.backpatch_list[sh4_x86.backpatch_posn].fixup_icount = (fixup_pc - sh4_x86.block_start_pc)>>1;
1.82 + sh4_x86.backpatch_list[sh4_x86.backpatch_posn].exc_code = exc_code;
1.83 + sh4_x86.backpatch_posn++;
1.84 }
1.85
1.86 -static void sh4_x86_do_backpatch( uint8_t *reloc_base )
1.87 +void sh4_x86_add_recovery( uint32_t pc )
1.88 {
1.89 - unsigned int i;
1.90 - for( i=0; i<sh4_x86.backpatch_posn; i++ ) {
1.91 - *sh4_x86.backpatch_list[i] += (reloc_base - ((uint8_t *)sh4_x86.backpatch_list[i]) - 4);
1.92 - }
1.93 + xlat_recovery[xlat_recovery_posn].xlat_pc = (uintptr_t)xlat_output;
1.94 + xlat_recovery[xlat_recovery_posn].sh4_icount = (pc - sh4_x86.block_start_pc)>>1;
1.95 + xlat_recovery_posn++;
1.96 }
1.97
1.98 /**
1.99 @@ -266,86 +277,46 @@
1.100 }
1.101
1.102 /* Exception checks - Note that all exception checks will clobber EAX */
1.103 -#define precheck() load_imm32(R_EDX, (pc-sh4_x86.block_start_pc-(sh4_x86.in_delay_slot?2:0))>>1)
1.104
1.105 #define check_priv( ) \
1.106 if( !sh4_x86.priv_checked ) { \
1.107 sh4_x86.priv_checked = TRUE;\
1.108 - precheck();\
1.109 load_spreg( R_EAX, R_SR );\
1.110 AND_imm32_r32( SR_MD, R_EAX );\
1.111 if( sh4_x86.in_delay_slot ) {\
1.112 - JE_exit( EXIT_SLOT_ILLEGAL );\
1.113 + JE_exc( EXC_SLOT_ILLEGAL );\
1.114 } else {\
1.115 - JE_exit( EXIT_ILLEGAL );\
1.116 + JE_exc( EXC_ILLEGAL );\
1.117 }\
1.118 }\
1.119
1.120 -
1.121 -static void check_priv_no_precheck()
1.122 -{
1.123 - if( !sh4_x86.priv_checked ) {
1.124 - sh4_x86.priv_checked = TRUE;
1.125 - load_spreg( R_EAX, R_SR );
1.126 - AND_imm32_r32( SR_MD, R_EAX );
1.127 - if( sh4_x86.in_delay_slot ) {
1.128 - JE_exit( EXIT_SLOT_ILLEGAL );
1.129 - } else {
1.130 - JE_exit( EXIT_ILLEGAL );
1.131 - }
1.132 - }
1.133 -}
1.134 -
1.135 #define check_fpuen( ) \
1.136 if( !sh4_x86.fpuen_checked ) {\
1.137 sh4_x86.fpuen_checked = TRUE;\
1.138 - precheck();\
1.139 load_spreg( R_EAX, R_SR );\
1.140 AND_imm32_r32( SR_FD, R_EAX );\
1.141 if( sh4_x86.in_delay_slot ) {\
1.142 - JNE_exit(EXIT_SLOT_FPU_DISABLED);\
1.143 + JNE_exc(EXC_SLOT_FPU_DISABLED);\
1.144 } else {\
1.145 - JNE_exit(EXIT_FPU_DISABLED);\
1.146 + JNE_exc(EXC_FPU_DISABLED);\
1.147 }\
1.148 }
1.149
1.150 -static void check_fpuen_no_precheck()
1.151 -{
1.152 - if( !sh4_x86.fpuen_checked ) {
1.153 - sh4_x86.fpuen_checked = TRUE;
1.154 - load_spreg( R_EAX, R_SR );
1.155 - AND_imm32_r32( SR_FD, R_EAX );
1.156 - if( sh4_x86.in_delay_slot ) {
1.157 - JNE_exit(EXIT_SLOT_FPU_DISABLED);
1.158 - } else {
1.159 - JNE_exit(EXIT_FPU_DISABLED);
1.160 - }
1.161 - }
1.162 +#define check_ralign16( x86reg ) \
1.163 + TEST_imm32_r32( 0x00000001, x86reg ); \
1.164 + JNE_exc(EXC_DATA_ADDR_READ)
1.165
1.166 -}
1.167 +#define check_walign16( x86reg ) \
1.168 + TEST_imm32_r32( 0x00000001, x86reg ); \
1.169 + JNE_exc(EXC_DATA_ADDR_WRITE);
1.170
1.171 -static void check_ralign16( int x86reg )
1.172 -{
1.173 - TEST_imm32_r32( 0x00000001, x86reg );
1.174 - JNE_exit(EXIT_DATA_ADDR_READ);
1.175 -}
1.176 +#define check_ralign32( x86reg ) \
1.177 + TEST_imm32_r32( 0x00000003, x86reg ); \
1.178 + JNE_exc(EXC_DATA_ADDR_READ)
1.179
1.180 -static void check_walign16( int x86reg )
1.181 -{
1.182 - TEST_imm32_r32( 0x00000001, x86reg );
1.183 - JNE_exit(EXIT_DATA_ADDR_WRITE);
1.184 -}
1.185 -
1.186 -static void check_ralign32( int x86reg )
1.187 -{
1.188 - TEST_imm32_r32( 0x00000003, x86reg );
1.189 - JNE_exit(EXIT_DATA_ADDR_READ);
1.190 -}
1.191 -static void check_walign32( int x86reg )
1.192 -{
1.193 - TEST_imm32_r32( 0x00000003, x86reg );
1.194 - JNE_exit(EXIT_DATA_ADDR_WRITE);
1.195 -}
1.196 +#define check_walign32( x86reg ) \
1.197 + TEST_imm32_r32( 0x00000003, x86reg ); \
1.198 + JNE_exc(EXC_DATA_ADDR_WRITE);
1.199
1.200 #define UNDEF()
1.201 #define MEM_RESULT(value_reg) if(value_reg != R_EAX) { MOV_r32_r32(R_EAX,value_reg); }
1.202 @@ -356,10 +327,22 @@
1.203 #define MEM_WRITE_WORD( addr_reg, value_reg ) call_func2(sh4_write_word, addr_reg, value_reg)
1.204 #define MEM_WRITE_LONG( addr_reg, value_reg ) call_func2(sh4_write_long, addr_reg, value_reg)
1.205
1.206 -#define SLOTILLEGAL() precheck(); JMP_exit(EXIT_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;
1.207 +/**
1.208 + * Perform MMU translation on the address in addr_reg for a read operation, iff the TLB is turned
1.209 + * on, otherwise do nothing. Clobbers EAX, ECX and EDX. May raise a TLB exception or address error.
1.210 + */
1.211 +#define MMU_TRANSLATE_READ( addr_reg ) if( sh4_x86.tlb_on ) { call_func1(mmu_vma_to_phys_read, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); MEM_RESULT(addr_reg); }
1.212 +/**
1.213 + * Perform MMU translation on the address in addr_reg for a write operation, iff the TLB is turned
1.214 + * on, otherwise do nothing. Clobbers EAX, ECX and EDX. May raise a TLB exception or address error.
1.215 + */
1.216 +#define MMU_TRANSLATE_WRITE( addr_reg ) if( sh4_x86.tlb_on ) { call_func1(mmu_vma_to_phys_write, addr_reg); CMP_imm32_r32(MMU_VMA_ERROR, R_EAX); JE_exc(-1); MEM_RESULT(addr_reg); }
1.217
1.218 -extern uint16_t *sh4_icache;
1.219 -extern uint32_t sh4_icache_addr;
1.220 +#define MEM_READ_SIZE (CALL_FUNC1_SIZE)
1.221 +#define MEM_WRITE_SIZE (CALL_FUNC2_SIZE)
1.222 +#define MMU_TRANSLATE_SIZE (sh4_x86.tlb_on ? (CALL_FUNC1_SIZE + 12) : 0 )
1.223 +
1.224 +#define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;
1.225
1.226 /****** Import appropriate calling conventions ******/
1.227 #if SH4_TRANSLATOR == TARGET_X86_64
1.228 @@ -372,11 +355,18 @@
1.229 #endif
1.230 #endif
1.231
1.232 +void sh4_translate_emit_breakpoint( sh4vma_t pc )
1.233 +{
1.234 + load_imm32( R_EAX, XLAT_EXIT_BREAKPOINT );
1.235 + call_func1( sh4_translate_exit, R_EAX );
1.236 +}
1.237 +
1.238
1.239 /**
1.240 * Translate a single instruction. Delayed branches are handled specially
1.241 * by translating both branch and delayed instruction as a single unit (as
1.242 *
1.243 + * The instruction MUST be in the icache (assert check)
1.244 *
1.245 * @return true if the instruction marks the end of a basic block
1.246 * (eg a branch or
1.247 @@ -384,24 +374,23 @@
1.248 uint32_t sh4_translate_instruction( sh4addr_t pc )
1.249 {
1.250 uint32_t ir;
1.251 - /* Read instruction */
1.252 - uint32_t pageaddr = pc >> 12;
1.253 - if( sh4_icache != NULL && pageaddr == sh4_icache_addr ) {
1.254 - ir = sh4_icache[(pc&0xFFF)>>1];
1.255 - } else {
1.256 - sh4_icache = (uint16_t *)mem_get_page(pc);
1.257 - if( ((uintptr_t)sh4_icache) < MAX_IO_REGIONS ) {
1.258 - /* If someone's actually been so daft as to try to execute out of an IO
1.259 - * region, fallback on the full-blown memory read
1.260 - */
1.261 - sh4_icache = NULL;
1.262 - ir = sh4_read_word(pc);
1.263 - } else {
1.264 - sh4_icache_addr = pageaddr;
1.265 - ir = sh4_icache[(pc&0xFFF)>>1];
1.266 - }
1.267 + /* Read instruction from icache */
1.268 + assert( IS_IN_ICACHE(pc) );
1.269 + ir = *(uint16_t *)GET_ICACHE_PTR(pc);
1.270 +
1.271 + /* PC is not in the current icache - this usually means we're running
1.272 + * with MMU on, and we've gone past the end of the page. And since
1.273 + * sh4_translate_block is pretty careful about this, it means we're
1.274 + * almost certainly in a delay slot.
1.275 + *
1.276 + * Since we can't assume the page is present (and we can't fault it in
1.277 + * at this point, inline a call to sh4_execute_instruction (with a few
1.278 + * small repairs to cope with the different environment).
1.279 + */
1.280 +
1.281 + if( !sh4_x86.in_delay_slot ) {
1.282 + sh4_x86_add_recovery(pc);
1.283 }
1.284 -
1.285 switch( (ir&0xF000) >> 12 ) {
1.286 case 0x0:
1.287 switch( ir&0xF ) {
1.288 @@ -514,8 +503,10 @@
1.289 MOV_r32_r32( R_EAX, R_ECX );
1.290 AND_imm32_r32( 0xFC000000, R_EAX );
1.291 CMP_imm32_r32( 0xE0000000, R_EAX );
1.292 - JNE_rel8(CALL_FUNC1_SIZE, end);
1.293 + JNE_rel8(8+CALL_FUNC1_SIZE, end);
1.294 call_func1( sh4_flush_store_queue, R_ECX );
1.295 + TEST_r32_r32( R_EAX, R_EAX );
1.296 + JE_exc(-1);
1.297 JMP_TARGET(end);
1.298 sh4_x86.tstate = TSTATE_NONE;
1.299 }
1.300 @@ -538,11 +529,11 @@
1.301 case 0xC:
1.302 { /* MOVCA.L R0, @Rn */
1.303 uint32_t Rn = ((ir>>8)&0xF);
1.304 - load_reg( R_EAX, 0 );
1.305 - load_reg( R_ECX, Rn );
1.306 - precheck();
1.307 - check_walign32( R_ECX );
1.308 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.309 + load_reg( R_EAX, Rn );
1.310 + check_walign32( R_EAX );
1.311 + MMU_TRANSLATE_WRITE( R_EAX );
1.312 + load_reg( R_EDX, 0 );
1.313 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.314 sh4_x86.tstate = TSTATE_NONE;
1.315 }
1.316 break;
1.317 @@ -556,9 +547,10 @@
1.318 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.319 load_reg( R_EAX, 0 );
1.320 load_reg( R_ECX, Rn );
1.321 - ADD_r32_r32( R_EAX, R_ECX );
1.322 - load_reg( R_EAX, Rm );
1.323 - MEM_WRITE_BYTE( R_ECX, R_EAX );
1.324 + ADD_r32_r32( R_ECX, R_EAX );
1.325 + MMU_TRANSLATE_WRITE( R_EAX );
1.326 + load_reg( R_EDX, Rm );
1.327 + MEM_WRITE_BYTE( R_EAX, R_EDX );
1.328 sh4_x86.tstate = TSTATE_NONE;
1.329 }
1.330 break;
1.331 @@ -567,11 +559,11 @@
1.332 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.333 load_reg( R_EAX, 0 );
1.334 load_reg( R_ECX, Rn );
1.335 - ADD_r32_r32( R_EAX, R_ECX );
1.336 - precheck();
1.337 - check_walign16( R_ECX );
1.338 - load_reg( R_EAX, Rm );
1.339 - MEM_WRITE_WORD( R_ECX, R_EAX );
1.340 + ADD_r32_r32( R_ECX, R_EAX );
1.341 + check_walign16( R_EAX );
1.342 + MMU_TRANSLATE_WRITE( R_EAX );
1.343 + load_reg( R_EDX, Rm );
1.344 + MEM_WRITE_WORD( R_EAX, R_EDX );
1.345 sh4_x86.tstate = TSTATE_NONE;
1.346 }
1.347 break;
1.348 @@ -580,11 +572,11 @@
1.349 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.350 load_reg( R_EAX, 0 );
1.351 load_reg( R_ECX, Rn );
1.352 - ADD_r32_r32( R_EAX, R_ECX );
1.353 - precheck();
1.354 - check_walign32( R_ECX );
1.355 - load_reg( R_EAX, Rm );
1.356 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.357 + ADD_r32_r32( R_ECX, R_EAX );
1.358 + check_walign32( R_EAX );
1.359 + MMU_TRANSLATE_WRITE( R_EAX );
1.360 + load_reg( R_EDX, Rm );
1.361 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.362 sh4_x86.tstate = TSTATE_NONE;
1.363 }
1.364 break;
1.365 @@ -791,8 +783,9 @@
1.366 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.367 load_reg( R_EAX, 0 );
1.368 load_reg( R_ECX, Rm );
1.369 - ADD_r32_r32( R_EAX, R_ECX );
1.370 - MEM_READ_BYTE( R_ECX, R_EAX );
1.371 + ADD_r32_r32( R_ECX, R_EAX );
1.372 + MMU_TRANSLATE_READ( R_EAX )
1.373 + MEM_READ_BYTE( R_EAX, R_EAX );
1.374 store_reg( R_EAX, Rn );
1.375 sh4_x86.tstate = TSTATE_NONE;
1.376 }
1.377 @@ -802,10 +795,10 @@
1.378 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.379 load_reg( R_EAX, 0 );
1.380 load_reg( R_ECX, Rm );
1.381 - ADD_r32_r32( R_EAX, R_ECX );
1.382 - precheck();
1.383 - check_ralign16( R_ECX );
1.384 - MEM_READ_WORD( R_ECX, R_EAX );
1.385 + ADD_r32_r32( R_ECX, R_EAX );
1.386 + check_ralign16( R_EAX );
1.387 + MMU_TRANSLATE_READ( R_EAX );
1.388 + MEM_READ_WORD( R_EAX, R_EAX );
1.389 store_reg( R_EAX, Rn );
1.390 sh4_x86.tstate = TSTATE_NONE;
1.391 }
1.392 @@ -815,10 +808,10 @@
1.393 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.394 load_reg( R_EAX, 0 );
1.395 load_reg( R_ECX, Rm );
1.396 - ADD_r32_r32( R_EAX, R_ECX );
1.397 - precheck();
1.398 - check_ralign32( R_ECX );
1.399 - MEM_READ_LONG( R_ECX, R_EAX );
1.400 + ADD_r32_r32( R_ECX, R_EAX );
1.401 + check_ralign32( R_EAX );
1.402 + MMU_TRANSLATE_READ( R_EAX );
1.403 + MEM_READ_LONG( R_EAX, R_EAX );
1.404 store_reg( R_EAX, Rn );
1.405 sh4_x86.tstate = TSTATE_NONE;
1.406 }
1.407 @@ -826,18 +819,34 @@
1.408 case 0xF:
1.409 { /* MAC.L @Rm+, @Rn+ */
1.410 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.411 - load_reg( R_ECX, Rm );
1.412 - precheck();
1.413 - check_ralign32( R_ECX );
1.414 - load_reg( R_ECX, Rn );
1.415 - check_ralign32( R_ECX );
1.416 - ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
1.417 - MEM_READ_LONG( R_ECX, R_EAX );
1.418 - PUSH_realigned_r32( R_EAX );
1.419 - load_reg( R_ECX, Rm );
1.420 - ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.421 + if( Rm == Rn ) {
1.422 + load_reg( R_EAX, Rm );
1.423 + check_ralign32( R_EAX );
1.424 + MMU_TRANSLATE_READ( R_EAX );
1.425 + PUSH_realigned_r32( R_EAX );
1.426 + load_reg( R_EAX, Rn );
1.427 + ADD_imm8s_r32( 4, R_EAX );
1.428 + MMU_TRANSLATE_READ( R_EAX );
1.429 + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rn]) );
1.430 + // Note translate twice in case of page boundaries. Maybe worth
1.431 + // adding a page-boundary check to skip the second translation
1.432 + } else {
1.433 + load_reg( R_EAX, Rm );
1.434 + check_ralign32( R_EAX );
1.435 + MMU_TRANSLATE_READ( R_EAX );
1.436 + PUSH_realigned_r32( R_EAX );
1.437 + load_reg( R_EAX, Rn );
1.438 + check_ralign32( R_EAX );
1.439 + MMU_TRANSLATE_READ( R_EAX );
1.440 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
1.441 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.442 + }
1.443 + MEM_READ_LONG( R_EAX, R_EAX );
1.444 + POP_r32( R_ECX );
1.445 + PUSH_r32( R_EAX );
1.446 MEM_READ_LONG( R_ECX, R_EAX );
1.447 POP_realigned_r32( R_ECX );
1.448 +
1.449 IMUL_r32( R_ECX );
1.450 ADD_r32_sh4r( R_EAX, R_MACL );
1.451 ADC_r32_sh4r( R_EDX, R_MACH );
1.452 @@ -858,12 +867,12 @@
1.453 case 0x1:
1.454 { /* MOV.L Rm, @(disp, Rn) */
1.455 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
1.456 - load_reg( R_ECX, Rn );
1.457 - load_reg( R_EAX, Rm );
1.458 - ADD_imm32_r32( disp, R_ECX );
1.459 - precheck();
1.460 - check_walign32( R_ECX );
1.461 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.462 + load_reg( R_EAX, Rn );
1.463 + ADD_imm32_r32( disp, R_EAX );
1.464 + check_walign32( R_EAX );
1.465 + MMU_TRANSLATE_WRITE( R_EAX );
1.466 + load_reg( R_EDX, Rm );
1.467 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.468 sh4_x86.tstate = TSTATE_NONE;
1.469 }
1.470 break;
1.471 @@ -872,68 +881,70 @@
1.472 case 0x0:
1.473 { /* MOV.B Rm, @Rn */
1.474 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.475 - load_reg( R_EAX, Rm );
1.476 - load_reg( R_ECX, Rn );
1.477 - MEM_WRITE_BYTE( R_ECX, R_EAX );
1.478 + load_reg( R_EAX, Rn );
1.479 + MMU_TRANSLATE_WRITE( R_EAX );
1.480 + load_reg( R_EDX, Rm );
1.481 + MEM_WRITE_BYTE( R_EAX, R_EDX );
1.482 sh4_x86.tstate = TSTATE_NONE;
1.483 }
1.484 break;
1.485 case 0x1:
1.486 { /* MOV.W Rm, @Rn */
1.487 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.488 - load_reg( R_ECX, Rn );
1.489 - precheck();
1.490 - check_walign16( R_ECX );
1.491 - load_reg( R_EAX, Rm );
1.492 - MEM_WRITE_WORD( R_ECX, R_EAX );
1.493 + load_reg( R_EAX, Rn );
1.494 + check_walign16( R_EAX );
1.495 + MMU_TRANSLATE_WRITE( R_EAX )
1.496 + load_reg( R_EDX, Rm );
1.497 + MEM_WRITE_WORD( R_EAX, R_EDX );
1.498 sh4_x86.tstate = TSTATE_NONE;
1.499 }
1.500 break;
1.501 case 0x2:
1.502 { /* MOV.L Rm, @Rn */
1.503 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.504 - load_reg( R_EAX, Rm );
1.505 - load_reg( R_ECX, Rn );
1.506 - precheck();
1.507 - check_walign32(R_ECX);
1.508 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.509 + load_reg( R_EAX, Rn );
1.510 + check_walign32(R_EAX);
1.511 + MMU_TRANSLATE_WRITE( R_EAX );
1.512 + load_reg( R_EDX, Rm );
1.513 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.514 sh4_x86.tstate = TSTATE_NONE;
1.515 }
1.516 break;
1.517 case 0x4:
1.518 { /* MOV.B Rm, @-Rn */
1.519 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.520 - load_reg( R_EAX, Rm );
1.521 - load_reg( R_ECX, Rn );
1.522 - ADD_imm8s_r32( -1, R_ECX );
1.523 - store_reg( R_ECX, Rn );
1.524 - MEM_WRITE_BYTE( R_ECX, R_EAX );
1.525 + load_reg( R_EAX, Rn );
1.526 + ADD_imm8s_r32( -1, R_EAX );
1.527 + MMU_TRANSLATE_WRITE( R_EAX );
1.528 + load_reg( R_EDX, Rm );
1.529 + ADD_imm8s_sh4r( -1, REG_OFFSET(r[Rn]) );
1.530 + MEM_WRITE_BYTE( R_EAX, R_EDX );
1.531 sh4_x86.tstate = TSTATE_NONE;
1.532 }
1.533 break;
1.534 case 0x5:
1.535 { /* MOV.W Rm, @-Rn */
1.536 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.537 - load_reg( R_ECX, Rn );
1.538 - precheck();
1.539 - check_walign16( R_ECX );
1.540 - load_reg( R_EAX, Rm );
1.541 - ADD_imm8s_r32( -2, R_ECX );
1.542 - store_reg( R_ECX, Rn );
1.543 - MEM_WRITE_WORD( R_ECX, R_EAX );
1.544 + load_reg( R_EAX, Rn );
1.545 + ADD_imm8s_r32( -2, R_EAX );
1.546 + check_walign16( R_EAX );
1.547 + MMU_TRANSLATE_WRITE( R_EAX );
1.548 + load_reg( R_EDX, Rm );
1.549 + ADD_imm8s_sh4r( -2, REG_OFFSET(r[Rn]) );
1.550 + MEM_WRITE_WORD( R_EAX, R_EDX );
1.551 sh4_x86.tstate = TSTATE_NONE;
1.552 }
1.553 break;
1.554 case 0x6:
1.555 { /* MOV.L Rm, @-Rn */
1.556 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.557 - load_reg( R_EAX, Rm );
1.558 - load_reg( R_ECX, Rn );
1.559 - precheck();
1.560 - check_walign32( R_ECX );
1.561 - ADD_imm8s_r32( -4, R_ECX );
1.562 - store_reg( R_ECX, Rn );
1.563 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.564 + load_reg( R_EAX, Rn );
1.565 + ADD_imm8s_r32( -4, R_EAX );
1.566 + check_walign32( R_EAX );
1.567 + MMU_TRANSLATE_WRITE( R_EAX );
1.568 + load_reg( R_EDX, Rm );
1.569 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.570 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.571 sh4_x86.tstate = TSTATE_NONE;
1.572 }
1.573 break;
1.574 @@ -1306,93 +1317,93 @@
1.575 case 0x0:
1.576 { /* STS.L MACH, @-Rn */
1.577 uint32_t Rn = ((ir>>8)&0xF);
1.578 - load_reg( R_ECX, Rn );
1.579 - precheck();
1.580 - check_walign32( R_ECX );
1.581 - ADD_imm8s_r32( -4, R_ECX );
1.582 - store_reg( R_ECX, Rn );
1.583 - load_spreg( R_EAX, R_MACH );
1.584 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.585 + load_reg( R_EAX, Rn );
1.586 + check_walign32( R_EAX );
1.587 + ADD_imm8s_r32( -4, R_EAX );
1.588 + MMU_TRANSLATE_WRITE( R_EAX );
1.589 + load_spreg( R_EDX, R_MACH );
1.590 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.591 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.592 sh4_x86.tstate = TSTATE_NONE;
1.593 }
1.594 break;
1.595 case 0x1:
1.596 { /* STS.L MACL, @-Rn */
1.597 uint32_t Rn = ((ir>>8)&0xF);
1.598 - load_reg( R_ECX, Rn );
1.599 - precheck();
1.600 - check_walign32( R_ECX );
1.601 - ADD_imm8s_r32( -4, R_ECX );
1.602 - store_reg( R_ECX, Rn );
1.603 - load_spreg( R_EAX, R_MACL );
1.604 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.605 + load_reg( R_EAX, Rn );
1.606 + check_walign32( R_EAX );
1.607 + ADD_imm8s_r32( -4, R_EAX );
1.608 + MMU_TRANSLATE_WRITE( R_EAX );
1.609 + load_spreg( R_EDX, R_MACL );
1.610 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.611 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.612 sh4_x86.tstate = TSTATE_NONE;
1.613 }
1.614 break;
1.615 case 0x2:
1.616 { /* STS.L PR, @-Rn */
1.617 uint32_t Rn = ((ir>>8)&0xF);
1.618 - load_reg( R_ECX, Rn );
1.619 - precheck();
1.620 - check_walign32( R_ECX );
1.621 - ADD_imm8s_r32( -4, R_ECX );
1.622 - store_reg( R_ECX, Rn );
1.623 - load_spreg( R_EAX, R_PR );
1.624 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.625 + load_reg( R_EAX, Rn );
1.626 + check_walign32( R_EAX );
1.627 + ADD_imm8s_r32( -4, R_EAX );
1.628 + MMU_TRANSLATE_WRITE( R_EAX );
1.629 + load_spreg( R_EDX, R_PR );
1.630 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.631 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.632 sh4_x86.tstate = TSTATE_NONE;
1.633 }
1.634 break;
1.635 case 0x3:
1.636 { /* STC.L SGR, @-Rn */
1.637 uint32_t Rn = ((ir>>8)&0xF);
1.638 - precheck();
1.639 - check_priv_no_precheck();
1.640 - load_reg( R_ECX, Rn );
1.641 - check_walign32( R_ECX );
1.642 - ADD_imm8s_r32( -4, R_ECX );
1.643 - store_reg( R_ECX, Rn );
1.644 - load_spreg( R_EAX, R_SGR );
1.645 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.646 + check_priv();
1.647 + load_reg( R_EAX, Rn );
1.648 + check_walign32( R_EAX );
1.649 + ADD_imm8s_r32( -4, R_EAX );
1.650 + MMU_TRANSLATE_WRITE( R_EAX );
1.651 + load_spreg( R_EDX, R_SGR );
1.652 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.653 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.654 sh4_x86.tstate = TSTATE_NONE;
1.655 }
1.656 break;
1.657 case 0x5:
1.658 { /* STS.L FPUL, @-Rn */
1.659 uint32_t Rn = ((ir>>8)&0xF);
1.660 - load_reg( R_ECX, Rn );
1.661 - precheck();
1.662 - check_walign32( R_ECX );
1.663 - ADD_imm8s_r32( -4, R_ECX );
1.664 - store_reg( R_ECX, Rn );
1.665 - load_spreg( R_EAX, R_FPUL );
1.666 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.667 + load_reg( R_EAX, Rn );
1.668 + check_walign32( R_EAX );
1.669 + ADD_imm8s_r32( -4, R_EAX );
1.670 + MMU_TRANSLATE_WRITE( R_EAX );
1.671 + load_spreg( R_EDX, R_FPUL );
1.672 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.673 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.674 sh4_x86.tstate = TSTATE_NONE;
1.675 }
1.676 break;
1.677 case 0x6:
1.678 { /* STS.L FPSCR, @-Rn */
1.679 uint32_t Rn = ((ir>>8)&0xF);
1.680 - load_reg( R_ECX, Rn );
1.681 - precheck();
1.682 - check_walign32( R_ECX );
1.683 - ADD_imm8s_r32( -4, R_ECX );
1.684 - store_reg( R_ECX, Rn );
1.685 - load_spreg( R_EAX, R_FPSCR );
1.686 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.687 + load_reg( R_EAX, Rn );
1.688 + check_walign32( R_EAX );
1.689 + ADD_imm8s_r32( -4, R_EAX );
1.690 + MMU_TRANSLATE_WRITE( R_EAX );
1.691 + load_spreg( R_EDX, R_FPSCR );
1.692 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.693 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.694 sh4_x86.tstate = TSTATE_NONE;
1.695 }
1.696 break;
1.697 case 0xF:
1.698 { /* STC.L DBR, @-Rn */
1.699 uint32_t Rn = ((ir>>8)&0xF);
1.700 - precheck();
1.701 - check_priv_no_precheck();
1.702 - load_reg( R_ECX, Rn );
1.703 - check_walign32( R_ECX );
1.704 - ADD_imm8s_r32( -4, R_ECX );
1.705 - store_reg( R_ECX, Rn );
1.706 - load_spreg( R_EAX, R_DBR );
1.707 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.708 + check_priv();
1.709 + load_reg( R_EAX, Rn );
1.710 + check_walign32( R_EAX );
1.711 + ADD_imm8s_r32( -4, R_EAX );
1.712 + MMU_TRANSLATE_WRITE( R_EAX );
1.713 + load_spreg( R_EDX, R_DBR );
1.714 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.715 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.716 sh4_x86.tstate = TSTATE_NONE;
1.717 }
1.718 break;
1.719 @@ -1408,13 +1419,15 @@
1.720 case 0x0:
1.721 { /* STC.L SR, @-Rn */
1.722 uint32_t Rn = ((ir>>8)&0xF);
1.723 - precheck();
1.724 - check_priv_no_precheck();
1.725 + check_priv();
1.726 + load_reg( R_EAX, Rn );
1.727 + check_walign32( R_EAX );
1.728 + ADD_imm8s_r32( -4, R_EAX );
1.729 + MMU_TRANSLATE_WRITE( R_EAX );
1.730 + PUSH_realigned_r32( R_EAX );
1.731 call_func0( sh4_read_sr );
1.732 - load_reg( R_ECX, Rn );
1.733 - check_walign32( R_ECX );
1.734 - ADD_imm8s_r32( -4, R_ECX );
1.735 - store_reg( R_ECX, Rn );
1.736 + POP_realigned_r32( R_ECX );
1.737 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.738 MEM_WRITE_LONG( R_ECX, R_EAX );
1.739 sh4_x86.tstate = TSTATE_NONE;
1.740 }
1.741 @@ -1422,55 +1435,55 @@
1.742 case 0x1:
1.743 { /* STC.L GBR, @-Rn */
1.744 uint32_t Rn = ((ir>>8)&0xF);
1.745 - load_reg( R_ECX, Rn );
1.746 - precheck();
1.747 - check_walign32( R_ECX );
1.748 - ADD_imm8s_r32( -4, R_ECX );
1.749 - store_reg( R_ECX, Rn );
1.750 - load_spreg( R_EAX, R_GBR );
1.751 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.752 + load_reg( R_EAX, Rn );
1.753 + check_walign32( R_EAX );
1.754 + ADD_imm8s_r32( -4, R_EAX );
1.755 + MMU_TRANSLATE_WRITE( R_EAX );
1.756 + load_spreg( R_EDX, R_GBR );
1.757 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.758 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.759 sh4_x86.tstate = TSTATE_NONE;
1.760 }
1.761 break;
1.762 case 0x2:
1.763 { /* STC.L VBR, @-Rn */
1.764 uint32_t Rn = ((ir>>8)&0xF);
1.765 - precheck();
1.766 - check_priv_no_precheck();
1.767 - load_reg( R_ECX, Rn );
1.768 - check_walign32( R_ECX );
1.769 - ADD_imm8s_r32( -4, R_ECX );
1.770 - store_reg( R_ECX, Rn );
1.771 - load_spreg( R_EAX, R_VBR );
1.772 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.773 + check_priv();
1.774 + load_reg( R_EAX, Rn );
1.775 + check_walign32( R_EAX );
1.776 + ADD_imm8s_r32( -4, R_EAX );
1.777 + MMU_TRANSLATE_WRITE( R_EAX );
1.778 + load_spreg( R_EDX, R_VBR );
1.779 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.780 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.781 sh4_x86.tstate = TSTATE_NONE;
1.782 }
1.783 break;
1.784 case 0x3:
1.785 { /* STC.L SSR, @-Rn */
1.786 uint32_t Rn = ((ir>>8)&0xF);
1.787 - precheck();
1.788 - check_priv_no_precheck();
1.789 - load_reg( R_ECX, Rn );
1.790 - check_walign32( R_ECX );
1.791 - ADD_imm8s_r32( -4, R_ECX );
1.792 - store_reg( R_ECX, Rn );
1.793 - load_spreg( R_EAX, R_SSR );
1.794 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.795 + check_priv();
1.796 + load_reg( R_EAX, Rn );
1.797 + check_walign32( R_EAX );
1.798 + ADD_imm8s_r32( -4, R_EAX );
1.799 + MMU_TRANSLATE_WRITE( R_EAX );
1.800 + load_spreg( R_EDX, R_SSR );
1.801 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.802 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.803 sh4_x86.tstate = TSTATE_NONE;
1.804 }
1.805 break;
1.806 case 0x4:
1.807 { /* STC.L SPC, @-Rn */
1.808 uint32_t Rn = ((ir>>8)&0xF);
1.809 - precheck();
1.810 - check_priv_no_precheck();
1.811 - load_reg( R_ECX, Rn );
1.812 - check_walign32( R_ECX );
1.813 - ADD_imm8s_r32( -4, R_ECX );
1.814 - store_reg( R_ECX, Rn );
1.815 - load_spreg( R_EAX, R_SPC );
1.816 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.817 + check_priv();
1.818 + load_reg( R_EAX, Rn );
1.819 + check_walign32( R_EAX );
1.820 + ADD_imm8s_r32( -4, R_EAX );
1.821 + MMU_TRANSLATE_WRITE( R_EAX );
1.822 + load_spreg( R_EDX, R_SPC );
1.823 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.824 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.825 sh4_x86.tstate = TSTATE_NONE;
1.826 }
1.827 break;
1.828 @@ -1482,14 +1495,14 @@
1.829 case 0x1:
1.830 { /* STC.L Rm_BANK, @-Rn */
1.831 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm_BANK = ((ir>>4)&0x7);
1.832 - precheck();
1.833 - check_priv_no_precheck();
1.834 - load_reg( R_ECX, Rn );
1.835 - check_walign32( R_ECX );
1.836 - ADD_imm8s_r32( -4, R_ECX );
1.837 - store_reg( R_ECX, Rn );
1.838 - load_spreg( R_EAX, REG_OFFSET(r_bank[Rm_BANK]) );
1.839 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.840 + check_priv();
1.841 + load_reg( R_EAX, Rn );
1.842 + check_walign32( R_EAX );
1.843 + ADD_imm8s_r32( -4, R_EAX );
1.844 + MMU_TRANSLATE_WRITE( R_EAX );
1.845 + load_spreg( R_EDX, REG_OFFSET(r_bank[Rm_BANK]) );
1.846 + ADD_imm8s_sh4r( -4, REG_OFFSET(r[Rn]) );
1.847 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.848 sh4_x86.tstate = TSTATE_NONE;
1.849 }
1.850 break;
1.851 @@ -1570,12 +1583,10 @@
1.852 { /* LDS.L @Rm+, MACH */
1.853 uint32_t Rm = ((ir>>8)&0xF);
1.854 load_reg( R_EAX, Rm );
1.855 - precheck();
1.856 check_ralign32( R_EAX );
1.857 - MOV_r32_r32( R_EAX, R_ECX );
1.858 - ADD_imm8s_r32( 4, R_EAX );
1.859 - store_reg( R_EAX, Rm );
1.860 - MEM_READ_LONG( R_ECX, R_EAX );
1.861 + MMU_TRANSLATE_READ( R_EAX );
1.862 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.863 + MEM_READ_LONG( R_EAX, R_EAX );
1.864 store_spreg( R_EAX, R_MACH );
1.865 sh4_x86.tstate = TSTATE_NONE;
1.866 }
1.867 @@ -1584,12 +1595,10 @@
1.868 { /* LDS.L @Rm+, MACL */
1.869 uint32_t Rm = ((ir>>8)&0xF);
1.870 load_reg( R_EAX, Rm );
1.871 - precheck();
1.872 check_ralign32( R_EAX );
1.873 - MOV_r32_r32( R_EAX, R_ECX );
1.874 - ADD_imm8s_r32( 4, R_EAX );
1.875 - store_reg( R_EAX, Rm );
1.876 - MEM_READ_LONG( R_ECX, R_EAX );
1.877 + MMU_TRANSLATE_READ( R_EAX );
1.878 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.879 + MEM_READ_LONG( R_EAX, R_EAX );
1.880 store_spreg( R_EAX, R_MACL );
1.881 sh4_x86.tstate = TSTATE_NONE;
1.882 }
1.883 @@ -1598,12 +1607,10 @@
1.884 { /* LDS.L @Rm+, PR */
1.885 uint32_t Rm = ((ir>>8)&0xF);
1.886 load_reg( R_EAX, Rm );
1.887 - precheck();
1.888 check_ralign32( R_EAX );
1.889 - MOV_r32_r32( R_EAX, R_ECX );
1.890 - ADD_imm8s_r32( 4, R_EAX );
1.891 - store_reg( R_EAX, Rm );
1.892 - MEM_READ_LONG( R_ECX, R_EAX );
1.893 + MMU_TRANSLATE_READ( R_EAX );
1.894 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.895 + MEM_READ_LONG( R_EAX, R_EAX );
1.896 store_spreg( R_EAX, R_PR );
1.897 sh4_x86.tstate = TSTATE_NONE;
1.898 }
1.899 @@ -1611,14 +1618,12 @@
1.900 case 0x3:
1.901 { /* LDC.L @Rm+, SGR */
1.902 uint32_t Rm = ((ir>>8)&0xF);
1.903 - precheck();
1.904 - check_priv_no_precheck();
1.905 + check_priv();
1.906 load_reg( R_EAX, Rm );
1.907 check_ralign32( R_EAX );
1.908 - MOV_r32_r32( R_EAX, R_ECX );
1.909 - ADD_imm8s_r32( 4, R_EAX );
1.910 - store_reg( R_EAX, Rm );
1.911 - MEM_READ_LONG( R_ECX, R_EAX );
1.912 + MMU_TRANSLATE_READ( R_EAX );
1.913 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.914 + MEM_READ_LONG( R_EAX, R_EAX );
1.915 store_spreg( R_EAX, R_SGR );
1.916 sh4_x86.tstate = TSTATE_NONE;
1.917 }
1.918 @@ -1627,12 +1632,10 @@
1.919 { /* LDS.L @Rm+, FPUL */
1.920 uint32_t Rm = ((ir>>8)&0xF);
1.921 load_reg( R_EAX, Rm );
1.922 - precheck();
1.923 check_ralign32( R_EAX );
1.924 - MOV_r32_r32( R_EAX, R_ECX );
1.925 - ADD_imm8s_r32( 4, R_EAX );
1.926 - store_reg( R_EAX, Rm );
1.927 - MEM_READ_LONG( R_ECX, R_EAX );
1.928 + MMU_TRANSLATE_READ( R_EAX );
1.929 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.930 + MEM_READ_LONG( R_EAX, R_EAX );
1.931 store_spreg( R_EAX, R_FPUL );
1.932 sh4_x86.tstate = TSTATE_NONE;
1.933 }
1.934 @@ -1641,12 +1644,10 @@
1.935 { /* LDS.L @Rm+, FPSCR */
1.936 uint32_t Rm = ((ir>>8)&0xF);
1.937 load_reg( R_EAX, Rm );
1.938 - precheck();
1.939 check_ralign32( R_EAX );
1.940 - MOV_r32_r32( R_EAX, R_ECX );
1.941 - ADD_imm8s_r32( 4, R_EAX );
1.942 - store_reg( R_EAX, Rm );
1.943 - MEM_READ_LONG( R_ECX, R_EAX );
1.944 + MMU_TRANSLATE_READ( R_EAX );
1.945 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.946 + MEM_READ_LONG( R_EAX, R_EAX );
1.947 store_spreg( R_EAX, R_FPSCR );
1.948 update_fr_bank( R_EAX );
1.949 sh4_x86.tstate = TSTATE_NONE;
1.950 @@ -1655,14 +1656,12 @@
1.951 case 0xF:
1.952 { /* LDC.L @Rm+, DBR */
1.953 uint32_t Rm = ((ir>>8)&0xF);
1.954 - precheck();
1.955 - check_priv_no_precheck();
1.956 + check_priv();
1.957 load_reg( R_EAX, Rm );
1.958 check_ralign32( R_EAX );
1.959 - MOV_r32_r32( R_EAX, R_ECX );
1.960 - ADD_imm8s_r32( 4, R_EAX );
1.961 - store_reg( R_EAX, Rm );
1.962 - MEM_READ_LONG( R_ECX, R_EAX );
1.963 + MMU_TRANSLATE_READ( R_EAX );
1.964 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.965 + MEM_READ_LONG( R_EAX, R_EAX );
1.966 store_spreg( R_EAX, R_DBR );
1.967 sh4_x86.tstate = TSTATE_NONE;
1.968 }
1.969 @@ -1682,14 +1681,12 @@
1.970 if( sh4_x86.in_delay_slot ) {
1.971 SLOTILLEGAL();
1.972 } else {
1.973 - precheck();
1.974 - check_priv_no_precheck();
1.975 + check_priv();
1.976 load_reg( R_EAX, Rm );
1.977 check_ralign32( R_EAX );
1.978 - MOV_r32_r32( R_EAX, R_ECX );
1.979 - ADD_imm8s_r32( 4, R_EAX );
1.980 - store_reg( R_EAX, Rm );
1.981 - MEM_READ_LONG( R_ECX, R_EAX );
1.982 + MMU_TRANSLATE_READ( R_EAX );
1.983 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.984 + MEM_READ_LONG( R_EAX, R_EAX );
1.985 call_func1( sh4_write_sr, R_EAX );
1.986 sh4_x86.priv_checked = FALSE;
1.987 sh4_x86.fpuen_checked = FALSE;
1.988 @@ -1701,12 +1698,10 @@
1.989 { /* LDC.L @Rm+, GBR */
1.990 uint32_t Rm = ((ir>>8)&0xF);
1.991 load_reg( R_EAX, Rm );
1.992 - precheck();
1.993 check_ralign32( R_EAX );
1.994 - MOV_r32_r32( R_EAX, R_ECX );
1.995 - ADD_imm8s_r32( 4, R_EAX );
1.996 - store_reg( R_EAX, Rm );
1.997 - MEM_READ_LONG( R_ECX, R_EAX );
1.998 + MMU_TRANSLATE_READ( R_EAX );
1.999 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1000 + MEM_READ_LONG( R_EAX, R_EAX );
1.1001 store_spreg( R_EAX, R_GBR );
1.1002 sh4_x86.tstate = TSTATE_NONE;
1.1003 }
1.1004 @@ -1714,14 +1709,12 @@
1.1005 case 0x2:
1.1006 { /* LDC.L @Rm+, VBR */
1.1007 uint32_t Rm = ((ir>>8)&0xF);
1.1008 - precheck();
1.1009 - check_priv_no_precheck();
1.1010 + check_priv();
1.1011 load_reg( R_EAX, Rm );
1.1012 check_ralign32( R_EAX );
1.1013 - MOV_r32_r32( R_EAX, R_ECX );
1.1014 - ADD_imm8s_r32( 4, R_EAX );
1.1015 - store_reg( R_EAX, Rm );
1.1016 - MEM_READ_LONG( R_ECX, R_EAX );
1.1017 + MMU_TRANSLATE_READ( R_EAX );
1.1018 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1019 + MEM_READ_LONG( R_EAX, R_EAX );
1.1020 store_spreg( R_EAX, R_VBR );
1.1021 sh4_x86.tstate = TSTATE_NONE;
1.1022 }
1.1023 @@ -1729,14 +1722,12 @@
1.1024 case 0x3:
1.1025 { /* LDC.L @Rm+, SSR */
1.1026 uint32_t Rm = ((ir>>8)&0xF);
1.1027 - precheck();
1.1028 - check_priv_no_precheck();
1.1029 + check_priv();
1.1030 load_reg( R_EAX, Rm );
1.1031 check_ralign32( R_EAX );
1.1032 - MOV_r32_r32( R_EAX, R_ECX );
1.1033 - ADD_imm8s_r32( 4, R_EAX );
1.1034 - store_reg( R_EAX, Rm );
1.1035 - MEM_READ_LONG( R_ECX, R_EAX );
1.1036 + MMU_TRANSLATE_READ( R_EAX );
1.1037 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1038 + MEM_READ_LONG( R_EAX, R_EAX );
1.1039 store_spreg( R_EAX, R_SSR );
1.1040 sh4_x86.tstate = TSTATE_NONE;
1.1041 }
1.1042 @@ -1744,14 +1735,12 @@
1.1043 case 0x4:
1.1044 { /* LDC.L @Rm+, SPC */
1.1045 uint32_t Rm = ((ir>>8)&0xF);
1.1046 - precheck();
1.1047 - check_priv_no_precheck();
1.1048 + check_priv();
1.1049 load_reg( R_EAX, Rm );
1.1050 check_ralign32( R_EAX );
1.1051 - MOV_r32_r32( R_EAX, R_ECX );
1.1052 - ADD_imm8s_r32( 4, R_EAX );
1.1053 - store_reg( R_EAX, Rm );
1.1054 - MEM_READ_LONG( R_ECX, R_EAX );
1.1055 + MMU_TRANSLATE_READ( R_EAX );
1.1056 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1057 + MEM_READ_LONG( R_EAX, R_EAX );
1.1058 store_spreg( R_EAX, R_SPC );
1.1059 sh4_x86.tstate = TSTATE_NONE;
1.1060 }
1.1061 @@ -1764,14 +1753,12 @@
1.1062 case 0x1:
1.1063 { /* LDC.L @Rm+, Rn_BANK */
1.1064 uint32_t Rm = ((ir>>8)&0xF); uint32_t Rn_BANK = ((ir>>4)&0x7);
1.1065 - precheck();
1.1066 - check_priv_no_precheck();
1.1067 + check_priv();
1.1068 load_reg( R_EAX, Rm );
1.1069 check_ralign32( R_EAX );
1.1070 - MOV_r32_r32( R_EAX, R_ECX );
1.1071 - ADD_imm8s_r32( 4, R_EAX );
1.1072 - store_reg( R_EAX, Rm );
1.1073 - MEM_READ_LONG( R_ECX, R_EAX );
1.1074 + MMU_TRANSLATE_READ( R_EAX );
1.1075 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1076 + MEM_READ_LONG( R_EAX, R_EAX );
1.1077 store_spreg( R_EAX, REG_OFFSET(r_bank[Rn_BANK]) );
1.1078 sh4_x86.tstate = TSTATE_NONE;
1.1079 }
1.1080 @@ -1931,12 +1918,14 @@
1.1081 case 0x1:
1.1082 { /* TAS.B @Rn */
1.1083 uint32_t Rn = ((ir>>8)&0xF);
1.1084 - load_reg( R_ECX, Rn );
1.1085 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1086 + load_reg( R_EAX, Rn );
1.1087 + MMU_TRANSLATE_WRITE( R_EAX );
1.1088 + PUSH_realigned_r32( R_EAX );
1.1089 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1090 TEST_r8_r8( R_AL, R_AL );
1.1091 SETE_t();
1.1092 OR_imm8_r8( 0x80, R_AL );
1.1093 - load_reg( R_ECX, Rn );
1.1094 + POP_realigned_r32( R_ECX );
1.1095 MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1096 sh4_x86.tstate = TSTATE_NONE;
1.1097 }
1.1098 @@ -2089,16 +2078,31 @@
1.1099 case 0xF:
1.1100 { /* MAC.W @Rm+, @Rn+ */
1.1101 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1102 - load_reg( R_ECX, Rm );
1.1103 - precheck();
1.1104 - check_ralign16( R_ECX );
1.1105 - load_reg( R_ECX, Rn );
1.1106 - check_ralign16( R_ECX );
1.1107 - ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) );
1.1108 - MEM_READ_WORD( R_ECX, R_EAX );
1.1109 - PUSH_realigned_r32( R_EAX );
1.1110 - load_reg( R_ECX, Rm );
1.1111 - ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
1.1112 + if( Rm == Rn ) {
1.1113 + load_reg( R_EAX, Rm );
1.1114 + check_ralign16( R_EAX );
1.1115 + MMU_TRANSLATE_READ( R_EAX );
1.1116 + PUSH_realigned_r32( R_EAX );
1.1117 + load_reg( R_EAX, Rn );
1.1118 + ADD_imm8s_r32( 2, R_EAX );
1.1119 + MMU_TRANSLATE_READ( R_EAX );
1.1120 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rn]) );
1.1121 + // Note translate twice in case of page boundaries. Maybe worth
1.1122 + // adding a page-boundary check to skip the second translation
1.1123 + } else {
1.1124 + load_reg( R_EAX, Rm );
1.1125 + check_ralign16( R_EAX );
1.1126 + MMU_TRANSLATE_READ( R_EAX );
1.1127 + PUSH_realigned_r32( R_EAX );
1.1128 + load_reg( R_EAX, Rn );
1.1129 + check_ralign16( R_EAX );
1.1130 + MMU_TRANSLATE_READ( R_EAX );
1.1131 + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rn]) );
1.1132 + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
1.1133 + }
1.1134 + MEM_READ_WORD( R_EAX, R_EAX );
1.1135 + POP_r32( R_ECX );
1.1136 + PUSH_r32( R_EAX );
1.1137 MEM_READ_WORD( R_ECX, R_EAX );
1.1138 POP_realigned_r32( R_ECX );
1.1139 IMUL_r32( R_ECX );
1.1140 @@ -2135,11 +2139,11 @@
1.1141 case 0x5:
1.1142 { /* MOV.L @(disp, Rm), Rn */
1.1143 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<2;
1.1144 - load_reg( R_ECX, Rm );
1.1145 - ADD_imm8s_r32( disp, R_ECX );
1.1146 - precheck();
1.1147 - check_ralign32( R_ECX );
1.1148 - MEM_READ_LONG( R_ECX, R_EAX );
1.1149 + load_reg( R_EAX, Rm );
1.1150 + ADD_imm8s_r32( disp, R_EAX );
1.1151 + check_ralign32( R_EAX );
1.1152 + MMU_TRANSLATE_READ( R_EAX );
1.1153 + MEM_READ_LONG( R_EAX, R_EAX );
1.1154 store_reg( R_EAX, Rn );
1.1155 sh4_x86.tstate = TSTATE_NONE;
1.1156 }
1.1157 @@ -2149,8 +2153,9 @@
1.1158 case 0x0:
1.1159 { /* MOV.B @Rm, Rn */
1.1160 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1161 - load_reg( R_ECX, Rm );
1.1162 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1163 + load_reg( R_EAX, Rm );
1.1164 + MMU_TRANSLATE_READ( R_EAX );
1.1165 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1166 store_reg( R_EAX, Rn );
1.1167 sh4_x86.tstate = TSTATE_NONE;
1.1168 }
1.1169 @@ -2158,10 +2163,10 @@
1.1170 case 0x1:
1.1171 { /* MOV.W @Rm, Rn */
1.1172 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1173 - load_reg( R_ECX, Rm );
1.1174 - precheck();
1.1175 - check_ralign16( R_ECX );
1.1176 - MEM_READ_WORD( R_ECX, R_EAX );
1.1177 + load_reg( R_EAX, Rm );
1.1178 + check_ralign16( R_EAX );
1.1179 + MMU_TRANSLATE_READ( R_EAX );
1.1180 + MEM_READ_WORD( R_EAX, R_EAX );
1.1181 store_reg( R_EAX, Rn );
1.1182 sh4_x86.tstate = TSTATE_NONE;
1.1183 }
1.1184 @@ -2169,10 +2174,10 @@
1.1185 case 0x2:
1.1186 { /* MOV.L @Rm, Rn */
1.1187 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1188 - load_reg( R_ECX, Rm );
1.1189 - precheck();
1.1190 - check_ralign32( R_ECX );
1.1191 - MEM_READ_LONG( R_ECX, R_EAX );
1.1192 + load_reg( R_EAX, Rm );
1.1193 + check_ralign32( R_EAX );
1.1194 + MMU_TRANSLATE_READ( R_EAX );
1.1195 + MEM_READ_LONG( R_EAX, R_EAX );
1.1196 store_reg( R_EAX, Rn );
1.1197 sh4_x86.tstate = TSTATE_NONE;
1.1198 }
1.1199 @@ -2187,11 +2192,10 @@
1.1200 case 0x4:
1.1201 { /* MOV.B @Rm+, Rn */
1.1202 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1203 - load_reg( R_ECX, Rm );
1.1204 - MOV_r32_r32( R_ECX, R_EAX );
1.1205 - ADD_imm8s_r32( 1, R_EAX );
1.1206 - store_reg( R_EAX, Rm );
1.1207 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1208 + load_reg( R_EAX, Rm );
1.1209 + MMU_TRANSLATE_READ( R_EAX );
1.1210 + ADD_imm8s_sh4r( 1, REG_OFFSET(r[Rm]) );
1.1211 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1212 store_reg( R_EAX, Rn );
1.1213 sh4_x86.tstate = TSTATE_NONE;
1.1214 }
1.1215 @@ -2200,12 +2204,10 @@
1.1216 { /* MOV.W @Rm+, Rn */
1.1217 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1218 load_reg( R_EAX, Rm );
1.1219 - precheck();
1.1220 check_ralign16( R_EAX );
1.1221 - MOV_r32_r32( R_EAX, R_ECX );
1.1222 - ADD_imm8s_r32( 2, R_EAX );
1.1223 - store_reg( R_EAX, Rm );
1.1224 - MEM_READ_WORD( R_ECX, R_EAX );
1.1225 + MMU_TRANSLATE_READ( R_EAX );
1.1226 + ADD_imm8s_sh4r( 2, REG_OFFSET(r[Rm]) );
1.1227 + MEM_READ_WORD( R_EAX, R_EAX );
1.1228 store_reg( R_EAX, Rn );
1.1229 sh4_x86.tstate = TSTATE_NONE;
1.1230 }
1.1231 @@ -2214,12 +2216,10 @@
1.1232 { /* MOV.L @Rm+, Rn */
1.1233 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1234 load_reg( R_EAX, Rm );
1.1235 - precheck();
1.1236 check_ralign32( R_EAX );
1.1237 - MOV_r32_r32( R_EAX, R_ECX );
1.1238 - ADD_imm8s_r32( 4, R_EAX );
1.1239 - store_reg( R_EAX, Rm );
1.1240 - MEM_READ_LONG( R_ECX, R_EAX );
1.1241 + MMU_TRANSLATE_READ( R_EAX );
1.1242 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1243 + MEM_READ_LONG( R_EAX, R_EAX );
1.1244 store_reg( R_EAX, Rn );
1.1245 sh4_x86.tstate = TSTATE_NONE;
1.1246 }
1.1247 @@ -2322,31 +2322,33 @@
1.1248 case 0x0:
1.1249 { /* MOV.B R0, @(disp, Rn) */
1.1250 uint32_t Rn = ((ir>>4)&0xF); uint32_t disp = (ir&0xF);
1.1251 - load_reg( R_EAX, 0 );
1.1252 - load_reg( R_ECX, Rn );
1.1253 - ADD_imm32_r32( disp, R_ECX );
1.1254 - MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1255 + load_reg( R_EAX, Rn );
1.1256 + ADD_imm32_r32( disp, R_EAX );
1.1257 + MMU_TRANSLATE_WRITE( R_EAX );
1.1258 + load_reg( R_EDX, 0 );
1.1259 + MEM_WRITE_BYTE( R_EAX, R_EDX );
1.1260 sh4_x86.tstate = TSTATE_NONE;
1.1261 }
1.1262 break;
1.1263 case 0x1:
1.1264 { /* MOV.W R0, @(disp, Rn) */
1.1265 uint32_t Rn = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
1.1266 - load_reg( R_ECX, Rn );
1.1267 - load_reg( R_EAX, 0 );
1.1268 - ADD_imm32_r32( disp, R_ECX );
1.1269 - precheck();
1.1270 - check_walign16( R_ECX );
1.1271 - MEM_WRITE_WORD( R_ECX, R_EAX );
1.1272 + load_reg( R_EAX, Rn );
1.1273 + ADD_imm32_r32( disp, R_EAX );
1.1274 + check_walign16( R_EAX );
1.1275 + MMU_TRANSLATE_WRITE( R_EAX );
1.1276 + load_reg( R_EDX, 0 );
1.1277 + MEM_WRITE_WORD( R_EAX, R_EDX );
1.1278 sh4_x86.tstate = TSTATE_NONE;
1.1279 }
1.1280 break;
1.1281 case 0x4:
1.1282 { /* MOV.B @(disp, Rm), R0 */
1.1283 uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF);
1.1284 - load_reg( R_ECX, Rm );
1.1285 - ADD_imm32_r32( disp, R_ECX );
1.1286 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1287 + load_reg( R_EAX, Rm );
1.1288 + ADD_imm32_r32( disp, R_EAX );
1.1289 + MMU_TRANSLATE_READ( R_EAX );
1.1290 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1291 store_reg( R_EAX, 0 );
1.1292 sh4_x86.tstate = TSTATE_NONE;
1.1293 }
1.1294 @@ -2354,11 +2356,11 @@
1.1295 case 0x5:
1.1296 { /* MOV.W @(disp, Rm), R0 */
1.1297 uint32_t Rm = ((ir>>4)&0xF); uint32_t disp = (ir&0xF)<<1;
1.1298 - load_reg( R_ECX, Rm );
1.1299 - ADD_imm32_r32( disp, R_ECX );
1.1300 - precheck();
1.1301 - check_ralign16( R_ECX );
1.1302 - MEM_READ_WORD( R_ECX, R_EAX );
1.1303 + load_reg( R_EAX, Rm );
1.1304 + ADD_imm32_r32( disp, R_EAX );
1.1305 + check_ralign16( R_EAX );
1.1306 + MMU_TRANSLATE_READ( R_EAX );
1.1307 + MEM_READ_WORD( R_EAX, R_EAX );
1.1308 store_reg( R_EAX, 0 );
1.1309 sh4_x86.tstate = TSTATE_NONE;
1.1310 }
1.1311 @@ -2378,8 +2380,9 @@
1.1312 if( sh4_x86.in_delay_slot ) {
1.1313 SLOTILLEGAL();
1.1314 } else {
1.1315 - JF_rel8( EXIT_BLOCK_SIZE, nottaken );
1.1316 - exit_block( disp + pc + 4, pc+2 );
1.1317 + sh4vma_t target = disp + pc + 4;
1.1318 + JF_rel8( EXIT_BLOCK_REL_SIZE(target), nottaken );
1.1319 + exit_block_rel(target, pc+2 );
1.1320 JMP_TARGET(nottaken);
1.1321 return 2;
1.1322 }
1.1323 @@ -2391,8 +2394,9 @@
1.1324 if( sh4_x86.in_delay_slot ) {
1.1325 SLOTILLEGAL();
1.1326 } else {
1.1327 - JT_rel8( EXIT_BLOCK_SIZE, nottaken );
1.1328 - exit_block( disp + pc + 4, pc+2 );
1.1329 + sh4vma_t target = disp + pc + 4;
1.1330 + JT_rel8( EXIT_BLOCK_REL_SIZE(target), nottaken );
1.1331 + exit_block_rel(target, pc+2 );
1.1332 JMP_TARGET(nottaken);
1.1333 return 2;
1.1334 }
1.1335 @@ -2411,7 +2415,7 @@
1.1336 }
1.1337 OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
1.1338 sh4_translate_instruction(pc+2);
1.1339 - exit_block( disp + pc + 4, pc+4 );
1.1340 + exit_block_rel( disp + pc + 4, pc+4 );
1.1341 // not taken
1.1342 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.1343 sh4_translate_instruction(pc+2);
1.1344 @@ -2425,6 +2429,7 @@
1.1345 if( sh4_x86.in_delay_slot ) {
1.1346 SLOTILLEGAL();
1.1347 } else {
1.1348 + sh4vma_t target = disp + pc + 4;
1.1349 sh4_x86.in_delay_slot = TRUE;
1.1350 if( sh4_x86.tstate == TSTATE_NONE ) {
1.1351 CMP_imm8s_sh4r( 1, R_T );
1.1352 @@ -2432,7 +2437,7 @@
1.1353 }
1.1354 OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
1.1355 sh4_translate_instruction(pc+2);
1.1356 - exit_block( disp + pc + 4, pc+4 );
1.1357 + exit_block_rel( target, pc+4 );
1.1358 // not taken
1.1359 *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.1360 sh4_translate_instruction(pc+2);
1.1361 @@ -2451,10 +2456,20 @@
1.1362 if( sh4_x86.in_delay_slot ) {
1.1363 SLOTILLEGAL();
1.1364 } else {
1.1365 - load_imm32( R_ECX, pc + disp + 4 );
1.1366 - MEM_READ_WORD( R_ECX, R_EAX );
1.1367 + // See comments for MOV.L @(disp, PC), Rn
1.1368 + uint32_t target = pc + disp + 4;
1.1369 + if( IS_IN_ICACHE(target) ) {
1.1370 + sh4ptr_t ptr = GET_ICACHE_PTR(target);
1.1371 + MOV_moff32_EAX( ptr );
1.1372 + MOVSX_r16_r32( R_EAX, R_EAX );
1.1373 + } else {
1.1374 + load_imm32( R_EAX, (pc - sh4_x86.block_start_pc) + disp + 4 );
1.1375 + ADD_sh4r_r32( R_PC, R_EAX );
1.1376 + MMU_TRANSLATE_READ( R_EAX );
1.1377 + MEM_READ_WORD( R_EAX, R_EAX );
1.1378 + sh4_x86.tstate = TSTATE_NONE;
1.1379 + }
1.1380 store_reg( R_EAX, Rn );
1.1381 - sh4_x86.tstate = TSTATE_NONE;
1.1382 }
1.1383 }
1.1384 break;
1.1385 @@ -2466,7 +2481,7 @@
1.1386 } else {
1.1387 sh4_x86.in_delay_slot = TRUE;
1.1388 sh4_translate_instruction( pc + 2 );
1.1389 - exit_block( disp + pc + 4, pc+4 );
1.1390 + exit_block_rel( disp + pc + 4, pc+4 );
1.1391 sh4_x86.branch_taken = TRUE;
1.1392 return 4;
1.1393 }
1.1394 @@ -2482,7 +2497,7 @@
1.1395 store_spreg( R_EAX, R_PR );
1.1396 sh4_x86.in_delay_slot = TRUE;
1.1397 sh4_translate_instruction( pc + 2 );
1.1398 - exit_block( disp + pc + 4, pc+4 );
1.1399 + exit_block_rel( disp + pc + 4, pc+4 );
1.1400 sh4_x86.branch_taken = TRUE;
1.1401 return 4;
1.1402 }
1.1403 @@ -2493,34 +2508,35 @@
1.1404 case 0x0:
1.1405 { /* MOV.B R0, @(disp, GBR) */
1.1406 uint32_t disp = (ir&0xFF);
1.1407 - load_reg( R_EAX, 0 );
1.1408 - load_spreg( R_ECX, R_GBR );
1.1409 - ADD_imm32_r32( disp, R_ECX );
1.1410 - MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1411 + load_spreg( R_EAX, R_GBR );
1.1412 + ADD_imm32_r32( disp, R_EAX );
1.1413 + MMU_TRANSLATE_WRITE( R_EAX );
1.1414 + load_reg( R_EDX, 0 );
1.1415 + MEM_WRITE_BYTE( R_EAX, R_EDX );
1.1416 sh4_x86.tstate = TSTATE_NONE;
1.1417 }
1.1418 break;
1.1419 case 0x1:
1.1420 { /* MOV.W R0, @(disp, GBR) */
1.1421 uint32_t disp = (ir&0xFF)<<1;
1.1422 - load_spreg( R_ECX, R_GBR );
1.1423 - load_reg( R_EAX, 0 );
1.1424 - ADD_imm32_r32( disp, R_ECX );
1.1425 - precheck();
1.1426 - check_walign16( R_ECX );
1.1427 - MEM_WRITE_WORD( R_ECX, R_EAX );
1.1428 + load_spreg( R_EAX, R_GBR );
1.1429 + ADD_imm32_r32( disp, R_EAX );
1.1430 + check_walign16( R_EAX );
1.1431 + MMU_TRANSLATE_WRITE( R_EAX );
1.1432 + load_reg( R_EDX, 0 );
1.1433 + MEM_WRITE_WORD( R_EAX, R_EDX );
1.1434 sh4_x86.tstate = TSTATE_NONE;
1.1435 }
1.1436 break;
1.1437 case 0x2:
1.1438 { /* MOV.L R0, @(disp, GBR) */
1.1439 uint32_t disp = (ir&0xFF)<<2;
1.1440 - load_spreg( R_ECX, R_GBR );
1.1441 - load_reg( R_EAX, 0 );
1.1442 - ADD_imm32_r32( disp, R_ECX );
1.1443 - precheck();
1.1444 - check_walign32( R_ECX );
1.1445 - MEM_WRITE_LONG( R_ECX, R_EAX );
1.1446 + load_spreg( R_EAX, R_GBR );
1.1447 + ADD_imm32_r32( disp, R_EAX );
1.1448 + check_walign32( R_EAX );
1.1449 + MMU_TRANSLATE_WRITE( R_EAX );
1.1450 + load_reg( R_EDX, 0 );
1.1451 + MEM_WRITE_LONG( R_EAX, R_EDX );
1.1452 sh4_x86.tstate = TSTATE_NONE;
1.1453 }
1.1454 break;
1.1455 @@ -2544,9 +2560,10 @@
1.1456 case 0x4:
1.1457 { /* MOV.B @(disp, GBR), R0 */
1.1458 uint32_t disp = (ir&0xFF);
1.1459 - load_spreg( R_ECX, R_GBR );
1.1460 - ADD_imm32_r32( disp, R_ECX );
1.1461 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1462 + load_spreg( R_EAX, R_GBR );
1.1463 + ADD_imm32_r32( disp, R_EAX );
1.1464 + MMU_TRANSLATE_READ( R_EAX );
1.1465 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1466 store_reg( R_EAX, 0 );
1.1467 sh4_x86.tstate = TSTATE_NONE;
1.1468 }
1.1469 @@ -2554,11 +2571,11 @@
1.1470 case 0x5:
1.1471 { /* MOV.W @(disp, GBR), R0 */
1.1472 uint32_t disp = (ir&0xFF)<<1;
1.1473 - load_spreg( R_ECX, R_GBR );
1.1474 - ADD_imm32_r32( disp, R_ECX );
1.1475 - precheck();
1.1476 - check_ralign16( R_ECX );
1.1477 - MEM_READ_WORD( R_ECX, R_EAX );
1.1478 + load_spreg( R_EAX, R_GBR );
1.1479 + ADD_imm32_r32( disp, R_EAX );
1.1480 + check_ralign16( R_EAX );
1.1481 + MMU_TRANSLATE_READ( R_EAX );
1.1482 + MEM_READ_WORD( R_EAX, R_EAX );
1.1483 store_reg( R_EAX, 0 );
1.1484 sh4_x86.tstate = TSTATE_NONE;
1.1485 }
1.1486 @@ -2566,11 +2583,11 @@
1.1487 case 0x6:
1.1488 { /* MOV.L @(disp, GBR), R0 */
1.1489 uint32_t disp = (ir&0xFF)<<2;
1.1490 - load_spreg( R_ECX, R_GBR );
1.1491 - ADD_imm32_r32( disp, R_ECX );
1.1492 - precheck();
1.1493 - check_ralign32( R_ECX );
1.1494 - MEM_READ_LONG( R_ECX, R_EAX );
1.1495 + load_spreg( R_EAX, R_GBR );
1.1496 + ADD_imm32_r32( disp, R_EAX );
1.1497 + check_ralign32( R_EAX );
1.1498 + MMU_TRANSLATE_READ( R_EAX );
1.1499 + MEM_READ_LONG( R_EAX, R_EAX );
1.1500 store_reg( R_EAX, 0 );
1.1501 sh4_x86.tstate = TSTATE_NONE;
1.1502 }
1.1503 @@ -2581,8 +2598,10 @@
1.1504 if( sh4_x86.in_delay_slot ) {
1.1505 SLOTILLEGAL();
1.1506 } else {
1.1507 - load_imm32( R_ECX, (pc & 0xFFFFFFFC) + disp + 4 );
1.1508 + load_imm32( R_ECX, (pc - sh4_x86.block_start_pc) + disp + 4 - (pc&0x03) );
1.1509 + ADD_sh4r_r32( R_PC, R_ECX );
1.1510 store_reg( R_ECX, 0 );
1.1511 + sh4_x86.tstate = TSTATE_NONE;
1.1512 }
1.1513 }
1.1514 break;
1.1515 @@ -2627,8 +2646,9 @@
1.1516 uint32_t imm = (ir&0xFF);
1.1517 load_reg( R_EAX, 0);
1.1518 load_reg( R_ECX, R_GBR);
1.1519 - ADD_r32_r32( R_EAX, R_ECX );
1.1520 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1521 + ADD_r32_r32( R_ECX, R_EAX );
1.1522 + MMU_TRANSLATE_READ( R_EAX );
1.1523 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1524 TEST_imm8_r8( imm, R_AL );
1.1525 SETE_t();
1.1526 sh4_x86.tstate = TSTATE_E;
1.1527 @@ -2639,9 +2659,10 @@
1.1528 uint32_t imm = (ir&0xFF);
1.1529 load_reg( R_EAX, 0 );
1.1530 load_spreg( R_ECX, R_GBR );
1.1531 - ADD_r32_r32( R_EAX, R_ECX );
1.1532 - PUSH_realigned_r32(R_ECX);
1.1533 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1534 + ADD_r32_r32( R_ECX, R_EAX );
1.1535 + MMU_TRANSLATE_WRITE( R_EAX );
1.1536 + PUSH_realigned_r32(R_EAX);
1.1537 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1538 POP_realigned_r32(R_ECX);
1.1539 AND_imm32_r32(imm, R_EAX );
1.1540 MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1541 @@ -2653,9 +2674,10 @@
1.1542 uint32_t imm = (ir&0xFF);
1.1543 load_reg( R_EAX, 0 );
1.1544 load_spreg( R_ECX, R_GBR );
1.1545 - ADD_r32_r32( R_EAX, R_ECX );
1.1546 - PUSH_realigned_r32(R_ECX);
1.1547 - MEM_READ_BYTE(R_ECX, R_EAX);
1.1548 + ADD_r32_r32( R_ECX, R_EAX );
1.1549 + MMU_TRANSLATE_WRITE( R_EAX );
1.1550 + PUSH_realigned_r32(R_EAX);
1.1551 + MEM_READ_BYTE(R_EAX, R_EAX);
1.1552 POP_realigned_r32(R_ECX);
1.1553 XOR_imm32_r32( imm, R_EAX );
1.1554 MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1555 @@ -2667,9 +2689,10 @@
1.1556 uint32_t imm = (ir&0xFF);
1.1557 load_reg( R_EAX, 0 );
1.1558 load_spreg( R_ECX, R_GBR );
1.1559 - ADD_r32_r32( R_EAX, R_ECX );
1.1560 - PUSH_realigned_r32(R_ECX);
1.1561 - MEM_READ_BYTE( R_ECX, R_EAX );
1.1562 + ADD_r32_r32( R_ECX, R_EAX );
1.1563 + MMU_TRANSLATE_WRITE( R_EAX );
1.1564 + PUSH_realigned_r32(R_EAX);
1.1565 + MEM_READ_BYTE( R_EAX, R_EAX );
1.1566 POP_realigned_r32(R_ECX);
1.1567 OR_imm32_r32(imm, R_EAX );
1.1568 MEM_WRITE_BYTE( R_ECX, R_EAX );
1.1569 @@ -2685,15 +2708,29 @@
1.1570 SLOTILLEGAL();
1.1571 } else {
1.1572 uint32_t target = (pc & 0xFFFFFFFC) + disp + 4;
1.1573 - sh4ptr_t ptr = mem_get_region(target);
1.1574 - if( ptr != NULL ) {
1.1575 + if( IS_IN_ICACHE(target) ) {
1.1576 + // If the target address is in the same page as the code, it's
1.1577 + // pretty safe to just ref it directly and circumvent the whole
1.1578 + // memory subsystem. (this is a big performance win)
1.1579 +
1.1580 + // FIXME: There's a corner-case that's not handled here when
1.1581 + // the current code-page is in the ITLB but not in the UTLB.
1.1582 + // (should generate a TLB miss although need to test SH4
1.1583 + // behaviour to confirm) Unlikely to be anyone depending on this
1.1584 + // behaviour though.
1.1585 + sh4ptr_t ptr = GET_ICACHE_PTR(target);
1.1586 MOV_moff32_EAX( ptr );
1.1587 } else {
1.1588 - load_imm32( R_ECX, target );
1.1589 - MEM_READ_LONG( R_ECX, R_EAX );
1.1590 + // Note: we use sh4r.pc for the calc as we could be running at a
1.1591 + // different virtual address than the translation was done with,
1.1592 + // but we can safely assume that the low bits are the same.
1.1593 + load_imm32( R_EAX, (pc-sh4_x86.block_start_pc) + disp + 4 - (pc&0x03) );
1.1594 + ADD_sh4r_r32( R_PC, R_EAX );
1.1595 + MMU_TRANSLATE_READ( R_EAX );
1.1596 + MEM_READ_LONG( R_EAX, R_EAX );
1.1597 + sh4_x86.tstate = TSTATE_NONE;
1.1598 }
1.1599 store_reg( R_EAX, Rn );
1.1600 - sh4_x86.tstate = TSTATE_NONE;
1.1601 }
1.1602 }
1.1603 break;
1.1604 @@ -2839,33 +2876,33 @@
1.1605 case 0x6:
1.1606 { /* FMOV @(R0, Rm), FRn */
1.1607 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1608 - precheck();
1.1609 - check_fpuen_no_precheck();
1.1610 - load_reg( R_ECX, Rm );
1.1611 - ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX );
1.1612 - check_ralign32( R_ECX );
1.1613 + check_fpuen();
1.1614 + load_reg( R_EAX, Rm );
1.1615 + ADD_sh4r_r32( REG_OFFSET(r[0]), R_EAX );
1.1616 + check_ralign32( R_EAX );
1.1617 + MMU_TRANSLATE_READ( R_EAX );
1.1618 load_spreg( R_EDX, R_FPSCR );
1.1619 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1620 - JNE_rel8(8 + CALL_FUNC1_SIZE, doublesize);
1.1621 - MEM_READ_LONG( R_ECX, R_EAX );
1.1622 + JNE_rel8(8 + MEM_READ_SIZE, doublesize);
1.1623 + MEM_READ_LONG( R_EAX, R_EAX );
1.1624 load_fr_bank( R_EDX );
1.1625 store_fr( R_EDX, R_EAX, FRn );
1.1626 if( FRn&1 ) {
1.1627 JMP_rel8(21 + MEM_READ_DOUBLE_SIZE, end);
1.1628 JMP_TARGET(doublesize);
1.1629 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1630 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1631 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1.1632 load_xf_bank( R_EDX );
1.1633 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1634 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1635 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1636 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1637 JMP_TARGET(end);
1.1638 } else {
1.1639 JMP_rel8(9 + MEM_READ_DOUBLE_SIZE, end);
1.1640 JMP_TARGET(doublesize);
1.1641 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1642 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1643 load_fr_bank( R_EDX );
1.1644 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1645 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1646 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1647 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1648 JMP_TARGET(end);
1.1649 }
1.1650 sh4_x86.tstate = TSTATE_NONE;
1.1651 @@ -2874,32 +2911,32 @@
1.1652 case 0x7:
1.1653 { /* FMOV FRm, @(R0, Rn) */
1.1654 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
1.1655 - precheck();
1.1656 - check_fpuen_no_precheck();
1.1657 - load_reg( R_ECX, Rn );
1.1658 - ADD_sh4r_r32( REG_OFFSET(r[0]), R_ECX );
1.1659 - check_walign32( R_ECX );
1.1660 + check_fpuen();
1.1661 + load_reg( R_EAX, Rn );
1.1662 + ADD_sh4r_r32( REG_OFFSET(r[0]), R_EAX );
1.1663 + check_walign32( R_EAX );
1.1664 + MMU_TRANSLATE_WRITE( R_EAX );
1.1665 load_spreg( R_EDX, R_FPSCR );
1.1666 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1667 - JNE_rel8(8 + CALL_FUNC2_SIZE, doublesize);
1.1668 + JNE_rel8(8 + MEM_WRITE_SIZE, doublesize);
1.1669 load_fr_bank( R_EDX );
1.1670 - load_fr( R_EDX, R_EAX, FRm );
1.1671 - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1.1672 + load_fr( R_EDX, R_ECX, FRm );
1.1673 + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12
1.1674 if( FRm&1 ) {
1.1675 JMP_rel8( 18 + MEM_WRITE_DOUBLE_SIZE, end );
1.1676 JMP_TARGET(doublesize);
1.1677 load_xf_bank( R_EDX );
1.1678 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1679 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1680 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1681 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1682 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1683 JMP_TARGET(end);
1.1684 } else {
1.1685 JMP_rel8( 9 + MEM_WRITE_DOUBLE_SIZE, end );
1.1686 JMP_TARGET(doublesize);
1.1687 load_fr_bank( R_EDX );
1.1688 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1689 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1690 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1691 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1692 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1693 JMP_TARGET(end);
1.1694 }
1.1695 sh4_x86.tstate = TSTATE_NONE;
1.1696 @@ -2908,32 +2945,32 @@
1.1697 case 0x8:
1.1698 { /* FMOV @Rm, FRn */
1.1699 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1700 - precheck();
1.1701 - check_fpuen_no_precheck();
1.1702 - load_reg( R_ECX, Rm );
1.1703 - check_ralign32( R_ECX );
1.1704 + check_fpuen();
1.1705 + load_reg( R_EAX, Rm );
1.1706 + check_ralign32( R_EAX );
1.1707 + MMU_TRANSLATE_READ( R_EAX );
1.1708 load_spreg( R_EDX, R_FPSCR );
1.1709 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1710 - JNE_rel8(8 + CALL_FUNC1_SIZE, doublesize);
1.1711 - MEM_READ_LONG( R_ECX, R_EAX );
1.1712 + JNE_rel8(8 + MEM_READ_SIZE, doublesize);
1.1713 + MEM_READ_LONG( R_EAX, R_EAX );
1.1714 load_fr_bank( R_EDX );
1.1715 store_fr( R_EDX, R_EAX, FRn );
1.1716 if( FRn&1 ) {
1.1717 JMP_rel8(21 + MEM_READ_DOUBLE_SIZE, end);
1.1718 JMP_TARGET(doublesize);
1.1719 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1720 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1721 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1.1722 load_xf_bank( R_EDX );
1.1723 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1724 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1725 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1726 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1727 JMP_TARGET(end);
1.1728 } else {
1.1729 JMP_rel8(9 + MEM_READ_DOUBLE_SIZE, end);
1.1730 JMP_TARGET(doublesize);
1.1731 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1732 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1733 load_fr_bank( R_EDX );
1.1734 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1735 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1736 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1737 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1738 JMP_TARGET(end);
1.1739 }
1.1740 sh4_x86.tstate = TSTATE_NONE;
1.1741 @@ -2942,38 +2979,34 @@
1.1742 case 0x9:
1.1743 { /* FMOV @Rm+, FRn */
1.1744 uint32_t FRn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.1745 - precheck();
1.1746 - check_fpuen_no_precheck();
1.1747 - load_reg( R_ECX, Rm );
1.1748 - check_ralign32( R_ECX );
1.1749 - MOV_r32_r32( R_ECX, R_EAX );
1.1750 + check_fpuen();
1.1751 + load_reg( R_EAX, Rm );
1.1752 + check_ralign32( R_EAX );
1.1753 + MMU_TRANSLATE_READ( R_EAX );
1.1754 load_spreg( R_EDX, R_FPSCR );
1.1755 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1756 - JNE_rel8(14 + CALL_FUNC1_SIZE, doublesize);
1.1757 - ADD_imm8s_r32( 4, R_EAX );
1.1758 - store_reg( R_EAX, Rm );
1.1759 - MEM_READ_LONG( R_ECX, R_EAX );
1.1760 + JNE_rel8(12 + MEM_READ_SIZE, doublesize);
1.1761 + ADD_imm8s_sh4r( 4, REG_OFFSET(r[Rm]) );
1.1762 + MEM_READ_LONG( R_EAX, R_EAX );
1.1763 load_fr_bank( R_EDX );
1.1764 store_fr( R_EDX, R_EAX, FRn );
1.1765 if( FRn&1 ) {
1.1766 - JMP_rel8(27 + MEM_READ_DOUBLE_SIZE, end);
1.1767 + JMP_rel8(25 + MEM_READ_DOUBLE_SIZE, end);
1.1768 JMP_TARGET(doublesize);
1.1769 - ADD_imm8s_r32( 8, R_EAX );
1.1770 - store_reg(R_EAX, Rm);
1.1771 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1772 + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rm]) );
1.1773 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1774 load_spreg( R_EDX, R_FPSCR ); // assume read_long clobbered it
1.1775 load_xf_bank( R_EDX );
1.1776 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1777 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1778 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1779 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1780 JMP_TARGET(end);
1.1781 } else {
1.1782 - JMP_rel8(15 + MEM_READ_DOUBLE_SIZE, end);
1.1783 - ADD_imm8s_r32( 8, R_EAX );
1.1784 - store_reg(R_EAX, Rm);
1.1785 - MEM_READ_DOUBLE( R_ECX, R_EAX, R_ECX );
1.1786 + JMP_rel8(13 + MEM_READ_DOUBLE_SIZE, end);
1.1787 + ADD_imm8s_sh4r( 8, REG_OFFSET(r[Rm]) );
1.1788 + MEM_READ_DOUBLE( R_EAX, R_ECX, R_EAX );
1.1789 load_fr_bank( R_EDX );
1.1790 - store_fr( R_EDX, R_EAX, FRn&0x0E );
1.1791 - store_fr( R_EDX, R_ECX, FRn|0x01 );
1.1792 + store_fr( R_EDX, R_ECX, FRn&0x0E );
1.1793 + store_fr( R_EDX, R_EAX, FRn|0x01 );
1.1794 JMP_TARGET(end);
1.1795 }
1.1796 sh4_x86.tstate = TSTATE_NONE;
1.1797 @@ -2982,31 +3015,31 @@
1.1798 case 0xA:
1.1799 { /* FMOV FRm, @Rn */
1.1800 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
1.1801 - precheck();
1.1802 - check_fpuen_no_precheck();
1.1803 - load_reg( R_ECX, Rn );
1.1804 - check_walign32( R_ECX );
1.1805 + check_fpuen();
1.1806 + load_reg( R_EAX, Rn );
1.1807 + check_walign32( R_EAX );
1.1808 + MMU_TRANSLATE_WRITE( R_EAX );
1.1809 load_spreg( R_EDX, R_FPSCR );
1.1810 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1811 - JNE_rel8(8 + CALL_FUNC2_SIZE, doublesize);
1.1812 + JNE_rel8(8 + MEM_WRITE_SIZE, doublesize);
1.1813 load_fr_bank( R_EDX );
1.1814 - load_fr( R_EDX, R_EAX, FRm );
1.1815 - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1.1816 + load_fr( R_EDX, R_ECX, FRm );
1.1817 + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12
1.1818 if( FRm&1 ) {
1.1819 JMP_rel8( 18 + MEM_WRITE_DOUBLE_SIZE, end );
1.1820 JMP_TARGET(doublesize);
1.1821 load_xf_bank( R_EDX );
1.1822 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1823 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1824 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1825 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1826 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1827 JMP_TARGET(end);
1.1828 } else {
1.1829 JMP_rel8( 9 + MEM_WRITE_DOUBLE_SIZE, end );
1.1830 JMP_TARGET(doublesize);
1.1831 load_fr_bank( R_EDX );
1.1832 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1833 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1834 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1835 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1836 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1837 JMP_TARGET(end);
1.1838 }
1.1839 sh4_x86.tstate = TSTATE_NONE;
1.1840 @@ -3015,37 +3048,39 @@
1.1841 case 0xB:
1.1842 { /* FMOV FRm, @-Rn */
1.1843 uint32_t Rn = ((ir>>8)&0xF); uint32_t FRm = ((ir>>4)&0xF);
1.1844 - precheck();
1.1845 - check_fpuen_no_precheck();
1.1846 - load_reg( R_ECX, Rn );
1.1847 - check_walign32( R_ECX );
1.1848 + check_fpuen();
1.1849 + load_reg( R_EAX, Rn );
1.1850 + check_walign32( R_EAX );
1.1851 load_spreg( R_EDX, R_FPSCR );
1.1852 TEST_imm32_r32( FPSCR_SZ, R_EDX );
1.1853 - JNE_rel8(14 + CALL_FUNC2_SIZE, doublesize);
1.1854 + JNE_rel8(15 + MEM_WRITE_SIZE + MMU_TRANSLATE_SIZE, doublesize);
1.1855 + ADD_imm8s_r32( -4, R_EAX );
1.1856 + MMU_TRANSLATE_WRITE( R_EAX );
1.1857 load_fr_bank( R_EDX );
1.1858 - load_fr( R_EDX, R_EAX, FRm );
1.1859 - ADD_imm8s_r32(-4,R_ECX);
1.1860 - store_reg( R_ECX, Rn );
1.1861 - MEM_WRITE_LONG( R_ECX, R_EAX ); // 12
1.1862 + load_fr( R_EDX, R_ECX, FRm );
1.1863 + ADD_imm8s_sh4r(-4,REG_OFFSET(r[Rn]));
1.1864 + MEM_WRITE_LONG( R_EAX, R_ECX ); // 12
1.1865 if( FRm&1 ) {
1.1866 - JMP_rel8( 24 + MEM_WRITE_DOUBLE_SIZE, end );
1.1867 + JMP_rel8( 25 + MEM_WRITE_DOUBLE_SIZE + MMU_TRANSLATE_SIZE, end );
1.1868 JMP_TARGET(doublesize);
1.1869 + ADD_imm8s_r32(-8,R_EAX);
1.1870 + MMU_TRANSLATE_WRITE( R_EAX );
1.1871 load_xf_bank( R_EDX );
1.1872 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1873 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1874 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1875 - ADD_imm8s_r32(-8,R_ECX);
1.1876 - store_reg( R_ECX, Rn );
1.1877 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1878 + ADD_imm8s_sh4r(-8,REG_OFFSET(r[Rn]));
1.1879 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1880 JMP_TARGET(end);
1.1881 } else {
1.1882 - JMP_rel8( 15 + MEM_WRITE_DOUBLE_SIZE, end );
1.1883 + JMP_rel8( 16 + MEM_WRITE_DOUBLE_SIZE + MMU_TRANSLATE_SIZE, end );
1.1884 JMP_TARGET(doublesize);
1.1885 + ADD_imm8s_r32(-8,R_EAX);
1.1886 + MMU_TRANSLATE_WRITE( R_EAX );
1.1887 load_fr_bank( R_EDX );
1.1888 - load_fr( R_EDX, R_EAX, FRm&0x0E );
1.1889 + load_fr( R_EDX, R_ECX, FRm&0x0E );
1.1890 load_fr( R_EDX, R_EDX, FRm|0x01 );
1.1891 - ADD_imm8s_r32(-8,R_ECX);
1.1892 - store_reg( R_ECX, Rn );
1.1893 - MEM_WRITE_DOUBLE( R_ECX, R_EAX, R_EDX );
1.1894 + ADD_imm8s_sh4r(-8,REG_OFFSET(r[Rn]));
1.1895 + MEM_WRITE_DOUBLE( R_EAX, R_ECX, R_EDX );
1.1896 JMP_TARGET(end);
1.1897 }
1.1898 sh4_x86.tstate = TSTATE_NONE;
1.1899 @@ -3405,8 +3440,7 @@
1.1900 if( sh4_x86.in_delay_slot ) {
1.1901 SLOTILLEGAL();
1.1902 } else {
1.1903 - precheck();
1.1904 - JMP_exit(EXIT_ILLEGAL);
1.1905 + JMP_exc(EXC_ILLEGAL);
1.1906 return 2;
1.1907 }
1.1908 }
.