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

📄 armmmu.h

📁 這是一個arm模擬器 以C++實做 主要模擬ARM9架構
💻 H
字号:
/*************************************************************************    Copyright (C) 2002 - 2007 Wei Qin    See file COPYING for more information.    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.*************************************************************************//*    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*/#ifndef SIMIT_ARMMMU_H#define SIMIT_ARMMMU_H#include "armemul.h"#include "tlb.h"namespace simit {#define ARMul_CP15_R5_ST_ALIGN  0x0001#define ARMul_CP15_R5_IMPRE     0x0406#define ARMul_CP15_R5_MMU_EXCPT 0x0400/* Bits in the control register */#define CONTROL_MMU             (1<<0)#define CONTROL_ALIGN_FAULT     (1<<1)#define CONTROL_CACHE           (1<<2)#define CONTROL_DATA_CACHE      (1<<2)#define CONTROL_WRITE_BUFFER    (1<<3)#define CONTROL_BIG_ENDIAN      (1<<7)#define CONTROL_SYSTEM          (1<<8)#define CONTROL_ROM             (1<<9)#define CONTROL_UNDEFINED            (1<<10)#define CONTROL_BRANCH_PREDICT       (1<<11)#define CONTROL_INSTRUCTION_CACHE    (1<<12)#define CONTROL_VECTOR               (1<<13)#define CONTROL_RR                   (1<<14)#define CONTROL_L4                   (1<<15)typedef enum mmu_size_t {	MMU_BYTE = 0x1,	MMU_HALF = 0x2,	MMU_WORD = 0x4,} mmu_size_t;typedef enum mmu_access_t {	MMU_WRITE = 0x0,	MMU_READ = 0x8,} mmu_access_t;/* FS[3:0] in the fault status register: */#ifndef SIMIT_TLB_Htypedef enum mmu_fault_t{	NO_FAULT = 0x0,	ALIGNMENT_FAULT = 0x1,	SECTION_TRANSLATION_FAULT = 0x5,	PAGE_TRANSLATION_FAULT = 0x7,	SECTION_DOMAIN_FAULT = 0x9,	PAGE_DOMAIN_FAULT = 0xB,	SECTION_PERMISSION_FAULT = 0xD,	SUBPAGE_PERMISSION_FAULT = 0xF,	/* this is for speed up checking access permisssion */		SLOW_ACCESS_CHECKING = 0x3,	/* this is for jit self-mofifying code check*/		JIT_ALARM_FAULT = 0xff,} mmu_fault_t;#endiftypedef struct mmu_page_table_entry_t{	unsigned int read_tag;	unsigned int write_tag;	word_t phys_addr;	byte_t *ptr;} mmu_page_table_entry_t;/* Register numbers in the MMU: */typedef enum mmu_regnum_t{	MMU_ID = 0,	MMU_CONTROL = 1,	MMU_TRANSLATION_TABLE_BASE = 2,	MMU_DOMAIN_ACCESS_CONTROL = 3,	MMU_FAULT_STATUS = 5,	MMU_FAULT_ADDRESS = 6,	MMU_CACHE_OPS = 7,	MMU_TLB_OPS = 8,	MMU_CACHE_LOCKDOWN = 9,	MMU_TLB_LOCKDOWN = 10,	MMU_PID = 13,	/*MMU_V4 */	MMU_V4_CACHE_OPS = 7,	MMU_V4_TLB_OPS = 8,	/*MMU_V3 */	MMU_V3_FLUSH_TLB = 5,	MMU_V3_FLUSH_TLB_ENTRY = 6,	MMU_V3_FLUSH_CACHE = 7,	/*MMU Intel SA-1100 */	MMU_SA_RB_OPS = 9,	MMU_SA_DEBUG = 14,	MMU_SA_CP15_R15 = 15,	//chy 2003-08-24	/*Intel xscale CP15 */	XSCALE_CP15_CACHE_TYPE = 0,	XSCALE_CP15_AUX_CONTROL = 1,	XSCALE_CP15_COPRO_ACCESS = 15,} mmu_regnum_t;/*virt_addr exchange according to CP15.R13(process id virtul mapping)*/#define MMU_PID_VA_MAP_MASK    0xfe000000#define MMU_ITLB_SIZE 32#define MMU_DTLB_SIZE 32#define MMU_HASH_SIZE 256#define MMU_HASH_INDEX(_a) ((_a>>12) & (MMU_HASH_SIZE - 1))#define MMU_HASH_MASK 0xfffff000class arm_mmu {	public:		/* constructor */		arm_mmu (arm_emulator *emula);		/* destructor */		~arm_mmu ();		/* reset */		void reset ();		mmu_fault_t read_byte (word_t virt_addr, byte_t  *data){			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);									if (pte->read_tag == (virt_addr & mask_array[MMU_BYTE - 1])){				DIRECT_READ_BYTE((pte->ptr+virt_addr),(*data));				return NO_FAULT;			}			else				return read_byte_slow(virt_addr,data);		}		mmu_fault_t read_hword (word_t virt_addr, hword_t *data){			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);						if (pte->read_tag == (virt_addr & mask_array[MMU_HALF - 1])){				DIRECT_READ_HALF_WORD((pte->ptr+virt_addr),(*data));				return NO_FAULT;			}			else				return read_hword_slow(virt_addr,data);		}		mmu_fault_t read_word (word_t virt_addr, word_t  *data){			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);						if (pte->read_tag == (virt_addr & mask_array[MMU_WORD - 1])){				DIRECT_READ_WORD((pte->ptr+virt_addr),(*data));				return NO_FAULT;			}			else				return read_word_slow(virt_addr,data);		}		mmu_fault_t write_byte (word_t virt_addr, byte_t  data){			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);						if (pte->write_tag == (virt_addr & mask_array[MMU_BYTE - 1])){				DIRECT_WRITE_BYTE((pte->ptr+virt_addr),data);				return NO_FAULT;			}			else				return write_byte_slow(virt_addr,data);		}		mmu_fault_t write_hword (word_t virt_addr, hword_t data) {			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);						if (pte->write_tag == (virt_addr & mask_array[MMU_HALF - 1])){				DIRECT_WRITE_HALF_WORD((pte->ptr+virt_addr),data);				return NO_FAULT;			}			else				return write_hword_slow(virt_addr,data);		}		mmu_fault_t write_word (word_t virt_addr, word_t  data) {			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);			if (pte->write_tag == (virt_addr & mask_array[MMU_WORD - 1])){				DIRECT_WRITE_WORD((pte->ptr+virt_addr),data);				return NO_FAULT;			}			else				return write_word_slow(virt_addr,data);		}		mmu_fault_t load_instr (word_t virt_addr, word_t  *instr) {			mmu_page_table_entry_t * pte = i_table + MMU_HASH_INDEX(virt_addr);						if (pte->read_tag == (virt_addr & MMU_HASH_MASK)){				DIRECT_READ_WORD((pte->ptr+virt_addr),(*instr));				return NO_FAULT;			}			else				return load_instr_slow(virt_addr,instr);		}				/* translates virtual instruction addr into physical address 			for jit directory */		mmu_fault_t translate_instr_addr (word_t virt_addr, word_t *phys_addr, 			byte_t **ptr){			mmu_page_table_entry_t * pte = i_table + MMU_HASH_INDEX(virt_addr);			if (pte->read_tag == (virt_addr & MMU_HASH_MASK)){				*phys_addr = (pte->phys_addr + virt_addr);				*ptr = (pte->ptr + virt_addr); 					return NO_FAULT;			}			else{				*ptr = NULL;				return translate_instr_addr_slow (virt_addr, phys_addr);			}		}		/* The MMU(copro 15) is accessible via MCR and MRC operations */		word_t mrc (word_t instr);		void mcr (word_t instr, word_t value);				/* evaluate all tlb entris access permision due to condition changeing*/		void evaluate_access_all	(void);				word_t high_vector(word_t vector) {			if (control & CONTROL_VECTOR)				return(vector + 0xffff0000); //for v4 high exception address			else				return(vector);	//for normal  address		}		void update_fsr_far (mmu_fault_t fault, word_t addr) {			fault_status =  (fault | (last_domain << 4))& 0xFF;			fault_address = addr;		}				/*XScale functions*/			void set_xscale(void){				set_control(0);			cache_type = 0xB1AA1AA;  //0000 1011 0001 1010 1010 0001 1010 1010			aux_control = 0;		}		word_t xscale_mrc (word_t instr);		void xscale_mcr (word_t instr, word_t value);				void xscale_update_fsr_far (word_t fsr, word_t far){			if (emu->is_xscale()) {				fault_status = fsr & 0x6FF;				fault_address = far;			}		}					bool cp_access_allowed (unsigned cpnum) {			if (emu->is_xscale())				return (copro_access & (1 << cpnum));			else				return true;		}		private:		/* translates virtual instruction addr into physical address */		mmu_fault_t translate_data_addr_slow (word_t virt_addr,				mmu_access_t read, mmu_size_t s,word_t *phys_addr);				/* data access routines */		mmu_fault_t read_byte_slow    (word_t virt_addr, byte_t  *data);		mmu_fault_t read_hword_slow   (word_t virt_addr, hword_t *data);		mmu_fault_t read_word_slow    (word_t virt_addr, word_t  *data);		mmu_fault_t write_byte_slow   (word_t virt_addr, byte_t  data);		mmu_fault_t write_hword_slow  (word_t virt_addr, hword_t data);		mmu_fault_t write_word_slow   (word_t virt_addr, word_t  data);		/* translates virtual instruction addr into physical address */		mmu_fault_t translate_instr_addr_slow (word_t virt_addr,			word_t *phys_addr);			/* load instruction uses itlb */		mmu_fault_t load_instr_slow (word_t virt_addr, word_t *instr);				/*retrive the page table entry from memory and save to designate TLB*/		mmu_fault_t translation_walk (word_t virt_addr, tlb_entry_t *tlb_e);				/*access permission calculating functions*/		void evaluate_access_entry	(int fast_access, tlb_entry_t *tlb_e);		mmu_fault_t check_access	(word_t virt_addr, tlb_entry_t *e,									mmu_access_t read);		int check_perms	(int ap, mmu_access_t rread) const;				/*set the value of control register*/		void set_control(word_t value);				/*set the value of process_id register*/		void set_process_id(word_t value);		/*set the value of domain access control register*/		void set_domain_access_control(word_t value){			if (domain_access_control != value){				domain_access_control = value;				for(int i=0;i<16;i++){					domain_access_array[i]=value & 3;					value= value>>2;				}				evaluate_access_all();			}		}		/*Fast Context Switch Extension (FCSE)*/		word_t mmu_pid_va_map(word_t va) {			if (process_id == 0)				return va;			else if (va & MMU_PID_VA_MAP_MASK)				return va; 			else 				return va | process_id;		}		void invalidate_tlb(word_t opcode2,word_t CRm,word_t value);		void add_mmu_page_entry(mmu_page_table_entry_t *x_table,				tlb_entry_t *tlb_e,word_t phys_addr,word_t virt_addr);		void remove_mmu_page_entry(mmu_page_table_entry_t *x_table,				tlb_entry_t *tlb_e);			protected:		arm_emulator *emu;		uint64_t fault_count;		word_t control;		word_t rs_flag;		word_t domain_access_array[16];		word_t domain_access_control;		word_t fault_status;		word_t fault_address;		word_t process_id;		word_t cache_locked_down;		word_t tlb_locked_down;		word_t last_domain;		word_t translation_table_base;		//chy 2003-08-24 for xscale		word_t cache_type;	// 0		word_t aux_control;	// 1		word_t copro_access;	// 15		/* tlbs */		tlb<MMU_ITLB_SIZE> *i_tlb;		tlb<MMU_DTLB_SIZE> *d_tlb;		/* FAST LOOK UP TABLE*/		mmu_page_table_entry_t	i_table[MMU_HASH_SIZE];		mmu_page_table_entry_t	d_table[MMU_HASH_SIZE];			tlb_entry_t dummy_entry;		word_t mask_array[4];	public:		/* Below is a special interface created for compiled simulation in		   system level. In compiled simulation, after a block of instruction		   is translated into a DLL, the block must be marked so that		   when a write to the block occurs, the simulator is notified so		   that the DLL is unloaded. We define an interface for the		   jit simulator to communicate with the MMU.		*/		/* call (*fcheck)(wchecker, addr) when loading an MMU cache entry,		   if it returns true, meaning the address is compiled, then		   set write_tag to an invalid value.		   In write_XXX_slow, call (*falarm)(wchecker, addr) to notify		   the simulator that an address is updated. If it returns true,		   then the write_slow function should return a JIT_ALARM_FAULT		   without updating the memory.		   Note addr should be physical address.		*/		typedef bool (wcheck_t)(void *, arm_addr_t);		typedef bool (walarm_t)(void *, arm_addr_t);		void register_write_checker(void * e, wcheck_t * fc, walarm_t * fa) {			wchecker = e;			fcheck = fc;			falarm = fa;		}			/* jit simulator calls this when a block is scheduled to be compiled */		void invalidate_write_cache(arm_addr_t virt_addr) {			mmu_page_table_entry_t * pte = d_table + MMU_HASH_INDEX(virt_addr);			if (pte->write_tag == (virt_addr & MMU_HASH_MASK))				pte->write_tag = 0xFFFFFFFF;		}		private:		void *wchecker;		wcheck_t *fcheck;		walarm_t *falarm;};} /* namespace */#endif /* SIMIT_ARMMMU_H */

⌨️ 快捷键说明

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