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
This commit is contained in:
edgar_igl 2009-01-07 12:25:15 +00:00
parent 10c144e2fb
commit a8cf66bb39
3 changed files with 79 additions and 62 deletions

View File

@ -14,6 +14,7 @@ DEF_HELPER_0(evaluate_flags_muls, void)
DEF_HELPER_0(evaluate_flags_mulu, void) DEF_HELPER_0(evaluate_flags_mulu, void)
DEF_HELPER_0(evaluate_flags_mcp, void) DEF_HELPER_0(evaluate_flags_mcp, void)
DEF_HELPER_0(evaluate_flags_alu_4, 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_4, void)
DEF_HELPER_0(evaluate_flags_move_2, void) DEF_HELPER_0(evaluate_flags_move_2, void)
DEF_HELPER_0(evaluate_flags, void) DEF_HELPER_0(evaluate_flags, void)

View File

@ -245,17 +245,19 @@ void helper_rfn(void)
static void evaluate_flags_writeback(uint32_t flags) static void evaluate_flags_writeback(uint32_t flags)
{ {
int x; unsigned int x, z, mask;
/* Extended arithmetics, leave the z flag alone. */ /* Extended arithmetics, leave the z flag alone. */
x = env->cc_x; x = env->cc_x;
if ((x || env->cc_op == CC_OP_ADDC) mask = env->cc_mask | X_FLAG;
&& flags & Z_FLAG) if (x) {
env->cc_mask &= ~Z_FLAG; z = flags & Z_FLAG;
mask = mask & ~z;
}
flags &= mask;
/* all insn clear the x-flag except setf or clrf. */ /* all insn clear the x-flag except setf or clrf. */
env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG); env->pregs[PR_CCS] &= ~mask;
flags &= env->cc_mask;
env->pregs[PR_CCS] |= flags; env->pregs[PR_CCS] |= flags;
} }
@ -323,33 +325,25 @@ void helper_evaluate_flags_mcp(void)
uint32_t res; uint32_t res;
uint32_t flags = 0; uint32_t flags = 0;
src = env->cc_src; src = env->cc_src & 0x80000000;
dst = env->cc_dest; dst = env->cc_dest & 0x80000000;
res = env->cc_result; res = env->cc_result;
if ((res & 0x80000000L) != 0L) if ((res & 0x80000000L) != 0L)
{ {
flags |= N_FLAG; flags |= N_FLAG;
if (((src & 0x80000000L) == 0L) if (!src && !dst)
&& ((dst & 0x80000000L) == 0L))
{
flags |= V_FLAG; flags |= V_FLAG;
} else if (src & dst)
else if (((src & 0x80000000L) != 0L) &&
((dst & 0x80000000L) != 0L))
{
flags |= R_FLAG; flags |= R_FLAG;
}
} }
else else
{ {
if (res == 0L) if (res == 0L)
flags |= Z_FLAG; flags |= Z_FLAG;
if (((src & 0x80000000L) != 0L) if (src & dst)
&& ((dst & 0x80000000L) != 0L))
flags |= V_FLAG; flags |= V_FLAG;
if ((dst & 0x80000000L) != 0L if (dst | src)
|| (src & 0x80000000L) != 0L)
flags |= R_FLAG; flags |= R_FLAG;
} }
@ -363,56 +357,61 @@ void helper_evaluate_flags_alu_4(void)
uint32_t res; uint32_t res;
uint32_t flags = 0; uint32_t flags = 0;
src = env->cc_src; src = env->cc_src & 0x80000000;
dst = env->cc_dest; dst = env->cc_dest & 0x80000000;
res = env->cc_result;
/* Reconstruct the result. */
switch (env->cc_op)
{
case CC_OP_SUB:
res = dst - src;
break;
case CC_OP_ADD:
res = dst + src;
break;
default:
res = env->cc_result;
break;
}
if (env->cc_op == CC_OP_SUB || env->cc_op == CC_OP_CMP)
src = ~src;
if ((res & 0x80000000L) != 0L) if ((res & 0x80000000L) != 0L)
{ {
flags |= N_FLAG; flags |= N_FLAG;
if (((src & 0x80000000L) == 0L) if (!src && !dst)
&& ((dst & 0x80000000L) == 0L))
{
flags |= V_FLAG; flags |= V_FLAG;
} else if (src & dst)
else if (((src & 0x80000000L) != 0L) &&
((dst & 0x80000000L) != 0L))
{
flags |= C_FLAG; flags |= C_FLAG;
}
} }
else else
{ {
if (res == 0L) if (res == 0L)
flags |= Z_FLAG; flags |= Z_FLAG;
if (((src & 0x80000000L) != 0L) if (src & dst)
&& ((dst & 0x80000000L) != 0L))
flags |= V_FLAG; flags |= V_FLAG;
if ((dst & 0x80000000L) != 0L if (dst | src)
|| (src & 0x80000000L) != 0L)
flags |= C_FLAG; flags |= C_FLAG;
} }
if (env->cc_op == CC_OP_SUB evaluate_flags_writeback(flags);
|| env->cc_op == CC_OP_CMP) { }
flags ^= C_FLAG;
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 && !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;
}
flags ^= C_FLAG;
evaluate_flags_writeback(flags); evaluate_flags_writeback(flags);
} }
@ -607,6 +606,13 @@ void helper_top_evaluate_flags(void)
case CC_OP_FLAGS: case CC_OP_FLAGS:
/* live. */ /* live. */
break; 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: default:
{ {
switch (env->cc_size) switch (env->cc_size)

View File

@ -728,8 +728,15 @@ static void cris_evaluate_flags(DisasContext *dc)
case CC_OP_FLAGS: case CC_OP_FLAGS:
/* live. */ /* live. */
break; 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: default:
{
switch (dc->cc_size) switch (dc->cc_size)
{ {
case 4: case 4:
@ -739,7 +746,6 @@ static void cris_evaluate_flags(DisasContext *dc)
gen_helper_evaluate_flags(); gen_helper_evaluate_flags();
break; break;
} }
}
break; break;
} }
if (dc->flagx_known) { 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. */ /* Update cc after executing ALU op. needs the result. */
static inline void cris_update_result(DisasContext *dc, TCGv res) static inline void cris_update_result(DisasContext *dc, TCGv res)
{ {
if (dc->update_cc) { if (dc->update_cc)
if (dc->cc_size == 4 &&
(dc->cc_op == CC_OP_SUB
|| dc->cc_op == CC_OP_ADD))
return;
tcg_gen_mov_tl(cc_result, res); tcg_gen_mov_tl(cc_result, res);
}
} }
/* Returns one if the write back stage should execute. */ /* 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", DIS(fprintf (logfile, "addc $r%u, $r%u\n",
dc->op1, dc->op2)); dc->op1, dc->op2));
cris_evaluate_flags(dc); 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_cc_mask(dc, CC_MASK_NZVC);
cris_alu(dc, CC_OP_ADDC, cris_alu(dc, CC_OP_ADDC,
cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op1], 4); 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)); dc->op2));
cris_evaluate_flags(dc); cris_evaluate_flags(dc);
/* Set for this insn. */
dc->flagx_known = 1;
dc->flags_x = X_FLAG;
cris_alu_m_alloc_temps(t); cris_alu_m_alloc_temps(t);
insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]); insn_len = dec_prep_alu_m(dc, 0, 4, t[0], t[1]);
cris_cc_mask(dc, CC_MASK_NZVC); cris_cc_mask(dc, CC_MASK_NZVC);