Commit e50e6a20192616b93d94be316556deb001e4f477

Authored by bellard
1 parent 430116a1

better arm conditionnal execution implementation (Paul Brook)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1399 c046a42c-6fe2-441c-8c8c-71466251a162
target-arm/op.c
@@ -251,104 +251,109 @@ void OPPROTO op_logic_T1_cc(void) @@ -251,104 +251,109 @@ void OPPROTO op_logic_T1_cc(void)
251 void OPPROTO op_test_eq(void) 251 void OPPROTO op_test_eq(void)
252 { 252 {
253 if (env->NZF == 0) 253 if (env->NZF == 0)
254 - JUMP_TB(op_test_eq, PARAM1, 0, PARAM2); 254 + GOTO_LABEL_PARAM(1);;
255 FORCE_RET(); 255 FORCE_RET();
256 } 256 }
257 257
258 void OPPROTO op_test_ne(void) 258 void OPPROTO op_test_ne(void)
259 { 259 {
260 if (env->NZF != 0) 260 if (env->NZF != 0)
261 - JUMP_TB(op_test_ne, PARAM1, 0, PARAM2); 261 + GOTO_LABEL_PARAM(1);;
262 FORCE_RET(); 262 FORCE_RET();
263 } 263 }
264 264
265 void OPPROTO op_test_cs(void) 265 void OPPROTO op_test_cs(void)
266 { 266 {
267 if (env->CF != 0) 267 if (env->CF != 0)
268 - JUMP_TB(op_test_cs, PARAM1, 0, PARAM2); 268 + GOTO_LABEL_PARAM(1);
269 FORCE_RET(); 269 FORCE_RET();
270 } 270 }
271 271
272 void OPPROTO op_test_cc(void) 272 void OPPROTO op_test_cc(void)
273 { 273 {
274 if (env->CF == 0) 274 if (env->CF == 0)
275 - JUMP_TB(op_test_cc, PARAM1, 0, PARAM2); 275 + GOTO_LABEL_PARAM(1);
276 FORCE_RET(); 276 FORCE_RET();
277 } 277 }
278 278
279 void OPPROTO op_test_mi(void) 279 void OPPROTO op_test_mi(void)
280 { 280 {
281 if ((env->NZF & 0x80000000) != 0) 281 if ((env->NZF & 0x80000000) != 0)
282 - JUMP_TB(op_test_mi, PARAM1, 0, PARAM2); 282 + GOTO_LABEL_PARAM(1);
283 FORCE_RET(); 283 FORCE_RET();
284 } 284 }
285 285
286 void OPPROTO op_test_pl(void) 286 void OPPROTO op_test_pl(void)
287 { 287 {
288 if ((env->NZF & 0x80000000) == 0) 288 if ((env->NZF & 0x80000000) == 0)
289 - JUMP_TB(op_test_pl, PARAM1, 0, PARAM2); 289 + GOTO_LABEL_PARAM(1);
290 FORCE_RET(); 290 FORCE_RET();
291 } 291 }
292 292
293 void OPPROTO op_test_vs(void) 293 void OPPROTO op_test_vs(void)
294 { 294 {
295 if ((env->VF & 0x80000000) != 0) 295 if ((env->VF & 0x80000000) != 0)
296 - JUMP_TB(op_test_vs, PARAM1, 0, PARAM2); 296 + GOTO_LABEL_PARAM(1);
297 FORCE_RET(); 297 FORCE_RET();
298 } 298 }
299 299
300 void OPPROTO op_test_vc(void) 300 void OPPROTO op_test_vc(void)
301 { 301 {
302 if ((env->VF & 0x80000000) == 0) 302 if ((env->VF & 0x80000000) == 0)
303 - JUMP_TB(op_test_vc, PARAM1, 0, PARAM2); 303 + GOTO_LABEL_PARAM(1);
304 FORCE_RET(); 304 FORCE_RET();
305 } 305 }
306 306
307 void OPPROTO op_test_hi(void) 307 void OPPROTO op_test_hi(void)
308 { 308 {
309 if (env->CF != 0 && env->NZF != 0) 309 if (env->CF != 0 && env->NZF != 0)
310 - JUMP_TB(op_test_hi, PARAM1, 0, PARAM2); 310 + GOTO_LABEL_PARAM(1);
311 FORCE_RET(); 311 FORCE_RET();
312 } 312 }
313 313
314 void OPPROTO op_test_ls(void) 314 void OPPROTO op_test_ls(void)
315 { 315 {
316 if (env->CF == 0 || env->NZF == 0) 316 if (env->CF == 0 || env->NZF == 0)
317 - JUMP_TB(op_test_ls, PARAM1, 0, PARAM2); 317 + GOTO_LABEL_PARAM(1);
318 FORCE_RET(); 318 FORCE_RET();
319 } 319 }
320 320
321 void OPPROTO op_test_ge(void) 321 void OPPROTO op_test_ge(void)
322 { 322 {
323 if (((env->VF ^ env->NZF) & 0x80000000) == 0) 323 if (((env->VF ^ env->NZF) & 0x80000000) == 0)
324 - JUMP_TB(op_test_ge, PARAM1, 0, PARAM2); 324 + GOTO_LABEL_PARAM(1);
325 FORCE_RET(); 325 FORCE_RET();
326 } 326 }
327 327
328 void OPPROTO op_test_lt(void) 328 void OPPROTO op_test_lt(void)
329 { 329 {
330 if (((env->VF ^ env->NZF) & 0x80000000) != 0) 330 if (((env->VF ^ env->NZF) & 0x80000000) != 0)
331 - JUMP_TB(op_test_lt, PARAM1, 0, PARAM2); 331 + GOTO_LABEL_PARAM(1);
332 FORCE_RET(); 332 FORCE_RET();
333 } 333 }
334 334
335 void OPPROTO op_test_gt(void) 335 void OPPROTO op_test_gt(void)
336 { 336 {
337 if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0) 337 if (env->NZF != 0 && ((env->VF ^ env->NZF) & 0x80000000) == 0)
338 - JUMP_TB(op_test_gt, PARAM1, 0, PARAM2); 338 + GOTO_LABEL_PARAM(1);
339 FORCE_RET(); 339 FORCE_RET();
340 } 340 }
341 341
342 void OPPROTO op_test_le(void) 342 void OPPROTO op_test_le(void)
343 { 343 {
344 if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0) 344 if (env->NZF == 0 || ((env->VF ^ env->NZF) & 0x80000000) != 0)
345 - JUMP_TB(op_test_le, PARAM1, 0, PARAM2); 345 + GOTO_LABEL_PARAM(1);
346 FORCE_RET(); 346 FORCE_RET();
347 } 347 }
348 348
349 -void OPPROTO op_jmp(void) 349 +void OPPROTO op_jmp0(void)
350 { 350 {
351 - JUMP_TB(op_jmp, PARAM1, 1, PARAM2); 351 + JUMP_TB(op_jmp0, PARAM1, 0, PARAM2);
  352 +}
  353 +
  354 +void OPPROTO op_jmp1(void)
  355 +{
  356 + JUMP_TB(op_jmp1, PARAM1, 1, PARAM2);
352 } 357 }
353 358
354 void OPPROTO op_exit_tb(void) 359 void OPPROTO op_exit_tb(void)
target-arm/translate.c
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 typedef struct DisasContext { 32 typedef struct DisasContext {
33 target_ulong pc; 33 target_ulong pc;
34 int is_jmp; 34 int is_jmp;
  35 + /* Nonzero if this instruction has been conditionally skipped. */
  36 + int condjmp;
  37 + /* The label that will be jumped to when the instruction is skipped. */
  38 + int condlabel;
35 struct TranslationBlock *tb; 39 struct TranslationBlock *tb;
36 int singlestep_enabled; 40 int singlestep_enabled;
37 } DisasContext; 41 } DisasContext;
@@ -53,7 +57,7 @@ enum { @@ -53,7 +57,7 @@ enum {
53 57
54 #include "gen-op.h" 58 #include "gen-op.h"
55 59
56 -static GenOpFunc2 *gen_test_cc[14] = { 60 +static GenOpFunc1 *gen_test_cc[14] = {
57 gen_op_test_eq, 61 gen_op_test_eq,
58 gen_op_test_ne, 62 gen_op_test_ne,
59 gen_op_test_cs, 63 gen_op_test_cs,
@@ -896,7 +900,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest) @@ -896,7 +900,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
896 gen_op_movl_T0_im(dest); 900 gen_op_movl_T0_im(dest);
897 gen_bx(s); 901 gen_bx(s);
898 } else { 902 } else {
899 - gen_op_jmp((long)s->tb, dest); 903 + gen_op_jmp0((long)s->tb, dest);
900 s->is_jmp = DISAS_TB_JUMP; 904 s->is_jmp = DISAS_TB_JUMP;
901 } 905 }
902 } 906 }
@@ -939,8 +943,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -939,8 +943,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
939 if (cond != 0xe) { 943 if (cond != 0xe) {
940 /* if not always execute, we generate a conditional jump to 944 /* if not always execute, we generate a conditional jump to
941 next instruction */ 945 next instruction */
942 - gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);  
943 - s->is_jmp = DISAS_JUMP_NEXT; 946 + s->condlabel = gen_new_label();
  947 + gen_test_cc[cond ^ 1](s->condlabel);
  948 + s->condjmp = 1;
  949 + //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
  950 + //s->is_jmp = DISAS_JUMP_NEXT;
944 } 951 }
945 if ((insn & 0x0f900000) == 0x03000000) { 952 if ((insn & 0x0f900000) == 0x03000000) {
946 if ((insn & 0x0ff0f000) != 0x0360f000) 953 if ((insn & 0x0ff0f000) != 0x0360f000)
@@ -1961,8 +1968,11 @@ static void disas_thumb_insn(DisasContext *s) @@ -1961,8 +1968,11 @@ static void disas_thumb_insn(DisasContext *s)
1961 break; 1968 break;
1962 } 1969 }
1963 /* generate a conditional jump to next instruction */ 1970 /* generate a conditional jump to next instruction */
1964 - gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);  
1965 - s->is_jmp = DISAS_JUMP_NEXT; 1971 + s->condlabel = gen_new_label();
  1972 + gen_test_cc[cond ^ 1](s->condlabel);
  1973 + s->condjmp = 1;
  1974 + //gen_test_cc[cond ^ 1]((long)s->tb, (long)s->pc);
  1975 + //s->is_jmp = DISAS_JUMP_NEXT;
