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

📄 armcopro.c

📁 skyeye-1.0.0.rar surce code
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  armcopro.c -- co-processor interface:  ARM6 Instruction Emulator.
    Copyright (C) 1994, 2000 Advanced RISC Machines Ltd.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#include "armdefs.h"
#include "armos.h"
#include "armemu.h"
//chy 2005-07-08
#include "ansidecl.h"
//chy -------
//#include "iwmmxt.h"



extern unsigned xscale_cp13_init (ARMul_State * state);
extern unsigned xscale_cp13_exit (ARMul_State * state);
extern unsigned xscale_cp13_ldc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp13_stc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mrc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp13_mcr (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp13_cdp (ARMul_State * state, unsigned type,
				 ARMword instr);
extern unsigned xscale_cp13_read_reg (ARMul_State * state, unsigned reg,
				      ARMword * data);
extern unsigned xscale_cp13_write_reg (ARMul_State * state, unsigned reg,
				       ARMword data);
extern unsigned xscale_cp14_init (ARMul_State * state);
extern unsigned xscale_cp14_exit (ARMul_State * state);
extern unsigned xscale_cp14_ldc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp14_stc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mrc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp14_mcr (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp14_cdp (ARMul_State * state, unsigned type,
				 ARMword instr);
extern unsigned xscale_cp14_read_reg (ARMul_State * state, unsigned reg,
				      ARMword * data);
extern unsigned xscale_cp14_write_reg (ARMul_State * state, unsigned reg,
				       ARMword data);
extern unsigned xscale_cp15_init (ARMul_State * state);
extern unsigned xscale_cp15_exit (ARMul_State * state);
extern unsigned xscale_cp15_ldc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp15_stc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mrc (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword * data);
extern unsigned xscale_cp15_mcr (ARMul_State * state, unsigned type,
				 ARMword instr, ARMword data);
extern unsigned xscale_cp15_cdp (ARMul_State * state, unsigned type,
				 ARMword instr);
extern unsigned xscale_cp15_read_reg (ARMul_State * state, unsigned reg,
				      ARMword * data);
extern unsigned xscale_cp15_write_reg (ARMul_State * state, unsigned reg,
				       ARMword data);





/* Dummy Co-processors.  */

static unsigned
NoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED,
	   unsigned a ATTRIBUTE_UNUSED, ARMword b ATTRIBUTE_UNUSED)
{
  return ARMul_CANT;
}

static unsigned
NoCoPro4R (ARMul_State * state ATTRIBUTE_UNUSED,
	   unsigned a ATTRIBUTE_UNUSED,
	   ARMword b ATTRIBUTE_UNUSED, ARMword c ATTRIBUTE_UNUSED)
{
  return ARMul_CANT;
}

static unsigned
NoCoPro4W (ARMul_State * state ATTRIBUTE_UNUSED,
	   unsigned a ATTRIBUTE_UNUSED,
	   ARMword b ATTRIBUTE_UNUSED, ARMword * c ATTRIBUTE_UNUSED)
{
  return ARMul_CANT;
}

/* The XScale Co-processors.  */

/* Coprocessor 15:  System Control.  */
static void write_cp14_reg (unsigned, ARMword);
static ARMword read_cp14_reg (unsigned);

/* There are two sets of registers for copro 15.
   One set is available when opcode_2 is 0 and
   the other set when opcode_2 >= 1.  */
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
/* There are also a set of breakpoint registers
   which are accessed via CRm instead of opcode_2.  */
static ARMword XScale_cp15_DBR1;
static ARMword XScale_cp15_DBCON;
static ARMword XScale_cp15_IBCR0;
static ARMword XScale_cp15_IBCR1;

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

  for (i = 16; i--;)
    {
      XScale_cp15_opcode_2_is_0_Regs[i] = 0;
      XScale_cp15_opcode_2_is_not_0_Regs[i] = 0;
    }

  /* Initialise the processor ID.  */
  //chy 2003-03-24, is same as cpu id in skyeye_options.c
  //XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
  XScale_cp15_opcode_2_is_0_Regs[0] = 0x69050000;

  /* Initialise the cache type.  */
  XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;

  /* Initialise the ARM Control Register.  */
  XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
}

