CRIS: Slight performance improvement for flag evaluation.
authoredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 7 Jan 2009 12:25:15 +0000 (12:25 +0000)
committeredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>
Wed, 7 Jan 2009 12:25:15 +0000 (12:25 +0000)
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
target-cris/op_helper.c
target-cris/translate.c

index 9034a61..e468439 100644 (file)
@@ -14,6 +14,7 @@ DEF_HELPER_0(evaluate_flags_muls, void)
 DEF_HELPER_0(evaluate_flags_mulu, void)
 DEF_HELPER_0(evaluate_flags_mcp, void)
 DEF_HELPER_0(evaluate_flags_alu_4, void)
+DEF_HELPER_0(evaluate_flags_sub_4, void)
 DEF_HELPER_0(evaluate_flags_move_4, void)
 DEF_HELPER_0(evaluate_flags_move_2, void)
 DEF_HELPER_0(evaluate_flags, void)
index 5db4575..51323a2 100644 (file)
@@ -245,17 +245,19 @@ void helper_rfn(void)
 
 static void evaluate_flags_writeback(uint32_t flags)
 {
-       int x;
+       unsigned int x, z, mask;
 
        /* Extended arithmetics, leave the z flag alone.  */
        x = env->cc_x;
-       if ((x || env->cc_op == CC_OP_ADDC)
-           && flags & Z_FLAG)
-               env->cc_mask &= ~Z_FLAG;
+       mask = env->cc_mask | X_FLAG;
+        if (x) {
+               z = flags & Z_FLAG;
+               mask = mask & ~z;
+       }
+       flags &= mask;
 
        /* all insn clear the x-flag except setf or clrf.  */
-       env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG);
-       flags &= env->cc_mask;
+       env->pregs[PR_CCS] &= ~mask;
        env->pregs[PR_CCS] |= flags;
 }
 
@@ -323,33 +325,25 @@ void  helper_evaluate_flags_mcp(void)
        uint32_t res;
        uint32_t flags = 0;
 
-       src = env->cc_src;
-       dst = env->cc_dest;
+       src = env->cc_src & 0x80000000;
+       dst = env->cc_dest & 0x80000000;
        res = env->cc_result;
 
        if ((res & 0x80000000L) != 0L)
        {
                flags |= N_FLAG;
-               if (((src & 0x80000000L) == 0L)
-                   && ((dst & 0x80000000L) == 0L))
-               {
+               if (!src && !dst)
                        flags |= V_FLAG;
-               }
-               else if (((src & 0x80000000L) != 0L) &&
-                        ((dst & 0x80000000L) != 0L))
-               {
+               else if (src & dst)
                        flags |= R_FLAG;
-               }
        }
        else
        {
                if (res == 0L)
                        flags |= Z_FLAG;
-               if (((src & 0x80000000L) != 0L)
-                   && ((dst & 0x80000000L) != 0L))
+               if (src & dst) 
                        flags |= V_FLAG;
-               if ((dst & 0x80000000L) != 0L
-                   || (src & 0x80000000L) != 0L)
+               if (dst | src) 
                        flags |= R_FLAG;
        }
 
@@ -363,56 +357,61 @@ void  helper_evaluate_flags_alu_4(void)
        uint32_t res;
        uint32_t flags = 0;
 
-       src = env->cc_src;
-       dst = env->cc_dest;
+       src = env->cc_src & 0x80000000;
+       dst = env->cc_dest & 0x80000000;
+       res = env->cc_result;
 
-       /* Reconstruct the result.  */
-       switch (env->cc_op)
+       if ((res & 0x80000000L) != 0L)
        {
-               case CC_OP_SUB:
-                       res = dst - src;
-                       break;
-               case CC_OP_ADD:
-                       res = dst + src;
-                       break;
-               default:
-                       res = env->cc_result;
-                       break;
+               flags |= N_FLAG;
+               if (!src && !dst)
+                       flags |= V_FLAG;
+               else if (src & dst)
+                       flags |= C_FLAG;
+       }
+       else
+       {
+               if (res == 0L)
+                       flags |= Z_FLAG;
+               if (src & dst) 
+                       flags |= V_FLAG;
+               if (dst | src) 
+                       flags |= C_FLAG;
        }
 
