diff options
author | Matthew Green <mrg@redhat.com> | 2001-04-18 16:39:37 +0000 |
---|---|---|
committer | Matthew Green <mrg@redhat.com> | 2001-04-18 16:39:37 +0000 |
commit | c3ae2f98d01baddf23a93ea5c2311701844f8b82 (patch) | |
tree | 3e361057a3fd8c1ac85f93f87282ce628e7f09ed /sim/arm/armemu.c | |
parent | c9e030cfcdebafd5fb515b93e9d30a6eda273d53 (diff) | |
download | gdb-c3ae2f98d01baddf23a93ea5c2311701844f8b82.zip gdb-c3ae2f98d01baddf23a93ea5c2311701844f8b82.tar.gz gdb-c3ae2f98d01baddf23a93ea5c2311701844f8b82.tar.bz2 |
* XScale coprocessor support.
2001-04-18 matthew green <mrg@redhat.com>
* armcopro.c (write_cp15_reg): Set CHANGEMODE if endianness changes.
(read_cp15_reg): Make non-static.
(XScale_cp15_LDC): Update for write_cp15_reg() change.
(XScale_cp15_MCR): Likewise.
(XScale_cp15_write_reg): Likewise.
(XScale_check_memacc): New function. Check for breakpoints being
activated by memory accesses. Does not support the Branch Target
Buffer.
(XScale_set_fsr_far): New function. Set FSR and FAR for XScale.
(XScale_debug_moe): New function. Set the debug Method Of Entry,
if configured.
(write_cp14_reg): Reset count counter if requested.
* armdefs.h (struct ARMul_State): New members `LastTime' and
`CP14R0_CCD' used for the timer/counters.
(ARMul_CP13_R0_FIQ, ARMul_CP13_R0_IRQ, ARMul_CP13_R8_PMUS,
ARMul_CP14_R0_ENABLE, ARMul_CP14_R0_CLKRST, ARMul_CP14_R0_CCD,
ARMul_CP14_R0_INTEN0, ARMul_CP14_R0_INTEN1, ARMul_CP14_R0_INTEN2,
ARMul_CP14_R0_FLAG0, ARMul_CP14_R0_FLAG1, ARMul_CP14_R0_FLAG2,
ARMul_CP14_R10_MOE_IB, ARMul_CP14_R10_MOE_DB, ARMul_CP14_R10_MOE_BT,
ARMul_CP15_R1_ENDIAN, ARMul_CP15_R1_ALIGN, ARMul_CP15_R5_X,
ARMul_CP15_R5_ST_ALIGN, ARMul_CP15_R5_IMPRE, ARMul_CP15_R5_MMU_EXCPT,
ARMul_CP15_DBCON_M, ARMul_CP15_DBCON_E1, ARMul_CP15_DBCON_E0): New
defines for XScale registers.
(XScale_check_memacc, XScale_set_fsr_far, XScale_debug_moe): Prototype.
(ARMul_Emulate32, ARMul_Emulate26): Clean up function definition.
(ARMul_Emulate32): Handle the clock counter and hardware instruction
breakpoints. Call XScale_set_fsr_far() for software breakpoints and
software interrupts.
(LoadMult): Call XScale_set_fsr_far() for data aborts.
(LoadSMult): Likewise.
(StoreMult): Likewise.
(StoreSMult): Likewise.
* armemu.h (write_cp15_reg): Update prototype.
* arminit.c (ARMul_NewState): Initialise CP14R0_CCD and LastTime.
(ARMul_Abort): If XScale, check for FIQ and IRQ being enabled in CP13
register 0.
* armvirt.c (GetWord): Call XScale_check_memacc().
(PutWord): Likewise.
Diffstat (limited to 'sim/arm/armemu.c')
-rw-r--r-- | sim/arm/armemu.c | 107 |
1 files changed, 87 insertions, 20 deletions
diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c index dcc505f..0947470 100644 --- a/sim/arm/armemu.c +++ b/sim/arm/armemu.c @@ -529,6 +529,79 @@ ARMul_Emulate26 (register ARMul_State * state) break; } /* cc check */ + /* Handle the Clock counter here. */ + if (state->is_XScale) + { + ARMword cp14r0 = state->CPRead[14] (state, 0, 0); + + if (cp14r0 && ARMul_CP14_R0_ENABLE) + { + unsigned long newcycles, nowtime = ARMul_Time(state); + + newcycles = nowtime - state->LastTime; + state->LastTime = nowtime; + if (cp14r0 && ARMul_CP14_R0_CCD) + { + if (state->CP14R0_CCD == -1) + state->CP14R0_CCD = newcycles; + else + state->CP14R0_CCD += newcycles; + if (state->CP14R0_CCD >= 64) + { + newcycles = 0; + while (state->CP14R0_CCD >= 64) + state->CP14R0_CCD -= 64, newcycles++; + goto check_PMUintr; + } + } + else + { + ARMword cp14r1; + int do_int = 0; + + state->CP14R0_CCD = -1; +check_PMUintr: + cp14r0 |= ARMul_CP14_R0_FLAG2; + (void) state->CPWrite[14] (state, 0, cp14r0); + + cp14r1 = state->CPRead[14] (state, 1, 0); + + /* coded like this for portability */ + while (newcycles) + { + if (cp14r1 == 0xffffffff) + { + cp14r1 = 0; + do_int = 1; + } + else + cp14r1++; + newcycles--; + } + (void) state->CPWrite[14] (state, 1, cp14r1); + if (do_int && (cp14r0 & ARMul_CP14_R0_INTEN2)) + { + if (state->CPRead[13] (state, 8, 0) + && ARMul_CP13_R8_PMUS) + ARMul_Abort (state, ARMul_FIQV); + else + ARMul_Abort (state, ARMul_IRQV); + } + } + } + } + + /* Handle hardware instructions breakpoints here. */ + if (state->is_XScale) + { + if ((pc | 3) == (read_cp15_reg (14, 0, 8) | 2) + || (pc | 3) == (read_cp15_reg (14, 0, 9) | 2)) + { + if (XScale_debug_moe (state, ARMul_CP14_R10_MOE_IB)) + ARMul_OSHandleSWI (state, SWI_Breakpoint); + } + } + /***************************************************************************\ * Actual execution of instructions begins here * \***************************************************************************/ @@ -1355,26 +1428,11 @@ ARMul_Emulate26 (register ARMul_State * state) ARMul_OSHandleSWI (state, SWI_Breakpoint); else { - /* BKPT - normally this will cause an abort, but for the - XScale if bit 31 in register 10 of coprocessor 14 is - clear, then this is treated as a no-op. */ - if (state->is_XScale) - { - if (read_cp14_reg (10) & (1UL << 31)) - { - ARMword value; - - value = read_cp14_reg (10); - value &= ~0x1c; - value |= 0xc; - - write_cp14_reg (10, value); - write_cp15_reg (state, 5, 0, 0, 0x200); /* Set FSR. */ - write_cp15_reg (state, 6, 0, 0, pc); /* Set FAR. */ - } - else - break; - } + /* BKPT - normally this will cause an abort, but on the + XScale we must check the DCSR. */ + XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); + if (!XScale_debug_moe (state, ARMul_CP14_R10_MOE_BT)) + break; } /* Force the next instruction to be refetched. */ @@ -3425,6 +3483,7 @@ ARMul_Emulate26 (register ARMul_State * state) if (instr == ARMul_ABORTWORD && state->AbortAddr == pc) { /* A prefetch abort. */ + XScale_set_fsr_far (state, ARMul_CP15_R5_MMU_EXCPT, pc); ARMul_Abort (state, ARMul_PrefetchAbortV); break; } @@ -4295,6 +4354,7 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) state->Reg[temp++] = dest; else if (!state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } @@ -4307,6 +4367,7 @@ LoadMult (ARMul_State * state, ARMword instr, ARMword address, ARMword WBBase) state->Reg[temp] = dest; else if (!state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } } @@ -4373,6 +4434,7 @@ LoadSMult (ARMul_State * state, state->Reg[temp++] = dest; else if (!state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } @@ -4388,6 +4450,7 @@ LoadSMult (ARMul_State * state, state->Reg[temp] = dest; else if (!state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } } @@ -4489,6 +4552,7 @@ StoreMult (ARMul_State * state, ARMword instr, if (state->abortSig && !state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } @@ -4504,6 +4568,7 @@ StoreMult (ARMul_State * state, ARMword instr, if (state->abortSig && !state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } } @@ -4585,6 +4650,7 @@ StoreSMult (ARMul_State * state, if (state->abortSig && !state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } @@ -4599,6 +4665,7 @@ StoreSMult (ARMul_State * state, if (state->abortSig && !state->Aborted) { + XScale_set_fsr_far(state, ARMul_CP15_R5_ST_ALIGN, address); state->Aborted = ARMul_DataAbortV; } } |