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

📄 sa_mmu.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
  va = mmu_pid_va_map (va);
  real_va = va;

  /*search instruction cache */
  cache = mmu_cache_search (state, I_CACHE (), va);
  if (cache)
    {
      update_cache (state, va, data, datatype, cache, I_CACHE (), real_va);
    }

  if (MMU_Disabled)
    {
      //mem_write_word(state, va, data);
      if (datatype == ARM_BYTE_TYPE)
	mem_write_byte (state, va, data);
      else if (datatype == ARM_HALFWORD_TYPE)
	mem_write_halfword (state, va, data);
      else if (datatype == ARM_WORD_TYPE)
	mem_write_word (state, va, data);
      else
	{
	  printf ("SKYEYE:1 sa_mmu_write error: unknown data type %d\n",
		  datatype);
	  exit (-1);
	}

      return 0;
    }
  /*align check */
  //if ((va & (WORD_SIZE - 1)) && MMU_Aligned){
  if (((va & 3) && (datatype == ARM_WORD_TYPE) && MMU_Aligned) ||
      ((va & 1) && (datatype == ARM_HALFWORD_TYPE) && MMU_Aligned))
    {
      d_msg ("align\n");
      return ALIGNMENT_FAULT;
    }				//else
  va &= ~(WORD_SIZE - 1);
  /*tlb translate */
  fault = translate (state, va, D_TLB (), &tlb);
  if (fault)
    {
      d_msg ("translate\n");
      return fault;
    }
  /*tlb check access */
  fault = check_access (state, va, tlb, 0);
  if (fault)
    {
      d_msg ("check_access\n");
      return fault;
    }
  /*search main cache */
  cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
  if (cache)
    {
      update_cache (state, va, data, datatype, cache, MAIN_D_CACHE (),
		    real_va);
    }
  else
    {
      /*search mini cache */
      cache = mmu_cache_search (state, MINI_D_CACHE (), va);
      if (cache)
	{
	  update_cache (state, va, data, datatype, cache, MINI_D_CACHE (),
			real_va);
	}
    }

  if (!cache)
    {
      b = tlb_b_flag (tlb);
      pa = tlb_va_to_pa (tlb, va);
      if (b)
	{
	  if (MMU_WBEnabled)
	    {
	      if (datatype == ARM_WORD_TYPE)
		mmu_wb_write_bytes (state, WB (), pa, &data, 4);
	      else if (datatype == ARM_HALFWORD_TYPE)
		mmu_wb_write_bytes (state, WB (), (pa | (real_va & 2)), &data,
				    2);
	      else if (datatype == ARM_BYTE_TYPE)
		mmu_wb_write_bytes (state, WB (), (pa | (real_va & 3)), &data,
				    1);

	    }
	  else
	    {
	      if (datatype == ARM_WORD_TYPE)
		mem_write_word (state, pa, data);
	      else if (datatype == ARM_HALFWORD_TYPE)
		mem_write_halfword (state, (pa | (real_va & 2)), data);
	      else if (datatype == ARM_BYTE_TYPE)
		mem_write_byte (state, (pa | (real_va & 3)), data);
	    }
	}
      else
	{
	  mmu_wb_drain_all (state, WB ());

	  if (datatype == ARM_WORD_TYPE)
	    mem_write_word (state, pa, data);
	  else if (datatype == ARM_HALFWORD_TYPE)
	    mem_write_halfword (state, (pa | (real_va & 2)), data);
	  else if (datatype == ARM_BYTE_TYPE)
	    mem_write_byte (state, (pa | (real_va & 3)), data);
	}
    }
  return 0;
}

static fault_t
update_cache (ARMul_State * state, ARMword va, ARMword data, ARMword datatype,
	      cache_line_t * cache, cache_t * cache_t, ARMword real_va)
{
  ARMword temp, offset;

  ARMword index = va_cache_index (va, cache_t);

  //cache->data[index] = data;

  if (datatype == ARM_WORD_TYPE)
    cache->data[index] = data;
  else if (datatype == ARM_HALFWORD_TYPE)
    {
      temp = cache->data[index];
      offset = (((ARMword) state->bigendSig * 2) ^ (real_va & 2)) << 3;	/* bit offset into the word */
      cache->data[index] =
	(temp & ~(0xffffL << offset)) | ((data & 0xffffL) << offset);
    }
  else if (datatype == ARM_BYTE_TYPE)
    {
      temp = cache->data[index];
      offset = (((ARMword) state->bigendSig * 3) ^ (real_va & 3)) << 3;	/* bit offset into the word */
      cache->data[index] =
	(temp & ~(0xffL << offset)) | ((data & 0xffL) << offset);
    }

  if (index < (cache_t->width >> (WORD_SHT + 1)))
    cache->tag |= TAG_FIRST_HALF_DIRTY;
  else
    cache->tag |= TAG_LAST_HALF_DIRTY;

  return 0;
}

ARMword
sa_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     ");
      data = 0x41007100;	/* v3 */
      data = skyeye_config.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;
    case MMU_PID:
      data = state->mmu.process_id;
    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;
}

void
sa_mmu_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
{
  int CRm, OPC_2;

  CRm = BITS (0, 3);
  OPC_2 = BITS (5, 7);

  if (OPC_2 == 0 && CRm == 7)
    {
      mmu_cache_invalidate_all (state, I_CACHE ());
      mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
      mmu_cache_invalidate_all (state, MINI_D_CACHE ());
      return;
    }

  if (OPC_2 == 0 && CRm == 5)
    {
      mmu_cache_invalidate_all (state, I_CACHE ());
      return;
    }

  if (OPC_2 == 0 && CRm == 6)
    {
      mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
      mmu_cache_invalidate_all (state, MINI_D_CACHE ());
      return;
    }

  if (OPC_2 == 1 && CRm == 6)
    {
      mmu_cache_invalidate (state, MAIN_D_CACHE (), value);
      mmu_cache_invalidate (state, MINI_D_CACHE (), value);
      return;
    }

  if (OPC_2 == 1 && CRm == 0xa)
    {
      mmu_cache_clean (state, MAIN_D_CACHE (), value);
      mmu_cache_clean (state, MINI_D_CACHE (), value);
      return;
    }

  if (OPC_2 == 4 && CRm == 0xa)
    {
      mmu_wb_drain_all (state, WB ());
      return;
    }
  err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}

static void
sa_mmu_tlb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
  int CRm, OPC_2;

  CRm = BITS (0, 3);
  OPC_2 = BITS (5, 7);


  if (OPC_2 == 0 && CRm == 0x7)
    {
      mmu_tlb_invalidate_all (state, I_TLB ());
      mmu_tlb_invalidate_all (state, D_TLB ());
      return;
    }

  if (OPC_2 == 0 && CRm == 0x5)
    {
      mmu_tlb_invalidate_all (state, I_TLB ());
      return;
    }

  if (OPC_2 == 0 && CRm == 0x6)
    {
      mmu_tlb_invalidate_all (state, D_TLB ());
      return;
    }

  if (OPC_2 == 1 && CRm == 0x6)
    {
      mmu_tlb_invalidate_entry (state, D_TLB (), value);
      return;
    }

  err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}

static void
sa_mmu_rb_ops (ARMul_State * state, ARMword instr, ARMword value)
{
  int CRm, OPC_2;

  CRm = BITS (0, 3);
  OPC_2 = BITS (5, 7);

  if (OPC_2 == 0x0 && CRm == 0x0)
    {
      mmu_rb_invalidate_all (RB ());
      return;
    }

  if (OPC_2 == 0x2)
    {
      int idx = CRm & 0x3;
      int type = ((CRm >> 2) & 0x3) + 1;

      if ((idx < 4) && (type < 4))
	mmu_rb_load (state, RB (), idx, type, value);
      return;
    }

  if ((OPC_2 == 1) && (CRm < 4))
    {
      mmu_rb_invalidate_entry (RB (), CRm);
      return;
    }

  err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}

static void
sa_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
  mmu_regnum_t creg = BITS (16, 19) & 15;
  if (!strncmp (skyeye_config.cpu->cpu_arch_name, "armv4", 5))
    {
      switch (creg)
	{
	case MMU_CONTROL:
//              printf("mmu_mcr wrote CONTROL      ");
	  state->mmu.control = (value | 0x70) & 0xFFFD;
	  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;

	case MMU_FAULT_STATUS:
	  state->mmu.fault_status = value & 0xFF;
	  break;
	case MMU_FAULT_ADDRESS:
	  state->mmu.fault_address = value;
	  break;

	case MMU_CACHE_OPS:
	  sa_mmu_cache_ops (state, instr, value);
	  break;
	case MMU_TLB_OPS:
	  sa_mmu_tlb_ops (state, instr, value);
	  break;
	case MMU_SA_RB_OPS:
	  sa_mmu_rb_ops (state, instr, value);
	  break;
	case MMU_SA_DEBUG:
	  break;
	case MMU_SA_CP15_R15:
	  break;
	case MMU_PID:
	  //2004-06-06 lyh, bug provided by wen ye wenye@cs.ucsb.edu
	  state->mmu.process_id = value & 0x7e000000;
	  break;

	default:
	  printf ("mmu_mcr wrote UNKNOWN - reg %d\n", creg);
	  break;
	}
    }
}

//teawater add for arm2x86 2005.06.24-------------------------------------------
static int 

sa_mmu_v2p_dbct (ARMul_State * state, ARMword virt_addr,
		 ARMword * phys_addr) 

{
  fault_t fault;
  
tlb_entry_t * tlb;

  virt_addr = mmu_pid_va_map (virt_addr);
  if (MMU_Enabled)
    {
      

	/*align check */ 

	if ((virt_addr & (WORD_SIZE - 1)) && MMU_Aligned)
	{
	  
d_msg ("align\n");
	  
return ALIGNMENT_FAULT;
	
}
      else
	
virt_addr &= ~(WORD_SIZE - 1);
      


	/*translate tlb */ 

	fault = translate (state, virt_addr, I_TLB (), &tlb);
      
if (fault)
	{
	  
d_msg ("translate\n");
	  
return fault;
	
}
      


	/*check access */ 

	fault = check_access (state, virt_addr, tlb, 1);
      
if (fault)
	{
	  
d_msg ("check_fault\n");
	  
return fault;
	
}
    
}

  if (MMU_Disabled)
    {
      *phys_addr = virt_addr;
    }
  else
    {
      *phys_addr = tlb_va_to_pa (tlb, virt_addr);
    }

  return (0);
}

//AJ2D--------------------------------------------------------------------------

/*sa mmu_ops_t*/
mmu_ops_t sa_mmu_ops = {
  sa_mmu_init,
  sa_mmu_exit,
  sa_mmu_read_byte,
  sa_mmu_write_byte,
  sa_mmu_read_halfword,
  sa_mmu_write_halfword,
  sa_mmu_read_word,
  sa_mmu_write_word,
  sa_mmu_load_instr,
  sa_mmu_mcr,
  sa_mmu_mrc,
//teawater add for arm2x86 2005.06.24-------------------------------------------
  sa_mmu_v2p_dbct, 

//AJ2D--------------------------------------------------------------------------
};

⌨️ 快捷键说明

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