diff options
-rw-r--r-- | target-cris/helper.h | 2 | ||||
-rw-r--r-- | target-cris/op_helper.c | 26 | ||||
-rw-r--r-- | target-cris/translate.c | 85 |
3 files changed, 39 insertions, 74 deletions
diff --git a/target-cris/helper.h b/target-cris/helper.h index e4684397a0..18195a01ba 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -10,6 +10,8 @@ DEF_HELPER_0(rfn, void); DEF_HELPER_2(movl_sreg_reg, 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_mulu, void) DEF_HELPER_0(evaluate_flags_mcp, void) diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 51323a2a5c..6b23980740 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -243,6 +243,32 @@ void helper_rfn(void) 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) { unsigned int x, z, mask; diff --git a/target-cris/translate.c b/target-cris/translate.c index 1dd880f4c5..243c789693 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -388,64 +388,6 @@ static void t_gen_lz_i32(TCGv d, TCGv x) 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) { int l1; @@ -885,9 +827,6 @@ static void cris_alu_op_exec(DisasContext *dc, int op, case CC_OP_LZ: t_gen_lz_i32(dst, b); break; - case CC_OP_BTST: - t_gen_btst(dst, a, b); - break; case CC_OP_MULS: t_gen_muls(dst, cpu_PR[PR_MOF], a, b); break; @@ -932,7 +871,7 @@ static void cris_alu(DisasContext *dc, int op, writeback = 1; - if (op == CC_OP_BOUND || op == CC_OP_BTST) + if (op == CC_OP_BOUND) tmp = tcg_temp_local_new(); if (op == CC_OP_CMP) { @@ -1560,18 +1499,17 @@ static unsigned int dec_orq(DisasContext *dc) } static unsigned int dec_btstq(DisasContext *dc) { - TCGv l0; dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); - l0 = tcg_temp_local_new(); - cris_alu(dc, CC_OP_BTST, - l0, cpu_R[dc->op2], tcg_const_tl(dc->op1), 4); + cris_evaluate_flags(dc); + gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2], + 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); - t_gen_mov_preg_TN(dc, PR_CCS, l0); dc->flags_uptodate = 1; - tcg_temp_free(l0); return 2; } 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) { - TCGv l0; DIS(fprintf (logfile, "btst $r%u, $r%u\n", dc->op1, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); - - l0 = tcg_temp_local_new(); - cris_alu(dc, CC_OP_BTST, l0, cpu_R[dc->op2], cpu_R[dc->op1], 4); + cris_evaluate_flags(dc); + gen_helper_btst(cpu_PR[PR_CCS], cpu_R[dc->op2], + 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); - t_gen_mov_preg_TN(dc, PR_CCS, l0); dc->flags_uptodate = 1; - tcg_temp_free(l0); return 2; } |