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

📄 armcopro.c

📁 skyeye-1.0.0.rar surce code
💻 C
📖 第 1 页 / 共 3 页
字号:
   1) It has eight registers, but only two are defined.
   2) You can only access its registers with MCR and MRC.
   3) MMU Register 0 (ID) returns 0x41440110
   4) Register 1 only has 4 bits defined.  Bits 0 to 3 are unused, bit 4
      controls 32/26 bit program space, bit 5 controls 32/26 bit data space,
      bit 6 controls late abort timimg and bit 7 controls big/little endian.  */

static ARMword MMUReg[8];

static unsigned
MMUInit (ARMul_State * state)
{
/* 2004-05-09 chy
-------------------------------------------------------------
read ARM Architecture Reference Manual
2.6.5 Data Abort
There are three Abort Model in ARM arch.

Early Abort Model: used in some ARMv3 and earlier implementations. In this
model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and
the base register was unchanged for all other instructions. (oldest)

Base Restored Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the value in the base register is
unchanged. (strongarm, xscale)

Base Updated Abort Model: If a Data Abort occurs in an instruction which
specifies base register writeback, the base register writeback still occurs.
(arm720T)

read PART B
chap2 The System Control Coprocessor  CP15
2.4 Register1:control register
L(bit 6): in some ARMv3 and earlier implementations, the abort model of the
processor could be configured:
0=early Abort Model Selected(now obsolete)
1=Late Abort Model selceted(same as Base Updated Abort Model)

on later processors, this bit reads as 1 and ignores writes.
-------------------------------------------------------------
So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model)
    if lateabtSig=0, then it means Base Restored Abort Model
because the ARMs which skyeye simulates are all belonged to  ARMv4,
so I think MMUReg[1]'s bit 6 should always be 1

*/

  MMUReg[1] = state->prog32Sig << 4 |
    state->data32Sig << 5 | 1 << 6 | state->bigendSig << 7;
  //state->data32Sig << 5 | state->lateabtSig << 6 | state->bigendSig << 7;


  ARMul_ConsolePrint (state, ", MMU present");

  return TRUE;
}

static unsigned
MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED, unsigned type ATTRIBUTE_UNUSED,
	ARMword instr, ARMword * value)
{
  mmu_mrc (state, instr, value);
  return (ARMul_DONE);
}

static unsigned
MMUMCR (ARMul_State * state, unsigned type, ARMword instr, ARMword value)
{
  mmu_mcr (state, instr, value);
  return (ARMul_DONE);
}