/* Check an access to a register.  */

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

  /* Opcode_1should be zero.  */
  if (opcode_1 != 0)
    return ARMul_CANT;

  /* Different register have different access requirements.  */
  switch (reg)
    {
    case 0:
    case 1:
      /* CRm must be 0.  Opcode_2 can be anything.  */
      if (CRm != 0)
	return ARMul_CANT;
      break;
    case 2:
    case 3:
      /* CRm must be 0.  Opcode_2 must be zero.  */
      if ((CRm != 0) || (opcode_2 != 0))
	return ARMul_CANT;
      break;
    case 4:
      /* Access not allowed.  */
      return ARMul_CANT;
    case 5:
    case 6:
      /* Opcode_2 must be zero.  CRm must be 0.  */
      if ((CRm != 0) || (opcode_2 != 0))
	return ARMul_CANT;
      break;
    case 7:
      /* Permissable combinations:
         Opcode_2  CRm
         0       5
         0       6
         0       7
         1       5
         1       6
         1      10
         4      10
         5       2
         6       5  */
      switch (opcode_2)
	{
	default:
	  return ARMul_CANT;
	case 6:
	  if (CRm != 5)
	    return ARMul_CANT;
	  break;
	case 5:
	  if (CRm != 2)
	    return ARMul_CANT;
	  break;
	case 4:
	  if (CRm != 10)
	    return ARMul_CANT;
	  break;
	case 1:
	  if ((CRm != 5) && (CRm != 6) && (CRm != 10))
	    return ARMul_CANT;
	  break;
	case 0:
	  if ((CRm < 5) || (CRm > 7))
	    return ARMul_CANT;
	  break;
	}
      break;

    case 8:
      /* Permissable combinations:
         Opcode_2  CRm
         0       5
         0       6
         0       7
         1       5
         1       6  */
      if (opcode_2 > 1)
	return ARMul_CANT;
      if ((CRm < 5) || (CRm > 7))
	return ARMul_CANT;
      if (opcode_2 == 1 && CRm == 7)
	return ARMul_CANT;
      break;
    case 9:
      /* Opcode_2 must be zero or one.  CRm must be 1 or 2.  */
      if (((CRm != 0) && (CRm != 1)) || ((opcode_2 != 1) && (opcode_2 != 2)))
	return ARMul_CANT;
      break;
    case 10:
      /* Opcode_2 must be zero or one.  CRm must be 4 or 8.  */
      if (((CRm != 0) && (CRm != 1)) || ((opcode_2 != 4) && (opcode_2 != 8)))
	return ARMul_CANT;
      break;
    case 11:
      /* Access not allowed.  */
      return ARMul_CANT;
    case 12:
      /* Access not allowed.  */
      return ARMul_CANT;
    case 13:
      /* Opcode_2 must be zero.  CRm must be 0.  */
      if ((CRm != 0) || (opcode_2 != 0))
	return ARMul_CANT;
      break;
    case 14:
      /* Opcode_2 must be 0.  CRm must be 0, 3, 4, 8 or 9.  */
      if (opcode_2 != 0)
	return ARMul_CANT;

      if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) && (CRm != 9))
	return ARMul_CANT;
      break;
    case 15:
      /* Opcode_2 must be zero.  CRm must be 1.  */
      if ((CRm != 1) || (opcode_2 != 0))
	return ARMul_CANT;
      break;
    default:
      /* Should never happen.  */
      return ARMul_CANT;
    }

  return ARMul_DONE;
}

//chy 2003-09-03 commit below funs
#if 0

/* Store a value into one of coprocessor 15's registers.  */

