diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-09-22 20:51:28 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-09-22 20:51:28 +0000 |
commit | 28de16da38f20b3fe76fa80d10561c3a998342e2 (patch) | |
tree | cd05930d4e9a1e936e20ddf9c11a1d9d4f18c3b7 /target-cris | |
parent | 4a6b819c09473acc362a9959603017a549d85ce3 (diff) |
CRIS: Improve ASID related TLB flushes.
* Speedup and correct ASID (PID) related TLB flushes.
* Use 64bit tcg load/stores to emulate movem.
* Remove unused helpers and other minor cleanups.
Signed-off-by: Edgar E. Iglesias <edgar@axis.com>
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5302 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-cris')
-rw-r--r-- | target-cris/helper.h | 2 | ||||
-rw-r--r-- | target-cris/mmu.c | 8 | ||||
-rw-r--r-- | target-cris/op_helper.c | 18 | ||||
-rw-r--r-- | target-cris/translate.c | 45 |
4 files changed, 36 insertions, 37 deletions
diff --git a/target-cris/helper.h b/target-cris/helper.h index 4c96f0487b..517e8f8bf5 100644 --- a/target-cris/helper.h +++ b/target-cris/helper.h @@ -3,10 +3,8 @@ void TCG_HELPER_PROTO helper_raise_exception(uint32_t index); void TCG_HELPER_PROTO helper_tlb_flush_pid(uint32_t pid); 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_rfn(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); diff --git a/target-cris/mmu.c b/target-cris/mmu.c index 5d21eaa5f4..f270d5b8fc 100644 --- a/target-cris/mmu.c +++ b/target-cris/mmu.c @@ -140,7 +140,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, r_cause = env->sregs[SFR_R_MM_CAUSE]; r_cfg = env->sregs[SFR_RW_MM_CFG]; - pid = env->pregs[PR_PID]; + pid = env->pregs[PR_PID] & 0xff; switch (rw) { case 2: rwcause = CRIS_MMU_ERR_EXEC; mmu = 0; break; @@ -270,7 +270,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, /* Update RW_MM_CAUSE. */ set_field(&r_cause, rwcause, 8, 2); set_field(&r_cause, vpage, 13, 19); - set_field(&r_cause, env->pregs[PR_PID], 0, 8); + set_field(&r_cause, pid, 0, 8); env->sregs[SFR_R_MM_CAUSE] = r_cause; D(printf("refill vaddr=%x pc=%x\n", vaddr, env->pc)); } @@ -280,7 +280,7 @@ static int cris_mmu_translate_page(struct cris_mmu_result_t *res, __func__, rw, match, env->pc, vaddr, vpage, tlb_vpn, tlb_pfn, tlb_pid, - env->pregs[PR_PID], + pid, r_cause, env->sregs[SFR_RW_MM_TLB_SEL], env->regs[R_SP], env->pregs[PR_USP], env->ksp)); @@ -315,7 +315,7 @@ void cris_mmu_flush_pid(CPUState *env, uint32_t pid) /* Kernel protected areas need to be flushed as well. */ - if (tlb_v && !tlb_g) { + if (tlb_v && !tlb_g && (tlb_pid == pid || tlb_k)) { vaddr = tlb_vpn << TARGET_PAGE_BITS; D(fprintf(logfile, "flush pid=%x vaddr=%x\n", diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index fcf80705e9..d9ddc3ad55 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -91,7 +91,9 @@ void helper_raise_exception(uint32_t index) void helper_tlb_flush_pid(uint32_t pid) { #if !defined(CONFIG_USER_ONLY) - cris_mmu_flush_pid(env, pid); + pid &= 0xff; + if (pid != (env->pregs[PR_PID] & 0xff)) + cris_mmu_flush_pid(env, env->pregs[PR_PID]); #endif } @@ -100,11 +102,6 @@ void helper_dump(uint32_t a0, uint32_t a1, uint32_t a2) (fprintf(logfile, "%s: a0=%x a1=%x\n", __func__, a0, a1)); } -void helper_dummy(void) -{ - -} - /* Used by the tlb decoder. */ #define EXTRACT_FIELD(src, start, end) \ (((src) >> start) & ((1 << (end - start + 1)) - 1)) @@ -239,15 +236,6 @@ void helper_rfn(void) env->pregs[PR_CCS] |= M_FLAG; } -void helper_store(uint32_t a0) -{ - if (env->pregs[PR_CCS] & P_FLAG ) - { - cpu_abort(env, "cond_store_failed! pc=%x a0=%x\n", - env->pc, a0); - } -} - void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, int is_asi) { diff --git a/target-cris/translate.c b/target-cris/translate.c index 4680dd7074..8b8ab8326b 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -216,11 +216,11 @@ static inline void t_gen_mov_preg_TN(DisasContext *dc, int r, TCGv tn) else if (r == PR_SRS) tcg_gen_andi_tl(cpu_PR[r], tn, 3); else { - tcg_gen_mov_tl(cpu_PR[r], tn); if (r == PR_PID) tcg_gen_helper_0_1(helper_tlb_flush_pid, tn); else if (r == PR_CCS) dc->cpustate_changed = 1; + tcg_gen_mov_tl(cpu_PR[r], tn); } } @@ -1223,9 +1223,12 @@ void gen_load(DisasContext *dc, TCGv dst, TCGv addr, else tcg_gen_qemu_ld16u(dst, addr, mem_index); } - else { + else if (size == 4) { tcg_gen_qemu_ld32u(dst, addr, mem_index); } + else if (size == 8) { + tcg_gen_qemu_ld64(dst, addr, mem_index); + } } void gen_store (DisasContext *dc, TCGv addr, TCGv val, @@ -1248,7 +1251,6 @@ void gen_store (DisasContext *dc, TCGv addr, TCGv val, return; } - /* Remember, operands are flipped. CRIS has reversed order. */ if (size == 1) tcg_gen_qemu_st8(val, addr, mem_index); else if (size == 2) @@ -2548,27 +2550,38 @@ static unsigned int dec_movem_mr(DisasContext *dc) { TCGv tmp[16]; int i; + int nr = dc->op2 + 1; DIS(fprintf (logfile, "movem [$r%u%s, $r%u\n", dc->op1, dc->postinc ? "+]" : "]", dc->op2)); - /* fetch the address into T0 and T1. */ + /* There are probably better ways of doing this. */ cris_flush_cc_state(dc); - for (i = 0; i <= dc->op2; i++) { - tmp[i] = tcg_temp_new(TCG_TYPE_TL); - /* Perform the load onto regnum i. Always dword wide. */ - tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 4); + for (i = 0; i < (nr >> 1); i++) { + tmp[i] = tcg_temp_new(TCG_TYPE_I64); + tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 8); + gen_load(dc, tmp[i], cpu_T[0], 8, 0); + } + if (nr & 1) { + tmp[i] = tcg_temp_new(TCG_TYPE_I32); + tcg_gen_addi_tl(cpu_T[0], cpu_R[dc->op1], i * 8); gen_load(dc, tmp[i], cpu_T[0], 4, 0); } - for (i = 0; i <= dc->op2; i++) { - tcg_gen_mov_tl(cpu_R[i], tmp[i]); + for (i = 0; i < (nr >> 1); i++) { + tcg_gen_trunc_i64_i32(cpu_R[i * 2], tmp[i]); + tcg_gen_shri_i64(tmp[i], tmp[i], 32); + tcg_gen_trunc_i64_i32(cpu_R[i * 2 + 1], tmp[i]); + tcg_temp_free(tmp[i]); + } + if (nr & 1) { + tcg_gen_mov_tl(cpu_R[dc->op2], tmp[i]); tcg_temp_free(tmp[i]); } /* writeback the updated pointer value. */ if (dc->postinc) - tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], i * 4); + tcg_gen_addi_tl(cpu_R[dc->op1], cpu_R[dc->op1], nr * 4); /* gen_load might want to evaluate the previous insns flags. */ cris_cc_mask(dc, 0); @@ -2948,6 +2961,9 @@ cris_decoder(DisasContext *dc) unsigned int insn_len = 2; int i; + if (unlikely(loglevel & CPU_LOG_TB_OP)) + tcg_gen_debug_insn_start(dc->pc); + /* Load a halfword onto the instruction register. */ dc->ir = lduw_code(dc->pc); @@ -3131,9 +3147,8 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb, if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) gen_io_start(); dc->clear_x = 1; - if (unlikely(loglevel & CPU_LOG_TB_OP)) - tcg_gen_debug_insn_start(dc->pc); - insn_len = cris_decoder(dc); + + insn_len = cris_decoder(dc); dc->ppc = dc->pc; dc->pc += insn_len; if (dc->clear_x) @@ -3357,9 +3372,7 @@ CPUCRISState *cpu_cris_init (const char *cpu_model) } TCG_HELPER(helper_raise_exception); - TCG_HELPER(helper_store); TCG_HELPER(helper_dump); - TCG_HELPER(helper_dummy); TCG_HELPER(helper_tlb_flush_pid); TCG_HELPER(helper_movl_sreg_reg); |