Search
lxdream.org :: lxdream/src/sh4/sh4x86.in :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.in
changeset 601:d8d1af0d133c
prev596:dfc0c93d882e
next604:1024c3a9cb88
author nkeynes
date Tue Jan 22 10:11:45 2008 +0000 (15 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.in Mon Jan 21 11:59:46 2008 +0000
1.2 +++ b/src/sh4/sh4x86.in 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 @@ -987,7 +997,7 @@
1.50 :}
1.51 SWAP.B Rm, Rn {:
1.52 load_reg( R_EAX, Rm );
1.53 - XCHG_r8_r8( R_AL, R_AH );
1.54 + XCHG_r8_r8( R_AL, R_AH ); // NB: does not touch EFLAGS
1.55 store_reg( R_EAX, Rn );
1.56 :}
1.57 SWAP.W Rm, Rn {:
1.58 @@ -1426,19 +1436,32 @@
1.59 if( sh4_x86.in_delay_slot ) {
1.60 SLOTILLEGAL();
1.61 } else {
1.62 - sh4vma_t target = disp + pc + 4;
1.63 sh4_x86.in_delay_slot = DELAY_PC;
1.64 - if( sh4_x86.tstate == TSTATE_NONE ) {
1.65 - CMP_imm8s_sh4r( 1, R_T );
1.66 - sh4_x86.tstate = TSTATE_E;
1.67 + if( UNTRANSLATABLE(pc+2) ) {
1.68 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
1.69 + JT_rel8(6,nottaken);
1.70 + ADD_imm32_r32( disp, R_EAX );
1.71 + JMP_TARGET(nottaken);
1.72 + ADD_sh4r_r32( R_PC, R_EAX );
1.73 + store_spreg( R_EAX, R_NEW_PC );
1.74 + exit_block_emu(pc+2);
1.75 + sh4_x86.branch_taken = TRUE;
1.76 + return 2;
1.77 + } else {
1.78 + if( sh4_x86.tstate == TSTATE_NONE ) {
1.79 + CMP_imm8s_sh4r( 1, R_T );
1.80 + sh4_x86.tstate = TSTATE_E;
1.81 + }
1.82 + sh4vma_t target = disp + pc + 4;
1.83 + OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JT rel32
1.84 + sh4_translate_instruction(pc+2);
1.85 + exit_block_rel( target, pc+4 );
1.86 +
1.87 + // not taken
1.88 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.89 + sh4_translate_instruction(pc+2);
1.90 + return 4;
1.91 }
1.92 - OP(0x0F); OP(0x80+sh4_x86.tstate); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel32
1.93 - sh4_translate_instruction(pc+2);
1.94 - exit_block_rel( target, pc+4 );
1.95 - // not taken
1.96 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.97 - sh4_translate_instruction(pc+2);
1.98 - return 4;
1.99 }
1.100 :}
1.101 BRA disp {:
1.102 @@ -1446,10 +1469,18 @@
1.103 SLOTILLEGAL();
1.104 } else {
1.105 sh4_x86.in_delay_slot = DELAY_PC;
1.106 - sh4_translate_instruction( pc + 2 );
1.107 - exit_block_rel( disp + pc + 4, pc+4 );
1.108 sh4_x86.branch_taken = TRUE;
1.109 - return 4;
1.110 + if( UNTRANSLATABLE(pc+2) ) {
1.111 + load_spreg( R_EAX, R_PC );
1.112 + ADD_imm32_r32( pc + disp + 4 - sh4_x86.block_start_pc, R_EAX );
1.113 + store_spreg( R_EAX, R_NEW_PC );
1.114 + exit_block_emu(pc+2);
1.115 + return 2;
1.116 + } else {
1.117 + sh4_translate_instruction( pc + 2 );
1.118 + exit_block_rel( disp + pc + 4, pc+4 );
1.119 + return 4;
1.120 + }
1.121 }
1.122 :}
1.123 BRAF Rn {:
1.124 @@ -1462,10 +1493,15 @@
1.125 store_spreg( R_EAX, R_NEW_PC );
1.126 sh4_x86.in_delay_slot = DELAY_PC;
1.127 sh4_x86.tstate = TSTATE_NONE;
1.128 - sh4_translate_instruction( pc + 2 );
1.129 - exit_block_newpcset(pc+2);
1.130 sh4_x86.branch_taken = TRUE;
1.131 - return 4;
1.132 + if( UNTRANSLATABLE(pc+2) ) {
1.133 + exit_block_emu(pc+2);
1.134 + return 2;
1.135 + } else {
1.136 + sh4_translate_instruction( pc + 2 );
1.137 + exit_block_newpcset(pc+2);
1.138 + return 4;
1.139 + }
1.140 }
1.141 :}
1.142 BSR disp {:
1.143 @@ -1476,10 +1512,18 @@
1.144 ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );
1.145 store_spreg( R_EAX, R_PR );
1.146 sh4_x86.in_delay_slot = DELAY_PC;
1.147 - sh4_translate_instruction( pc + 2 );
1.148 - exit_block_rel( disp + pc + 4, pc+4 );
1.149 sh4_x86.branch_taken = TRUE;
1.150 - return 4;
1.151 + sh4_x86.tstate = TSTATE_NONE;
1.152 + if( UNTRANSLATABLE(pc+2) ) {
1.153 + ADD_imm32_r32( disp, R_EAX );
1.154 + store_spreg( R_EAX, R_NEW_PC );
1.155 + exit_block_emu(pc+2);
1.156 + return 2;
1.157 + } else {
1.158 + sh4_translate_instruction( pc + 2 );
1.159 + exit_block_rel( disp + pc + 4, pc+4 );
1.160 + return 4;
1.161 + }
1.162 }
1.163 :}
1.164 BSRF Rn {:
1.165 @@ -1492,11 +1536,17 @@
1.166 ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );
1.167 store_spreg( R_EAX, R_NEW_PC );
1.168
1.169 + sh4_x86.in_delay_slot = DELAY_PC;
1.170 sh4_x86.tstate = TSTATE_NONE;
1.171 - sh4_translate_instruction( pc + 2 );
1.172 - exit_block_newpcset(pc+2);
1.173 sh4_x86.branch_taken = TRUE;
1.174 - return 4;
1.175 + if( UNTRANSLATABLE(pc+2) ) {
1.176 + exit_block_emu(pc+2);
1.177 + return 2;
1.178 + } else {
1.179 + sh4_translate_instruction( pc + 2 );
1.180 + exit_block_newpcset(pc+2);
1.181 + return 4;
1.182 + }
1.183 }
1.184 :}
1.185 BT disp {:
1.186 @@ -1515,17 +1565,29 @@
1.187 SLOTILLEGAL();
1.188 } else {
1.189 sh4_x86.in_delay_slot = DELAY_PC;
1.190 - if( sh4_x86.tstate == TSTATE_NONE ) {
1.191 - CMP_imm8s_sh4r( 1, R_T );
1.192 - sh4_x86.tstate = TSTATE_E;
1.193 + if( UNTRANSLATABLE(pc+2) ) {
1.194 + load_imm32( R_EAX, pc + 4 - sh4_x86.block_start_pc );
1.195 + JF_rel8(6,nottaken);
1.196 + ADD_imm32_r32( disp, R_EAX );
1.197 + JMP_TARGET(nottaken);
1.198 + ADD_sh4r_r32( R_PC, R_EAX );
1.199 + store_spreg( R_EAX, R_NEW_PC );
1.200 + exit_block_emu(pc+2);
1.201 + sh4_x86.branch_taken = TRUE;
1.202 + return 2;
1.203 + } else {
1.204 + if( sh4_x86.tstate == TSTATE_NONE ) {
1.205 + CMP_imm8s_sh4r( 1, R_T );
1.206 + sh4_x86.tstate = TSTATE_E;
1.207 + }
1.208 + OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JF rel32
1.209 + sh4_translate_instruction(pc+2);
1.210 + exit_block_rel( disp + pc + 4, pc+4 );
1.211 + // not taken
1.212 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.213 + sh4_translate_instruction(pc+2);
1.214 + return 4;
1.215 }
1.216 - OP(0x0F); OP(0x80+(sh4_x86.tstate^1)); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel32
1.217 - sh4_translate_instruction(pc+2);
1.218 - exit_block_rel( disp + pc + 4, pc+4 );
1.219 - // not taken
1.220 - *patch = (xlat_output - ((uint8_t *)patch)) - 4;
1.221 - sh4_translate_instruction(pc+2);
1.222 - return 4;
1.223 }
1.224 :}
1.225 JMP @Rn {:
1.226 @@ -1535,10 +1597,15 @@
1.227 load_reg( R_ECX, Rn );
1.228 store_spreg( R_ECX, R_NEW_PC );
1.229 sh4_x86.in_delay_slot = DELAY_PC;
1.230 - sh4_translate_instruction(pc+2);
1.231 - exit_block_newpcset(pc+2);
1.232 sh4_x86.branch_taken = TRUE;
1.233 - return 4;
1.234 + if( UNTRANSLATABLE(pc+2) ) {
1.235 + exit_block_emu(pc+2);
1.236 + return 2;
1.237 + } else {
1.238 + sh4_translate_instruction(pc+2);
1.239 + exit_block_newpcset(pc+2);
1.240 + return 4;
1.241 + }
1.242 }
1.243 :}
1.244 JSR @Rn {:
1.245 @@ -1550,10 +1617,17 @@
1.246 store_spreg( R_EAX, R_PR );
1.247 load_reg( R_ECX, Rn );
1.248 store_spreg( R_ECX, R_NEW_PC );
1.249 - sh4_translate_instruction(pc+2);
1.250 - exit_block_newpcset(pc+2);
1.251 + sh4_x86.in_delay_slot = DELAY_PC;
1.252 sh4_x86.branch_taken = TRUE;
1.253 - return 4;
1.254 + sh4_x86.tstate = TSTATE_NONE;
1.255 + if( UNTRANSLATABLE(pc+2) ) {
1.256 + exit_block_emu(pc+2);
1.257 + return 2;
1.258 + } else {
1.259 + sh4_translate_instruction(pc+2);
1.260 + exit_block_newpcset(pc+2);
1.261 + return 4;
1.262 + }
1.263 }
1.264 :}
1.265 RTE {:
1.266 @@ -1569,10 +1643,15 @@
1.267 sh4_x86.priv_checked = FALSE;
1.268 sh4_x86.fpuen_checked = FALSE;
1.269 sh4_x86.tstate = TSTATE_NONE;
1.270 - sh4_translate_instruction(pc+2);
1.271 - exit_block_newpcset(pc+2);
1.272 sh4_x86.branch_taken = TRUE;
1.273 - return 4;
1.274 + if( UNTRANSLATABLE(pc+2) ) {
1.275 + exit_block_emu(pc+2);
1.276 + return 2;
1.277 + } else {
1.278 + sh4_translate_instruction(pc+2);
1.279 + exit_block_newpcset(pc+2);
1.280 + return 4;
1.281 + }
1.282 }
1.283 :}
1.284 RTS {:
1.285 @@ -1582,10 +1661,15 @@
1.286 load_spreg( R_ECX, R_PR );
1.287 store_spreg( R_ECX, R_NEW_PC );
1.288 sh4_x86.in_delay_slot = DELAY_PC;
1.289 - sh4_translate_instruction(pc+2);
1.290 - exit_block_newpcset(pc+2);
1.291 sh4_x86.branch_taken = TRUE;
1.292 - return 4;
1.293 + if( UNTRANSLATABLE(pc+2) ) {
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_newpcset(pc+2);
1.299 + return 4;
1.300 + }
1.301 }
1.302 :}
1.303 TRAPA #imm {:
.