1966 gen_movl_T1_reg(s, 15); 1976 gen_movl_T1_reg(s, 15);
1967 1977
1968 /* jump to the offset */ 1978 /* jump to the offset */
@@ -2034,6 +2044,8 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -2034,6 +2044,8 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2034 dc->is_jmp = DISAS_NEXT; 2044 dc->is_jmp = DISAS_NEXT;
2035 dc->pc = pc_start; 2045 dc->pc = pc_start;
2036 dc->singlestep_enabled = env->singlestep_enabled; 2046 dc->singlestep_enabled = env->singlestep_enabled;
  2047 + dc->condjmp = 0;
  2048 + nb_gen_labels = 0;
2037 lj = -1; 2049 lj = -1;
2038 do { 2050 do {
2039 if (env->nb_breakpoints > 0) { 2051 if (env->nb_breakpoints > 0) {
@@ -2057,25 +2069,41 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -2057,25 +2069,41 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2057 gen_opc_pc[lj] = dc->pc; 2069 gen_opc_pc[lj] = dc->pc;
2058 gen_opc_instr_start[lj] = 1; 2070 gen_opc_instr_start[lj] = 1;
2059 } 2071 }
  2072 +
2060 if (env->thumb) 2073 if (env->thumb)
2061 disas_thumb_insn(dc); 2074 disas_thumb_insn(dc);
2062 else 2075 else
2063 disas_arm_insn(env, dc); 2076 disas_arm_insn(env, dc);
  2077 +
  2078 + if (dc->condjmp && !dc->is_jmp) {
  2079 + gen_set_label(dc->condlabel);
  2080 + dc->condjmp = 0;
  2081 + }
  2082 + /* Translation stops when a conditional branch is enoutered.
  2083 + * Otherwise the subsequent code could get translated several times.
  2084 + */
2064 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end && 2085 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2065 !env->singlestep_enabled && 2086 !env->singlestep_enabled &&
2066 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32)); 2087 (dc->pc - pc_start) < (TARGET_PAGE_SIZE - 32));
  2088 + /* It this stage dc->condjmp will only be set when the skipped
  2089 + * instruction was a conditional branch, and teh PC has already been
  2090 + * written. */
