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

📄 armcopro.c

📁 skyeye-1.0.0.rar surce code
💻 C
📖 第 1 页 / 共 3 页
字号:

void
XScale_check_memacc (ARMul_State * state, ARMword * address, int store)
{
  ARMword dbcon, r0, r1;
  int e1, e0;

  if (!state->is_XScale)
    return;

  /* Check for PID-ification.
     XXX BTB access support will require this test failing.  */
  r0 = (read_cp15_reg (13, 0, 0) & 0xfe000000);
  if (r0 && (*address & 0xfe000000) == 0)
    *address |= r0;

  /* Check alignment fault enable/disable.  */
  if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN) && (*address & 3))
    {
      /* Set the FSR and FAR.
         Do not use XScale_set_fsr_far as this checks the DCSR register.  */
      write_cp15_reg (state, 5, 0, 0, ARMul_CP15_R5_MMU_EXCPT);
      write_cp15_reg (state, 6, 0, 0, *address);

      ARMul_Abort (state, ARMul_DataAbortV);
    }

  if (XScale_debug_moe (state, -1))
    return;

  /* Check the data breakpoint registers.  */
  dbcon = read_cp15_reg (14, 0, 4);
  r0 = read_cp15_reg (14, 0, 0);
  r1 = read_cp15_reg (14, 0, 3);
  e0 = dbcon & ARMul_CP15_DBCON_E0;

  if (dbcon & ARMul_CP15_DBCON_M)
    {
      /* r1 is a inverse mask.  */
      if (e0 != 0 && ((store && e0 != 3) || (!store && e0 != 1))
	  && ((*address & ~r1) == (r0 & ~r1)))
	{
	  XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
	  ARMul_OSHandleSWI (state, SWI_Breakpoint);
	}
    }
  else
    {
      if (e0 != 0 && ((store && e0 != 3) || (!store && e0 != 1))
	  && ((*address & ~3) == (r0 & ~3)))
	{
	  XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
	  ARMul_OSHandleSWI (state, SWI_Breakpoint);
	}

      e1 = (dbcon & ARMul_CP15_DBCON_E1) >> 2;
      if (e1 != 0 && ((store && e1 != 3) || (!store && e1 != 1))
	  && ((*address & ~3) == (r1 & ~3)))
	{
	  XScale_debug_moe (state, ARMul_CP14_R10_MOE_DB);
	  ARMul_OSHandleSWI (state, SWI_Breakpoint);
	}
    }
}

/* Set the XScale FSR and FAR registers.  */

void
XScale_set_fsr_far (ARMul_State * state, ARMword fsr, ARMword far)
{
  if (!state->is_XScale || (read_cp14_reg (10) & (1UL << 31)) == 0)
    return;

  write_cp15_reg (state, 5, 0, 0, fsr);
  write_cp15_reg (state, 6, 0, 0, far);
}

/* Set the XScale debug `method of entry' if it is enabled.  */

int
XScale_debug_moe (ARMul_State * state, int moe)
{
  ARMword value;

  if (!state->is_XScale)
    return 1;

  value = read_cp14_reg (10);
  if (value & (1UL << 31))
    {
      if (moe != -1)
	{
	  value &= ~0x1c;
	  value |= moe;

	  write_cp14_reg (10, value);
	}
      return 1;
    }
  return 0;
}
#endif

/* Coprocessor 13:  Interrupt Controller and Bus Controller.  */

/* There are two sets of registers for copro 13.
   One set (of three registers) is available when CRm is 0
   and the other set (of six registers) when CRm is 1.  */

static ARMword XScale_cp13_CR0_Regs[16];
static ARMword XScale_cp13_CR1_Regs[16];

static unsigned
XScale_cp13_init (ARMul_State * state ATTRIBUTE_UNUSED)
{
  int i;

  for (i = 16; i--;)
    {
      XScale_cp13_CR0_Regs[i] = 0;
      XScale_cp13_CR1_Regs[i] = 0;
    }
}

/* Check an access to a register.  */

static unsigned
check_cp13_access (ARMul_State * state,
		   unsigned reg,
		   unsigned CRm, unsigned opcode_1, unsigned opcode_2)
{
  /* Do not allow access to these registers in USER mode.  */
  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
    return ARMul_CANT;

  /* The opcodes should be zero.  */
  if ((opcode_1 != 0) || (opcode_2 != 0))
    return ARMul_CANT;

  /* Do not allow access to these register if bit
     13 of coprocessor 15's register 15 is zero.  */
  if (!CP_ACCESS_ALLOWED (state, 13))
    return ARMul_CANT;

  /* Registers 0, 4 and 8 are defined when CRm == 0.
     Registers 0, 1, 4, 5, 6, 7, 8 are defined when CRm == 1.
     For all other CRm values undefined behaviour results.  */
  if (CRm == 0)
    {
      if (reg == 0 || reg == 4 || reg == 8)
	return ARMul_DONE;
    }
  else if (CRm == 1)
    {
      if (reg == 0 || reg == 1 || (reg >= 4 && reg <= 8))
	return ARMul_DONE;
    }

  return ARMul_CANT;
}

