📄 armcopro.c
字号:
/* 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 + -