#if 0
static unsigned
MMUMRC (ARMul_State * state ATTRIBUTE_UNUSED,
	unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
{
  int reg = BITS (16, 19) & 7;

  if (reg == 0)
    *value = 0x41440110;
  else
    *value = MMUReg[reg];

  return ARMul_DONE;
}

static unsigned
MMUMCR (ARMul_State * state,
	unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
{
  int reg = BITS (16, 19) & 7;

  MMUReg[reg] = value;

  if (reg == 1)
    {
      ARMword p, d, l, b;

      p = state->prog32Sig;
      d = state->data32Sig;
      l = state->lateabtSig;
      b = state->bigendSig;

      state->prog32Sig = value >> 4 & 1;
      state->data32Sig = value >> 5 & 1;
      state->lateabtSig = value >> 6 & 1;
      state->bigendSig = value >> 7 & 1;

      if (p != state->prog32Sig
	  || d != state->data32Sig
	  || l != state->lateabtSig || b != state->bigendSig)
	/* Force ARMulator to notice these now.  */
	state->Emulate = CHANGEMODE;
    }

  return ARMul_DONE;
}

static unsigned
MMURead (ARMul_State * state ATTRIBUTE_UNUSED, unsigned reg, ARMword * value)
{
  if (reg == 0)
    *value = 0x41440110;
  else if (reg < 8)
    *value = MMUReg[reg];

  return TRUE;
}

static unsigned
MMUWrite (ARMul_State * state, unsigned reg, ARMword value)
{
  if (reg < 8)
    MMUReg[reg] = value;

  if (reg == 1)
    {
      ARMword p, d, l, b;

      p = state->prog32Sig;
      d = state->data32Sig;
      l = state->lateabtSig;
      b = state->bigendSig;

      state->prog32Sig = value >> 4 & 1;
      state->data32Sig = value >> 5 & 1;
      state->lateabtSig = value >> 6 & 1;
      state->bigendSig = value >> 7 & 1;

      if (p != state->prog32Sig
	  || d != state->data32Sig
	  || l != state->lateabtSig || b != state->bigendSig)
	/* Force ARMulator to notice these now.  */
	state->Emulate = CHANGEMODE;
    }

  return TRUE;
}
#endif

/* What follows is the Validation Suite Coprocessor.  It uses two
   co-processor numbers (4 and 5) and has the follwing functionality.
   Sixteen registers.  Both co-processor nuimbers can be used in an MCR
   and MRC to access these registers.  CP 4 can LDC and STC to and from
   the registers.  CP 4 and CP 5 CDP 0 will busy wait for the number of
   cycles specified by a CP register.  CP 5 CDP 1 issues a FIQ after a
   number of cycles (specified in a CP register), CDP 2 issues an IRQW
   in the same way, CDP 3 and 4 turn of the FIQ and IRQ source, and CDP 5
   stores a 32 bit time value in a CP register (actually it's the total
   number of N, S, I, C and F cyles).  */

static ARMword ValReg[16];

static unsigned
ValLDC (ARMul_State * state ATTRIBUTE_UNUSED,
	unsigned type, ARMword instr, ARMword data)
{
  static unsigned words;

  if (type != ARMul_DATA)
    words = 0;
  else
    {
      ValReg[BITS (12, 15)] = data;

      if (BIT (22))
	/* It's a long access, get two words.  */
	if (words++ != 4)
	  return ARMul_INC;
    }

  return ARMul_DONE;
}

static unsigned
ValSTC (ARMul_State * state ATTRIBUTE_UNUSED,
	unsigned type, ARMword instr, ARMword * data)
{
  static unsigned words;

  if (type != ARMul_DATA)
    words = 0;
  else
    {
      *data = ValReg[BITS (12, 15)];

      if (BIT (22))
	/* It's a long access, get two words.  */
	if (words++ != 4)
	  return ARMul_INC;
    }

  return ARMul_DONE;
}

static unsigned
ValMRC (ARMul_State * state ATTRIBUTE_UNUSED,
	unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword * value)
{
  *value = ValReg[BITS (16, 19)];

  return ARMul_DONE;
}

static unsigned
ValMCR (ARMul_State * state ATTRIBUTE_UNUSED,
	unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMword value)
{
  ValReg[BITS (16, 19)] = value;

  return ARMul_DONE;
}

static unsigned
ValCDP (ARMul_State * state, unsigned type, ARMword instr)
{
  static unsigned long finish = 0;

  if (BITS (20, 23) != 0)
    return ARMul_CANT;

  if (type == ARMul_FIRST)
    {
      ARMword howlong;

      howlong = ValReg[BITS (0, 3)];

      /* First cycle of a busy wait.  */
      finish = ARMul_Time (state) + howlong;

      return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
    }
  else if (type == ARMul_BUSY)
    {
      if (ARMul_Time (state) >= finish)
	return ARMul_DONE;
      else
	return ARMul_BUSY;
    }

  return ARMul_CANT;
}

static unsigned
DoAFIQ (ARMul_State * state)
{
  state->NfiqSig = LOW;
  state->Exception++;
  return 0;
}

static unsigned
DoAIRQ (ARMul_State * state)
{
  state->NirqSig = LOW;
  state->Exception++;
  return 0;
}

static unsigned
IntCDP (ARMul_State * state, unsigned type, ARMword instr)
{
  static unsigned long finish;
  ARMword howlong;

  howlong = ValReg[BITS (0, 3)];

  switch ((int) BITS (20, 23))
    {
    case 0:
      if (type == ARMul_FIRST)
	{
	  /* First cycle of a busy wait.  */
	  finish = ARMul_Time (state) + howlong;

	  return howlong == 0 ? ARMul_DONE : ARMul_BUSY;
	}
      else if (type == ARMul_BUSY)
	{
	  if (ARMul_Time (state) >= finish)
	    return ARMul_DONE;
	  else
	    return ARMul_BUSY;
	}
      return ARMul_DONE;

    case 1:
      if (howlong == 0)
	ARMul_Abort (state, ARMul_FIQV);
      else
	ARMul_ScheduleEvent (state, howlong, DoAFIQ);
      return ARMul_DONE;

    case 2:
      if (howlong == 0)
	ARMul_Abort (state, ARMul_IRQV);
      else
	ARMul_ScheduleEvent (state, howlong, DoAIRQ);
      return ARMul_DONE;

    case 3:
      state->NfiqSig = HIGH;
      state->Exception--;
      return ARMul_DONE;

    case 4:
      state->NirqSig = HIGH;
      state->Exception--;
      return ARMul_DONE;

    case 5:
      ValReg[BITS (0, 3)] = ARMul_Time (state);
      return ARMul_DONE;
    }

  return ARMul_CANT;
}

/* Install co-processor instruction handlers in this routine.  */

unsigned
ARMul_CoProInit (ARMul_State * state)
{
  unsigned int i;

  /* Initialise tham all first.  */
  for (i = 0; i < 16; i++)
    ARMul_CoProDetach (state, i);

  /* Install CoPro Instruction handlers here.
     The format is:
     ARMul_CoProAttach (state, CP Number, Init routine, Exit routine
     LDC routine, STC routine, MRC routine, MCR routine,
     CDP routine, Read Reg routine, Write Reg routine).  */
  if (state->is_ep9312)
    {
      ARMul_CoProAttach (state, 4, NULL, NULL, DSPLDC4, DSPSTC4,
			 DSPMRC4, DSPMCR4, DSPCDP4, NULL, NULL);
      ARMul_CoProAttach (state, 5, NULL, NULL, DSPLDC5, DSPSTC5,
			 DSPMRC5, DSPMCR5, DSPCDP5, NULL, NULL);
      ARMul_CoProAttach (state, 6, NULL, NULL, NULL, NULL,
			 DSPMRC6, DSPMCR6, DSPCDP6, NULL, NULL);
    }
  else
    {
      ARMul_CoProAttach (state, 4, NULL, NULL, ValLDC, ValSTC,
			 ValMRC, ValMCR, ValCDP, NULL, NULL);

      ARMul_CoProAttach (state, 5, NULL, NULL, NULL, NULL,
			 ValMRC, ValMCR, IntCDP, NULL, NULL);
    }

  if (state->is_XScale)
    {
      ARMul_CoProAttach (state, 13, xscale_cp13_init, xscale_cp13_exit,
			 xscale_cp13_ldc, xscale_cp13_stc, xscale_cp13_mrc,
			 xscale_cp13_mcr, xscale_cp13_cdp,
			 xscale_cp13_read_reg, xscale_cp13_write_reg);

      ARMul_CoProAttach (state, 14, xscale_cp14_init, xscale_cp14_exit,
			 xscale_cp14_ldc, xscale_cp14_stc, xscale_cp14_mrc,
			 xscale_cp14_mcr, xscale_cp14_cdp,
			 xscale_cp14_read_reg, xscale_cp14_write_reg);
      //chy: 2003-08-24.
      ARMul_CoProAttach (state, 15, xscale_cp15_init, xscale_cp15_exit,
			 xscale_cp15_ldc, xscale_cp15_stc, xscale_cp15_mrc,
			 xscale_cp15_mcr, xscale_cp15_cdp,
			 xscale_cp15_read_reg, xscale_cp15_write_reg);
    }
  else
    {				//all except xscale
      ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
			 //                  MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
			 MMUMRC, MMUMCR, NULL, NULL, NULL);
    }
//chy 2003-09-03 do it in future!!!!????
#if 0
  if (state->is_iWMMXt)
    {
      ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
			 NULL, NULL, IwmmxtCDP, NULL, NULL);

      ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
			 IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, NULL);
    }