#if 0
/* Store a value into one of coprocessor 13's registers.  */

static void
write_cp13_reg (unsigned reg, unsigned CRm, ARMword value)
{
  switch (CRm)
    {
    case 0:
      switch (reg)
	{
	case 0:		/* INTCTL */
	  /* Only BITS (3:0) can be written.  */
	  value &= 0xf;
	  break;

	case 4:		/* INTSRC */
	  /* No bits may be written.  */
	  return;

	case 8:		/* INTSTR */
	  /* Only BITS (1:0) can be written.  */
	  value &= 0x3;
	  break;

	default:
	  /* Should not happen.  Ignore any writes to unimplemented registers.  */
	  return;
	}

      XScale_cp13_CR0_Regs[reg] = value;
      break;

    case 1:
      switch (reg)
	{
	case 0:		/* BCUCTL */
	  /* Only BITS (30:28) and BITS (3:0) can be written.
	     BIT(31) is write ignored.  */
	  value &= 0x7000000f;
	  value |= XScale_cp13_CR1_Regs[0] & (1UL << 31);
	  break;

	case 1:		/* BCUMOD */
	  /* Only bit 0 is accecssible.  */
	  value &= 1;
	  value |= XScale_cp13_CR1_Regs[1] & ~1;
	  break;

	case 4:		/* ELOG0 */
	case 5:		/* ELOG1 */
	case 6:		/* ECAR0 */
	case 7:		/* ECAR1 */
	  /* No bits can be written.  */
	  return;

	case 8:		/* ECTST */
	  /* Only BITS (7:0) can be written.  */
	  value &= 0xff;
	  break;

	default:
	  /* Should not happen.  Ignore any writes to unimplemented registers.  */
	  return;
	}

      XScale_cp13_CR1_Regs[reg] = value;
      break;

    default:
      /* Should not happen.  */
      break;
    }

  return;
}

/* Return the value in a cp13 register.  */

static ARMword
read_cp13_reg (unsigned reg, unsigned CRm)
{
  if (CRm == 0)
    return XScale_cp13_CR0_Regs[reg];
  else if (CRm == 1)
    return XScale_cp13_CR1_Regs[reg];

  return 0;
}

static unsigned
XScale_cp13_LDC (ARMul_State * state, unsigned type, ARMword instr,
		 ARMword data)
{
  unsigned reg = BITS (12, 15);
  unsigned result;

  result = check_cp13_access (state, reg, 0, 0, 0);

  if (result == ARMul_DONE && type == ARMul_DATA)
    write_cp13_reg (reg, 0, data);

  return result;
}

static unsigned
XScale_cp13_STC (ARMul_State * state, unsigned type, ARMword instr,
		 ARMword * data)
{
  unsigned reg = BITS (12, 15);
  unsigned result;

  result = check_cp13_access (state, reg, 0, 0, 0);

  if (result == ARMul_DONE && type == ARMul_DATA)
    *data = read_cp13_reg (reg, 0);

  return result;
}

static unsigned
XScale_cp13_MRC (ARMul_State * state,
		 unsigned type ATTRIBUTE_UNUSED,
		 ARMword instr, ARMword * value)
{
  unsigned CRm = BITS (0, 3);
  unsigned reg = BITS (16, 19);
  unsigned result;

  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));

  if (result == ARMul_DONE)
    *value = read_cp13_reg (reg, CRm);

  return result;
}

static unsigned
XScale_cp13_MCR (ARMul_State * state,
		 unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
{
  unsigned CRm = BITS (0, 3);
  unsigned reg = BITS (16, 19);
  unsigned result;

  result = check_cp13_access (state, reg, CRm, BITS (21, 23), BITS (5, 7));

  if (result == ARMul_DONE)
    write_cp13_reg (reg, CRm, value);

  return result;
}

static unsigned
XScale_cp13_read_reg (ARMul_State * state ATTRIBUTE_UNUSED,
		      unsigned reg, ARMword * value)
{
  /* FIXME: Not sure what to do about the alternative register set
     here.  For now default to just accessing CRm == 0 registers.  */
  *value = read_cp13_reg (reg, 0);

  return TRUE;
}

static unsigned
XScale_cp13_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
		       unsigned reg, ARMword value)
{
  /* FIXME: Not sure what to do about the alternative register set
     here.  For now default to just accessing CRm == 0 registers.  */
  write_cp13_reg (reg, 0, value);

  return TRUE;
}
#endif
/* Coprocessor 14:  Performance Monitoring,  Clock and Power management,
   Software Debug.  */

