⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arm7100_mmu.c

📁 skyeye的开源代码
💻 C
字号:
/*    armmmu.c - Memory Management Unit emulation.    ARMulator extensions for the ARM7100 family.    Copyright (C) 1999  Ben Williamson    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include <assert.h>#include <string.h>#include "armdefs.h"#ifdef CACHE#undef CACHE#endif /*  */#ifdef TLB#undef TLB#endif /*  */#define	CACHE() (&state->mmu.u.arm7100_mmu.cache_t)#define TLB() (&state->mmu.u.arm7100_mmu.tlb_t)static fault_t a71_mmu_read (ARMul_State * state, ARMword virt_addr,			     ARMword * data, ARMword datatype);static fault_t a71_mmu_write (ARMul_State * state, ARMword virt_addr,			      ARMword data, ARMword datatype);static inta71_mmu_init (ARMul_State * state){	state->mmu.control = 0x70;	state->mmu.translation_table_base = 0xDEADC0DE;	state->mmu.domain_access_control = 0xDEADC0DE;	state->mmu.fault_status = 0;	state->mmu.fault_address = 0;	if (mmu_cache_init (CACHE (), 16, 4, 128, CACHE_WRITE_THROUGH)) {		err_msg ("cache init %d\n", -1);		goto cache_error;	}	if (mmu_tlb_init (TLB (), 64)) {		err_msg ("tlb init %d\n", -1);		goto tlb_error;	};	return 0;      tlb_error:mmu_cache_exit (CACHE ());      cache_error:return -1;}static voida71_mmu_exit (ARMul_State * state){	mmu_cache_exit (CACHE ());	mmu_tlb_exit (TLB ());} static fault_ta71_mmu_read_byte (ARMul_State * state, ARMword virt_addr, ARMword * data){	//ARMword temp,offset;	fault_t fault;	fault = a71_mmu_read (state, virt_addr, data, ARM_BYTE_TYPE);	return fault;}static fault_ta71_mmu_read_halfword (ARMul_State * state, ARMword virt_addr, ARMword * data){	//ARMword temp,offset;	fault_t fault;	fault = a71_mmu_read (state, virt_addr, data, ARM_HALFWORD_TYPE);	return fault;}static fault_ta71_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data){	return a71_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);}static fault_ta71_mmu_read (ARMul_State * state, ARMword virt_addr, ARMword * data,	      ARMword datatype){	tlb_entry_t *tlb;	ARMword phys_addr;	ARMword temp, offset;	fault_t fault;	if (!(state->mmu.control & CONTROL_MMU)) {//              *data = mem_read_word(state, virt_addr);//#if 0		if (datatype == ARM_BYTE_TYPE)			*data = mem_read_byte (state, virt_addr);		else if (datatype == ARM_HALFWORD_TYPE)			*data = mem_read_halfword (state, virt_addr);		else if (datatype == ARM_WORD_TYPE)			*data = mem_read_word (state, virt_addr);		else {			printf ("SKYEYE:1 a71_mmu_read error: unknown data type %d\n", datatype);			skyeye_exit (-1);		}//#endif		return NO_FAULT;	}#if 0/* XXX */	if (hack && (virt_addr >= 0xc0000000) && (virt_addr < 0xc0200000)) {		printf ("0x%08x\n", virt_addr);	}#endif /*  */	if ((virt_addr & 3) && (datatype == ARM_WORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT) || (virt_addr & 1)	    && (datatype == ARM_HALFWORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT)) {		fprintf (stderr, "SKYEYE, a71_mmu_read ALIGNMENT_FAULT\n");		return ALIGNMENT_FAULT;	}	if (state->mmu.control & CONTROL_CACHE) {		cache_line_t *cache;		cache = mmu_cache_search (state, CACHE (), virt_addr);		if (cache) {			if (datatype == ARM_WORD_TYPE)				*data = cache->data[(virt_addr >> 2) & 3];			else if (datatype == ARM_HALFWORD_TYPE) {				temp = cache->data[(virt_addr >> 2) & 3];				offset = (((ARMword) state->bigendSig * 2) ^ (virt_addr & 2)) << 3;	/* bit offset into the word */				*data = (temp >> offset) & 0xffff;			}			else if (datatype == ARM_BYTE_TYPE) {				temp = cache->data[(virt_addr >> 2) & 3];				offset = (((ARMword) state->bigendSig * 3) ^ (virt_addr & 3)) << 3;	/* bit offset into the word */				*data = (temp >> offset & 0xffL);			}			return NO_FAULT;		}	}	fault = translate (state, virt_addr, TLB (), &tlb);	if (fault) {		return fault;	}	fault = check_access (state, virt_addr, tlb, 1);	if (fault) {		return fault;	}	phys_addr = (tlb->phys_addr & tlb_masks[tlb->mapping]) |		(virt_addr & ~tlb_masks[tlb->mapping]);	/* allocate to the cache if cacheable */	if ((tlb->perms & 0x08) && (state->mmu.control & CONTROL_CACHE)) {		cache_line_t *cache;		ARMword fetch;		int i;		cache = mmu_cache_alloc (state, CACHE (), virt_addr, 0);		fetch = phys_addr & 0xFFFFFFF0;		for (i = 0; i < 4; i++) {			cache->data[i] = mem_read_word (state, fetch);			fetch += 4;		}		cache->tag =			va_cache_align (virt_addr, CACHE ()) | TAG_VALID_FLAG;		//*data = cache->data[(virt_addr >> 2) & 3];		if (datatype == ARM_WORD_TYPE)			*data = cache->data[(virt_addr >> 2) & 3];		else if (datatype == ARM_HALFWORD_TYPE) {			temp = cache->data[(virt_addr >> 2) & 3];			offset = (((ARMword) state->bigendSig * 2) ^ (virt_addr & 2)) << 3;	/* bit offset into the word */			*data = (temp >> offset) & 0xffff;		}		else if (datatype == ARM_BYTE_TYPE) {			temp = cache->data[(virt_addr >> 2) & 3];			offset = (((ARMword) state->bigendSig * 3) ^ (virt_addr & 3)) << 3;	/* bit offset into the word */			*data = (temp >> offset & 0xffL);		}		return NO_FAULT;	}	else {		if (datatype == ARM_BYTE_TYPE)			*data = mem_read_byte (state, phys_addr);		else if (datatype == ARM_HALFWORD_TYPE)			*data = mem_read_halfword (state, phys_addr);		else if (datatype == ARM_WORD_TYPE)			*data = mem_read_word (state, phys_addr);		else {			printf ("SKYEYE:2 a71_mmu_read error: unknown data type %d\n", datatype);			skyeye_exit (-1);		}		return NO_FAULT;	}}static fault_ta71_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data){	return a71_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);}static fault_ta71_mmu_write_halfword (ARMul_State * state, ARMword virt_addr, ARMword data){	return a71_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);}static fault_ta71_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data){	return a71_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);}static fault_ta71_mmu_write (ARMul_State * state, ARMword virt_addr, ARMword data,	       ARMword datatype){	tlb_entry_t *tlb;	ARMword phys_addr;	fault_t fault;	ARMword temp, offset;	if (!(state->mmu.control & CONTROL_MMU)) {		if (datatype == ARM_BYTE_TYPE)			mem_write_byte (state, virt_addr, data);		else if (datatype == ARM_HALFWORD_TYPE)			mem_write_halfword (state, virt_addr, data);		else if (datatype == ARM_WORD_TYPE)			mem_write_word (state, virt_addr, data);		else {			printf ("SKYEYE:1 a71_mmu_write error: unknown data type %d\n", datatype);			skyeye_exit (-1);		}		return NO_FAULT;	}//      if ((virt_addr & 3) && (state->mmu.control & CONTROL_ALIGN_FAULT)) {	if ((virt_addr & 3) && (datatype == ARM_WORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT) || (virt_addr & 1)	    && (datatype == ARM_HALFWORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT)) {		fprintf (stderr, "SKYEYE, a71_mmu_write ALIGNMENT_FAULT\n");		return ALIGNMENT_FAULT;	}	if (state->mmu.control & CONTROL_CACHE) {		cache_line_t *cache;		cache = mmu_cache_search (state, CACHE (), virt_addr);		if (cache) {			if (datatype == ARM_WORD_TYPE)				cache->data[(virt_addr >> 2) & 3] = data;			else if (datatype == ARM_HALFWORD_TYPE) {				temp = cache->data[(virt_addr >> 2) & 3];				offset = (((ARMword) state->bigendSig * 2) ^ (virt_addr & 2)) << 3;	/* bit offset into the word */				cache->data[(virt_addr >> 2) & 3] =					(temp & ~(0xffffL << offset)) |					((data & 0xffffL) << offset);			}			else if (datatype == ARM_BYTE_TYPE) {				temp = cache->data[(virt_addr >> 2) & 3];				offset = (((ARMword) state->bigendSig * 3) ^ (virt_addr & 3)) << 3;	/* bit offset into the word */				cache->data[(virt_addr >> 2) & 3] =					(temp & ~(0xffL << offset)) |					((data & 0xffL) << offset);			}		}	}	fault = translate (state, virt_addr, TLB (), &tlb);	if (fault) {		return fault;	}	fault = check_access (state, virt_addr, tlb, 0);	if (fault) {		return fault;	}	phys_addr = (tlb->phys_addr & tlb_masks[tlb->mapping]) |		(virt_addr & ~tlb_masks[tlb->mapping]);	if (datatype == ARM_BYTE_TYPE)		mem_write_byte (state, phys_addr, data);	else if (datatype == ARM_HALFWORD_TYPE)		mem_write_halfword (state, phys_addr, data);	else if (datatype == ARM_WORD_TYPE)		mem_write_word (state, phys_addr, data);	else {		printf ("SKYEYE:2  a71_mmu_write error: unknown data type %d \n", datatype);		skyeye_exit (-1);	}	return NO_FAULT;}static ARMworda71_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value){	mmu_regnum_t creg = BITS (16, 19) & 15;	ARMword data;	switch (creg) {	case MMU_ID://              printf("mmu_mrc read ID     ");#if 0#ifdef MMU_V4		data = 0x41018100;	/* v4 */#else /*  */		data = 0x41007100;	/* v3 */#endif /*  */#endif /*  */		//data = 0x41007100; 		data = state->cpu->cpu_val;		break;	case MMU_CONTROL://              printf("mmu_mrc read CONTROL");		data = state->mmu.control;		break;	case MMU_TRANSLATION_TABLE_BASE://              printf("mmu_mrc read TTB    ");		data = state->mmu.translation_table_base;		break;	case MMU_DOMAIN_ACCESS_CONTROL://              printf("mmu_mrc read DACR   ");		data = state->mmu.domain_access_control;		break;	case MMU_FAULT_STATUS://              printf("mmu_mrc read FSR    ");		data = state->mmu.fault_status;		break;	case MMU_FAULT_ADDRESS://              printf("mmu_mrc read FAR    ");		data = state->mmu.fault_address;		break;	default:		printf ("mmu_mrc read UNKNOWN - reg %d\n", creg);		data = 0;		break;	}//      printf("\t\t\t\t\tpc = 0x%08x\n", state->Reg[15]);	*value = data;	return data;}static voida71_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value){	mmu_regnum_t creg = BITS (16, 19) & 15;	if (!strncmp (state->cpu->cpu_arch_name, "armv4", 5))	{		switch (creg) {		case MMU_CONTROL://              printf("mmu_mcr wrote CONTROL      ");			state->mmu.control = (value | 0x70) & 0xFFFF;			break;		case MMU_TRANSLATION_TABLE_BASE://              printf("mmu_mcr wrote TTB          ");			state->mmu.translation_table_base =				value & 0xFFFFC000;			break;		case MMU_DOMAIN_ACCESS_CONTROL://              printf("mmu_mcr wrote DACR         ");			state->mmu.domain_access_control = value;			break;//#ifdef MMU_V4		case MMU_FAULT_STATUS:			state->mmu.fault_status = value & 0xFF;			break;		case MMU_FAULT_ADDRESS:			state->mmu.fault_address = value;			break;		case MMU_V4_CACHE_OPS:	/* incomplete */			if ((BITS (5, 7) & 7) == 0) {				mmu_cache_invalidate_all (state, CACHE ());			}			break;		case MMU_V4_TLB_OPS:	/* incomplete */			switch (BITS (5, 7) & 7) {			case 0:				mmu_tlb_invalidate_all (state, TLB ());				break;			case 1:				mmu_tlb_invalidate_entry (state, TLB (),							  value);				break;			}			break;		default:			printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);			break;		}//#else	}	else {		switch (creg) {		case MMU_CONTROL:			state->mmu.control = (value | 0x70) & 0xFFFF;			break;		case MMU_TRANSLATION_TABLE_BASE:			state->mmu.translation_table_base =				value & 0xFFFFC000;			break;		case MMU_DOMAIN_ACCESS_CONTROL:			state->mmu.domain_access_control = value;			break;		case MMU_V3_FLUSH_TLB://              printf("mmu_mcr wrote FLUSH_TLB    ");			mmu_tlb_invalidate_all (state, TLB ());			break;		case MMU_V3_FLUSH_TLB_ENTRY://              printf("mmu_mcr wrote FLUSH_TLB_ENTRY");			mmu_tlb_invalidate_entry (state, TLB (), value);			break;		case MMU_V3_FLUSH_CACHE://              printf("mmu_mcr wrote FLUSH_CACHE    ");			mmu_cache_invalidate_all (state, CACHE ());			break;		default:			printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);			break;//#endif		}	}//      printf("\t\t\t\tpc = 0x%08x\n", state->Reg[15]);}static inta71_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr, ARMword * phys_addr){	tlb_entry_t *tlb;	ARMword temp, offset;	fault_t fault;	ARMword datatype = ARM_WORD_TYPE;	int ret = -1;	if ((virt_addr & 3) && (datatype == ARM_WORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT) || (virt_addr & 1)	    && (datatype == ARM_HALFWORD_TYPE)	    && (state->mmu.control & CONTROL_ALIGN_FAULT)) {		fprintf (stderr, "SKYEYE, a71_mmu_read ALIGNMENT_FAULT\n");		goto out;	}	if (!(state->mmu.control & CONTROL_MMU)) {		*phys_addr = virt_addr;	}	else {		fault = translate (state, virt_addr, TLB (), &tlb);		if (fault) {			goto out;		}		fault = check_access (state, virt_addr, tlb, 1);		if (fault) {			goto out;		}		*phys_addr = (tlb->phys_addr & tlb_masks[tlb->mapping]) |			(virt_addr & ~tlb_masks[tlb->mapping]);	}	ret = 0;      out:return (ret);}#undef CACHE#undef TLBmmu_ops_t arm7100_mmu_ops = {	a71_mmu_init, a71_mmu_exit, a71_mmu_read_byte, a71_mmu_write_byte, a71_mmu_read_halfword, a71_mmu_write_halfword, a71_mmu_read_word, a71_mmu_write_word, a71_mmu_read_word,	// load instr	a71_mmu_mcr, a71_mmu_mrc, a71_mmu_v2p_dbct	// ywc 2005-04-16 test};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -