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 251 void OPPROTO op_test_eq(void)
252 252 {
253 253 if (env->NZF == 0)
254   - JUMP_TB(op_test_eq, PARAM1, 0, PARAM2);
  254 + GOTO_LABEL_PARAM(1);;
255 255 FORCE_RET();
256 256 }
257 257  
258 258 void OPPROTO op_test_ne(void)
259 259 {
260 260 if (env->NZF != 0)
261   - JUMP_TB(op_test_ne, PARAM1, 0, PARAM2);
  261 + GOTO_LABEL_PARAM(1);;
262 262 FORCE_RET();
263 263 }
264 264  
265 265 void OPPROTO op_test_cs(void)
266 266 {
267 267 if (env->CF != 0)
268   - JUMP_TB(op_test_cs, PARAM1, 0, PARAM2);
  268 + GOTO_LABEL_PARAM(1);
269 269 FORCE_RET();
270 270 }
271 271  
272 272 void OPPROTO op_test_cc(void)
273 273 {
274 274 if (env->CF == 0)
275   - JUMP_TB(op_test_cc, PARAM1, 0, PARAM2);
  275 + GOTO_LABEL_PARAM(1);
276 276 FORCE_RET();
277 277 }
278 278  
279 279 void OPPROTO op_test_mi(void)
280 280 {
281 281 if ((env->NZF & 0x80000000) != 0)
282   - JUMP_TB(op_test_mi, PARAM1, 0, PARAM2);
  282 + GOTO_LABEL_PARAM(1);
283 283 FORCE_RET();
284 284 }
285 285  
286 286 void OPPROTO op_test_pl(void)
287 287 {
288 288 if ((env->NZF & 0x80000000) == 0)
289   - JUMP_TB(op_test_pl, PARAM1, 0, PARAM2);
  289 + GOTO_LABEL_PARAM(1);
290 290 FORCE_RET();
291 291 }
292 292  
293 293 void OPPROTO op_test_vs(void)
294 294 {
295 295 if ((env->VF & 0x80000000) != 0)
296   - JUMP_TB(op_test_vs, PARAM1, 0, PARAM2);
  296 + GOTO_LABEL_PARAM(1);
297 297 FORCE_RET();
298 298 }
299 299  
300 300 void OPPROTO op_test_vc(void)
301 301 {
302 302 if ((env->VF & 0x80000000) == 0)
303   - JUMP_TB(op_test_vc, PARAM1, 0, PARAM2);
  303 + GOTO_LABEL_PARAM(1);
304 304 FORCE_RET();
305 305 }
306 306  
307 307 void OPPROTO op_test_hi(void)
308 308 {
309 309 if (env->CF != 0 && env->NZF != 0)
310   - JUMP_TB(op_test_hi, PARAM1, 0, PARAM2);
  310 + GOTO_LABEL_PARAM(1);
311 311 FORCE_RET();
312 312 }
313 313  
314 314 void OPPROTO op_test_ls(void)
315 315 {
316 316 if (env->CF == 0 || env->NZF == 0)
317   - JUMP_TB(op_test_ls, PARAM1, 0, PARAM2);
  317 + GOTO_LABEL_PARAM(1);
318 318 FORCE_RET();
319 319 }
320 320  
321 321 void OPPROTO op_test_ge(void)
322 322 {
323 323 if (((env->VF ^ env->NZF) & 0x80000000) == 0)
324   - JUMP_TB(op_test_ge, PARAM1, 0, PARAM2);
  324 + GOTO_LABEL_PARAM(1);
325 325 FORCE_RET();
326 326 }
327 327  
328 328 void OPPROTO op_test_lt(void)
329 329 {
330 330 if (((env->VF ^ env->NZF) & 0x80000000) != 0)
331   - JUMP_TB(op_test_lt, PARAM1, 0, PARAM2);
  331 + GOTO_LABEL_PARAM(1);
332 332 FORCE_RET();
333 333 }
334 334  
335 335 void OPPROTO op_test_gt(void)
336 336 {
337 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 339 FORCE_RET();
340 340 }
341 341  
342 342 void OPPROTO op_test_le(void)
343 343 {
344 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 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 359 void OPPROTO op_exit_tb(void)
... ...
target-arm/translate.c
... ... @@ -32,6 +32,10 @@
32 32 typedef struct DisasContext {
33 33 target_ulong pc;
34 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 39 struct TranslationBlock *tb;
36 40 int singlestep_enabled;
37 41 } DisasContext;
... ... @@ -53,7 +57,7 @@ enum {
53 57  
54 58 #include "gen-op.h"
55 59  
56   -static GenOpFunc2 *gen_test_cc[14] = {
  60 +static GenOpFunc1 *gen_test_cc[14] = {
57 61 gen_op_test_eq,
58 62 gen_op_test_ne,
59 63 gen_op_test_cs,
... ... @@ -896,7 +900,7 @@ static inline void gen_jmp (DisasContext *s, uint32_t dest)
896 900 gen_op_movl_T0_im(dest);
897 901 gen_bx(s);
898 902 } else {
899   - gen_op_jmp((long)s->tb, dest);
  903 + gen_op_jmp0((long)s->tb, dest);
900 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 943 if (cond != 0xe) {
940 944 /* if not always execute, we generate a conditional jump to
941 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 952 if ((insn & 0x0f900000) == 0x03000000) {
946 953 if ((insn & 0x0ff0f000) != 0x0360f000)
... ... @@ -1961,8 +1968,11 @@ static void disas_thumb_insn(DisasContext *s)
1961 1968 break;
1962 1969 }
1963 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 1976 gen_movl_T1_reg(s, 15);
1967 1977  
1968 1978 /* jump to the offset */
... ... @@ -2034,6 +2044,8 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2034 2044 dc->is_jmp = DISAS_NEXT;
2035 2045 dc->pc = pc_start;
2036 2046 dc->singlestep_enabled = env->singlestep_enabled;
  2047 + dc->condjmp = 0;
  2048 + nb_gen_labels = 0;
2037 2049 lj = -1;
2038 2050 do {
2039 2051 if (env->nb_breakpoints > 0) {
... ... @@ -2057,25 +2069,41 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2057 2069 gen_opc_pc[lj] = dc->pc;
2058 2070 gen_opc_instr_start[lj] = 1;
2059 2071 }
  2072 +
2060 2073 if (env->thumb)
2061 2074 disas_thumb_insn(dc);
2062 2075 else
2063 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 2085 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
2065 2086 !env->singlestep_enabled &&
2066 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 2091 if (__builtin_expect(env->singlestep_enabled, 0)) {
2068 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 2098 gen_op_movl_T0_im((long)dc->pc);
2071 2099 gen_op_movl_reg_TN[0][15]();
  2100 + dc->condjmp = 0;
2072 2101 }
2073 2102 gen_op_debug();
2074 2103 } else {
2075 2104 switch(dc->is_jmp) {
2076   - case DISAS_JUMP_NEXT:
2077 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 2107 break;
2080 2108 default:
2081 2109 case DISAS_JUMP:
... ... @@ -2088,6 +2116,11 @@ static inline int gen_intermediate_code_internal(CPUState *env,
2088 2116 /* nothing more to generate */
2089 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 2125 *gen_opc_ptr = INDEX_op_end;
2093 2126  
... ...