revision 590:4db6a084ca3c
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 590:4db6a084ca3c |
parent | 589:045ba6eb6df1 |
child | 591:7b9612fd2395 |
author | nkeynes |
date | Wed Jan 16 09:39:16 2008 +0000 (16 years ago) |
Ensure PC correctness in presence of delay-slot exceptions
src/sh4/ia32abi.h | view | annotate | diff | log | ||
src/sh4/ia32mac.h | view | annotate | diff | log | ||
src/sh4/ia64abi.h | view | annotate | diff | log | ||
src/sh4/sh4x86.c | view | annotate | diff | log | ||
src/sh4/sh4x86.in | view | annotate | diff | log | ||
src/sh4/x86op.h | view | annotate | diff | log |
1.1 --- a/src/sh4/ia32abi.h Wed Jan 16 09:37:47 2008 +00001.2 +++ b/src/sh4/ia32abi.h Wed Jan 16 09:39:16 2008 +00001.3 @@ -116,13 +116,30 @@1.5 /**1.6 * Exit the block with sh4r.pc already written1.7 - * Bytes: 151.8 */1.9 void exit_block_pcset( sh4addr_t pc )1.10 {1.11 load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 51.12 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 61.13 - load_spreg( R_EAX, REG_OFFSET(pc) );1.14 + load_spreg( R_EAX, R_PC );1.15 + if( sh4_x86.tlb_on ) {1.16 + call_func1(xlat_get_code_by_vma,R_EAX);1.17 + } else {1.18 + call_func1(xlat_get_code,R_EAX);1.19 + }1.20 + POP_r32(R_EBP);1.21 + RET();1.22 +}1.23 +1.24 +/**1.25 + * Exit the block with sh4r.new_pc written with the target pc1.26 + */1.27 +void exit_block_newpcset( sh4addr_t pc )1.28 +{1.29 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 51.30 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 61.31 + load_spreg( R_EAX, R_NEW_PC );1.32 + store_spreg( R_EAX, R_PC );1.33 if( sh4_x86.tlb_on ) {1.34 call_func1(xlat_get_code_by_vma,R_EAX);1.35 } else {
2.1 --- a/src/sh4/ia32mac.h Wed Jan 16 09:37:47 2008 +00002.2 +++ b/src/sh4/ia32mac.h Wed Jan 16 09:39:16 2008 +00002.3 @@ -138,14 +138,13 @@2.4 }2.6 /**2.7 - * Exit the block with sh4r.pc already written2.8 - * Bytes: 152.9 + * Exit the block with sh4r.new_pc written with the target pc2.10 */2.11 void exit_block_pcset( sh4addr_t pc )2.12 {2.13 load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 52.14 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 62.15 - load_spreg( R_EAX, REG_OFFSET(pc) );2.16 + load_spreg( R_EAX, R_PC );2.17 if( sh4_x86.tlb_on ) {2.18 call_func1(xlat_get_code_by_vma,R_EAX);2.19 } else {2.20 @@ -155,6 +154,25 @@2.21 RET();2.22 }2.24 +/**2.25 + * Exit the block with sh4r.new_pc written with the target pc2.26 + */2.27 +void exit_block_newpcset( sh4addr_t pc )2.28 +{2.29 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 52.30 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 62.31 + load_spreg( R_EAX, R_NEW_PC );2.32 + store_spreg( R_EAX, R_PC );2.33 + if( sh4_x86.tlb_on ) {2.34 + call_func1(xlat_get_code_by_vma,R_EAX);2.35 + } else {2.36 + call_func1(xlat_get_code,R_EAX);2.37 + }2.38 + POP_r32(R_EBP);2.39 + RET();2.40 +}2.41 +2.42 +2.43 #define EXIT_BLOCK_SIZE(pc) (24 + (IS_IN_ICACHE(pc)?5:CALL_FUNC1_SIZE))
3.1 --- a/src/sh4/ia64abi.h Wed Jan 16 09:37:47 2008 +00003.2 +++ b/src/sh4/ia64abi.h Wed Jan 16 09:39:16 2008 +00003.3 @@ -110,13 +110,30 @@3.5 /**3.6 * Exit the block with sh4r.pc already written3.7 - * Bytes: 153.8 */3.9 void exit_block_pcset( sh4addr_t pc )3.10 {3.11 load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 53.12 ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 63.13 - load_spreg( R_EAX, REG_OFFSET(pc) );3.14 + load_spreg( R_EAX, R_PC );3.15 + if( sh4_x86.tlb_on ) {3.16 + call_func1(xlat_get_code_by_vma,R_EAX);3.17 + } else {3.18 + call_func1(xlat_get_code,R_EAX);3.19 + }3.20 + POP_r32(R_EBP);3.21 + RET();3.22 +}3.23 +3.24 +/**3.25 + * Exit the block with sh4r.new_pc written with the target address3.26 + */3.27 +void exit_block_newpcset( sh4addr_t pc )3.28 +{3.29 + load_imm32( R_ECX, ((pc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 53.30 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 63.31 + load_spreg( R_EAX, R_NEW_PC );3.32 + store_spreg( R_EAX, R_PC );3.33 if( sh4_x86.tlb_on ) {3.34 call_func1(xlat_get_code_by_vma,R_EAX);3.35 } else {
4.1 --- a/src/sh4/sh4x86.c Wed Jan 16 09:37:47 2008 +00004.2 +++ b/src/sh4/sh4x86.c Wed Jan 16 09:39:16 2008 +00004.3 @@ -42,13 +42,17 @@4.5 #define MAX_RECOVERY_SIZE 20484.7 +#define DELAY_NONE 04.8 +#define DELAY_PC 14.9 +#define DELAY_PC_PR 24.10 +4.11 /**4.12 * Struct to manage internal translation state. This state is not saved -4.13 * it is only valid between calls to sh4_translate_begin_block() and4.14 * sh4_translate_end_block()4.15 */4.16 struct sh4_x86_state {4.17 - gboolean in_delay_slot;4.18 + int in_delay_slot;4.19 gboolean priv_checked; /* true if we've already checked the cpu mode. */4.20 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */4.21 gboolean branch_taken; /* true if we branched unconditionally */4.22 @@ -342,7 +346,7 @@4.23 #define MEM_WRITE_SIZE (CALL_FUNC2_SIZE)4.24 #define MMU_TRANSLATE_SIZE (sh4_x86.tlb_on ? (CALL_FUNC1_SIZE + 12) : 0 )4.26 -#define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;4.27 +#define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = DELAY_NONE; return 1;4.29 /****** Import appropriate calling conventions ******/4.30 #if SH4_TRANSLATOR == TARGET_X86_644.31 @@ -355,12 +359,41 @@4.32 #endif4.33 #endif4.35 +/**4.36 + * Embed a breakpoint into the generated code4.37 + */4.38 void sh4_translate_emit_breakpoint( sh4vma_t pc )4.39 {4.40 load_imm32( R_EAX, XLAT_EXIT_BREAKPOINT );4.41 call_func1( sh4_translate_exit, R_EAX );4.42 }4.43 +4.44 +/**4.45 + * Embed a call to sh4_execute_instruction for situations that we4.46 + * can't translate (mainly page-crossing delay slots at the moment).4.47 + * Caller is responsible for setting new_pc.4.48 + */4.49 +void sh4_emulator_exit( sh4vma_t endpc )4.50 +{4.51 + load_imm32( R_ECX, endpc - sh4_x86.block_start_pc ); // 54.52 + ADD_r32_sh4r( R_ECX, R_PC );4.54 + load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 54.55 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 64.56 + load_imm32( R_ECX, sh4_x86.in_delay_slot ? 1 : 0 );4.57 + store_spreg( R_ECX, REG_OFFSET(in_delay_slot) );4.58 +4.59 + call_func0( sh4_execute_instruction );4.60 + load_imm32( R_EAX, R_PC );4.61 + if( sh4_x86.tlb_on ) {4.62 + call_func1(xlat_get_code_by_vma,R_EAX);4.63 + } else {4.64 + call_func1(xlat_get_code,R_EAX);4.65 + }4.66 + AND_imm8s_r32( 0xFC, R_EAX ); // 34.67 + POP_r32(R_EBP);4.68 + RET();4.69 +}4.71 /**4.72 * Translate a single instruction. Delayed branches are handled specially4.73 @@ -371,7 +404,7 @@4.74 * @return true if the instruction marks the end of a basic block4.75 * (eg a branch or4.76 */4.77 -uint32_t sh4_translate_instruction( sh4addr_t pc )4.78 +uint32_t sh4_translate_instruction( sh4vma_t pc )4.79 {4.80 uint32_t ir;4.81 /* Read instruction from icache */4.82 @@ -465,14 +498,15 @@4.83 if( sh4_x86.in_delay_slot ) {4.84 SLOTILLEGAL();4.85 } else {4.86 - load_imm32( R_ECX, pc + 4 );4.87 - store_spreg( R_ECX, R_PR );4.88 - ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );4.89 - store_spreg( R_ECX, REG_OFFSET(pc) );4.90 - sh4_x86.in_delay_slot = TRUE;4.91 + load_spreg( R_EAX, R_PC );4.92 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );4.93 + store_spreg( R_EAX, R_PR );4.94 + ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );4.95 + store_spreg( R_EAX, R_NEW_PC );4.96 +4.97 sh4_x86.tstate = TSTATE_NONE;4.98 sh4_translate_instruction( pc + 2 );4.99 - exit_block_pcset(pc+2);4.100 + exit_block_newpcset(pc+2);4.101 sh4_x86.branch_taken = TRUE;4.102 return 4;4.103 }4.104 @@ -484,13 +518,14 @@4.105 if( sh4_x86.in_delay_slot ) {4.106 SLOTILLEGAL();4.107 } else {4.108 - load_reg( R_EAX, Rn );4.109 - ADD_imm32_r32( pc + 4, R_EAX );4.110 - store_spreg( R_EAX, REG_OFFSET(pc) );4.111 - sh4_x86.in_delay_slot = TRUE;4.112 + load_spreg( R_EAX, R_PC );4.113 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );4.114 + ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );4.115 + store_spreg( R_EAX, R_NEW_PC );4.116 + sh4_x86.in_delay_slot = DELAY_PC;4.117 sh4_x86.tstate = TSTATE_NONE;4.118 sh4_translate_instruction( pc + 2 );4.119 - exit_block_pcset(pc+2);4.120 + exit_block_newpcset(pc+2);4.121 sh4_x86.branch_taken = TRUE;4.122 return 4;4.123 }4.124 @@ -734,10 +769,10 @@4.125 SLOTILLEGAL();4.126 } else {4.127 load_spreg( R_ECX, R_PR );4.128 - store_spreg( R_ECX, REG_OFFSET(pc) );4.129 - sh4_x86.in_delay_slot = TRUE;4.130 + store_spreg( R_ECX, R_NEW_PC );4.131 + sh4_x86.in_delay_slot = DELAY_PC;4.132 sh4_translate_instruction(pc+2);4.133 - exit_block_pcset(pc+2);4.134 + exit_block_newpcset(pc+2);4.135 sh4_x86.branch_taken = TRUE;4.136 return 4;4.137 }4.138 @@ -748,7 +783,7 @@4.139 check_priv();4.140 call_func0( sh4_sleep );4.141 sh4_x86.tstate = TSTATE_NONE;4.142 - sh4_x86.in_delay_slot = FALSE;4.143 + sh4_x86.in_delay_slot = DELAY_NONE;4.144 return 2;4.145 }4.146 break;4.147 @@ -759,15 +794,15 @@4.148 } else {4.149 check_priv();4.150 load_spreg( R_ECX, R_SPC );4.151 - store_spreg( R_ECX, REG_OFFSET(pc) );4.152 + store_spreg( R_ECX, R_NEW_PC );4.153 load_spreg( R_EAX, R_SSR );4.154 call_func1( sh4_write_sr, R_EAX );4.155 - sh4_x86.in_delay_slot = TRUE;4.156 + sh4_x86.in_delay_slot = DELAY_PC;4.157 sh4_x86.priv_checked = FALSE;4.158 sh4_x86.fpuen_checked = FALSE;4.159 sh4_x86.tstate = TSTATE_NONE;4.160 sh4_translate_instruction(pc+2);4.161 - exit_block_pcset(pc+2);4.162 + exit_block_newpcset(pc+2);4.163 sh4_x86.branch_taken = TRUE;4.164 return 4;4.165 }4.166 @@ -1903,13 +1938,13 @@4.167 if( sh4_x86.in_delay_slot ) {4.168 SLOTILLEGAL();4.169 } else {4.170 - load_imm32( R_EAX, pc + 4 );4.171 + load_spreg( R_EAX, R_PC );4.172 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );4.173 store_spreg( R_EAX, R_PR );4.174 load_reg( R_ECX, Rn );4.175 - store_spreg( R_ECX, REG_OFFSET(pc) );4.176 - sh4_x86.in_delay_slot = TRUE;4.177 + store_spreg( R_ECX, R_NEW_PC );4.178 sh4_translate_instruction(pc+2);4.179 - exit_block_pcset(pc+2);4.180 + exit_block_newpcset(pc+2);4.181 sh4_x86.branch_taken = TRUE;4.182 return 4;4.183 }4.184 @@ -1937,10 +1972,10 @@4.185 SLOTILLEGAL();4.186 } else {4.187 load_reg( R_ECX, Rn );4.188 - store_spreg( R_ECX, REG_OFFSET(pc) );4.189 - sh4_x86.in_delay_slot = TRUE;4.190 + store_spreg( R_ECX, R_NEW_PC );4.191 + sh4_x86.in_delay_slot = DELAY_PC;4.192 sh4_translate_instruction(pc+2);4.193 - exit_block_pcset(pc+2);4.194 + exit_block_newpcset(pc+2);4.195 sh4_x86.branch_taken = TRUE;4.196 return 4;4.197 }4.198 @@ -2408,7 +2443,7 @@4.199 if( sh4_x86.in_delay_slot ) {4.200 SLOTILLEGAL();4.201 } else {4.202 - sh4_x86.in_delay_slot = TRUE;4.203 + sh4_x86.in_delay_slot = DELAY_PC;4.204 if( sh4_x86.tstate == TSTATE_NONE ) {4.205 CMP_imm8s_sh4r( 1, R_T );4.206 sh4_x86.tstate = TSTATE_E;4.207 @@ -2430,7 +2465,7 @@4.208 SLOTILLEGAL();4.209 } else {4.210 sh4vma_t target = disp + pc + 4;4.211 - sh4_x86.in_delay_slot = TRUE;4.212 + sh4_x86.in_delay_slot = DELAY_PC;4.213 if( sh4_x86.tstate == TSTATE_NONE ) {4.214 CMP_imm8s_sh4r( 1, R_T );4.215 sh4_x86.tstate = TSTATE_E;4.216 @@ -2479,7 +2514,7 @@4.217 if( sh4_x86.in_delay_slot ) {4.218 SLOTILLEGAL();4.219 } else {4.220 - sh4_x86.in_delay_slot = TRUE;4.221 + sh4_x86.in_delay_slot = DELAY_PC;4.222 sh4_translate_instruction( pc + 2 );4.223 exit_block_rel( disp + pc + 4, pc+4 );4.224 sh4_x86.branch_taken = TRUE;4.225 @@ -2493,9 +2528,10 @@4.226 if( sh4_x86.in_delay_slot ) {4.227 SLOTILLEGAL();4.228 } else {4.229 - load_imm32( R_EAX, pc + 4 );4.230 + load_spreg( R_EAX, R_PC );4.231 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );4.232 store_spreg( R_EAX, R_PR );4.233 - sh4_x86.in_delay_slot = TRUE;4.234 + sh4_x86.in_delay_slot = DELAY_PC;4.235 sh4_translate_instruction( pc + 2 );4.236 exit_block_rel( disp + pc + 4, pc+4 );4.237 sh4_x86.branch_taken = TRUE;4.238 @@ -2546,8 +2582,8 @@4.239 if( sh4_x86.in_delay_slot ) {4.240 SLOTILLEGAL();4.241 } else {4.242 - load_imm32( R_ECX, pc+2 );4.243 - store_spreg( R_ECX, REG_OFFSET(pc) );4.244 + load_imm32( R_ECX, pc+2 - sh4_x86.block_start_pc ); // 54.245 + ADD_r32_sh4r( R_ECX, R_PC );4.246 load_imm32( R_EAX, imm );4.247 call_func1( sh4_raise_trap, R_EAX );4.248 sh4_x86.tstate = TSTATE_NONE;4.249 @@ -3492,6 +3528,6 @@4.250 break;4.251 }4.253 - sh4_x86.in_delay_slot = FALSE;4.254 + sh4_x86.in_delay_slot = DELAY_NONE;4.255 return 0;4.256 }
5.1 --- a/src/sh4/sh4x86.in Wed Jan 16 09:37:47 2008 +00005.2 +++ b/src/sh4/sh4x86.in Wed Jan 16 09:39:16 2008 +00005.3 @@ -42,13 +42,17 @@5.5 #define MAX_RECOVERY_SIZE 20485.7 +#define DELAY_NONE 05.8 +#define DELAY_PC 15.9 +#define DELAY_PC_PR 25.10 +5.11 /**5.12 * Struct to manage internal translation state. This state is not saved -5.13 * it is only valid between calls to sh4_translate_begin_block() and5.14 * sh4_translate_end_block()5.15 */5.16 struct sh4_x86_state {5.17 - gboolean in_delay_slot;5.18 + int in_delay_slot;5.19 gboolean priv_checked; /* true if we've already checked the cpu mode. */5.20 gboolean fpuen_checked; /* true if we've already checked fpu enabled. */5.21 gboolean branch_taken; /* true if we branched unconditionally */5.22 @@ -342,7 +346,7 @@5.23 #define MEM_WRITE_SIZE (CALL_FUNC2_SIZE)5.24 #define MMU_TRANSLATE_SIZE (sh4_x86.tlb_on ? (CALL_FUNC1_SIZE + 12) : 0 )5.26 -#define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = FALSE; return 1;5.27 +#define SLOTILLEGAL() JMP_exc(EXC_SLOT_ILLEGAL); sh4_x86.in_delay_slot = DELAY_NONE; return 1;5.29 /****** Import appropriate calling conventions ******/5.30 #if SH4_TRANSLATOR == TARGET_X86_645.31 @@ -355,12 +359,41 @@5.32 #endif5.33 #endif5.35 +/**5.36 + * Embed a breakpoint into the generated code5.37 + */5.38 void sh4_translate_emit_breakpoint( sh4vma_t pc )5.39 {5.40 load_imm32( R_EAX, XLAT_EXIT_BREAKPOINT );5.41 call_func1( sh4_translate_exit, R_EAX );5.42 }5.43 +5.44 +/**5.45 + * Embed a call to sh4_execute_instruction for situations that we5.46 + * can't translate (mainly page-crossing delay slots at the moment).5.47 + * Caller is responsible for setting new_pc.5.48 + */5.49 +void sh4_emulator_exit( sh4vma_t endpc )5.50 +{5.51 + load_imm32( R_ECX, endpc - sh4_x86.block_start_pc ); // 55.52 + ADD_r32_sh4r( R_ECX, R_PC );5.54 + load_imm32( R_ECX, ((endpc - sh4_x86.block_start_pc)>>1)*sh4_cpu_period ); // 55.55 + ADD_r32_sh4r( R_ECX, REG_OFFSET(slice_cycle) ); // 65.56 + load_imm32( R_ECX, sh4_x86.in_delay_slot ? 1 : 0 );5.57 + store_spreg( R_ECX, REG_OFFSET(in_delay_slot) );5.58 +5.59 + call_func0( sh4_execute_instruction );5.60 + load_imm32( R_EAX, R_PC );5.61 + if( sh4_x86.tlb_on ) {5.62 + call_func1(xlat_get_code_by_vma,R_EAX);5.63 + } else {5.64 + call_func1(xlat_get_code,R_EAX);5.65 + }5.66 + AND_imm8s_r32( 0xFC, R_EAX ); // 35.67 + POP_r32(R_EBP);5.68 + RET();5.69 +}5.71 /**5.72 * Translate a single instruction. Delayed branches are handled specially5.73 @@ -371,7 +404,7 @@5.74 * @return true if the instruction marks the end of a basic block5.75 * (eg a branch or5.76 */5.77 -uint32_t sh4_translate_instruction( sh4addr_t pc )5.78 +uint32_t sh4_translate_instruction( sh4vma_t pc )5.79 {5.80 uint32_t ir;5.81 /* Read instruction from icache */5.82 @@ -1389,7 +1422,7 @@5.83 SLOTILLEGAL();5.84 } else {5.85 sh4vma_t target = disp + pc + 4;5.86 - sh4_x86.in_delay_slot = TRUE;5.87 + sh4_x86.in_delay_slot = DELAY_PC;5.88 if( sh4_x86.tstate == TSTATE_NONE ) {5.89 CMP_imm8s_sh4r( 1, R_T );5.90 sh4_x86.tstate = TSTATE_E;5.91 @@ -1407,7 +1440,7 @@5.92 if( sh4_x86.in_delay_slot ) {5.93 SLOTILLEGAL();5.94 } else {5.95 - sh4_x86.in_delay_slot = TRUE;5.96 + sh4_x86.in_delay_slot = DELAY_PC;5.97 sh4_translate_instruction( pc + 2 );5.98 exit_block_rel( disp + pc + 4, pc+4 );5.99 sh4_x86.branch_taken = TRUE;5.100 @@ -1418,13 +1451,14 @@5.101 if( sh4_x86.in_delay_slot ) {5.102 SLOTILLEGAL();5.103 } else {5.104 - load_reg( R_EAX, Rn );5.105 - ADD_imm32_r32( pc + 4, R_EAX );5.106 - store_spreg( R_EAX, REG_OFFSET(pc) );5.107 - sh4_x86.in_delay_slot = TRUE;5.108 + load_spreg( R_EAX, R_PC );5.109 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );5.110 + ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );5.111 + store_spreg( R_EAX, R_NEW_PC );5.112 + sh4_x86.in_delay_slot = DELAY_PC;5.113 sh4_x86.tstate = TSTATE_NONE;5.114 sh4_translate_instruction( pc + 2 );5.115 - exit_block_pcset(pc+2);5.116 + exit_block_newpcset(pc+2);5.117 sh4_x86.branch_taken = TRUE;5.118 return 4;5.119 }5.120 @@ -1433,9 +1467,10 @@5.121 if( sh4_x86.in_delay_slot ) {5.122 SLOTILLEGAL();5.123 } else {5.124 - load_imm32( R_EAX, pc + 4 );5.125 + load_spreg( R_EAX, R_PC );5.126 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );5.127 store_spreg( R_EAX, R_PR );5.128 - sh4_x86.in_delay_slot = TRUE;5.129 + sh4_x86.in_delay_slot = DELAY_PC;5.130 sh4_translate_instruction( pc + 2 );5.131 exit_block_rel( disp + pc + 4, pc+4 );5.132 sh4_x86.branch_taken = TRUE;5.133 @@ -1446,14 +1481,15 @@5.134 if( sh4_x86.in_delay_slot ) {5.135 SLOTILLEGAL();5.136 } else {5.137 - load_imm32( R_ECX, pc + 4 );5.138 - store_spreg( R_ECX, R_PR );5.139 - ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_ECX );5.140 - store_spreg( R_ECX, REG_OFFSET(pc) );5.141 - sh4_x86.in_delay_slot = TRUE;5.142 + load_spreg( R_EAX, R_PC );5.143 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );5.144 + store_spreg( R_EAX, R_PR );5.145 + ADD_sh4r_r32( REG_OFFSET(r[Rn]), R_EAX );5.146 + store_spreg( R_EAX, R_NEW_PC );5.147 +5.148 sh4_x86.tstate = TSTATE_NONE;5.149 sh4_translate_instruction( pc + 2 );5.150 - exit_block_pcset(pc+2);5.151 + exit_block_newpcset(pc+2);5.152 sh4_x86.branch_taken = TRUE;5.153 return 4;5.154 }5.155 @@ -1473,7 +1509,7 @@5.156 if( sh4_x86.in_delay_slot ) {5.157 SLOTILLEGAL();5.158 } else {5.159 - sh4_x86.in_delay_slot = TRUE;5.160 + sh4_x86.in_delay_slot = DELAY_PC;5.161 if( sh4_x86.tstate == TSTATE_NONE ) {5.162 CMP_imm8s_sh4r( 1, R_T );5.163 sh4_x86.tstate = TSTATE_E;5.164 @@ -1492,10 +1528,10 @@5.165 SLOTILLEGAL();5.166 } else {5.167 load_reg( R_ECX, Rn );5.168 - store_spreg( R_ECX, REG_OFFSET(pc) );5.169 - sh4_x86.in_delay_slot = TRUE;5.170 + store_spreg( R_ECX, R_NEW_PC );5.171 + sh4_x86.in_delay_slot = DELAY_PC;5.172 sh4_translate_instruction(pc+2);5.173 - exit_block_pcset(pc+2);5.174 + exit_block_newpcset(pc+2);5.175 sh4_x86.branch_taken = TRUE;5.176 return 4;5.177 }5.178 @@ -1504,13 +1540,13 @@5.179 if( sh4_x86.in_delay_slot ) {5.180 SLOTILLEGAL();5.181 } else {5.182 - load_imm32( R_EAX, pc + 4 );5.183 + load_spreg( R_EAX, R_PC );5.184 + ADD_imm32_r32( pc + 4 - sh4_x86.block_start_pc, R_EAX );5.185 store_spreg( R_EAX, R_PR );5.186 load_reg( R_ECX, Rn );5.187 - store_spreg( R_ECX, REG_OFFSET(pc) );5.188 - sh4_x86.in_delay_slot = TRUE;5.189 + store_spreg( R_ECX, R_NEW_PC );5.190 sh4_translate_instruction(pc+2);5.191 - exit_block_pcset(pc+2);5.192 + exit_block_newpcset(pc+2);5.193 sh4_x86.branch_taken = TRUE;5.194 return 4;5.195 }5.196 @@ -1521,15 +1557,15 @@5.197 } else {5.198 check_priv();5.199 load_spreg( R_ECX, R_SPC );5.200 - store_spreg( R_ECX, REG_OFFSET(pc) );5.201 + store_spreg( R_ECX, R_NEW_PC );5.202 load_spreg( R_EAX, R_SSR );5.203 call_func1( sh4_write_sr, R_EAX );5.204 - sh4_x86.in_delay_slot = TRUE;5.205 + sh4_x86.in_delay_slot = DELAY_PC;5.206 sh4_x86.priv_checked = FALSE;5.207 sh4_x86.fpuen_checked = FALSE;5.208 sh4_x86.tstate = TSTATE_NONE;5.209 sh4_translate_instruction(pc+2);5.210 - exit_block_pcset(pc+2);5.211 + exit_block_newpcset(pc+2);5.212 sh4_x86.branch_taken = TRUE;5.213 return 4;5.214 }5.215 @@ -1539,10 +1575,10 @@5.216 SLOTILLEGAL();5.217 } else {5.218 load_spreg( R_ECX, R_PR );5.219 - store_spreg( R_ECX, REG_OFFSET(pc) );5.220 - sh4_x86.in_delay_slot = TRUE;5.221 + store_spreg( R_ECX, R_NEW_PC );5.222 + sh4_x86.in_delay_slot = DELAY_PC;5.223 sh4_translate_instruction(pc+2);5.224 - exit_block_pcset(pc+2);5.225 + exit_block_newpcset(pc+2);5.226 sh4_x86.branch_taken = TRUE;5.227 return 4;5.228 }5.229 @@ -1551,8 +1587,8 @@5.230 if( sh4_x86.in_delay_slot ) {5.231 SLOTILLEGAL();5.232 } else {5.233 - load_imm32( R_ECX, pc+2 );5.234 - store_spreg( R_ECX, REG_OFFSET(pc) );5.235 + load_imm32( R_ECX, pc+2 - sh4_x86.block_start_pc ); // 55.236 + ADD_r32_sh4r( R_ECX, R_PC );5.237 load_imm32( R_EAX, imm );5.238 call_func1( sh4_raise_trap, R_EAX );5.239 sh4_x86.tstate = TSTATE_NONE;5.240 @@ -2451,7 +2487,7 @@5.241 check_priv();5.242 call_func0( sh4_sleep );5.243 sh4_x86.tstate = TSTATE_NONE;5.244 - sh4_x86.in_delay_slot = FALSE;5.245 + sh4_x86.in_delay_slot = DELAY_NONE;5.246 return 2;5.247 :}5.248 STC SR, Rn {:5.249 @@ -2662,6 +2698,6 @@5.251 NOP {: /* Do nothing. Well, we could emit an 0x90, but what would really be the point? */ :}5.252 %%5.253 - sh4_x86.in_delay_slot = FALSE;5.254 + sh4_x86.in_delay_slot = DELAY_NONE;5.255 return 0;5.256 }
6.1 --- a/src/sh4/x86op.h Wed Jan 16 09:37:47 2008 +00006.2 +++ b/src/sh4/x86op.h Wed Jan 16 09:39:16 2008 +00006.3 @@ -100,6 +100,7 @@6.4 #define R_MACH REG_OFFSET(mac)+46.5 #define R_MACL REG_OFFSET(mac)6.6 #define R_PC REG_OFFSET(pc)6.7 +#define R_NEW_PC REG_OFFSET(new_pc)6.8 #define R_PR REG_OFFSET(pr)6.9 #define R_SGR REG_OFFSET(sgr)6.10 #define R_FPUL REG_OFFSET(fpul)
.