X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=sim%2Farm%2Farmcopro.c;h=aa75243dc3385c9dc7c8f4086896d35993be18e5;hb=3a3d6f654d63d306828ad47e9204b8e3ea2685ec;hp=fc93a863135d9b0880ab3d4b4e5dcc5c23912649;hpb=8b0b198558d0fc981f129e2e3dcbe00a0f308449;p=platform%2Fupstream%2Fbinutils.git diff --git a/sim/arm/armcopro.c b/sim/arm/armcopro.c index fc93a863..aa75243 100644 --- a/sim/arm/armcopro.c +++ b/sim/arm/armcopro.c @@ -1,5 +1,5 @@ /* 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 @@ -13,345 +13,1437 @@ 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; +}