Search
lxdream.org :: lxdream/src/sh4/sh4x86.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/sh4x86.c
changeset 408:af496b734734
prev401:f79327f39818
next409: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 +0000
1.2 +++ b/src/sh4/sh4x86.c Fri Sep 28 07:27:20 2007 +0000
1.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 just
1.9 * outputs straight-line x86 code - it mainly exists to provide a baseline
1.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.16
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 save
1.21 * SI/DI as required
1.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.32
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.40
1.41 /**
1.42 - * Exit the block early (ie branch out), conditionally or otherwise
1.43 + * Exit the block to an absolute PC
1.44 + * Bytes: 30
1.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 ); // 5
1.57 + store_spreg( R_ECX, REG_OFFSET(pc) ); // 3
1.58 + MOV_moff32_EAX( (uint32_t)xlat_get_lut_entry(pc) ); // 5
1.59 + AND_imm8s_r32( 0xFC, R_EAX ); // 3
1.60 + load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
1.61 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
1.62 POP_r32(R_ESI);
1.63 - POP_r32(R_EDI);
1.64 POP_r32(R_EBP);
1.65 RET();
1.66 }
1.67
1.68 /**
1.69 - * Flush any open regs back to memory, restore SI/DI/, update PC, etc
1.70 + * Exit the block with sh4r.pc already written
1.71 + * Bytes: 16
1.72 + */
1.73 +void exit_block_pcset( pc )
1.74 +{
1.75 + XOR_r32_r32( R_EAX, R_EAX ); // 2
1.76 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 5
1.77 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 6
1.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 here
1.88 - // Normal termination - save PC, cycle count
1.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 ); // 6
1.96 CALL_r32( R_EAX ); // 2
1.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.103
1.104 @@ -457,7 +465,7 @@
1.105 * @return true if the instruction marks the end of a basic block
1.106 * (eg a branch or
1.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 rel32
1.278 + sh4_x86_translate_instruction(pc+2);
1.279 + exit_block( disp + pc + 4, pc+4 );
1.280 + // not taken
1.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 rel32
1.301 + sh4_x86_translate_instruction(pc+2);
1.302 + exit_block( disp + pc + 4, pc+4 );
1.303 + // not taken
1.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 }
.