filename | src/sh4/sh4x86.c |
changeset | 408:af496b734734 |
prev | 401:f79327f39818 |
next | 409:549e00835448 |
author | nkeynes |
date | Fri Sep 28 07:27:20 2007 +0000 (14 years ago) |
permissions | -rw-r--r-- |
last change | Change block signature to return pointer to next block (if known) Rewrite block-exit code |
file | annotate | diff | log | raw |
1.1 --- a/src/sh4/sh4x86.c Thu Sep 20 08:37:19 2007 +00001.2 +++ b/src/sh4/sh4x86.c Fri Sep 28 07:27:20 2007 +00001.3 @@ -1,5 +1,5 @@1.4 /**1.5 - * $Id: sh4x86.c,v 1.14 2007-09-20 08:37:19 nkeynes Exp $1.6 + * $Id: sh4x86.c,v 1.15 2007-09-28 07:27:20 nkeynes Exp $1.7 *1.8 * SH4 => x86 translation. This version does no real optimization, it just1.9 * outputs straight-line x86 code - it mainly exists to provide a baseline1.10 @@ -42,7 +42,7 @@1.11 gboolean in_delay_slot;1.12 gboolean priv_checked; /* true if we've already checked the cpu mode. */1.13 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */1.14 - int exit_code;1.15 + uint32_t block_start_pc;1.17 /* Allocated memory for the (block-wide) back-patch list */1.18 uint32_t **backpatch_list;1.19 @@ -360,12 +360,11 @@1.20 * Emit the 'start of block' assembly. Sets up the stack frame and save1.21 * SI/DI as required1.22 */1.23 -void sh4_translate_begin_block()1.24 +void sh4_translate_begin_block( sh4addr_t pc )1.25 {1.26 PUSH_r32(R_EBP);1.27 /* mov &sh4r, ebp */1.28 load_imm32( R_EBP, (uint32_t)&sh4r );1.29 - PUSH_r32(R_EDI);1.30 PUSH_r32(R_ESI);1.31 XOR_r32_r32(R_ESI, R_ESI);1.33 @@ -373,35 +372,44 @@1.34 sh4_x86.priv_checked = FALSE;1.35 sh4_x86.fpuen_checked = FALSE;1.36 sh4_x86.backpatch_posn = 0;1.37 - sh4_x86.exit_code = 1;1.38 + sh4_x86.block_start_pc = pc;1.39 }1.41 /**1.42 - * Exit the block early (ie branch out), conditionally or otherwise1.43 + * Exit the block to an absolute PC1.44 + * Bytes: 301.45 */1.46 -void exit_block( )1.47 +void exit_block( sh4addr_t pc, sh4addr_t endpc )1.48 {1.49 - store_spreg( R_EDI, REG_OFFSET(pc) );1.50 - MOV_moff32_EAX( (uint32_t)&sh4_cpu_period );1.51 - load_spreg( R_ECX, REG_OFFSET(slice_cycle) );1.52 - MUL_r32( R_ESI );1.53 - ADD_r32_r32( R_EAX, R_ECX );1.54 - store_spreg( R_ECX, REG_OFFSET(slice_cycle) );1.55 - load_imm32( R_EAX, sh4_x86.exit_code );1.56 + load_imm32( R_ECX, pc ); // 51.57 + store_spreg( R_ECX, REG_OFFSET(pc) ); // 31.58 + MOV_moff32_EAX( (uint32_t)xlat_get_lut_entry(pc) ); // 51.59 + AND_imm8s_r32( 0xFC, R_EAX ); // 31.60 + load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 51.61 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 61.62 POP_r32(R_ESI);1.63 - POP_r32(R_EDI);1.64 POP_r32(R_EBP);1.65 RET();1.66 }1.68 /**1.69 - * Flush any open regs back to memory, restore SI/DI/, update PC, etc1.70 + * Exit the block with sh4r.pc already written1.71 + * Bytes: 161.72 + */1.73 +void exit_block_pcset( pc )1.74 +{1.75 + XOR_r32_r32( R_EAX, R_EAX ); // 21.76 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 51.77 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 61.78 + POP_r32(R_ESI);1.79 + POP_r32(R_EBP);1.80 + RET();1.81 +}1.82 +1.83 +/**1.84 + * Write the block trailer (exception handling block)1.85 */1.86 void sh4_translate_end_block( sh4addr_t pc ) {1.87 - assert( !sh4_x86.in_delay_slot ); // should never stop here1.88 - // Normal termination - save PC, cycle count1.89 - exit_block( );1.90 -1.91 if( sh4_x86.backpatch_posn != 0 ) {1.92 uint8_t *end_ptr = xlat_output;1.93 // Exception termination. Jump block for various exception codes:1.94 @@ -435,8 +443,8 @@1.95 load_imm32( R_EAX, (uint32_t)sh4_raise_exception ); // 61.96 CALL_r32( R_EAX ); // 21.97 ADD_imm8s_r32( 4, R_ESP );1.98 + XOR_r32_r32( R_EAX, R_EAX );1.99 POP_r32(R_ESI);1.100 - POP_r32(R_EDI);1.101 POP_r32(R_EBP);1.102 RET();1.104 @@ -457,7 +465,7 @@1.105 * @return true if the instruction marks the end of a basic block1.106 * (eg a branch or1.107 */1.108 -uint32_t sh4_x86_translate_instruction( uint32_t pc )1.109 +uint32_t sh4_x86_translate_instruction( sh4addr_t pc )1.110 {1.111 uint32_t ir;1.112 /* Read instruction */1.113 @@ -547,12 +555,14 @@1.114 if( sh4_x86.in_delay_slot ) {1.115 SLOTILLEGAL();1.116 } else {1.117 - load_imm32( R_EAX, pc + 4 );1.118 - store_spreg( R_EAX, R_PR );1.119 - load_reg( R_EDI, Rn );1.120 - ADD_r32_r32( R_EAX, R_EDI );1.121 + load_imm32( R_ECX, pc + 4 );1.122 + store_spreg( R_ECX, R_PR );1.123 + ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );1.124 + store_spreg( R_ECX, REG_OFFSET(pc) );1.125 sh4_x86.in_delay_slot = TRUE;1.126 - return 0;1.127 + sh4_x86_translate_instruction( pc + 2 );1.128 + exit_block_pcset(pc+2);1.129 + return 4;1.130 }1.131 }1.132 break;1.133 @@ -562,10 +572,13 @@1.134 if( sh4_x86.in_delay_slot ) {1.135 SLOTILLEGAL();1.136 } else {1.137 - load_reg( R_EDI, Rn );1.138 - ADD_imm32_r32( pc + 4, R_EDI );1.139 + load_reg( R_EAX, Rn );1.140 + ADD_imm32_r32( pc + 4, R_EAX );1.141 + store_spreg( R_EAX, REG_OFFSET(pc) );1.142 sh4_x86.in_delay_slot = TRUE;1.143 - return 0;1.144 + sh4_x86_translate_instruction( pc + 2 );1.145 + exit_block_pcset(pc+2);1.146 + return 4;1.147 }1.148 }1.149 break;1.150 @@ -786,9 +799,12 @@1.151 if( sh4_x86.in_delay_slot ) {1.152 SLOTILLEGAL();1.153 } else {1.154 - load_spreg( R_EDI, R_PR );1.155 + load_spreg( R_ECX, R_PR );1.156 + store_spreg( R_ECX, REG_OFFSET(pc) );1.157 sh4_x86.in_delay_slot = TRUE;1.158 - return 0;1.159 + sh4_x86_translate_instruction(pc+2);1.160 + exit_block_pcset(pc+2);1.161 + return 4;1.162 }1.163 }1.164 break;1.165 @@ -796,25 +812,28 @@1.166 { /* SLEEP */1.167 check_priv();1.168 call_func0( sh4_sleep );1.169 - sh4_x86.exit_code = 0;1.170 sh4_x86.in_delay_slot = FALSE;1.171 INC_r32(R_ESI);1.172 - return 1;1.173 + exit_block(pc+2, pc+2);1.174 + return 2;1.175 }1.176 break;1.177 case 0x2:1.178 { /* RTE */1.179 - check_priv();1.180 if( sh4_x86.in_delay_slot ) {1.181 SLOTILLEGAL();1.182 } else {1.183 - load_spreg( R_EDI, R_SPC );1.184 + check_priv();1.185 + load_spreg( R_ECX, R_SPC );1.186 + store_spreg( R_ECX, REG_OFFSET(pc) );1.187 load_spreg( R_EAX, R_SSR );1.188 call_func1( sh4_write_sr, R_EAX );1.189 sh4_x86.in_delay_slot = TRUE;1.190 sh4_x86.priv_checked = FALSE;1.191 sh4_x86.fpuen_checked = FALSE;1.192 - return 0;1.193 + sh4_x86_translate_instruction(pc+2);1.194 + exit_block_pcset(pc+2);1.195 + return 4;1.196 }1.197 }1.198 break;1.199 @@ -1830,9 +1849,12 @@1.200 } else {1.201 load_imm32( R_EAX, pc + 4 );1.202 store_spreg( R_EAX, R_PR );1.203 - load_reg( R_EDI, Rn );1.204 + load_reg( R_ECX, Rn );1.205 + store_spreg( R_ECX, REG_OFFSET(pc) );1.206 sh4_x86.in_delay_slot = TRUE;1.207 - return 0;1.208 + sh4_x86_translate_instruction(pc+2);1.209 + exit_block_pcset(pc+2);1.210 + return 4;1.211 }1.212 }1.213 break;1.214 @@ -1854,9 +1876,12 @@1.215 if( sh4_x86.in_delay_slot ) {1.216 SLOTILLEGAL();1.217 } else {1.218 - load_reg( R_EDI, Rn );1.219 + load_reg( R_ECX, Rn );1.220 + store_spreg( R_ECX, REG_OFFSET(pc) );1.221 sh4_x86.in_delay_slot = TRUE;1.222 - return 0;1.223 + sh4_x86_translate_instruction(pc+2);1.224 + exit_block_pcset(pc+2);1.225 + return 4;1.226 }1.227 }1.228 break;1.229 @@ -2248,13 +2273,12 @@1.230 if( sh4_x86.in_delay_slot ) {1.231 SLOTILLEGAL();1.232 } else {1.233 - load_imm32( R_EDI, pc + 2 );1.234 CMP_imm8s_sh4r( 0, R_T );1.235 - JE_rel8( 5, nottaken );1.236 - load_imm32( R_EDI, disp + pc + 4 );1.237 + JE_rel8( 30, nottaken );1.238 + exit_block( disp + pc + 4, pc+2 );1.239 JMP_TARGET(nottaken);1.240 - INC_r32(R_ESI);1.241 - return 1;1.242 + exit_block( pc + 2, pc+2 );1.243 + return 2;1.244 }1.245 }1.246 break;1.247 @@ -2264,13 +2288,12 @@1.248 if( sh4_x86.in_delay_slot ) {1.249 SLOTILLEGAL();1.250 } else {1.251 - load_imm32( R_EDI, pc + 2 );1.252 CMP_imm8s_sh4r( 0, R_T );1.253 - JNE_rel8( 5, nottaken );1.254 - load_imm32( R_EDI, disp + pc + 4 );1.255 + JNE_rel8( 30, nottaken );1.256 + exit_block( disp + pc + 4, pc+2 );1.257 JMP_TARGET(nottaken);1.258 - INC_r32(R_ESI);1.259 - return 1;1.260 + exit_block( pc + 2, pc + 2 );1.261 + return 2;1.262 }1.263 }1.264 break;1.265 @@ -2280,13 +2303,16 @@1.266 if( sh4_x86.in_delay_slot ) {1.267 SLOTILLEGAL();1.268 } else {1.269 - load_imm32( R_EDI, pc + 4 );1.270 + sh4_x86.in_delay_slot = TRUE;1.271 CMP_imm8s_sh4r( 0, R_T );1.272 - JE_rel8( 5, nottaken );1.273 - load_imm32( R_EDI, disp + pc + 4 );1.274 - JMP_TARGET(nottaken);1.275 - sh4_x86.in_delay_slot = TRUE;1.276 - return 0;1.277 + OP(0x0F); OP(0x84); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JE rel321.278 + sh4_x86_translate_instruction(pc+2);1.279 + exit_block( disp + pc + 4, pc+4 );1.280 + // not taken1.281 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;1.282 + sh4_x86_translate_instruction(pc+2);1.283 + exit_block( pc + 4, pc+4 );1.284 + return 4;1.285 }1.286 }1.287 break;1.288 @@ -2296,13 +2322,16 @@1.289 if( sh4_x86.in_delay_slot ) {1.290 SLOTILLEGAL();1.291 } else {1.292 - load_imm32( R_EDI, pc + 4 );1.293 + sh4_x86.in_delay_slot = TRUE;1.294 CMP_imm8s_sh4r( 0, R_T );1.295 - JNE_rel8( 5, nottaken );1.296 - load_imm32( R_EDI, disp + pc + 4 );1.297 - JMP_TARGET(nottaken);1.298 - sh4_x86.in_delay_slot = TRUE;1.299 - return 0;1.300 + OP(0x0F); OP(0x85); uint32_t *patch = (uint32_t *)xlat_output; OP32(0); // JNE rel321.301 + sh4_x86_translate_instruction(pc+2);1.302 + exit_block( disp + pc + 4, pc+4 );1.303 + // not taken1.304 + *patch = (xlat_output - ((uint8_t *)patch)) - 4;1.305 + sh4_x86_translate_instruction(pc+2);1.306 + exit_block( pc + 4, pc+4 );1.307 + return 4;1.308 }1.309 }1.310 break;1.311 @@ -2329,9 +2358,10 @@1.312 if( sh4_x86.in_delay_slot ) {1.313 SLOTILLEGAL();1.314 } else {1.315 - load_imm32( R_EDI, disp + pc + 4 );1.316 sh4_x86.in_delay_slot = TRUE;1.317 - return 0;1.318 + sh4_x86_translate_instruction( pc + 2 );1.319 + exit_block( disp + pc + 4, pc+4 );1.320 + return 4;1.321 }1.322 }1.323 break;1.324 @@ -2343,9 +2373,10 @@1.325 } else {1.326 load_imm32( R_EAX, pc + 4 );1.327 store_spreg( R_EAX, R_PR );1.328 - load_imm32( R_EDI, disp + pc + 4 );1.329 sh4_x86.in_delay_slot = TRUE;1.330 - return 0;1.331 + sh4_x86_translate_instruction( pc + 2 );1.332 + exit_block( disp + pc + 4, pc+4 );1.333 + return 4;1.334 }1.335 }1.336 break;1.337 @@ -2389,6 +2420,8 @@1.338 PUSH_imm32( imm );1.339 call_func0( sh4_raise_trap );1.340 ADD_imm8s_r32( 4, R_ESP );1.341 + exit_block_pcset(pc);1.342 + return 2;1.343 }1.344 }1.345 break;1.346 @@ -3207,7 +3240,7 @@1.347 SLOTILLEGAL();1.348 } else {1.349 JMP_exit(EXIT_ILLEGAL);1.350 - return 1;1.351 + return 2;1.352 }1.353 }1.354 break;1.355 @@ -3260,7 +3293,6 @@1.356 if( sh4_x86.in_delay_slot ) {1.357 ADD_imm8s_r32(2,R_ESI);1.358 sh4_x86.in_delay_slot = FALSE;1.359 - return 1;1.360 } else {1.361 INC_r32(R_ESI);1.362 }
.