#endif
  //-----------------------------------------------------------------------------
  //chy 2004-05-25, found the user/system code visit CP 1,2, so I add below code.
  ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
		     ValMRC, ValMCR, NULL, NULL, NULL);
  ARMul_CoProAttach (state, 2, NULL, NULL, ValLDC, ValSTC,
		     NULL, NULL, NULL, NULL, NULL);
  //------------------------------------------------------------------------------
  /* No handlers below here.  */

  /* Call all the initialisation routines.  */
  for (i = 0; i < 16; i++)
    if (state->CPInit[i])
      (state->CPInit[i]) (state);

  return TRUE;
}

/* Install co-processor finalisation routines in this routine.  */

void
ARMul_CoProExit (ARMul_State * state)
{
  register unsigned i;

  for (i = 0; i < 16; i++)
    if (state->CPExit[i])
      (state->CPExit[i]) (state);

  for (i = 0; i < 16; i++)	/* Detach all handlers.  */
    ARMul_CoProDetach (state, i);
}

/* Routines to hook Co-processors into ARMulator.  */

void
ARMul_CoProAttach (ARMul_State * state,
		   unsigned number,
		   ARMul_CPInits * init,
		   ARMul_CPExits * exit,
		   ARMul_LDCs * ldc,
		   ARMul_STCs * stc,
		   ARMul_MRCs * mrc,
		   ARMul_MCRs * mcr,
		   ARMul_CDPs * cdp,
		   ARMul_CPReads * read, ARMul_CPWrites * write)
{
  if (init != NULL)
    state->CPInit[number] = init;
  if (exit != NULL)
    state->CPExit[number] = exit;
  if (ldc != NULL)
    state->LDC[number] = ldc;
  if (stc != NULL)
    state->STC[number] = stc;
  if (mrc != NULL)
    state->MRC[number] = mrc;
  if (mcr != NULL)
    state->MCR[number] = mcr;
  if (cdp != NULL)
    state->CDP[number] = cdp;
  if (read != NULL)
    state->CPRead[number] = read;
  if (write != NULL)
    state->CPWrite[number] = write;
}

