Commit a8cf66bb393ff420d40ae172a4c817bf2752918a

Authored by edgar_igl
1 parent 10c144e2

CRIS: Slight performance improvement for flag evaluation.

Translate sub and cmp ops separately when evaluating flags to avoid checking
for them at runtime.

Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6198 c046a42c-6fe2-441c-8c8c-71466251a162
target-cris/helper.h
... ... @@ -14,6 +14,7 @@ DEF_HELPER_0(evaluate_flags_muls, void)
14 14 DEF_HELPER_0(evaluate_flags_mulu, void)
15 15 DEF_HELPER_0(evaluate_flags_mcp, void)
16 16 DEF_HELPER_0(evaluate_flags_alu_4, void)
  17 +DEF_HELPER_0(evaluate_flags_sub_4, void)
17 18 DEF_HELPER_0(evaluate_flags_move_4, void)
18 19 DEF_HELPER_0(evaluate_flags_move_2, void)
19 20 DEF_HELPER_0(evaluate_flags, void)
... ...
target-cris/op_helper.c
... ... @@ -245,17 +245,19 @@ void helper_rfn(void)
245 245  
246 246 static void evaluate_flags_writeback(uint32_t flags)
247 247 {
248   - int x;
  248 + unsigned int x, z, mask;
249 249  
250 250 /* Extended arithmetics, leave the z flag alone. */
251 251 x = env->cc_x;
252   - if ((x || env->cc_op == CC_OP_ADDC)
253   - && flags & Z_FLAG)
254   - env->cc_mask &= ~Z_FLAG;
  252 + mask = env->cc_mask | X_FLAG;
  253 + if (x) {
  254 + z = flags & Z_FLAG;
  255 + mask = mask & ~z;
  256 + }
  257 + flags &= mask;
255 258  
256 259 /* all insn clear the x-flag except setf or clrf. */
257   - env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
258   - flags &= env->cc_mask;
  260 + env->pregs[PR_CCS] &= ~mask;
259 261 env->pregs[PR_CCS] |= flags;
260 262 }
261 263  
... ... @@ -323,33 +325,25 @@ void helper_evaluate_flags_mcp(void)
323 325 uint32_t res;
324 326 uint32_t flags = 0;
325 327  
326   - src = env->cc_src;
327   - dst = env->cc_dest;
  328 + src = env->cc_src & 0x80000000;
  329 + dst = env->cc_dest & 0x80000000;
328 330 res = env->cc_result;
329 331  
330 332 if ((res & 0x80000000L) != 0L)
331 333 {
332 334 flags |= N_FLAG;
333   - if (((src & 0x80000000L) == 0L)
334   - && ((dst & 0x80000000L) == 0L))
335   - {
  335 + if (!src && !dst)
336 336 flags |= V_FLAG;
337   - }
338   - else if (((src & 0x80000000L) != 0L) &&
339   - ((dst & 0x80000000L) != 0L))
340   - {
  337 + else if (src & dst)
341 338 flags |= R_FLAG;
342   - }
343 339 }
344 340 else
345 341 {
346 342 if (res == 0L)
347 343 flags |= Z_FLAG;
348   - if (((src & 0x80000000L) != 0L)
349   - && ((dst & 0x80000000L) != 0L))
  344 + if (src & dst)
350 345 flags |= V_FLAG;
351   - if ((dst & 0x80000000L) != 0L
352   - || (src & 0x80000000L) != 0L)
  346 + if (dst | src)
353 347 flags |= R_FLAG;
354 348 }
355 349  
... ... @@ -363,56 +357,61 @@ void helper_evaluate_flags_alu_4(void)
363 357 uint32_t res;
364 358 uint32_t flags = 0;
365 359  
366   - src = env->cc_src;
367   - dst = env->cc_dest;
  360 + src = env->cc_src & 0x80000000;
  361 + dst = env->cc_dest & 0x80000000;
  362 + res = env->cc_result;
368 363  
369   - /* Reconstruct the result. */
370   - switch (env->cc_op)
  364 + if ((res & 0x80000000L) != 0L)