2067 if (__builtin_expect(env->singlestep_enabled, 0)) { 2091 if (__builtin_expect(env->singlestep_enabled, 0)) {
2068 /* Make sure the pc is updated, and raise a debug exception. */ 2092 /* Make sure the pc is updated, and raise a debug exception. */
2069 - if (dc->is_jmp == DISAS_NEXT || dc->is_jmp == DISAS_JUMP_NEXT) { 2093 + if (dc->condjmp) {
  2094 + gen_op_debug();
  2095 + gen_set_label(dc->condlabel);
  2096 + }
  2097 + if (dc->condjmp || !dc->is_jmp) {
2070 gen_op_movl_T0_im((long)dc->pc); 2098 gen_op_movl_T0_im((long)dc->pc);
2071 gen_op_movl_reg_TN[0][15](); 2099 gen_op_movl_reg_TN[0][15]();
  2100 + dc->condjmp = 0;
2072 } 2101 }
2073 gen_op_debug(); 2102 gen_op_debug();
2074 } else { 2103 } else {
2075 switch(dc->is_jmp) { 2104 switch(dc->is_jmp) {
2076 - case DISAS_JUMP_NEXT:  
2077 case DISAS_NEXT: 2105 case DISAS_NEXT:
2078 - gen_op_jmp((long)dc->tb, (long)dc->pc); 2106 + gen_op_jmp1((long)dc->tb, (long)dc->pc);
2079 break; 2107 break;
2080 default: 2108 default:
2081 case DISAS_JUMP: 2109 case DISAS_JUMP:
@@ -2088,6 +2116,11 @@ static inline int gen_intermediate_code_internal(CPUState *env, @@ -2088,6 +2116,11 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2088 /* nothing more to generate */ 2116 /* nothing more to generate */
2089 break; 2117 break;
2090 } 2118 }
  2119 + if (dc->condjmp) {
  2120 + gen_set_label(dc->condlabel);
  2121 + gen_op_jmp1((long)dc->tb, (long)dc->pc);
  2122 + dc->condjmp = 0;
  2123 + }
2091 } 2124 }
2092 *gen_opc_ptr = INDEX_op_end; 2125 *gen_opc_ptr = INDEX_op_end;
2093 2126