void
ARMul_CoProDetach (ARMul_State * state, unsigned number)
{
  ARMul_CoProAttach (state, number, NULL, NULL,
		     NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
		     NoCoPro3R, NULL, NULL);

  state->CPInit[number] = NULL;
  state->CPExit[number] = NULL;
  state->CPRead[number] = NULL;
  state->CPWrite[number] = NULL;
}

//chy 2003-09-03:below funs just replace the old ones

/* 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)
  if (!state->is_XScale)
    return;
  //assume opcode2=0 crm =0
  xscale_cp15_write_reg (state, 5, fsr);
  xscale_cp15_write_reg (state, 6, far);
}


//chy 2003-09-03 seems 0 is CANT, 1 is DONE ????
int
XScale_debug_moe (ARMul_State * state, int moe)
{
  //chy 2003-09-03 , W/R CP14 reg, now it's no use ????
  printf ("SKYEYE: XScale_debug_moe called !!!!\n");
  return 1;
}

#if 0
//chy 2003-09-03 : only called by iwmmxt.c!!!!
//chy assume opcode_2=0
/* Return the value in a cp15 register.  */
ARMword
read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm)
{
  unsigned value;
  if (reg != 15)
    {
      printf ("SKYEYE: read_cp15_reg read other reg 0x%x \n", reg);
      exit (-1);
    }
  xscale_cp15_read_reg (reg, &value);
  printf ("SKYEYE: read_cp15_reg read reg 0x%x, val 0x%x \n", reg, value);
  return value;
}
#endif

⌨️ 快捷键说明

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