371 365 {
372   - case CC_OP_SUB:
373   - res = dst - src;
374   - break;
375   - case CC_OP_ADD:
376   - res = dst + src;
377   - break;
378   - default:
379   - res = env->cc_result;
380   - break;
  366 + flags |= N_FLAG;
  367 + if (!src && !dst)
  368 + flags |= V_FLAG;
  369 + else if (src & dst)
  370 + flags |= C_FLAG;
  371 + }
  372 + else
  373 + {
  374 + if (res == 0L)
  375 + flags |= Z_FLAG;
  376 + if (src & dst)
  377 + flags |= V_FLAG;
  378 + if (dst | src)
  379 + flags |= C_FLAG;
381 380 }
382 381  
383   - if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
384   - src = ~src;
  382 + evaluate_flags_writeback(flags);
  383 +}
  384 +
  385 +void helper_evaluate_flags_sub_4(void)
  386 +{
  387 + uint32_t src;
  388 + uint32_t dst;
  389 + uint32_t res;
  390 + uint32_t flags = 0;
  391 +
  392 + src = (~env->cc_src) & 0x80000000;
  393 + dst = env->cc_dest & 0x80000000;
  394 + res = env->cc_result;
385 395  
386 396 if ((res & 0x80000000L) != 0L)
387 397 {
388 398 flags |= N_FLAG;
389   - if (((src & 0x80000000L) == 0L)
390   - && ((dst & 0x80000000L) == 0L))
391   - {
  399 + if (!src && !dst)
392 400 flags |= V_FLAG;
393   - }
394   - else if (((src & 0x80000000L) != 0L) &&
395   - ((dst & 0x80000000L) != 0L))
396   - {
  401 + else if (src & dst)
397 402 flags |= C_FLAG;
398   - }
399 403 }
400 404 else
401 405 {
402 406 if (res == 0L)
403 407 flags |= Z_FLAG;
404   - if (((src & 0x80000000L) != 0L)
405   - && ((dst & 0x80000000L) != 0L))
  408 + if (src & dst)
406 409 flags |= V_FLAG;
407   - if ((dst & 0x80000000L) != 0L
408   - || (src & 0x80000000L) != 0L)
  410 + if (dst | src)
409 411 flags |= C_FLAG;
410 412 }
411 413  
412   - if (env->cc_op == CC_OP_SUB
413   - || env->cc_op == CC_OP_CMP) {
414   - flags ^= C_FLAG;
415   - }
  414 + flags ^= C_FLAG;
416 415 evaluate_flags_writeback(flags);
417 416 }
418 417  
... ... @@ -607,6 +606,13 @@ void helper_top_evaluate_flags(void)
607 606 case CC_OP_FLAGS:
608 607 /* live. */
609 608 break;
  609 + case CC_OP_SUB:
  610 + case CC_OP_CMP:
  611 + if (env->cc_size == 4)
  612 + helper_evaluate_flags_sub_4();
  613 + else
  614 + helper_evaluate_flags();
  615 + break;
610 616 default:
611 617 {
612 618 switch (env->cc_size)
... ...
target-cris/translate.c
... ... @@ -728,8 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc)
728 728 case CC_OP_FLAGS:
729 729 /* live. */
730 730 break;
  731 + case CC_OP_SUB:
  732 + case CC_OP_CMP:
  733 + if (dc->cc_size == 4)
  734 + gen_helper_evaluate_flags_sub_4();
  735 + else
  736 + gen_helper_evaluate_flags();
  737 +
  738 + break;
731 739 default:
732   - {
733 740 switch (dc->cc_size)
734 741 {
735 742 case 4:
... ... @@ -739,7 +746,6 @@ static void cris_evaluate_flags(DisasContext *dc)
739 746 gen_helper_evaluate_flags();
740 747 break;
741 748 }
742   - }
743 749 break;
744 750 }
745 751 if (dc->flagx_known) {
... ... @@ -821,13 +827,8 @@ static void cris_pre_alu_update_cc(DisasContext *dc, int op,
821 827 /* Update cc after executing ALU op. needs the result. */
822 828 static inline void cris_update_result(DisasContext *dc, TCGv res)
823 829 {
824   - if (dc->update_cc) {
825   - if (dc->cc_size == 4 &&
826   - (dc->cc_op == CC_OP_SUB
827   - || dc->cc_op == CC_OP_ADD))
828   - return;
  830 + if (dc->update_cc)
829 831 tcg_gen_mov_tl(cc_result, res);
830   - }
831 832 }
832 833  
833 834 /* Returns one if the write back stage should execute. */
... ... @@ -1890,6 +1891,10 @@ static unsigned int dec_addc_r(DisasContext *dc)
1890 1891 DIS(fprintf (logfile, "addc $r%u, $r%u\n",
1891 1892 dc->op1, dc->op2));
1892 1893 cris_evaluate_flags(dc);
  1894 + /* Set for this insn. */
  1895 + dc->flagx_known = 1;
  1896 + dc->flags_x = X_FLAG;
  1897 +
1893 1898 cris_cc_mask(dc, CC_MASK_NZVC);
1894 1899 cris_alu(dc, CC_OP_ADDC,
1895 1900 cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4);
... ... @@ -2615,6 +2620,11 @@ static unsigned int dec_addc_mr(DisasContext *dc)
2615 2620 dc->op2));
2616 2621  
2617 2622 cris_evaluate_flags(dc);
  2623 +
  2624 + /* Set for this insn. */
  2625 + dc->flagx_known = 1;
  2626 + dc->flags_x = X_FLAG;
  2627 +
2618 2628 cris_alu_m_alloc_temps(t);
2619 2629 insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
2620 2630 cris_cc_mask(dc, CC_MASK_NZVC);
... ...