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

📄 xscale_copro.c

📁 这是Skyeye 0.9 版本的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  /*search main cache */
  b = tlb_b_flag (tlb);
  pa = tlb_va_to_pa (tlb, va);
  cache = mmu_cache_search (state, MAIN_D_CACHE (), va);
  if (cache)
    {
      cache_t = MAIN_D_CACHE ();
      goto has_cache;
    }
  //chy 2003-08-24, now maybe we don't need minidcache  ????
#if 0
  /*search mini cache */
  cache = mmu_cache_search (state, MINI_D_CACHE (), va);
  if (cache)
    {
      cache_t = MINI_D_CACHE ();
      goto has_cache;
    }
#endif
  b = tlb_b_flag (tlb);
  pa = tlb_va_to_pa (tlb, va);
  //chy 2003-08-24, check phy addr 0xa0000000, size 0x04000000
  //ywc 2004-11-30, inactive this check because of using 0xc0000000 as the framebuffer start address
  /*
     if(pa >= 0xb0000000){
     printf("SKYEYE:xscale_mmu_write phy address 0x%x error,reg[15] 0x%x\n",pa,state->Reg[15]);
     return 0;
     }
   */

  //chy 2003-08-24, now maybe we don't need WB  ????
#if 0
  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);
    }
#endif
  //chy 2003-08-24, just write phy addr
  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);
#if 0
//-------------------------------------------------------------
//chy 2003-09-02 for test ????
  if (datatype == ARM_WORD_TYPE)
    {
      if (real_va >= 0xffff0000 && real_va <= 0xffff0020)
	{
	  printf ("**SKYEYE:mmu_write word: pa %x, va %x, data %x, R15 %x \n",
		  pa, real_va, data, state->Reg[15]);
	}
    }
//--------------------------------------------------------------
#endif
  return 0;

has_cache:
  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;
//-------------------------------------------------------------
//chy 2003-09-03 be sure the changed value will be in memory as soon as possible, so I cache can get the newest value
#if 0
  {
    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);
  }
#endif
#if 0
//chy 2003-09-02 for test ????
  if (datatype == ARM_WORD_TYPE)
    {
      if (real_va >= 0xffff0000 && real_va <= 0xffff0020)
	{
	  printf
	    ("**SKYEYE:mmu_write word:cache: pa %x, va %x, data %x, R15 %x\n",
	     pa, real_va, data, state->Reg[15]);
	}
    }
//-------------------------------------------------------------
#endif
  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;
}

ARMword xscale_cp15_mrc (ARMul_State * state,
			 unsigned type, ARMword instr, ARMword * value)
{
  return xscale_mmu_mrc (state, instr, value);
}

ARMword xscale_mmu_mrc (ARMul_State * state, ARMword instr, ARMword * value)
{
  ARMword data;
  unsigned opcode_2 = BITS (5, 7);
  unsigned CRm = BITS (0, 3);
  unsigned reg = BITS (16, 19);
  unsigned result;
  mmu_regnum_t creg = reg;

/*
 printf("SKYEYE: xscale_cp15_mrc:opcode_2 0x%x, CRm 0x%x, reg 0x%x,reg[15] 0x%x, instr %x\n",opcode_2,CRm,reg,\
	state->Reg[15], instr);
*/
  switch (creg)
    {
    case MMU_ID:		//XSCALE_CP15
      //printf("mmu_mrc read ID       \n");
      data = (opcode_2 ? state->mmu.cache_type : skyeye_config.cpu->cpu_val);
      break;
    case MMU_CONTROL:		//XSCALE_CP15_AUX_CONTROL
      //printf("mmu_mrc read CONTROL  \n");
      data = (opcode_2 ? state->mmu.aux_control : state->mmu.control);
      break;
    case MMU_TRANSLATION_TABLE_BASE:
      //printf("mmu_mrc read TTB      \n");
      data = state->mmu.translation_table_base;
      break;
    case MMU_DOMAIN_ACCESS_CONTROL:
      //printf("mmu_mrc read DACR     \n");
      data = state->mmu.domain_access_control;
      break;
    case MMU_FAULT_STATUS:
      //printf("mmu_mrc read FSR      \n");
      data = state->mmu.fault_status;
      break;
    case MMU_FAULT_ADDRESS:
      //printf("mmu_mrc read FAR      \n");
      data = state->mmu.fault_address;
      break;
    case MMU_PID:
      //printf("mmu_mrc read PID      \n");
      data = state->mmu.process_id;
    case XSCALE_CP15_COPRO_ACCESS:
      //printf("xscale cp15 read coprocessor access\n");
      data = state->mmu.copro_access;
      break;
    default:
      data = 0;
      printf ("SKYEYE: xscale_cp15_mrc read UNKNOWN - reg %d, pc 0x%x\n",
	      creg, state->Reg[15]);
      exit (-1);
      break;
    }
  *value = data;
  //printf("SKYEYE: xscale_cp15_mrc:end value  0x%x\n",data);
  return data;
}

