CRIS: Speedup btst by using a helper.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6203 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
4a1e6beab6
commit
abd5c94ee1
@ -10,6 +10,8 @@ DEF_HELPER_0(rfn, void);
|
|||||||
DEF_HELPER_2(movl_sreg_reg, void, i32, i32)
|
DEF_HELPER_2(movl_sreg_reg, void, i32, i32)
|
||||||
DEF_HELPER_2(movl_reg_sreg, void, i32, i32)
|
DEF_HELPER_2(movl_reg_sreg, void, i32, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_FLAGS_3(btst, TCG_CALL_PURE, i32, i32, i32, i32);
|
||||||
|
|
||||||
DEF_HELPER_0(evaluate_flags_muls, void)
|
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)
|
||||||
|
@ -243,6 +243,32 @@ void helper_rfn(void)
|
|||||||
env->pregs[PR_CCS] |= M_FLAG;
|
env->pregs[PR_CCS] |= M_FLAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t helper_btst(uint32_t t0, uint32_t t1, uint32_t ccs)
|
||||||
|
{
|
||||||
|
/* FIXME: clean this up. */
|
||||||
|
|
||||||
|
/* des ref:
|
||||||
|
The N flag is set according to the selected bit in the dest reg.
|
||||||
|
The Z flag is set if the selected bit and all bits to the right are
|
||||||
|
zero.
|
||||||
|
The X flag is cleared.
|
||||||
|
Other flags are left untouched.
|
||||||
|
The destination reg is not affected.*/
|
||||||
|
unsigned int fz, sbit, bset, mask, masked_t0;
|
||||||
|
|
||||||
|
sbit = t1 & 31;
|
||||||
|
bset = !!(t0 & (1 << sbit));
|
||||||
|
mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
|
||||||
|
masked_t0 = t0 & mask;
|
||||||
|
fz = !(masked_t0 | bset);
|
||||||
|
|
||||||
|
/* Clear the X, N and Z flags. */
|
||||||
|
ccs = ccs & ~(X_FLAG | N_FLAG | Z_FLAG);
|
||||||
|
/* Set the N and Z flags accordingly. */
|
||||||
|
ccs |= (bset << 3) | (fz << 2);
|
||||||
|
return ccs;
|
||||||
|
}
|
||||||
|
|
||||||
static void evaluate_flags_writeback(uint32_t flags)
|
static void evaluate_flags_writeback(uint32_t flags)
|
||||||
{
|
{
|
||||||
unsigned int x, z, mask;
|
unsigned int x, z, mask;
|
||||||
|
@ -388,64 +388,6 @@ static void t_gen_lz_i32(TCGv d, TCGv x)
|
|||||||
tcg_temp_free(n);
|
tcg_temp_free(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void t_gen_btst(TCGv d, TCGv a, TCGv b)
|
|
||||||
{
|
|
||||||
TCGv sbit;
|
|
||||||
TCGv bset;
|
|
||||||
TCGv t0;
|
|
||||||
int l1;
|
|
||||||
|
|
||||||
/* des ref:
|
|
||||||
The N flag is set according to the selected bit in the dest reg.
|
|
||||||
The Z flag is set if the selected bit and all bits to the right are
|
|
||||||
zero.
|
|
||||||
The X flag is cleared.
|
|
||||||
Other flags are left untouched.
|
|
||||||
The destination reg is not affected.
|
|
||||||
|
|
||||||
unsigned int fz, sbit, bset, mask, masked_t0;
|
|
||||||
|
|
||||||
sbit = T1 & 31;
|
|
||||||
bset = !!(T0 & (1 << sbit));
|
|
||||||
mask = sbit == 31 ? -1 : (1 << (sbit + 1)) - 1;
|
|
||||||
masked_t0 = T0 & mask;
|
|
||||||
fz = !(masked_t0 | bset);
|
|
||||||
|
|
||||||
// Clear the X, N and Z flags.
|
|
||||||
T0 = env->pregs[PR_CCS] & ~(X_FLAG | N_FLAG | Z_FLAG);
|
|
||||||
// Set the N and Z flags accordingly.
|
|
||||||
T0 |= (bset << 3) | (fz << 2);
|
|
||||||
*/
|
|
||||||
|
|
||||||
l1 = gen_new_label();
|
|
||||||
sbit = tcg_temp_new();
|
|
||||||
bset = tcg_temp_new();
|
|
||||||
t0 = tcg_temp_new();
|
|
||||||
|
|
||||||
/* Compute bset and sbit. */
|
|
||||||
tcg_gen_andi_tl(sbit, b, 31);
|
|
||||||
tcg_gen_shl_tl(t0, tcg_const_tl(1), sbit);
|
|
||||||
tcg_gen_and_tl(bset, a, t0);
|
|
||||||
tcg_gen_shr_tl(bset, bset, sbit);
|
|
||||||
/* Displace to N_FLAG. */
|
|
||||||
tcg_gen_shli_tl(bset, bset, 3);
|
|
||||||
|
|
||||||
tcg_gen_shl_tl(sbit, tcg_const_tl(2), sbit);
|
|
||||||
tcg_gen_subi_tl(sbit, sbit, 1);
|
|
||||||
tcg_gen_and_tl(sbit, a, sbit);
|
|
||||||
|
|
||||||
tcg_gen_andi_tl(d, cpu_PR[PR_CCS], ~(X_FLAG | N_FLAG | Z_FLAG));
|
|
||||||
/* or in the N_FLAG. */
|
|
||||||
tcg_gen_or_tl(d, d, bset);
|
|
||||||
tcg_gen_brcondi_tl(TCG_COND_NE, sbit, 0, l1);
|
|
||||||
/* or in the Z_FLAG. */
|
|
||||||
tcg_gen_ori_tl(d, d, Z_FLAG);
|
|
||||||
gen_set_label(l1);
|
|
||||||
|
|
||||||
tcg_temp_free(sbit);
|
|
||||||
tcg_temp_free(bset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
|
static void t_gen_cris_dstep(TCGv d, TCGv a, TCGv b)
|
||||||
{
|
{
|
||||||
int l1;
|
int l1;
|
||||||
@ -885,9 +827,6 @@ static void cris_alu_op_exec(DisasContext *dc, int op,
|
|||||||
case CC_OP_LZ:
|
case CC_OP_LZ:
|
||||||
t_gen_lz_i32(dst, b);
|
t_gen_lz_i32(dst, b);
|
||||||
break;
|
break;
|
||||||
case CC_OP_BTST:
|
|
||||||
t_gen_btst(dst, a, b);
|
|
||||||
break;
|
|
||||||
case CC_OP_MULS:
|
case CC_OP_MULS:
|
||||||
t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
|
t_gen_muls(dst, cpu_PR[PR_MOF], a, b);
|
||||||
break;
|
break;
|
||||||
@ -932,7 +871,7 @@ static void cris_alu(DisasContext *dc, int op,
|
|||||||
|
|
||||||
writeback = 1;
|
writeback = 1;
|
||||||
|
|
||||||
if (op == CC_OP_BOUND || op == CC_OP_BTST)
|
if (op == CC_OP_BOUND)
|
||||||
tmp = tcg_temp_local_new();
|
tmp = tcg_temp_local_new();
|
||||||
|
|
||||||
if (op == CC_OP_CMP) {
|
if (op == CC_OP_CMP) {
|
||||||
@ -1560,18 +1499,17 @@ static unsigned int dec_orq(DisasContext *dc)
|
|||||||
}
|
}
|
||||||
static unsigned int dec_btstq(DisasContext *dc)
|
static unsigned int dec_btstq(DisasContext *dc)
|
||||||
{
|
{
|
||||||
TCGv l0;
|
|
||||||
dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
|
dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4);
|
||||||
DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
|
DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2));
|
||||||
|
|
||||||
cris_cc_mask(dc, CC_MASK_NZ);
|
cris_cc_mask(dc, CC_MASK_NZ);
|
||||||
l0 = tcg_temp_local_new();
|
cris_evaluate_flags(dc);
|
||||||
cris_alu(dc, CC_OP_BTST,
|
gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
|
||||||
l0, cpu_R[dc->op2], tcg_const_tl(dc->op1), 4);
|
tcg_const_tl(dc->op1), cpu_PR[PR_CCS]);
|
||||||
|
cris_alu(dc, CC_OP_MOVE,
|
||||||
|
cpu_R[dc->op2], cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
||||||
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
||||||
t_gen_mov_preg_TN(dc, PR_CCS, l0);
|
|
||||||
dc->flags_uptodate = 1;
|
dc->flags_uptodate = 1;
|
||||||
tcg_temp_free(l0);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
static unsigned int dec_asrq(DisasContext *dc)
|
static unsigned int dec_asrq(DisasContext *dc)
|
||||||
@ -2012,17 +1950,16 @@ static unsigned int dec_neg_r(DisasContext *dc)
|
|||||||
|
|
||||||
static unsigned int dec_btst_r(DisasContext *dc)
|
static unsigned int dec_btst_r(DisasContext *dc)
|
||||||
{
|
{
|
||||||
TCGv l0;
|
|
||||||
DIS(fprintf (logfile, "btst $r%u, $r%u\n",
|
DIS(fprintf (logfile, "btst $r%u, $r%u\n",
|
||||||
dc->op1, dc->op2));
|
dc->op1, dc->op2));
|
||||||
cris_cc_mask(dc, CC_MASK_NZ);
|
cris_cc_mask(dc, CC_MASK_NZ);
|
||||||
|
cris_evaluate_flags(dc);
|
||||||
l0 = tcg_temp_local_new();
|
gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2],
|
||||||
cris_alu(dc, CC_OP_BTST, l0, cpu_R[dc->op2], cpu_R[dc->op1], 4);
|
cpu_R[dc->op1], cpu_PR[PR_CCS]);
|
||||||
|
cris_alu(dc, CC_OP_MOVE, cpu_R[dc->op2],
|
||||||
|
cpu_R[dc->op2], cpu_R[dc->op2], 4);
|
||||||
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
cris_update_cc_op(dc, CC_OP_FLAGS, 4);
|
||||||
t_gen_mov_preg_TN(dc, PR_CCS, l0);
|
|
||||||
dc->flags_uptodate = 1;
|
dc->flags_uptodate = 1;
|
||||||
tcg_temp_free(l0);
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user