📄 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"//chy 2005-09-19 add CP6 MRC support (for get irq number and base)extern unsigned xscale_cp6_mrc (ARMul_State * state, unsigned type, ARMword instr, ARMword * data);//chy 2005-09-19---------------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 unsignedNoCoPro3R (ARMul_State * state ATTRIBUTE_UNUSED, unsigned a ATTRIBUTE_UNUSED, ARMword b ATTRIBUTE_UNUSED){ return ARMul_CANT;}static unsignedNoCoPro4R (ARMul_State * state ATTRIBUTE_UNUSED, unsigned a ATTRIBUTE_UNUSED, ARMword b ATTRIBUTE_UNUSED, ARMword c ATTRIBUTE_UNUSED){ return ARMul_CANT;}static unsignedNoCoPro4W (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 unsignedXScale_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 unsignedcheck_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. */ //chy 2006-02-16 , should not consider system mode, don't conside 26bit 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 voidwrite_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. */ARMwordread_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 unsignedXScale_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 unsignedXScale_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 unsignedXScale_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 unsignedXScale_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 unsignedXScale_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 unsignedXScale_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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -