mirror of https://github.com/xemu-project/xemu.git
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:
parent
10c144e2fb
commit
a8cf66bb39
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue