#include "armdefs.h"
#include "armos.h"
#include "armemu.h"
#include "ansidecl.h"
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;
}
static void write_cp14_reg (unsigned, ARMword);
static ARMword read_cp14_reg (unsigned);
static ARMword XScale_cp15_opcode_2_is_0_Regs[16];
static ARMword XScale_cp15_opcode_2_is_not_0_Regs[16];
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;
}
XScale_cp15_opcode_2_is_0_Regs[0] = 0x69052000;
XScale_cp15_opcode_2_is_not_0_Regs[0] = 0x0B1AA1AA;
XScale_cp15_opcode_2_is_0_Regs[1] = 0x00000078;
}
static unsigned
check_cp15_access (ARMul_State * state,
unsigned reg,
unsigned CRm,
unsigned opcode_1,
unsigned opcode_2)
{
if (state->Mode == USER26MODE || state->Mode == USER32MODE)
return ARMul_CANT;
if (opcode_1 != 0)
return ARMul_CANT;
switch (reg)
{
case 0:
case 1:
if (CRm != 0)
return ARMul_CANT;
break;
case 2:
case 3:
if ((CRm != 0) || (opcode_2 != 0))
return ARMul_CANT;
break;
case 4:
return ARMul_CANT;
case 5:
case 6:
if ((CRm != 0) || (opcode_2 != 0))
return ARMul_CANT;
break;
case 7:
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:
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:
if ( ((CRm != 0) && (CRm != 1))
|| ((opcode_2 != 1) && (opcode_2 != 2)))
return ARMul_CANT;
break;
case 10:
if ( ((CRm != 0) && (CRm != 1))
|| ((opcode_2 != 4) && (opcode_2 != 8)))
return ARMul_CANT;
break;
case 11:
return ARMul_CANT;
case 12:
return ARMul_CANT;
case 13:
if ((CRm != 0) || (opcode_2 != 0))
return ARMul_CANT;
break;
case 14:
if (opcode_2 != 0)
return ARMul_CANT;
if ((CRm != 0) && (CRm != 3) && (CRm != 4) && (CRm != 8) && (CRm != 9))
return ARMul_CANT;
break;
case 15:
if ((CRm != 1) || (opcode_2 != 0))
return ARMul_CANT;
break;
default:
return ARMul_CANT;
}
return ARMul_DONE;
}
static void
write_cp15_reg (ARMul_State * state,
unsigned reg,
unsigned opcode_2,
unsigned CRm,
ARMword value)
{
if (opcode_2)
{
switch (reg)
{
case 0:
return;
case 1:
value &= 0x33;
break;
default:
return;
}
XScale_cp15_opcode_2_is_not_0_Regs [reg] = value;
}
else
{
switch (reg)
{
case 0:
return;
case 1:
value &= 0x00003b87;
value |= 0x00000078;
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;
state->Emulate = CHANGEMODE;
}
break;
case 2:
value &= 0xffffc000;
break;
case 3:
break;
case 5:
value &= 0x000006ff;
break;
case 6:
break;
case 7:
case 8:
case 10:
return;
case 9:
value &= 0x1;
break;
case 13:
value &= 0xfe000000;
break;
case 14:
switch (CRm)
{
case 0:
break;
case 3:
XScale_cp15_DBR1 = value;
break;
case 4:
XScale_cp15_DBCON = value;
break;
case 8:
XScale_cp15_IBCR0 = value;
break;
case 9:
XScale_cp15_IBCR1 = value;
break;
default:
return;
}
break;
case 15:
if (CRm != 1)
return;
value &= 0x00003fff;
break;
default:
return;
}
XScale_cp15_opcode_2_is_0_Regs [reg] = value;
}
return;
}
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)
{
* value = read_cp15_reg (reg, 0, 0);
return TRUE;
}
static unsigned
XScale_cp15_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
unsigned reg,
ARMword value)
{
write_cp15_reg (state, reg, 0, 0, value);
return TRUE;
}
void
XScale_check_memacc (ARMul_State * state, ARMword * address, int store)
{
ARMword dbcon, r0, r1;
int e1, e0;
if (!state->is_XScale)
return;
r0 = (read_cp15_reg (13, 0, 0) & 0xfe000000);
if (r0 && (* address & 0xfe000000) == 0)
* address |= r0;
if ((read_cp15_reg (1, 0, 0) & ARMul_CP15_R1_ALIGN) && (* address & 3))
{
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;
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)
{
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);
}
}
}
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);
}
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;
}
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;
}
}
static unsigned
check_cp13_access (ARMul_State * state,
unsigned reg,
unsigned CRm,
unsigned opcode_1,
unsigned opcode_2)
{
if (state->Mode == USER26MODE || state->Mode == USER32MODE)
return ARMul_CANT;
if ((opcode_1 != 0) || (opcode_2 != 0))
return ARMul_CANT;
if (! CP_ACCESS_ALLOWED (state, 13))
return ARMul_CANT;
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;
}
static void
write_cp13_reg (unsigned reg, unsigned CRm, ARMword value)
{
switch (CRm)
{
case 0:
switch (reg)
{
case 0:
value &= 0xf;
break;
case 4:
return;
case 8:
value &= 0x3;
break;
default:
return;
}
XScale_cp13_CR0_Regs [reg] = value;
break;
case 1:
switch (reg)
{
case 0:
value &= 0x7000000f;
value |= XScale_cp13_CR1_Regs[0] & (1UL << 31);
break;
case 1:
value &= 1;
value |= XScale_cp13_CR1_Regs[1] & ~ 1;
break;
case 4:
case 5:
case 6:
case 7:
return;
case 8:
value &= 0xff;
break;
default:
return;
}
XScale_cp13_CR1_Regs [reg] = value;
break;
default:
break;
}
return;
}
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)
{
* value = read_cp13_reg (reg, 0);
return TRUE;
}
static unsigned
XScale_cp13_write_reg (ARMul_State * state ATTRIBUTE_UNUSED,
unsigned reg,
ARMword value)
{
write_cp13_reg (reg, 0, value);
return TRUE;
}
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;
}
static unsigned
check_cp14_access (ARMul_State * state,
unsigned reg,
unsigned CRm,
unsigned opcode1,
unsigned opcode2)
{
if (state->Mode == USER26MODE || state->Mode == USER32MODE)
return ARMul_CANT;
if (CRm != 0)
return ARMul_CANT;
if (opcode1 != 0 || opcode2 != 0)
return ARMul_CANT;
if (reg >= 4 && reg <= 5)
return ARMul_CANT;
return ARMul_DONE;
}
static void
write_cp14_reg (unsigned reg, ARMword value)
{
switch (reg)
{
case 0:
value &= 0x0ffff77f;
if (value & ARMul_CP14_R0_CLKRST)
XScale_cp14_Regs [1] = 0;
break;
case 4:
case 5:
value = 0;
break;
case 6:
value &= 0xf;
break;
case 7:
value = 0;
break;
case 10:
value &= 0xc0df003f;
break;
case 11:
value = 0;
break;
case 14:
value &= 0xc0000000;
break;
default:
break;
}
XScale_cp14_Regs [reg] = value;
}
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;
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;
}
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)
state->Emulate = CHANGEMODE;
}
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)
state->Emulate = CHANGEMODE;
}
return TRUE;
}
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))
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))
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)];
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_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)
{
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;
}
return ARMul_CANT;
}
unsigned
ARMul_CoProInit (ARMul_State * state)
{
unsigned int i;
for (i = 0; i < 16; i++)
ARMul_CoProDetach (state, i);
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);
ARMul_CoProAttach (state, 15, MMUInit, NULL,
NULL, NULL, MMUMRC, MMUMCR, NULL, MMURead, MMUWrite);
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);
for (i = 0; i < 16; i++)
if (state->CPInit[i])
(state->CPInit[i]) (state);
return TRUE;
}
void
ARMul_CoProExit (ARMul_State * state)
{
register unsigned i;
for (i = 0; i < 16; i++)
if (state->CPExit[i])
(state->CPExit[i]) (state);
for (i = 0; i < 16; i++)
ARMul_CoProDetach (state, i);
}
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;
}