Search
lxdream.org :: lxdream :: r601:d8d1af0d133c
lxdream 0.9.1
released Jun 29
Download Now
changeset601:d8d1af0d133c
parent600:3b0f94d0faed
child602:a3aae8cbd1d7
authornkeynes
dateTue Jan 22 10:11:45 2008 +0000 (12 years ago)
Invoke emulator single-step for untranslatable delay slots (and fix a few
related bugs)
src/sh4/sh4x86.c
src/sh4/sh4x86.in
src/sh4/x86op.h
1.1 --- a/src/sh4/sh4x86.c Tue Jan 22 10:10:46 2008 +0000
1.2 +++ b/src/sh4/sh4x86.c Tue Jan 22 10:11:45 2008 +0000
1.3 @@ -371,29 +371,39 @@
1.4 call_func1( sh4_translate_breakpoint_hit, R_EAX );
1.5 }
1.6
1.7 +
1.8 +#define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
1.9 +
1.10 /**
1.11 * Embed a call to sh4_execute_instruction for situations that we
1.12 - * can't translate (mainly page-crossing delay slots at the moment).
1.13 - * Caller is responsible for setting new_pc.
1.14 + * can't translate (just page-crossing delay slots at the moment).
1.15 + * Caller is responsible for setting new_pc before calling this function.
1.16 + *
1.17 + * Performs:
1.18 + * Set PC = endpc
1.19 + * Set sh4r.in_delay_slot = sh4_x86.in_delay_slot
1.20 + * Update slice_cycle for endpc+2 (single step doesn't update slice_cycle)
1.21 + * Call sh4_execute_instruction
1.22 + * Call xlat_get_code_by_vma / xlat_get_code as for normal exit
1.23 */
1.24 -void sh4_emulator_exit( sh4vma_t endpc )
1.25 +void exit_block_emu( sh4vma_t endpc )
1.26 {
1.27 load_imm32( R_ECX, endpc - sh4_x86.block_start_pc ); // 5
1.28 ADD_r32_sh4r( R_ECX, R_PC );
1.29
1.30 - load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
1.31 + load_imm32( R_ECX, (((endpc - sh4_x86.block_start_pc)>>1)+1)*sh4_cpu_period ); // 5
1.32 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
1.33 load_imm32( R_ECX, sh4_x86.in_delay_slot ? 1 : 0 );
1.34 store_spreg( R_ECX, REG_OFFSET(in_delay_slot) );
1.35
1.36 call_func0( sh4_execute_instruction );
1.37 - load_imm32( R_EAX, R_PC );
1.38 + load_spreg( R_EAX, R_PC );
1.39 if( sh4_x86.tlb_on ) {
1.40 call_func1(xlat_get_code_by_vma,R_EAX);
1.41 } else {
1.42 call_func1(xlat_get_code,R_EAX);
1.43 }
1.44 - AND_imm8s_r32( 0xFC, R_EAX ); // 3
1.45 + AND_imm8s_rptr( 0xFC, R_EAX );
1.46 POP_r32(R_EBP);
1.47 RET();
1.48 }
1.49 @@ -507,11 +517,17 @@
1.50 ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );
1.51 store_spreg( R_EAX, R_NEW_PC );
1.52
1.53 + sh4_x86.in_delay_slot = DELAY_PC;
1.54 sh4_x86.tstate = TSTATE_NONE;
1.55 - sh4_translate_instruction( pc + 2 );
1.56 - exit_block_newpcset(pc+2);
1.57 sh4_x86.branch_taken = TRUE;
1.58 - return 4;
1.59 + if( UNTRANSLATABLE(pc+2) ) {
1.60 + exit_block_emu(pc+2);
1.61 + return 2;
1.62 + } else {
1.63 + sh4_translate_instruction( pc + 2 );
1.64 + exit_block_newpcset(pc+2);
1.65 + return 4;
1.66 + }
1.67 }
1.68 }
1.69 break;
1.70 @@ -527,10 +543,15 @@
1.71 store_spreg( R_EAX, R_NEW_PC );
1.72 sh4_x86.in_delay_slot = DELAY_PC;
1.73 sh4_x86.tstate = TSTATE_NONE;
1.74 - sh4_translate_instruction( pc + 2 );
1.75 - exit_block_newpcset(pc+2);
1.76 sh4_x86.branch_taken = TRUE;
1.77 - return 4;
1.78 + if( UNTRANSLATABLE(pc+2) ) {
1.79 + exit_block_emu(pc+2);
1.80 + return 2;
1.81 + } else {
1.82 + sh4_translate_instruction( pc + 2 );
1.83 + exit_block_newpcset(pc+2);
1.84 + return 4;
1.85 + }
1.86 }
1.87 }
1.88 break;
1.89 @@ -774,10 +795,15 @@
1.90 load_spreg( R_ECX, R_PR );
1.91 store_spreg( R_ECX, R_NEW_PC );
1.92 sh4_x86.in_delay_slot = DELAY_PC;
1.93 - sh4_translate_instruction(pc+2);
1.94 - exit_block_newpcset(pc+2);
1.95 sh4_x86.branch_taken = TRUE;
1.96 - return 4;
1.97 + if( UNTRANSLATABLE(pc+2) ) {
1.98 + exit_block_emu(pc+2);
1.99 + return 2;
1.100 + } else {
1.101 + sh4_translate_instruction(pc+2);
1.102 + exit_block_newpcset(pc+2);
1.103 + return 4;
1.104 + }
1.105 }
1.106 }
1.107 break;
1.108 @@ -804,10 +830,15 @@
1.109 sh4_x86.priv_checked = FALSE;
1.110 sh4_x86.fpuen_checked = FALSE;
1.111 sh4_x86.tstate = TSTATE_NONE;
1.112 - sh4_translate_instruction(pc+2);
1.113 - exit_block_newpcset(pc+2);
1.114 sh4_x86.branch_taken = TRUE;
1.115 - return 4;
1.116 + if( UNTRANSLATABLE(pc+2) ) {
1.117 + exit_block_emu(pc+2);
1.118 + return 2;
1.119 + } else {
1.120 + sh4_translate_instruction(pc+2);
1.121 + exit_block_newpcset(pc+2);
1.122 + return 4;
1.123 + }
1.124 }
1.125 }
1.126 break;
1.127 @@ -1947,10 +1978,17 @@
1.128 store_spreg( R_EAX, R_PR );
1.129 load_reg( R_ECX, Rn );
1.130 store_spreg( R_ECX, R_NEW_PC );
1.131 - sh4_translate_instruction(pc+2);
1.132 - exit_block_newpcset(pc+2);
1.133 + sh4_x86.in_delay_slot = DELAY_PC;
1.134 sh4_x86.branch_taken = TRUE;
1.135 - return 4;
1.136 + sh4_x86.tstate = TSTATE_NONE;
1.137 + if( UNTRANSLATABLE(pc+2) ) {
1.138 + exit_block_emu(pc+2);
1.139 + return 2;
1.140 + } else {
1.141 + sh4_translate_instruction(pc+2);
1.142 + exit_block_newpcset(pc+2);
1.143 + return 4;
1.144 + }
1.145 }
1.146 }
1.147 break;
1.148 @@ -1978,10 +2016,15 @@
1.149 load_reg( R_ECX, Rn );
1.150 store_spreg( R_ECX, R_NEW_PC );
1.151 sh4_x86.in_delay_slot = DELAY_PC;
1.152 - sh4_translate_instruction(pc+2);
1.153 - exit_block_newpcset(pc+2);
1.154 sh4_x86.branch_taken = TRUE;
1.155 - return 4;
1.156 + if( UNTRANSLATABLE(pc+2) ) {
1.157 + exit_block_emu(pc+2);
1.158 + return 2;
1.159 + } else {
1.160 + sh4_translate_instruction(pc+2);
1.161 + exit_block_newpcset(pc+2);
1.162 + return 4;
1.163 + }
1.164 }
1.165 }
1.166 break;
1.167 @@ -2277,7 +2320,7 @@
1.168 { /* SWAP.B Rm, Rn */
1.169 uint32_t Rn = ((ir>>8)&0xF); uint32_t Rm = ((ir>>4)&0xF);
1.170 load_reg( R_EAX, Rm );
1.171 - XCHG_r8_r8( R_AL, R_AH );
1.172 + XCHG_r8_r8( R_AL, R_AH ); // NB: does not touch EFLAGS
1.173 store_reg( R_EAX, Rn );
1.174 }
1.175 break;
1.176 @@ -2449,17 +2492,29 @@
1.177 SLOTILLEGAL();
1.178 } else {
1.179 sh4_x86.in_delay_slot = DELAY_PC;
1.180 - if( sh4_x86.tstate == TSTATE_NONE ) {
1.181 - CMP_imm8s_sh4r( 1, R_T );
1.182 - sh4_x86.tstate = TSTATE_E;
1.183 + if( UNTRANSLATABLE(pc+2) ) {
1.184 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
1.185 + JF_rel8(6,nottaken);
1.186 + ADD_imm32_r32( disp, R_EAX );
1.187 + JMP_TARGET(nottaken);
1.188 + ADD_sh4r_r32( R_PC, R_EAX );
1.189 + store_spreg( R_EAX, R_NEW_PC );
1.190 + exit_block_emu(pc+2);
1.191 + sh4_x86.branch_taken = TRUE;
1.192 + return 2;
1.193 + } else {
1.194 + if( sh4_x86.tstate == TSTATE_NONE ) {
1.195 + CMP_imm8s_sh4r( 1, R_T );
1.196 + sh4_x86.tstate = TSTATE_E;
1.197 + }
1.198 + OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JF rel32
1.199 + sh4_translate_instruction(pc+2);
1.200 + exit_block_rel( disp + pc + 4, pc+4 );
1.201 + // not taken
1.202 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.203 + sh4_translate_instruction(pc+2);
1.204 + return 4;
1.205 }
1.206 - OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
1.207 - sh4_translate_instruction(pc+2);
1.208 - exit_block_rel( disp + pc + 4, pc+4 );
1.209 - // not taken
1.210 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.211 - sh4_translate_instruction(pc+2);
1.212 - return 4;
1.213 }
1.214 }
1.215 break;
1.216 @@ -2469,19 +2524,32 @@
1.217 if( sh4_x86.in_delay_slot ) {
1.218 SLOTILLEGAL();
1.219 } else {
1.220 - sh4vma_t target = disp + pc + 4;
1.221 sh4_x86.in_delay_slot = DELAY_PC;
1.222 - if( sh4_x86.tstate == TSTATE_NONE ) {
1.223 - CMP_imm8s_sh4r( 1, R_T );
1.224 - sh4_x86.tstate = TSTATE_E;
1.225 + if( UNTRANSLATABLE(pc+2) ) {
1.226 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
1.227 + JT_rel8(6,nottaken);
1.228 + ADD_imm32_r32( disp, R_EAX );
1.229 + JMP_TARGET(nottaken);
1.230 + ADD_sh4r_r32( R_PC, R_EAX );
1.231 + store_spreg( R_EAX, R_NEW_PC );
1.232 + exit_block_emu(pc+2);
1.233 + sh4_x86.branch_taken = TRUE;
1.234 + return 2;
1.235 + } else {
1.236 + if( sh4_x86.tstate == TSTATE_NONE ) {
1.237 + CMP_imm8s_sh4r( 1, R_T );
1.238 + sh4_x86.tstate = TSTATE_E;
1.239 + }
1.240 + sh4vma_t target = disp + pc + 4;
1.241 + OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JT rel32
1.242 + sh4_translate_instruction(pc+2);
1.243 + exit_block_rel( target, pc+4 );
1.244 +
1.245 + // not taken
1.246 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.247 + sh4_translate_instruction(pc+2);
1.248 + return 4;
1.249 }
1.250 - OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
1.251 - sh4_translate_instruction(pc+2);
1.252 - exit_block_rel( target, pc+4 );
1.253 - // not taken
1.254 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.255 - sh4_translate_instruction(pc+2);
1.256 - return 4;
1.257 }
1.258 }
1.259 break;
1.260 @@ -2520,10 +2588,18 @@
1.261 SLOTILLEGAL();
1.262 } else {
1.263 sh4_x86.in_delay_slot = DELAY_PC;
1.264 - sh4_translate_instruction( pc + 2 );
1.265 - exit_block_rel( disp + pc + 4, pc+4 );
1.266 sh4_x86.branch_taken = TRUE;
1.267 - return 4;
1.268 + if( UNTRANSLATABLE(pc+2) ) {
1.269 + load_spreg( R_EAX, R_PC );
1.270 + ADD_imm32_r32( pc + disp + 4 - sh4_x86.block_start_pc, R_EAX );
1.271 + store_spreg( R_EAX, R_NEW_PC );
1.272 + exit_block_emu(pc+2);
1.273 + return 2;
1.274 + } else {
1.275 + sh4_translate_instruction( pc + 2 );
1.276 + exit_block_rel( disp + pc + 4, pc+4 );
1.277 + return 4;
1.278 + }
1.279 }
1.280 }
1.281 break;
1.282 @@ -2537,10 +2613,18 @@
1.283 ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );
1.284 store_spreg( R_EAX, R_PR );
1.285 sh4_x86.in_delay_slot = DELAY_PC;
1.286 - sh4_translate_instruction( pc + 2 );
1.287 - exit_block_rel( disp + pc + 4, pc+4 );
1.288 sh4_x86.branch_taken = TRUE;
1.289 - return 4;
1.290 + sh4_x86.tstate = TSTATE_NONE;
1.291 + if( UNTRANSLATABLE(pc+2) ) {
1.292 + ADD_imm32_r32( disp, R_EAX );
1.293 + store_spreg( R_EAX, R_NEW_PC );
1.294 + exit_block_emu(pc+2);
1.295 + return 2;
1.296 + } else {
1.297 + sh4_translate_instruction( pc + 2 );
1.298 + exit_block_rel( disp + pc + 4, pc+4 );
1.299 + return 4;
1.300 + }
1.301 }
1.302 }
1.303 break;
2.1 --- a/src/sh4/sh4x86.in Tue Jan 22 10:10:46 2008 +0000
2.2 +++ b/src/sh4/sh4x86.in Tue Jan 22 10:11:45 2008 +0000
2.3 @@ -371,29 +371,39 @@
2.4 call_func1( sh4_translate_breakpoint_hit, R_EAX );
2.5 }
2.6
2.7 +
2.8 +#define UNTRANSLATABLE(pc) !IS_IN_ICACHE(pc)
2.9 +
2.10 /**
2.11 * Embed a call to sh4_execute_instruction for situations that we
2.12 - * can't translate (mainly page-crossing delay slots at the moment).
2.13 - * Caller is responsible for setting new_pc.
2.14 + * can't translate (just page-crossing delay slots at the moment).
2.15 + * Caller is responsible for setting new_pc before calling this function.
2.16 + *
2.17 + * Performs:
2.18 + * Set PC = endpc
2.19 + * Set sh4r.in_delay_slot = sh4_x86.in_delay_slot
2.20 + * Update slice_cycle for endpc+2 (single step doesn't update slice_cycle)
2.21 + * Call sh4_execute_instruction
2.22 + * Call xlat_get_code_by_vma / xlat_get_code as for normal exit
2.23 */
2.24 -void sh4_emulator_exit( sh4vma_t endpc )
2.25 +void exit_block_emu( sh4vma_t endpc )
2.26 {
2.27 load_imm32( R_ECX, endpc - sh4_x86.block_start_pc ); // 5
2.28 ADD_r32_sh4r( R_ECX, R_PC );
2.29
2.30 - load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
2.31 + load_imm32( R_ECX, (((endpc - sh4_x86.block_start_pc)>>1)+1)*sh4_cpu_period ); // 5
2.32 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
2.33 load_imm32( R_ECX, sh4_x86.in_delay_slot ? 1 : 0 );
2.34 store_spreg( R_ECX, REG_OFFSET(in_delay_slot) );
2.35
2.36 call_func0( sh4_execute_instruction );
2.37 - load_imm32( R_EAX, R_PC );
2.38 + load_spreg( R_EAX, R_PC );
2.39 if( sh4_x86.tlb_on ) {
2.40 call_func1(xlat_get_code_by_vma,R_EAX);
2.41 } else {
2.42 call_func1(xlat_get_code,R_EAX);
2.43 }
2.44 - AND_imm8s_r32( 0xFC, R_EAX ); // 3
2.45 + AND_imm8s_rptr( 0xFC, R_EAX );
2.46 POP_r32(R_EBP);
2.47 RET();
2.48 }
2.49 @@ -987,7 +997,7 @@
2.50 :}
2.51 SWAP.B Rm, Rn {:
2.52 load_reg( R_EAX, Rm );
2.53 - XCHG_r8_r8( R_AL, R_AH );
2.54 + XCHG_r8_r8( R_AL, R_AH ); // NB: does not touch EFLAGS
2.55 store_reg( R_EAX, Rn );
2.56 :}
2.57 SWAP.W Rm, Rn {:
2.58 @@ -1426,19 +1436,32 @@
2.59 if( sh4_x86.in_delay_slot ) {
2.60 SLOTILLEGAL();
2.61 } else {
2.62 - sh4vma_t target = disp + pc + 4;
2.63 sh4_x86.in_delay_slot = DELAY_PC;
2.64 - if( sh4_x86.tstate == TSTATE_NONE ) {
2.65 - CMP_imm8s_sh4r( 1, R_T );
2.66 - sh4_x86.tstate = TSTATE_E;
2.67 + if( UNTRANSLATABLE(pc+2) ) {
2.68 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
2.69 + JT_rel8(6,nottaken);
2.70 + ADD_imm32_r32( disp, R_EAX );
2.71 + JMP_TARGET(nottaken);
2.72 + ADD_sh4r_r32( R_PC, R_EAX );
2.73 + store_spreg( R_EAX, R_NEW_PC );
2.74 + exit_block_emu(pc+2);
2.75 + sh4_x86.branch_taken = TRUE;
2.76 + return 2;
2.77 + } else {
2.78 + if( sh4_x86.tstate == TSTATE_NONE ) {
2.79 + CMP_imm8s_sh4r( 1, R_T );
2.80 + sh4_x86.tstate = TSTATE_E;
2.81 + }
2.82 + sh4vma_t target = disp + pc + 4;
2.83 + OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JT rel32
2.84 + sh4_translate_instruction(pc+2);
2.85 + exit_block_rel( target, pc+4 );
2.86 +
2.87 + // not taken
2.88 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2.89 + sh4_translate_instruction(pc+2);
2.90 + return 4;
2.91 }
2.92 - OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
2.93 - sh4_translate_instruction(pc+2);
2.94 - exit_block_rel( target, pc+4 );
2.95 - // not taken
2.96 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2.97 - sh4_translate_instruction(pc+2);
2.98 - return 4;
2.99 }
2.100 :}
2.101 BRA disp {:
2.102 @@ -1446,10 +1469,18 @@
2.103 SLOTILLEGAL();
2.104 } else {
2.105 sh4_x86.in_delay_slot = DELAY_PC;
2.106 - sh4_translate_instruction( pc + 2 );
2.107 - exit_block_rel( disp + pc + 4, pc+4 );
2.108 sh4_x86.branch_taken = TRUE;
2.109 - return 4;
2.110 + if( UNTRANSLATABLE(pc+2) ) {
2.111 + load_spreg( R_EAX, R_PC );
2.112 + ADD_imm32_r32( pc + disp + 4 - sh4_x86.block_start_pc, R_EAX );
2.113 + store_spreg( R_EAX, R_NEW_PC );
2.114 + exit_block_emu(pc+2);
2.115 + return 2;
2.116 + } else {
2.117 + sh4_translate_instruction( pc + 2 );
2.118 + exit_block_rel( disp + pc + 4, pc+4 );
2.119 + return 4;
2.120 + }
2.121 }
2.122 :}
2.123 BRAF Rn {:
2.124 @@ -1462,10 +1493,15 @@
2.125 store_spreg( R_EAX, R_NEW_PC );
2.126 sh4_x86.in_delay_slot = DELAY_PC;
2.127 sh4_x86.tstate = TSTATE_NONE;
2.128 - sh4_translate_instruction( pc + 2 );
2.129 - exit_block_newpcset(pc+2);
2.130 sh4_x86.branch_taken = TRUE;
2.131 - return 4;
2.132 + if( UNTRANSLATABLE(pc+2) ) {
2.133 + exit_block_emu(pc+2);
2.134 + return 2;
2.135 + } else {
2.136 + sh4_translate_instruction( pc + 2 );
2.137 + exit_block_newpcset(pc+2);
2.138 + return 4;
2.139 + }
2.140 }
2.141 :}
2.142 BSR disp {:
2.143 @@ -1476,10 +1512,18 @@
2.144 ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );
2.145 store_spreg( R_EAX, R_PR );
2.146 sh4_x86.in_delay_slot = DELAY_PC;
2.147 - sh4_translate_instruction( pc + 2 );
2.148 - exit_block_rel( disp + pc + 4, pc+4 );
2.149 sh4_x86.branch_taken = TRUE;
2.150 - return 4;
2.151 + sh4_x86.tstate = TSTATE_NONE;
2.152 + if( UNTRANSLATABLE(pc+2) ) {
2.153 + ADD_imm32_r32( disp, R_EAX );
2.154 + store_spreg( R_EAX, R_NEW_PC );
2.155 + exit_block_emu(pc+2);
2.156 + return 2;
2.157 + } else {
2.158 + sh4_translate_instruction( pc + 2 );
2.159 + exit_block_rel( disp + pc + 4, pc+4 );
2.160 + return 4;
2.161 + }
2.162 }
2.163 :}
2.164 BSRF Rn {:
2.165 @@ -1492,11 +1536,17 @@
2.166 ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );
2.167 store_spreg( R_EAX, R_NEW_PC );
2.168
2.169 + sh4_x86.in_delay_slot = DELAY_PC;
2.170 sh4_x86.tstate = TSTATE_NONE;
2.171 - sh4_translate_instruction( pc + 2 );
2.172 - exit_block_newpcset(pc+2);
2.173 sh4_x86.branch_taken = TRUE;
2.174 - return 4;
2.175 + if( UNTRANSLATABLE(pc+2) ) {
2.176 + exit_block_emu(pc+2);
2.177 + return 2;
2.178 + } else {
2.179 + sh4_translate_instruction( pc + 2 );
2.180 + exit_block_newpcset(pc+2);
2.181 + return 4;
2.182 + }
2.183 }
2.184 :}
2.185 BT disp {:
2.186 @@ -1515,17 +1565,29 @@
2.187 SLOTILLEGAL();
2.188 } else {
2.189 sh4_x86.in_delay_slot = DELAY_PC;
2.190 - if( sh4_x86.tstate == TSTATE_NONE ) {
2.191 - CMP_imm8s_sh4r( 1, R_T );
2.192 - sh4_x86.tstate = TSTATE_E;
2.193 + if( UNTRANSLATABLE(pc+2) ) {
2.194 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
2.195 + JF_rel8(6,nottaken);
2.196 + ADD_imm32_r32( disp, R_EAX );
2.197 + JMP_TARGET(nottaken);
2.198 + ADD_sh4r_r32( R_PC, R_EAX );
2.199 + store_spreg( R_EAX, R_NEW_PC );
2.200 + exit_block_emu(pc+2);
2.201 + sh4_x86.branch_taken = TRUE;
2.202 + return 2;
2.203 + } else {
2.204 + if( sh4_x86.tstate == TSTATE_NONE ) {
2.205 + CMP_imm8s_sh4r( 1, R_T );
2.206 + sh4_x86.tstate = TSTATE_E;
2.207 + }
2.208 + OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JF rel32
2.209 + sh4_translate_instruction(pc+2);
2.210 + exit_block_rel( disp + pc + 4, pc+4 );
2.211 + // not taken
2.212 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2.213 + sh4_translate_instruction(pc+2);
2.214 + return 4;
2.215 }
2.216 - OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
2.217 - sh4_translate_instruction(pc+2);
2.218 - exit_block_rel( disp + pc + 4, pc+4 );
2.219 - // not taken
2.220 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
2.221 - sh4_translate_instruction(pc+2);
2.222 - return 4;
2.223 }
2.224 :}
2.225 JMP @Rn {:
2.226 @@ -1535,10 +1597,15 @@
2.227 load_reg( R_ECX, Rn );
2.228 store_spreg( R_ECX, R_NEW_PC );
2.229 sh4_x86.in_delay_slot = DELAY_PC;
2.230 - sh4_translate_instruction(pc+2);
2.231 - exit_block_newpcset(pc+2);
2.232 sh4_x86.branch_taken = TRUE;
2.233 - return 4;
2.234 + if( UNTRANSLATABLE(pc+2) ) {
2.235 + exit_block_emu(pc+2);
2.236 + return 2;
2.237 + } else {
2.238 + sh4_translate_instruction(pc+2);
2.239 + exit_block_newpcset(pc+2);
2.240 + return 4;
2.241 + }
2.242 }
2.243 :}
2.244 JSR @Rn {:
2.245 @@ -1550,10 +1617,17 @@
2.246 store_spreg( R_EAX, R_PR );
2.247 load_reg( R_ECX, Rn );
2.248 store_spreg( R_ECX, R_NEW_PC );
2.249 - sh4_translate_instruction(pc+2);
2.250 - exit_block_newpcset(pc+2);
2.251 + sh4_x86.in_delay_slot = DELAY_PC;
2.252 sh4_x86.branch_taken = TRUE;
2.253 - return 4;
2.254 + sh4_x86.tstate = TSTATE_NONE;
2.255 + if( UNTRANSLATABLE(pc+2) ) {
2.256 + exit_block_emu(pc+2);
2.257 + return 2;
2.258 + } else {
2.259 + sh4_translate_instruction(pc+2);
2.260 + exit_block_newpcset(pc+2);
2.261 + return 4;
2.262 + }
2.263 }
2.264 :}
2.265 RTE {:
2.266 @@ -1569,10 +1643,15 @@
2.267 sh4_x86.priv_checked = FALSE;
2.268 sh4_x86.fpuen_checked = FALSE;
2.269 sh4_x86.tstate = TSTATE_NONE;
2.270 - sh4_translate_instruction(pc+2);
2.271 - exit_block_newpcset(pc+2);
2.272 sh4_x86.branch_taken = TRUE;
2.273 - return 4;
2.274 + if( UNTRANSLATABLE(pc+2) ) {
2.275 + exit_block_emu(pc+2);
2.276 + return 2;
2.277 + } else {
2.278 + sh4_translate_instruction(pc+2);
2.279 + exit_block_newpcset(pc+2);
2.280 + return 4;
2.281 + }
2.282 }
2.283 :}
2.284 RTS {:
2.285 @@ -1582,10 +1661,15 @@
2.286 load_spreg( R_ECX, R_PR );
2.287 store_spreg( R_ECX, R_NEW_PC );
2.288 sh4_x86.in_delay_slot = DELAY_PC;
2.289 - sh4_translate_instruction(pc+2);
2.290 - exit_block_newpcset(pc+2);
2.291 sh4_x86.branch_taken = TRUE;
2.292 - return 4;
2.293 + if( UNTRANSLATABLE(pc+2) ) {
2.294 + exit_block_emu(pc+2);
2.295 + return 2;
2.296 + } else {
2.297 + sh4_translate_instruction(pc+2);
2.298 + exit_block_newpcset(pc+2);
2.299 + return 4;
2.300 + }
2.301 }
2.302 :}
2.303 TRAPA #imm {:
3.1 --- a/src/sh4/x86op.h Tue Jan 22 10:10:46 2008 +0000
3.2 +++ b/src/sh4/x86op.h Tue Jan 22 10:11:45 2008 +0000
3.3 @@ -55,6 +55,8 @@
3.4 #define OP64(x) *((uint64_t *)xlat_output) = (x); xlat_output+=8
3.5 #if SH4_TRANSLATOR == TARGET_X86_64
3.6 #define OPPTR(x) OP64((uint64_t)(x))
3.7 +#define AND_imm8s_rptr(imm, r1) REXW(); AND_imm8s_r32( imm, r1 )
3.8 +#define MOV_moffptr_EAX(offptr) REXW(); MOV_moff32_EAX( offptr )
3.9 #define STACK_ALIGN 16
3.10 #define POP_r32(r1) OP(0x58 + r1);
3.11 #define POP_realigned_r32(r1) OP(0x58 + r1); REXW(); ADD_imm8s_r32(8,R_ESP)
3.12 @@ -64,6 +66,8 @@
3.13 #define PUSH_imm64(imm) REXW(); OP(0x68); OP64(imm);
3.14 #else
3.15 #define OPPTR(x) OP32((uint32_t)(x))
3.16 +#define AND_imm8s_rptr(imm, r1) AND_imm8s_r32( imm, r1 )
3.17 +#define MOV_moffptr_EAX(offptr) MOV_moff32_EAX( offptr )
3.18 #define POP_realigned_r32(r1) POP_r32(r1)
3.19 #define PUSH_realigned_r32(r1) PUSH_r32(r1)
3.20 #ifdef APPLE_BUILD
.