static ARMword XScale_cp14_Regs[16];

static unsigned
XScale_cp14_init (ARMul_State * state ATTRIBUTE_UNUSED)
{
  int i;

  for (i = 16; i--;)
    XScale_cp14_Regs[i] = 0;
}

/* Check an access to a register.  */

static unsigned
check_cp14_access (ARMul_State * state,
		   unsigned reg,
		   unsigned CRm, unsigned opcode1, unsigned opcode2)
{
  /* Not allowed to access these register in USER mode.  */
  if (state->Mode == USER26MODE || state->Mode == USER32MODE)
    return ARMul_CANT;

  /* CRm should be zero.  */
  if (CRm != 0)
    return ARMul_CANT;

  /* OPcodes should be zero.  */
  if (opcode1 != 0 || opcode2 != 0)
    return ARMul_CANT;

  /* Accessing registers 4 or 5 has unpredicatable results.  */
  if (reg >= 4 && reg <= 5)
    return ARMul_CANT;

  return ARMul_DONE;
}

#if 0
/* Store a value into one of coprocessor 14's registers.  */

static void
write_cp14_reg (unsigned reg, ARMword value)
{
  switch (reg)
    {
    case 0:			/* PMNC */
      /* Only BITS (27:12), BITS (10:8) and BITS (6:0) can be written.  */
      value &= 0x0ffff77f;

      /* Reset the clock counter if necessary.  */
      if (value & ARMul_CP14_R0_CLKRST)
	XScale_cp14_Regs[1] = 0;
      break;

    case 4:
    case 5:
      /* We should not normally reach this code.  The debugger interface
         can bypass the normal checks though, so it could happen.  */
      value = 0;
      break;

    case 6:			/* CCLKCFG */
      /* Only BITS (3:0) can be written.  */
      value &= 0xf;
      break;

    case 7:			/* PWRMODE */
      /* Although BITS (1:0) can be written with non-zero values, this would
         have the side effect of putting the processor to sleep.  Thus in
         order for the register to be read again, it would have to go into
         ACTIVE mode, which means that any read will see these bits as zero.

         Rather than trying to implement complex reset-to-zero-upon-read logic
         we just override the write value with zero.  */
      value = 0;
      break;

    case 10:			/* DCSR */
      /* Only BITS (31:30), BITS (23:22), BITS (20:16) and BITS (5:0) can
         be written.  */
      value &= 0xc0df003f;
      break;

    case 11:			/* TBREG */
      /* No writes are permitted.  */
      value = 0;
      break;

    case 14:			/* TXRXCTRL */
      /* Only BITS (31:30) can be written.  */
      value &= 0xc0000000;
      break;

    default:
      /* All bits can be written.  */
      break;
    }

  XScale_cp14_Regs[reg] = value;
}

/* Return the value in a cp14 register.  Not a static function since
   it is used by the code to emulate the BKPT instruction in armemu.c.  */

ARMword
read_cp14_reg (unsigned reg)
{
  return XScale_cp14_Regs[reg];
}

static unsigned
XScale_cp14_LDC (ARMul_State * state, unsigned type, ARMword instr,
		 ARMword data)
{
  unsigned reg = BITS (12, 15);
  unsigned result;

  result = check_cp14_access (state, reg, 0, 0, 0);

  if (result == ARMul_DONE && type == ARMul_DATA)
    write_cp14_reg (reg, data);

  return result;
}

static unsigned
XScale_cp14_STC (ARMul_State * state, unsigned type, ARMword instr,
		 ARMword * data)
{
  unsigned reg = BITS (12, 15);
  unsigned result;

  result = check_cp14_access (state, reg, 0, 0, 0);

  if (result == ARMul_DONE && type == ARMul_DATA)
    *data = read_cp14_reg (reg);

  return result;
}

static unsigned
  XScale_cp14_MRC
  (ARMul_State * state,
   unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
{
  unsigned reg = BITS (16, 19);
  unsigned result;

  result =
    check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));

  if (result == ARMul_DONE)
    *value = read_cp14_reg (reg);

  return result;
}

static unsigned
  XScale_cp14_MCR
  (ARMul_State * state,
   unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
{
  unsigned reg = BITS (16, 19);
  unsigned result;

  result =
    check_cp14_access (state, reg, BITS (0, 3), BITS (21, 23), BITS (5, 7));

  if (result == ARMul_DONE)
    write_cp14_reg (reg, value);

  return result;
}

static unsigned
  XScale_cp14_read_reg
  (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
{
  *value = read_cp14_reg (reg);

  return TRUE;
}

static unsigned
  XScale_cp14_write_reg
  (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword value)
{
  write_cp14_reg (reg, value);

  return TRUE;
}
#endif
/* Here's ARMulator's MMU definition.  A few things to note:

⌨️ 快捷键说明

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