/* armcopro.c -- co-processor interface: ARM6 Instruction Emulator.
- Copyright (C) 1994 Advanced RISC Machines Ltd.
+ 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
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. */
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "armdefs.h"
+#include "armos.h"
+#include "armemu.h"
+#include "ansidecl.h"
+#include "iwmmxt.h"
-extern unsigned ARMul_CoProInit(ARMul_State *state) ;
-extern void ARMul_CoProExit(ARMul_State *state) ;
-extern 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) ;
-extern void ARMul_CoProDetach(ARMul_State *state, unsigned number) ;
+/* 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. */
+ XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
+
+ /* 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;
+}
+
+/* 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. */
+
+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;
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/* 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;
+}
+
+/* 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;
+}
-/***************************************************************************\
-* Dummy Co-processors *
-\***************************************************************************/
+/* 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. */
-static unsigned NoCoPro3R(ARMul_State *state,unsigned,ARMword) ;
-static unsigned NoCoPro4R(ARMul_State *state,unsigned,ARMword,ARMword) ;
-static unsigned NoCoPro4W(ARMul_State *state,unsigned,ARMword,ARMword *) ;
+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;
-/***************************************************************************\
-* Define Co-Processor instruction handlers here *
-\***************************************************************************/
+ 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;
+}
/* Here's ARMulator's MMU definition. A few things to note:
-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)
-{MMUReg[1] = state->prog32Sig << 4 |
- state->data32Sig << 5 |
- state->lateabtSig << 6 |
- state->bigendSig << 7 ;
- ARMul_ConsolePrint (state, ", MMU present") ;
- return(TRUE) ;
-}
-
-static unsigned MMUMRC(ARMul_State *state, unsigned type, 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, ARMword instr, ARMword value)
-{int reg = BITS(16,19) & 7 ;
-
- MMUReg[reg] = value ;
- if (reg == 1) {
- state->prog32Sig = value >> 4 & 1 ;
- state->data32Sig = value >> 5 & 1 ;
- state->lateabtSig = value >> 6 & 1 ;
- state->bigendSig = value >> 7 & 1 ;
- state->Emulate = TRUE ; /* force ARMulator to notice these now !*/
+ 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)
+{
+ MMUReg[1] = state->prog32Sig << 4 |
+ 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)
+{
+ 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, 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) {
- state->prog32Sig = value >> 4 & 1 ;
- state->data32Sig = value >> 5 & 1 ;
- state->lateabtSig = value >> 6 & 1 ;
- state->bigendSig = value >> 7 & 1 ;
- state->Emulate = TRUE ; /* force ARMulator to notice these now !*/
+
+ 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) ;
- }
+
+ return TRUE;
+}
/* 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, unsigned type,
- ARMword instr, ARMword data)
-{static unsigned words ;
-
- if (type != ARMul_DATA) {
- words = 0 ;
- return(ARMul_DONE) ;
+ 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;
}
- if (BIT(22)) { /* it's a long access, get two words */
- ValReg[BITS(12,15)] = data ;
- if (words++ == 4)
- return(ARMul_DONE) ;
- else
- return(ARMul_INC) ;
+ else if (type == ARMul_BUSY)
+ {
+ if (ARMul_Time (state) >= finish)
+ return ARMul_DONE;
+ else
+ return ARMul_BUSY;
}
- else { /* get just one word */
- ValReg[BITS(12,15)] = data ;
- return(ARMul_DONE) ;
+
+ 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;
}
- }
-static unsigned ValSTC(ARMul_State *state, unsigned type,
- ARMword instr, ARMword *data)
-{static unsigned words ;
+ return ARMul_CANT;
+}
+
+/* Install co-processor instruction handlers in this routine. */
- if (type != ARMul_DATA) {
- words = 0 ;
- return(ARMul_DONE) ;
+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);
}
- if (BIT(22)) { /* it's a long access, get two words */
- *data = ValReg[BITS(12,15)] ;
- if (words++ == 4)
- return(ARMul_DONE) ;
- else
- return(ARMul_INC) ;
- }
- else { /* get just one word */
- *data = ValReg[BITS(12,15)] ;
- return(ARMul_DONE) ;
+ 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);
}
- }
-
-static unsigned ValMRC(ARMul_State *state, unsigned type, ARMword instr,ARMword *value)
-{
- *value = ValReg[BITS(16,19)] ;
- return(ARMul_DONE) ;
- }
-
-static unsigned ValMCR(ARMul_State *state, unsigned type, 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 ;
- ARMword howlong ;
-
- howlong = ValReg[BITS(0,3)] ;
- if (BITS(20,23)==0) {
- if (type == ARMul_FIRST) { /* First cycle of a busy wait */
- finish = ARMul_Time(state) + howlong ;
- if (howlong == 0)
- return(ARMul_DONE) ;
- else
- return(ARMul_BUSY) ;
- }
- else if (type == ARMul_BUSY) {
- if (ARMul_Time(state) >= finish)
- return(ARMul_DONE) ;
- else
- return(ARMul_BUSY) ;
- }
+
+ if (state->is_XScale)
+ {
+ ARMul_CoProAttach (state, 13, XScale_cp13_init, NULL,
+ XScale_cp13_LDC, XScale_cp13_STC, XScale_cp13_MRC,
+ XScale_cp13_MCR, NULL, XScale_cp13_read_reg,
+ XScale_cp13_write_reg);
+
+ ARMul_CoProAttach (state, 14, XScale_cp14_init, NULL,
+ XScale_cp14_LDC, XScale_cp14_STC, XScale_cp14_MRC,
+ XScale_cp14_MCR, NULL, XScale_cp14_read_reg,
+ XScale_cp14_write_reg);
+
+ ARMul_CoProAttach (state, 15, XScale_cp15_init, NULL,
+ NULL, NULL, XScale_cp15_MRC, XScale_cp15_MCR,
+ NULL, XScale_cp15_read_reg, XScale_cp15_write_reg);
}
- 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 ;
- if (howlong == 0)
- return(ARMul_DONE) ;
- else
- return(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) ;
+ else
+ {
+ ARMul_CoProAttach (state, 15, MMUInit, NULL, NULL, NULL,
+ MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
}
- return(ARMul_CANT) ;
- }
-/***************************************************************************\
-* Install co-processor instruction handlers in this routine *
-\***************************************************************************/
+ if (state->is_iWMMXt)
+ {
+ ARMul_CoProAttach (state, 0, NULL, NULL, IwmmxtLDC, IwmmxtSTC,
+ NULL, NULL, IwmmxtCDP, NULL, NULL);
-unsigned ARMul_CoProInit(ARMul_State *state)
-{register unsigned i ;
+ ARMul_CoProAttach (state, 1, NULL, NULL, NULL, NULL,
+ IwmmxtMRC, IwmmxtMCR, IwmmxtCDP, NULL, NULL);
+ }
- for (i = 0 ; i < 16 ; i++) /* initialise tham all first */
- ARMul_CoProDetach(state, i) ;
+ /* No handlers below here. */
- /* 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) ;
- */
+ /* Call all the initialisation routines. */
+ for (i = 0; i < 16; i++)
+ if (state->CPInit[i])
+ (state->CPInit[i]) (state);
- ARMul_CoProAttach(state, 4, NULL, NULL,
- ValLDC, ValSTC, ValMRC, ValMCR,
- ValCDP, NULL, NULL) ;
+ return TRUE;
+}
- ARMul_CoProAttach(state, 5, NULL, NULL,
- NULL, NULL, ValMRC, ValMCR,
- IntCDP, NULL, NULL) ;
+/* Install co-processor finalisation routines in this routine. */
- ARMul_CoProAttach(state, 15, MMUInit, NULL,
- NULL, NULL, MMUMRC, MMUMCR,
- NULL, MMURead, MMUWrite) ;
+void
+ARMul_CoProExit (ARMul_State * state)
+{
+ register unsigned i;
+ for (i = 0; i < 16; i++)
+ if (state->CPExit[i])
+ (state->CPExit[i]) (state);
- /* No handlers below here */
+ for (i = 0; i < 16; i++) /* Detach all handlers. */
+ ARMul_CoProDetach (state, i);
+}
- for (i = 0 ; i < 16 ; i++) /* Call all the initialisation routines */
- if (state->CPInit[i])
- (state->CPInit[i])(state) ;
- return(TRUE) ;
- }
+/* Routines to hook Co-processors into ARMulator. */
-/***************************************************************************\
-* Install co-processor finalisation routines in this routine *
-\***************************************************************************/
+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_CoProExit(ARMul_State *state)
-{register unsigned i ;
+void
+ARMul_CoProDetach (ARMul_State * state, unsigned number)
+{
+ ARMul_CoProAttach (state, number, NULL, NULL,
+ NoCoPro4R, NoCoPro4W, NoCoPro4W, NoCoPro4R,
+ NoCoPro3R, NULL, NULL);
- 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 ;
-}
-
-/***************************************************************************\
-* There is no CoPro around, so Undefined Instruction trap *
-\***************************************************************************/
-
-static unsigned NoCoPro3R(ARMul_State *state,unsigned a,ARMword b)
-{return(ARMul_CANT) ;}
-
-static unsigned NoCoPro4R(ARMul_State *state, unsigned a,ARMword b,ARMword c)
-{return(ARMul_CANT) ;}
-
-static unsigned NoCoPro4W(ARMul_State *state, unsigned a,ARMword b,ARMword *c)
-{return(ARMul_CANT) ;}
+ state->CPInit[number] = NULL;
+ state->CPExit[number] = NULL;
+ state->CPRead[number] = NULL;
+ state->CPWrite[number] = NULL;
+}