-       if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
-               src = ~src;
+       evaluate_flags_writeback(flags);
+}
+
+void  helper_evaluate_flags_sub_4(void)
+{
+       uint32_t src;
+       uint32_t dst;
+       uint32_t res;
+       uint32_t flags = 0;
+
+       src = (~env->cc_src) & 0x80000000;
+       dst = env->cc_dest & 0x80000000;
+       res = env->cc_result;
 
        if ((res & 0x80000000L) != 0L)
        {
                flags |= N_FLAG;
-               if (((src & 0x80000000L) == 0L)
-                   && ((dst & 0x80000000L) == 0L))
-               {
+               if (!src && !dst)
                        flags |= V_FLAG;
-               }
-               else if (((src & 0x80000000L) != 0L) &&
-                        ((dst & 0x80000000L) != 0L))
-               {
+               else if (src & dst)
                        flags |= C_FLAG;
-               }
        }
        else
        {
                if (res == 0L)
                        flags |= Z_FLAG;
-               if (((src & 0x80000000L) != 0L)
-                   && ((dst & 0x80000000L) != 0L))
+               if (src & dst) 
                        flags |= V_FLAG;
-               if ((dst & 0x80000000L) != 0L
-                   || (src & 0x80000000L) != 0L)
+               if (dst | src) 
                        flags |= C_FLAG;
        }
 
-       if (env->cc_op == CC_OP_SUB
-           || env->cc_op == CC_OP_CMP) {
-               flags ^= C_FLAG;
-       }
+       flags ^= C_FLAG;
        evaluate_flags_writeback(flags);
 }
 
@@ -607,6 +606,13 @@ void helper_top_evaluate_flags(void)
                case CC_OP_FLAGS:
                        /* live.  */
                        break;
+               case CC_OP_SUB:
+               case CC_OP_CMP:
+                       if (env->cc_size == 4)
+                               helper_evaluate_flags_sub_4();
+                       else
+                               helper_evaluate_flags();
+                       break;
                default:
                {
                        switch (env->cc_size)
index 6a8c355..24ae03c 100644 (file)
@@ -728,8 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc)
                        case CC_OP_FLAGS:
                                /* live.  */
                                break;
+                       case CC_OP_SUB:
+                       case CC_OP_CMP:
+                               if (dc->cc_size == 4)
+                                       gen_helper_evaluate_flags_sub_4();
+                               else
+                                       gen_helper_evaluate_flags();
+
+                               break;
                        default:
-                       {
                                switch (dc->cc_size)
                                {
                                        case 4:
@@ -739,7 +746,6 @@ static void cris_evaluate_flags(DisasContext *dc)
                                                gen_helper_evaluate_flags();
                                                break;
                                }
-                       }
                        break;
                }
                if (dc->flagx_known) {
@@ -821,13 +827,8 @@ static void cris_pre_alu_update_cc(DisasContext *dc, int op,
 /* Update cc after executing ALU op. needs the result.  */
 static inline void cris_update_result(DisasContext *dc, TCGv res)
 {
-       if (dc->update_cc) {
-               if (dc->cc_size == 4 && 
-                   (dc->cc_op == CC_OP_SUB
-                    || dc->cc_op == CC_OP_ADD))
-                       return;
+       if (dc->update_cc)
                tcg_gen_mov_tl(cc_result, res);
-       }
 }
 
 /* Returns one if the write back stage should execute.  */
@@ -1890,6 +1891,10 @@ static unsigned int dec_addc_r(DisasContext *dc)
        DIS(fprintf (logfile, "addc $r%u, $r%u\n",
                    dc->op1, dc->op2));
        cris_evaluate_flags(dc);
+       /* Set for this insn.  */
+       dc->flagx_known = 1;
+       dc->flags_x = X_FLAG;
+
        cris_cc_mask(dc, CC_MASK_NZVC);
        cris_alu(dc, CC_OP_ADDC,
                 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)
                    dc->op2));
 
        cris_evaluate_flags(dc);
+
+       /* Set for this insn.  */
+       dc->flagx_known = 1;
+       dc->flags_x = X_FLAG;
+
        cris_alu_m_alloc_temps(t);
        insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
        cris_cc_mask(dc, CC_MASK_NZVC);