static void
write_cp15_reg (ARMul_State * state,
		unsigned reg, unsigned opcode_2, unsigned CRm, ARMword value)
{
  if (opcode_2)
    {
      switch (reg)
	{
	case 0:		/* Cache Type.  */
	  /* Writes are not allowed.  */
	  return;

	case 1:		/* Auxillary Control.  */
	  /* Only BITS (5, 4) and BITS (1, 0) can be written.  */
	  value &= 0x33;
	  break;

	default:
	  return;
	}

      XScale_cp15_opcode_2_is_not_0_Regs[reg] = value;
    }
  else
    {
      switch (reg)
	{
	case 0:		/* ID.  */
	  /* Writes are not allowed.  */
	  return;

	case 1:		/* ARM Control.  */
	  /* Only BITS (13, 11), BITS (9, 7) and BITS (2, 0) can be written.
	     BITS (31, 14) and BIT (10) write as zero, BITS (6, 3) write as one.  */
	  value &= 0x00003b87;
	  value |= 0x00000078;

	  /* Change the endianness if necessary.  */
	  if ((value & ARMul_CP15_R1_ENDIAN) !=
	      (XScale_cp15_opcode_2_is_0_Regs[reg] & ARMul_CP15_R1_ENDIAN))
	    {
	      state->bigendSig = value & ARMul_CP15_R1_ENDIAN;
	      /* Force ARMulator to notice these now.  */
	      state->Emulate = CHANGEMODE;
	    }
	  break;

	case 2:		/* Translation Table Base.  */
	  /* Only BITS (31, 14) can be written.  */
	  value &= 0xffffc000;
	  break;

	case 3:		/* Domain Access Control.  */
	  /* All bits writable.  */
	  break;

	case 5:		/* Fault Status Register.  */
	  /* BITS (10, 9) and BITS (7, 0) can be written.  */
	  value &= 0x000006ff;
	  break;

	case 6:		/* Fault Address Register.  */
	  /* All bits writable.  */
	  break;

	case 7:		/* Cache Functions.  */
	case 8:		/* TLB Operations.  */
	case 10:		/* TLB Lock Down.  */
	  /* Ignore writes.  */
	  return;

	case 9:		/* Data Cache Lock.  */
	  /* Only BIT (0) can be written.  */
	  value &= 0x1;
	  break;

	case 13:		/* Process ID.  */
	  /* Only BITS (31, 25) are writable.  */
	  value &= 0xfe000000;
	  break;

	case 14:		/* DBR0, DBR1, DBCON, IBCR0, IBCR1 */
	  /* All bits can be written.  Which register is accessed is
	     dependent upon CRm.  */
	  switch (CRm)
	    {
	    case 0:		/* DBR0 */
	      break;
	    case 3:		/* DBR1 */
	      XScale_cp15_DBR1 = value;
	      break;
	    case 4:		/* DBCON */
	      XScale_cp15_DBCON = value;
	      break;
	    case 8:		/* IBCR0 */
	      XScale_cp15_IBCR0 = value;
	      break;
	    case 9:		/* IBCR1 */
	      XScale_cp15_IBCR1 = value;
	      break;
	    default:
	      return;
	    }
	  break;

	case 15:		/* Coprpcessor Access Register.  */
	  /* Access is only valid if CRm == 1.  */
	  if (CRm != 1)
	    return;

	  /* Only BITS (13, 0) may be written.  */
	  value &= 0x00003fff;
	  break;

	default:
	  return;
	}

      XScale_cp15_opcode_2_is_0_Regs[reg] = value;
    }

  return;
}

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

ARMword
read_cp15_reg (unsigned reg, unsigned opcode_2, unsigned CRm)
{
  if (opcode_2 == 0)
    {
      if (reg == 15 && CRm != 1)
	return 0;

      if (reg == 14)
	{
	  switch (CRm)
	    {
	    case 3:
	      return XScale_cp15_DBR1;
	    case 4:
	      return XScale_cp15_DBCON;
	    case 8:
	      return XScale_cp15_IBCR0;
	    case 9:
	      return XScale_cp15_IBCR1;
	    default:
	      break;
	    }
	}

      return XScale_cp15_opcode_2_is_0_Regs[reg];
    }
  else
    return XScale_cp15_opcode_2_is_not_0_Regs[reg];

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

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

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

  return result;
}

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

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

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

  return result;
}

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

  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);

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

  return result;
}

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

  result = check_cp15_access (state, reg, CRm, BITS (21, 23), opcode_2);

  if (result == ARMul_DONE)
    write_cp15_reg (state, reg, opcode_2, CRm, value);

  return result;
}

static unsigned
XScale_cp15_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_cp15_reg (reg, 0, 0);

  return TRUE;
}

static unsigned
XScale_cp15_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_cp15_reg (state, reg, 0, 0, value);

  return TRUE;
}

/* Check for special XScale memory access features.  */

⌨️ 快捷键说明

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