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

📄 arm7100_mmu.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*

    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 int 

a71_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 void 

a71_mmu_exit (ARMul_State * state) 

{
  
mmu_cache_exit (CACHE ());
  
mmu_tlb_exit (TLB ());

} 

static fault_t 


a71_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_t 

a71_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_t 

a71_mmu_read_word (ARMul_State * state, ARMword virt_addr, ARMword * data) 

{
  
return a71_mmu_read (state, virt_addr, data, ARM_WORD_TYPE);

}




static fault_t 

a71_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);
	  
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);
	  
exit (-1);
	
}
      
return NO_FAULT;
    
}

}



static fault_t 

a71_mmu_write_byte (ARMul_State * state, ARMword virt_addr, ARMword data) 

{
  
return a71_mmu_write (state, virt_addr, data, ARM_BYTE_TYPE);

}

static fault_t 

a71_mmu_write_halfword (ARMul_State * state, ARMword virt_addr,
			ARMword data) 

{
  
return a71_mmu_write (state, virt_addr, data, ARM_HALFWORD_TYPE);

}

static fault_t 

a71_mmu_write_word (ARMul_State * state, ARMword virt_addr, ARMword data) 

{
  
return a71_mmu_write (state, virt_addr, data, ARM_WORD_TYPE);

}


static fault_t 

a71_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);
	  
exit (-1);

⌨️ 快捷键说明

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