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
This commit is contained in:
		
							parent
							
								
									4a6b819c09
								
							
						
					
					
						commit
						28de16da38
					
				| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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", 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue