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

📄 arm920t_mmu.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    {
      d_msg ("align\n");
      return ALIGNMENT_FAULT;
    }				//else
  va &= ~(WORD_SIZE - 1);
  /*tlb translate */
  fault = translate (state, va, ARM920T_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, ARM920T_D_CACHE (), va);
  if (cache)
    {
      update_cache (state, va, data, datatype, cache, ARM920T_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, ARM920T_WB (), pa, &data, 4);
	      else if (datatype == ARM_HALFWORD_TYPE)
		mmu_wb_write_bytes (state, ARM920T_WB (),
				    (pa | (real_va & 2)), &data, 2);
	      else if (datatype == ARM_BYTE_TYPE)
		mmu_wb_write_bytes (state, ARM920T_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, ARM920T_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
arm920t_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
  mmu_regnum_t creg = BITS (16, 19) & 0xf;
  int OPC_2 = BITS (5, 7) & 0x7;
  ARMword data;

  switch (creg)
    {
    case MMU_ID:
      if (OPC_2 == 0)
	data = skyeye_config.cpu->cpu_val;
      else if (OPC_2 == 1)
	/* Cache type: 
	 * 000 0110 1 000 101 110 0 10 000 101 110 0 10
	 * */
	data = 0x0D172172;
      break;
    case MMU_CONTROL:
      /*
       * 6:3          should be 1.
       * 11:10        should be 0
       * */
      data = (state->mmu.control | 0x78) & 0xFFFFF3FF;;
      break;
    case MMU_TRANSLATION_TABLE_BASE:
      data = state->mmu.translation_table_base;
      break;
    case MMU_DOMAIN_ACCESS_CONTROL:
      data = state->mmu.domain_access_control;
      break;
    case MMU_FAULT_STATUS:
      /* OPC_2 = 0: data FSR value
       * */
      if (OPC_2 == 0)
	data = state->mmu.fault_status;
      break;
    case MMU_FAULT_ADDRESS:
      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;
}

/* ARM920T Cache Operation, P44
 * */
void
arm920t_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, ARM920T_I_CACHE ());
      mmu_cache_invalidate_all (state, ARM920T_D_CACHE ());
      return;
    }

  if (OPC_2 == 0 && CRm == 5)
    {
      mmu_cache_invalidate_all (state, ARM920T_I_CACHE ());
      return;
    }
  /*Invalidate ICache single entry
   **/
  if (OPC_2 == 1 && CRm == 5)
    {
      mmu_cache_invalidate (state, ARM920T_I_CACHE (), value);
      return;
    }
  /* FIXME: should complete
   * Prefetch ICache line (using MVA)
   * */
  if (OPC_2 == 1 && CRm == 13)
    {
      //mmu_cache_invalidate(state, ARM920T_I_CACHE(), value);
      return;
    }

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

  /* Invalidate DCache single entry (using MVA)
   * */
  if (OPC_2 == 1 && CRm == 6)
    {
      mmu_cache_invalidate (state, ARM920T_D_CACHE (), value);
      return;
    }
  /* Clean DCache single entry (using MVA)
   * */
  if (OPC_2 == 1 && CRm == 0xa)
    {
      mmu_cache_clean (state, ARM920T_D_CACHE (), value);
      return;
    }
  /* Clean and Invalidate DCache entry (using MVA)
   * */
  if (OPC_2 == 1 && CRm == 14)
    {
      mmu_cache_clean (state, ARM920T_D_CACHE (), value);
      mmu_cache_invalidate (state, ARM920T_D_CACHE (), value);
      return;
    }
  /* Clean DCache single entry (using index)
   * */
  if (OPC_2 == 2 && CRm == 0xa)
    {
      mmu_cache_clean_by_index (state, ARM920T_D_CACHE (), value);
      return;
    }
  /* Clean and Invalidate DCache entry (using index)
   * */
  if (OPC_2 == 2 && CRm == 14)
    {
      mmu_cache_clean_by_index (state, ARM920T_D_CACHE (), value);
      mmu_cache_invalidate_by_index (state, ARM920T_D_CACHE (), value);
      return;
    }

  /* Drain write buffer
   * */
  if (OPC_2 == 4 && CRm == 0xa)
    {
      mmu_wb_drain_all (state, ARM920T_WB ());
      return;
    }
  /* FIXME: how to do a waiting operation?
   * Wait for a interrupt
   * */
  if (OPC_2 == 4 && CRm == 0)
    {
      return;
    }
  err_msg ("Unknow OPC_2 = %x CRm = %x\n", OPC_2, CRm);
}

static void
arm920t_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, ARM920T_I_TLB ());
      mmu_tlb_invalidate_all (state, ARM920T_D_TLB ());
      return;
    }

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

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

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

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

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

static void
arm920t_mmu_cache_lockdown (ARMul_State * state, ARMword instr, ARMword value)
{
  int OPC_2 = BITS (5, 7) & 0x7;
}
static void
arm920t_mmu_tlb_lockdown (ARMul_State * state, ARMword instr, ARMword value)
{
}


static ARMword
arm920t_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
  mmu_regnum_t creg = BITS (16, 19) & 15;
  int OPC_2 = BITS (5, 7) & 0x7;
  if (!strncmp (skyeye_config.cpu->cpu_arch_name, "armv4", 5))
    {
      switch (creg)
	{
	case MMU_CONTROL:
//              printf("mmu_mcr wrote CONTROL      ");
	  state->mmu.control = (value | 0x78) & 0xFFFFF3FF;
	  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:
	  if (OPC_2 == 0)
	    state->mmu.fault_status = value & 0xFF;
	  break;
	case MMU_FAULT_ADDRESS:
	  state->mmu.fault_address = value;
	  break;

	case MMU_CACHE_OPS:
	  arm920t_mmu_cache_ops (state, instr, value);
	  break;
	case MMU_TLB_OPS:
	  arm920t_mmu_tlb_ops (state, instr, value);
	  break;
	case MMU_CACHE_LOCKDOWN:
	  /* 
	   * FIXME: cache lock down*/
	  break;
	case MMU_TLB_LOCKDOWN:
	  /* FIXME:tlb lock down */
	  break;
	case MMU_PID:
	  /*0:24 should be zero. */
	  state->mmu.process_id = value & 0xfe000000;
	  break;

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

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

arm920t_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, ARM920T_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--------------------------------------------------------------------------

/*arm920t mmu_ops_t*/
mmu_ops_t arm920t_mmu_ops = {
  arm920t_mmu_init,
  arm920t_mmu_exit,
  arm920t_mmu_read_byte,
  arm920t_mmu_write_byte,
  arm920t_mmu_read_halfword,
  arm920t_mmu_write_halfword,
  arm920t_mmu_read_word,
  arm920t_mmu_write_word,
  arm920t_mmu_load_instr,
  arm920t_mmu_mcr,
  arm920t_mmu_mrc,
//teawater add for arm2x86 2005.06.19-------------------------------------------
  arm920t_mmu_v2p_dbct,
//AJ2D--------------------------------------------------------------------------
};

⌨️ 快捷键说明

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