Search
lxdream.org :: lxdream/src/sh4/sh4x86.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.c
changeset 601:d8d1af0d133c
prev596:dfc0c93d882e
next604:1024c3a9cb88
author nkeynes
date Tue Jan 22 10:11:45 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Invoke emulator single-step for untranslatable delay slots (and fix a few
related bugs)
file annotate diff log raw
1.1 --- a/src/sh4/sh4x86.c Mon Jan 21 11:59: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;
.