diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-07 15:24:53 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-07 15:24:53 +0000 |
commit | dceaf394585191ced65ce6a478580ac1655510d7 (patch) | |
tree | e355c9a1cd5b6d328d1ed737f6db312112ffb4e6 /target-cris | |
parent | 069de562774880ec2133022aee211329ff174b6a (diff) |
CRIS: More TCG conversion.
* Convert moves to/from support function regs (including TLB updates) to TCG.
* SCC no longer requires T0 to strictly be 0 or 1, relaxed to 0 or non-zero.
* Convert the the condition code evaluation to TCG.
* Convert rfe into a helper and TCG.
* Convert evaluate_bcc and setf to TCG.
* Convert clrf to TCG.
* Convert CRIS exception raising to TCG.
* Convert btst to TCG.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4376 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-cris')
-rw-r--r-- | target-cris/helper.h | 6 | ||||
-rw-r--r-- | target-cris/mmu.c | 2 | ||||
-rw-r--r-- | target-cris/mmu.h | 2 | ||||
-rw-r--r-- | target-cris/op_helper.c | 138 | ||||
-rw-r--r-- | target-cris/translate.c | 287 |
5 files changed, 332 insertions, 103 deletions
diff --git a/target-cris/helper.h b/target-cris/helper.h index d20b9f78d1..7aa126df5b 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -1,11 +1,15 @@ #define TCG_HELPER_PROTO -void TCG_HELPER_PROTO helper_tlb_update(uint32_t T0); + +void TCG_HELPER_PROTO helper_raise_exception(uint32_t index); void TCG_HELPER_PROTO helper_tlb_flush(void); void TCG_HELPER_PROTO helper_dump(uint32_t a0, uint32_t a1, uint32_t a2); void TCG_HELPER_PROTO helper_dummy(void); void TCG_HELPER_PROTO helper_rfe(void); void TCG_HELPER_PROTO helper_store(uint32_t a0); +void TCG_HELPER_PROTO helper_movl_sreg_reg (uint32_t sreg, uint32_t reg); +void TCG_HELPER_PROTO helper_movl_reg_sreg (uint32_t reg, uint32_t sreg); + void TCG_HELPER_PROTO helper_evaluate_flags_muls(void); void TCG_HELPER_PROTO helper_evaluate_flags_mulu(void); void TCG_HELPER_PROTO helper_evaluate_flags_mcp(void); diff --git a/target-cris/mmu.c b/target-cris/mmu.c index a17d21d120..5ec9b37757 100644 --- a/target-cris/mmu.c +++ b/target-cris/mmu.c @@ -265,7 +265,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, } /* Give us the vaddr corresponding to the latest TLB update. */ -target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo) +target_ulong cris_mmu_tlb_latest_update(CPUState *env) { uint32_t sel = env->sregs[SFR_RW_MM_TLB_SEL]; uint32_t vaddr; diff --git a/target-cris/mmu.h b/target-cris/mmu.h index 32c2b689ca..1d6d33f3ab 100644 --- a/target-cris/mmu.h +++ b/target-cris/mmu.h @@ -11,7 +11,7 @@ struct cris_mmu_result_t int bf_vec; }; -target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo); +target_ulong cris_mmu_tlb_latest_update(CPUState *env); int cris_mmu_translate(struct cris_mmu_result_t *res, CPUState *env, uint32_t vaddr, int rw, int mmu_idx); diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index dfc213c7aa..197fdcc884 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -79,20 +79,10 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) env = saved_env; } -void helper_tlb_update(uint32_t T0) +void helper_raise_exception(uint32_t index) { -#if !defined(CONFIG_USER_ONLY) - uint32_t vaddr; - uint32_t srs = env->pregs[PR_SRS]; - - if (srs != 1 && srs != 2) - return; - - vaddr = cris_mmu_tlb_latest_update(env, T0); - D(fprintf(logfile, "flush old_vaddr=%x vaddr=%x T0=%x\n", vaddr, - env->sregs[SFR_R_MM_CAUSE] & TARGET_PAGE_MASK, T0)); - tlb_flush_page(env, vaddr); -#endif + env->exception_index = index; + cpu_loop_exit(); } void helper_tlb_flush(void) @@ -110,13 +100,105 @@ void helper_dummy(void) } -/* Only used for debugging at the moment. */ +void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) +{ + uint32_t srs; + srs = env->pregs[PR_SRS]; + srs &= 3; + env->sregs[srs][sreg] = env->regs[reg]; + +#if !defined(CONFIG_USER_ONLY) + if (srs == 1 || srs == 2) { + if (sreg == 6) { + /* Writes to tlb-hi write to mm_cause as a side + effect. */ + env->sregs[SFR_RW_MM_TLB_HI] = T0; + env->sregs[SFR_R_MM_CAUSE] = T0; + } + else if (sreg == 5) { + uint32_t set; + uint32_t idx; + uint32_t lo, hi; + uint32_t vaddr; + + vaddr = cris_mmu_tlb_latest_update(env); + D(fprintf(logfile, "tlb flush vaddr=%x\n", vaddr)); + tlb_flush_page(env, vaddr); + + idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; + set >>= 4; + set &= 3; + + idx &= 15; + /* We've just made a write to tlb_lo. */ + lo = env->sregs[SFR_RW_MM_TLB_LO]; + /* Writes are done via r_mm_cause. */ + hi = env->sregs[SFR_R_MM_CAUSE]; + env->tlbsets[srs - 1][set][idx].lo = lo; + env->tlbsets[srs - 1][set][idx].hi = hi; + } + } +#endif +} + +void helper_movl_reg_sreg (uint32_t reg, uint32_t sreg) +{ + uint32_t srs; + env->pregs[PR_SRS] &= 3; + srs = env->pregs[PR_SRS]; + +#if !defined(CONFIG_USER_ONLY) + if (srs == 1 || srs == 2) + { + uint32_t set; + uint32_t idx; + uint32_t lo, hi; + + idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; + set >>= 4; + set &= 3; + idx &= 15; + + /* Update the mirror regs. */ + hi = env->tlbsets[srs - 1][set][idx].hi; + lo = env->tlbsets[srs - 1][set][idx].lo; + env->sregs[SFR_RW_MM_TLB_HI] = hi; + env->sregs[SFR_RW_MM_TLB_LO] = lo; + } +#endif + env->regs[reg] = env->sregs[srs][sreg]; + RETURN(); +} + +static void cris_ccs_rshift(CPUState *env) +{ + uint32_t ccs; + + /* Apply the ccs shift. */ + ccs = env->pregs[PR_CCS]; + ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10); + if (ccs & U_FLAG) + { + /* Enter user mode. */ + env->ksp = env->regs[R_SP]; + env->regs[R_SP] = env->pregs[PR_USP]; + } + + env->pregs[PR_CCS] = ccs; +} + void helper_rfe(void) { D(fprintf(logfile, "rfe: erp=%x pid=%x ccs=%x btarget=%x\n", env->pregs[PR_ERP], env->pregs[PR_PID], env->pregs[PR_CCS], env->btarget)); + + cris_ccs_rshift(env); + + /* RFE sets the P_FLAG only if the R_FLAG is not set. */ + if (!(env->pregs[PR_CCS] & R_FLAG)) + env->pregs[PR_CCS] |= P_FLAG; } void helper_store(uint32_t a0) @@ -155,7 +237,6 @@ static void evaluate_flags_writeback(uint32_t flags) env->pregs[PR_CCS] &= ~(env->cc_mask | X_FLAG); flags &= env->cc_mask; env->pregs[PR_CCS] |= flags; - RETURN(); } void helper_evaluate_flags_muls(void) @@ -164,8 +245,7 @@ void helper_evaluate_flags_muls(void) uint32_t dst; uint32_t res; uint32_t flags = 0; - /* were gonna have to redo the muls. */ - int64_t tmp, t0 ,t1; + int64_t tmp; int32_t mof; int dneg; @@ -173,14 +253,12 @@ void helper_evaluate_flags_muls(void) dst = env->cc_dest; res = env->cc_result; - - /* cast into signed values to make GCC sign extend. */ - t0 = (int32_t)src; - t1 = (int32_t)dst; dneg = ((int32_t)res) < 0; - tmp = t0 * t1; - mof = tmp >> 32; + mof = env->pregs[PR_MOF]; + tmp = mof; + tmp <<= 32; + tmp |= res; if (tmp == 0) flags |= Z_FLAG; else if (tmp < 0) @@ -197,21 +275,17 @@ void helper_evaluate_flags_mulu(void) uint32_t dst; uint32_t res; uint32_t flags = 0; - /* were gonna have to redo the muls. */ - uint64_t tmp, t0 ,t1; + uint64_t tmp; uint32_t mof; src = env->cc_src; dst = env->cc_dest; res = env->cc_result; - - /* cast into signed values to make GCC sign extend. */ - t0 = src; - t1 = dst; - - tmp = t0 * t1; - mof = tmp >> 32; + mof = env->pregs[PR_MOF]; + tmp = mof; + tmp <<= 32; + tmp |= res; if (tmp == 0) flags |= Z_FLAG; else if (tmp >> 63) diff --git a/target-cris/translate.c b/target-cris/translate.c index fffc98d37e..854878ebf5 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -223,9 +223,9 @@ static inline void t_gen_mov_preg_TN(int r, TCGv tn) } } -static inline void t_gen_mov_TN_im(TCGv tn, int32_t val) +static inline void t_gen_raise_exception(uint32_t index) { - tcg_gen_movi_tl(tn, val); + tcg_gen_helper_0_1(helper_raise_exception, tcg_const_tl(index)); } static void t_gen_lsl(TCGv d, TCGv a, TCGv b) @@ -375,6 +375,62 @@ static void t_gen_lz_i32(TCGv d, TCGv x) tcg_gen_discard_i32(n); } +static void t_gen_btst(TCGv d, TCGv s) +{ + TCGv sbit; + TCGv bset; + 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(TCG_TYPE_TL); + bset = tcg_temp_new(TCG_TYPE_TL); + + /* Compute bset and sbit. */ + tcg_gen_andi_tl(sbit, s, 31); + tcg_gen_shl_tl(s, tcg_const_tl(1), sbit); + tcg_gen_and_tl(bset, d, s); + 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, d, 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_brcond_tl(TCG_COND_NE, sbit, tcg_const_tl(0), l1); + /* or in the Z_FLAG. */ + tcg_gen_ori_tl(d, d, Z_FLAG); + gen_set_label(l1); + + tcg_gen_discard_tl(sbit); + tcg_gen_discard_tl(bset); +} + static void t_gen_cris_dstep(TCGv d, TCGv s) { int l1; @@ -738,7 +794,7 @@ static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size) t_gen_lz_i32(cpu_T[0], cpu_T[1]); break; case CC_OP_BTST: - gen_op_btst_T0_T1(); + t_gen_btst(cpu_T[0], cpu_T[1]); writeback = 0; break; case CC_OP_MULS: @@ -846,83 +902,172 @@ static void gen_tst_cc (DisasContext *dc, int cond) int arith_opt; /* TODO: optimize more condition codes. */ + + /* + * If the flags are live, we've gotta look into the bits of CCS. + * Otherwise, if we just did an arithmetic operation we try to + * evaluate the condition code faster. + * + * When this function is done, T0 should be non-zero if the condition + * code is true. + */ arith_opt = arith_cc(dc) && !dc->flags_live; switch (cond) { case CC_EQ: - if (arith_opt) - gen_op_tst_cc_eq_fast (); + if (arith_opt) { + /* If cc_result is zero, T0 should be + non-zero otherwise T0 should be zero. */ + int l1; + l1 = gen_new_label(); + tcg_gen_movi_tl(cpu_T[0], 0); + tcg_gen_brcond_tl(TCG_COND_NE, cc_result, + tcg_const_tl(0), l1); + tcg_gen_movi_tl(cpu_T[0], 1); + gen_set_label(l1); + } else { cris_evaluate_flags(dc); - gen_op_tst_cc_eq (); + tcg_gen_andi_tl(cpu_T[0], + cpu_PR[PR_CCS], Z_FLAG); } break; case CC_NE: if (arith_opt) - gen_op_tst_cc_ne_fast (); + tcg_gen_mov_tl(cpu_T[0], cc_result); else { cris_evaluate_flags(dc); - gen_op_tst_cc_ne (); + tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], + Z_FLAG); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG); } break; case CC_CS: cris_evaluate_flags(dc); - gen_op_tst_cc_cs (); + tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG); break; case CC_CC: cris_evaluate_flags(dc); - gen_op_tst_cc_cc (); + tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], + C_FLAG); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG); break; case CC_VS: cris_evaluate_flags(dc); - gen_op_tst_cc_vs (); + tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], V_FLAG); break; case CC_VC: cris_evaluate_flags(dc); - gen_op_tst_cc_vc (); + tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], + V_FLAG); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG); break; case CC_PL: if (arith_opt) - gen_op_tst_cc_pl_fast (); + tcg_gen_shli_tl(cpu_T[0], cc_result, 31); else { cris_evaluate_flags(dc); - gen_op_tst_cc_pl (); + tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], + N_FLAG); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); } break; case CC_MI: - if (arith_opt) - gen_op_tst_cc_mi_fast (); + if (arith_opt) { + tcg_gen_shli_tl(cpu_T[0], cc_result, 31); + tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); + } else { cris_evaluate_flags(dc); - gen_op_tst_cc_mi (); + tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], + N_FLAG); } break; case CC_LS: cris_evaluate_flags(dc); - gen_op_tst_cc_ls (); + tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], + C_FLAG | Z_FLAG); break; case CC_HI: cris_evaluate_flags(dc); - gen_op_tst_cc_hi (); + { + TCGv tmp; + + tmp = tcg_temp_new(TCG_TYPE_TL); + tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS], + C_FLAG | Z_FLAG); + /* Overlay the C flag on top of the Z. */ + tcg_gen_shli_tl(cpu_T[0], tmp, 2); + tcg_gen_and_tl(cpu_T[0], tmp, cpu_T[0]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG); + + tcg_gen_discard_tl(tmp); + } break; case CC_GE: cris_evaluate_flags(dc); - gen_op_tst_cc_ge (); + /* Overlay the V flag on top of the N. */ + tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2); + tcg_gen_xor_tl(cpu_T[0], + cpu_PR[PR_CCS], cpu_T[0]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); + tcg_gen_xori_tl(cpu_T[0], cpu_T[0], N_FLAG); break; case CC_LT: cris_evaluate_flags(dc); - gen_op_tst_cc_lt (); + /* Overlay the V flag on top of the N. */ + tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2); + tcg_gen_xor_tl(cpu_T[0], + cpu_PR[PR_CCS], cpu_T[0]); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); break; case CC_GT: cris_evaluate_flags(dc); - gen_op_tst_cc_gt (); + { + TCGv n, z; + + n = tcg_temp_new(TCG_TYPE_TL); + z = tcg_temp_new(TCG_TYPE_TL); + + /* To avoid a shift we overlay everything on + the V flag. */ + tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); + tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); + /* invert Z. */ + tcg_gen_xori_tl(z, z, 2); + + tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); + tcg_gen_xori_tl(n, n, 2); + tcg_gen_and_tl(cpu_T[0], z, n); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2); + + tcg_gen_discard_tl(n); + tcg_gen_discard_tl(z); + } break; case CC_LE: cris_evaluate_flags(dc); - gen_op_tst_cc_le (); + { + TCGv n, z; + + n = tcg_temp_new(TCG_TYPE_TL); + z = tcg_temp_new(TCG_TYPE_TL); + + /* To avoid a shift we overlay everything on + the V flag. */ + tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); + tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); + + tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); + tcg_gen_or_tl(cpu_T[0], z, n); + tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2); + + tcg_gen_discard_tl(n); + tcg_gen_discard_tl(z); + } break; case CC_P: cris_evaluate_flags(dc); - gen_op_tst_cc_p (); + tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], P_FLAG); break; case CC_A: cris_evaluate_flags(dc); @@ -944,7 +1089,7 @@ static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond) if (cond != CC_A) { gen_tst_cc (dc, cond); - gen_op_evaluate_bcc (); + t_gen_mov_env_TN(btaken, cpu_T[0]); } tcg_gen_movi_tl(env_btarget, dc->delayed_pc); } @@ -1225,7 +1370,7 @@ static unsigned int dec_subq(DisasContext *dc) cris_cc_mask(dc, CC_MASK_NZVC); /* Fetch register operand, */ t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], dc->op1); + tcg_gen_movi_tl(cpu_T[1], dc->op1); crisv32_alu_op(dc, CC_OP_SUB, dc->op2, 4); return 2; } @@ -1238,7 +1383,7 @@ static unsigned int dec_cmpq(DisasContext *dc) DIS(fprintf (logfile, "cmpq %d, $r%d\n", imm, dc->op2)); cris_cc_mask(dc, CC_MASK_NZVC); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], imm); + tcg_gen_movi_tl(cpu_T[1], imm); crisv32_alu_op(dc, CC_OP_CMP, dc->op2, 4); return 2; } @@ -1251,7 +1396,7 @@ static unsigned int dec_andq(DisasContext *dc) DIS(fprintf (logfile, "andq %d, $r%d\n", imm, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], imm); + tcg_gen_movi_tl(cpu_T[1], imm); crisv32_alu_op(dc, CC_OP_AND, dc->op2, 4); return 2; } @@ -1263,7 +1408,7 @@ static unsigned int dec_orq(DisasContext *dc) DIS(fprintf (logfile, "orq %d, $r%d\n", imm, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], imm); + tcg_gen_movi_tl(cpu_T[1], imm); crisv32_alu_op(dc, CC_OP_OR, dc->op2, 4); return 2; } @@ -1272,10 +1417,9 @@ static unsigned int dec_btstq(DisasContext *dc) dc->op1 = EXTRACT_FIELD(dc->ir, 0, 4); DIS(fprintf (logfile, "btstq %u, $r%d\n", dc->op1, dc->op2)); - cris_evaluate_flags(dc); cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], dc->op1); + tcg_gen_movi_tl(cpu_T[1], dc->op1); crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4); cris_update_cc_op(dc, CC_OP_FLAGS, 4); @@ -1289,7 +1433,7 @@ static unsigned int dec_asrq(DisasContext *dc) DIS(fprintf (logfile, "asrq %u, $r%d\n", dc->op1, dc->op2)); cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], dc->op1); + tcg_gen_movi_tl(cpu_T[1], dc->op1); crisv32_alu_op(dc, CC_OP_ASR, dc->op2, 4); return 2; } @@ -1300,7 +1444,7 @@ static unsigned int dec_lslq(DisasContext *dc) cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], dc->op1); + tcg_gen_movi_tl(cpu_T[1], dc->op1); crisv32_alu_op(dc, CC_OP_LSL, dc->op2, 4); return 2; } @@ -1311,7 +1455,7 @@ static unsigned int dec_lsrq(DisasContext *dc) cris_cc_mask(dc, CC_MASK_NZ); t_gen_mov_TN_reg(cpu_T[0], dc->op2); - t_gen_mov_TN_im(cpu_T[1], dc->op1); + tcg_gen_movi_tl(cpu_T[1], dc->op1); crisv32_alu_op(dc, CC_OP_LSR, dc->op2, 4); return 2; } @@ -1338,14 +1482,20 @@ static unsigned int dec_scc_r(DisasContext *dc) if (cond != CC_A) { + int l1; + gen_tst_cc (dc, cond); - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); + + l1 = gen_new_label(); + tcg_gen_movi_tl(cpu_R[dc->op1], 0); + tcg_gen_brcond_tl(TCG_COND_EQ, cpu_T[0], tcg_const_tl(0), l1); + tcg_gen_movi_tl(cpu_R[dc->op1], 1); + gen_set_label(l1); } else - tcg_gen_movi_tl(cpu_T[1], 1); + tcg_gen_movi_tl(cpu_R[dc->op1], 1); cris_cc_mask(dc, 0); - crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4); return 2; } @@ -1624,7 +1774,6 @@ static unsigned int dec_btst_r(DisasContext *dc) { DIS(fprintf (logfile, "btst $r%u, $r%u\n", dc->op1, dc->op2)); - cris_evaluate_flags(dc); cris_cc_mask(dc, CC_MASK_NZ); dec_prep_alu_r(dc, dc->op1, dc->op2, 4, 0); crisv32_alu_op(dc, CC_OP_BTST, dc->op2, 4); @@ -1772,10 +1921,18 @@ static unsigned int dec_setclrf(DisasContext *dc) cris_update_cc_op(dc, CC_OP_FLAGS, 4); tcg_gen_movi_tl(cc_op, dc->cc_op); - if (set) - gen_op_setf(flags); + if (set) { + if (!dc->user && (flags & U_FLAG)) { + /* Enter user mode. */ + t_gen_mov_env_TN(ksp, cpu_R[R_SP]); + tcg_gen_mov_tl(cpu_R[R_SP], cpu_PR[PR_USP]); + dc->is_jmp = DISAS_UPDATE; + } + tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], flags); + } else - gen_op_clrf(flags); + tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~flags); + dc->flags_live = 1; dc->clear_x = 0; return 2; @@ -1785,28 +1942,19 @@ static unsigned int dec_move_rs(DisasContext *dc) { DIS(fprintf (logfile, "move $r%u, $s%u\n", dc->op1, dc->op2)); cris_cc_mask(dc, 0); - t_gen_mov_TN_reg(cpu_T[0], dc->op1); - gen_op_movl_sreg_T0(dc->op2); - -#if !defined(CONFIG_USER_ONLY) - if (dc->op2 == 6) - gen_op_movl_tlb_hi_T0(); - else if (dc->op2 == 5) { /* srs is checked at runtime. */ - tcg_gen_helper_0_1(helper_tlb_update, cpu_T[0]); - gen_op_movl_tlb_lo_T0(); - } -#endif + tcg_gen_helper_0_2(helper_movl_sreg_reg, + tcg_const_tl(dc->op2), tcg_const_tl(dc->op1)); return 2; } static unsigned int dec_move_sr(DisasContext *dc) { DIS(fprintf (logfile, "move $s%u, $r%u\n", dc->op2, dc->op1)); cris_cc_mask(dc, 0); - gen_op_movl_T0_sreg(dc->op2); - tcg_gen_mov_tl(cpu_T[1], cpu_T[0]); - crisv32_alu_op(dc, CC_OP_MOVE, dc->op1, 4); + tcg_gen_helper_0_2(helper_movl_reg_sreg, + tcg_const_tl(dc->op1), tcg_const_tl(dc->op2)); return 2; } + static unsigned int dec_move_rp(DisasContext *dc) { DIS(fprintf (logfile, "move $r%u, $p%u\n", dc->op1, dc->op2)); @@ -2024,9 +2172,11 @@ static unsigned int dec_test_m(DisasContext *dc) dc->op1, dc->postinc ? "+]" : "]", dc->op2)); + cris_evaluate_flags(dc); + insn_len = dec_prep_alu_m(dc, 0, memsize); cris_cc_mask(dc, CC_MASK_NZ); - gen_op_clrf(3); + tcg_gen_andi_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~3); tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); tcg_gen_movi_tl(cpu_T[1], 0); @@ -2444,10 +2594,6 @@ static unsigned int dec_rfe_etc(DisasContext *dc) case 2: /* rfe. */ cris_evaluate_flags(dc); - gen_op_ccs_rshift(); - /* FIXME: don't set the P-FLAG if R is set. */ - tcg_gen_ori_tl(cpu_PR[PR_CCS], cpu_PR[PR_CCS], P_FLAG); - /* Debug helper. */ tcg_gen_helper_0_0(helper_rfe); dc->is_jmp = DISAS_UPDATE; break; @@ -2460,7 +2606,9 @@ static unsigned int dec_rfe_etc(DisasContext *dc) tcg_gen_movi_tl(cpu_T[0], dc->pc); t_gen_mov_env_TN(pc, cpu_T[0]); /* Breaks start at 16 in the exception vector. */ - gen_op_break_im(dc->op1 + 16); + t_gen_mov_env_TN(trap_vector, + tcg_const_tl(dc->op1 + 16)); + t_gen_raise_exception(EXCP_BREAK); dc->is_jmp = DISAS_UPDATE; break; default: @@ -2642,7 +2790,7 @@ static void check_breakpoint(CPUState *env, DisasContext *dc) cris_evaluate_flags (dc); tcg_gen_movi_tl(cpu_T[0], dc->pc); t_gen_mov_env_TN(pc, cpu_T[0]); - gen_op_debug(); + t_gen_raise_exception(EXCP_DEBUG); dc->is_jmp = DISAS_UPDATE; } } @@ -2689,13 +2837,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (loglevel & CPU_LOG_TB_IN_ASM) { fprintf(logfile, - "search=%d pc=%x ccs=%x pid=%x usp=%x\n" + "search=%d pc=%x ccs=%x pid=%x usp=%x dbg=%x %x %x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n" "%x.%x.%x.%x\n", search_pc, env->pc, env->pregs[PR_CCS], env->pregs[PR_PID], env->pregs[PR_USP], + env->debug1, env->debug2, env->debug3, env->regs[0], env->regs[1], env->regs[2], env->regs[3], env->regs[4], env->regs[5], env->regs[6], env->regs[7], env->regs[8], env->regs[9], @@ -2733,7 +2882,6 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, dc->clear_x = 1; insn_len = cris_decoder(dc); - STATS(gen_op_exec_insn()); dc->ppc = dc->pc; dc->pc += insn_len; if (dc->clear_x) @@ -2778,7 +2926,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, cris_evaluate_flags (dc); done: if (__builtin_expect(env->singlestep_enabled, 0)) { - gen_op_debug(); + t_gen_raise_exception(EXCP_DEBUG); } else { switch(dc->is_jmp) { case DISAS_NEXT: @@ -2933,13 +3081,16 @@ CPUCRISState *cpu_cris_init (const char *cpu_model) pregnames[i]); } - TCG_HELPER(helper_tlb_update); - TCG_HELPER(helper_tlb_flush); - TCG_HELPER(helper_rfe); + TCG_HELPER(helper_raise_exception); TCG_HELPER(helper_store); TCG_HELPER(helper_dump); TCG_HELPER(helper_dummy); + TCG_HELPER(helper_tlb_flush); + TCG_HELPER(helper_movl_sreg_reg); + TCG_HELPER(helper_movl_reg_sreg); + TCG_HELPER(helper_rfe); + TCG_HELPER(helper_evaluate_flags_muls); TCG_HELPER(helper_evaluate_flags_mulu); TCG_HELPER(helper_evaluate_flags_mcp); |