void xscale_cp15_cache_ops (ARMul_State * state, ARMword instr, ARMword value)
{
//chy: 2003-08-24 now, the BTB isn't simualted ....????

  unsigned CRm, OPC_2;

  CRm = BITS (0, 3);
  OPC_2 = BITS (5, 7);
  //err_msg("SKYEYE: xscale cp15_cache_ops:OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n", OPC_2, CRm,state->Reg[15]);

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

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

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

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

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

  if (OPC_2 == 4 && CRm == 0xa)
    {
      mmu_wb_drain_all (state, WB ());
      return;
    }

  if (OPC_2 == 6 && CRm == 5)
    {
      //chy 2004-07-19 shoud fix in the future????!!!!
      //printf("SKYEYE: xscale_cp15_cache_ops:invalidate BTB CANT!!!!!!!!!!\n"); 
      //exit(-1);
      return;
    }

  if (OPC_2 == 5 && CRm == 2)
    {
      //printf("SKYEYE: cp15_c_o: A L in D C, value %x, reg15 %x\n",value, state->Reg[15]); 
      //exit(-1);
      //chy 2003-09-01 for test
      mmu_cache_invalidate_all (state, MAIN_D_CACHE ());
      return;
    }

  err_msg
    ("SKYEYE: xscale cp15_cache_ops:Unknown OPC_2 = 0x%x CRm = 0x%x, Reg15 0x%x\n",
     OPC_2, CRm, state->Reg[15]);
  exit (-1);
}

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

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


  //err_msg("SKYEYE:xscale_cp15_tlb_ops:OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n", OPC_2, CRm,state->Reg[15]);
  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 == 1 && CRm == 0x5)
    {
      mmu_tlb_invalidate_entry (state, I_TLB (), value);
      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
    ("SKYEYE:xscale_cp15_tlb_ops:Unknow OPC_2 = 0x%x CRm = 0x%x,Reg[15] 0x%x\n",
     OPC_2, CRm, state->Reg[15]);
  exit (-1);
}


ARMword xscale_cp15_mcr (ARMul_State * state,
			 unsigned type, ARMword instr, ARMword value)
{
  return xscale_mmu_mcr (state, instr, value);
}

ARMword xscale_mmu_mcr (ARMul_State * state, ARMword instr, ARMword value)
{
  ARMword data;
  unsigned opcode_2 = BITS (5, 7);
  unsigned CRm = BITS (0, 3);
  unsigned reg = BITS (16, 19);
  unsigned result;
  mmu_regnum_t creg = reg;

  //printf("SKYEYE: xscale_cp15_mcr: opcode_2 0x%x, CRm 0x%x, reg ox%x, value 0x%x, reg[15] 0x%x, instr 0x%x\n",opcode_2,CRm,reg, value, state->Reg[15], instr);

  switch (creg)
    {
    case MMU_CONTROL:
      //printf("mmu_mcr wrote CONTROL  val 0x%x       \n",value);
      state->mmu.control = (opcode_2 ? (value & 0x33) : (value & 0x3FFF));
      break;
    case MMU_TRANSLATION_TABLE_BASE:
      //printf("mmu_mcr wrote TTB      val 0x%x       \n",value);
      state->mmu.translation_table_base = value & 0xFFFFC000;
      break;
    case MMU_DOMAIN_ACCESS_CONTROL:
      //printf("mmu_mcr wrote DACR    val 0x%x \n",value);
      state->mmu.domain_access_control = value;
      break;

    case MMU_FAULT_STATUS:
      //printf("mmu_mcr wrote FS        val 0x%x \n",value);
      state->mmu.fault_status = value & 0x6FF;
      break;
    case MMU_FAULT_ADDRESS:
      //printf("mmu_mcr wrote FA         val 0x%x \n",value);
      state->mmu.fault_address = value;
      break;

    case MMU_CACHE_OPS:
//              printf("mmu_mcr wrote CO         val 0x%x \n",value);
      xscale_cp15_cache_ops (state, instr, value);
      break;
    case MMU_TLB_OPS:
      //printf("mmu_mcr wrote TO          val 0x%x \n",value);
      xscale_cp15_tlb_ops (state, instr, value);
      break;
    case MMU_PID:
      //printf("mmu_mcr wrote PID          val 0x%x \n",value);
      state->mmu.process_id = value & 0xfe000000;
      break;
    case XSCALE_CP15_COPRO_ACCESS:
      //printf("xscale cp15 write coprocessor access  val 0x %x\n",value);
      state->mmu.copro_access = value & 0x3ff;
      break;

    default:
      printf ("SKYEYE: xscale_cp15_mcr wrote UNKNOWN - reg %d, reg15 0x%x\n",
	      creg, state->Reg[15]);
      break;
    }
  //printf("SKYEYE: xscale_cp15_mcr wrote val 0x%x\n", value);
  return 0;
}

//teawater add for arm2x86 2005.06.24-------------------------------------------
static int 
xscale_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--------------------------------------------------------------------------

/*xscale mmu_ops_t*/
mmu_ops_t xscale_mmu_ops =
{
  xscale_cp15_init,
    xscale_cp15_exit,
    xscale_mmu_read_byte,
    xscale_mmu_write_byte,
    xscale_mmu_read_halfword,
    xscale_mmu_write_halfword,
    xscale_mmu_read_word,
    xscale_mmu_write_word,
    xscale_mmu_load_instr, xscale_mmu_mcr, xscale_mmu_mrc,
//teawater add for arm2x86 2005.06.24-------------------------------------------
    xscale_mmu_v2p_dbct,
//AJ2D--------------------------------------------------------------------------
};

⌨️ 快捷键说明

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