From c1a72ffdd6aecb2880a7ea3a00234fd48142074c Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Tue, 30 May 2000 17:13:37 +0000 Subject: [PATCH] Add support for v4 SystemMode. --- sim/arm/ChangeLog | 28 ++++++++++++- sim/arm/Makefile.in | 8 ++-- sim/arm/armcopro.c | 38 ++++++++++++++++-- sim/arm/armdefs.h | 21 ++++++---- sim/arm/armemu.c | 6 ++- sim/arm/arminit.c | 8 +++- sim/arm/armos.c | 1 + sim/arm/armsupp.c | 93 ++++++++++++++++++++++++++++---------------- sim/arm/configure | 2 + sim/arm/configure.in | 3 ++ sim/arm/wrapper.c | 8 ++-- 11 files changed, 159 insertions(+), 57 deletions(-) diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index b58b9add26..f7b7895649 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,4 +1,30 @@ -Tue May 23 21:39:23 2000 Andrew Cagney +2000-05-25 Nick Clifton + + * armcopro.c (MMUMCR): Only indicate mode change if a singal has + really changed. + (MMUWrite): Only indicate mode change if a singal has really + changed. + + * armdefs.h (SYSTEMMODE): Define. + (BANK_CAN_ACEESS_SPSR): Define. + + * armemu.c (ARM_Emulate26): If the mode has changed allow the PC + to advance before stopping the emulation. + + * arminit.c (ARMul_Reset): Ensure Mode field of State is set + correctly. + + * armos.c (ARMul_OSInit): Create a initial stack pointer for + System mode. + + * armsupp.c (ModeToBank): Remove unused first parameter. + Add support for System Mode. + (ARMul_GetSPSR): Use BANK_CAN_ACCESS_SPSR macro. + (ARMul_SetSPSR): Use BANK_CAN_ACCESS_SPSR macro. + (ARMul_FixSPSR): Use BANK_CAN_ACCESS_SPSR macro. + (ARMulSwitchMode): Add support for System Mode. + +Wed May 24 14:40:34 2000 Andrew Cagney * configure: Regenerated to track ../common/aclocal.m4 changes. diff --git a/sim/arm/Makefile.in b/sim/arm/Makefile.in index e2f2b3c5f0..19a9bcab4f 100644 --- a/sim/arm/Makefile.in +++ b/sim/arm/Makefile.in @@ -20,15 +20,17 @@ SIM_EXTRA_CFLAGS = -DMODET -DNEED_UI_LOOP_HOOK -SIM_OBJS = armcopro.o armemu26.o armemu32.o arminit.o armos.o armsupp.o \ - armvirt.o bag.o thumbemu.o wrapper.o sim-load.o +COPRO=@COPRO@ + +SIM_OBJS = armemu26.o armemu32.o arminit.o armos.o armsupp.o \ + armvirt.o bag.o thumbemu.o wrapper.o sim-load.o $(COPRO) ## COMMON_POST_CONFIG_FRAG armos.o: armos.c armdefs.h armos.h armfpe.h -armcopro.o: armcopro.c armdefs.h +armcopro.o: armcopro.c armdefs.h armemu26.o: armemu.c armdefs.h armemu.h $(CC) -c $< -o armemu26.o $(ALL_CFLAGS) diff --git a/sim/arm/armcopro.c b/sim/arm/armcopro.c index 579446c195..48be6806ea 100644 --- a/sim/arm/armcopro.c +++ b/sim/arm/armcopro.c @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "armdefs.h" +#include "armemu.h" #include "ansidecl.h" extern unsigned ARMul_CoProInit (ARMul_State * state); @@ -79,15 +80,29 @@ MMUMCR (ARMul_State * state, unsigned type ATTRIBUTE_UNUSED, ARMword instr, ARMw 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; - state->Emulate = TRUE; /* force ARMulator to notice these now ! */ + + if (p != state->prog32Sig + || d != state->data32Sig + || l != state->lateabtSig + || b != state->bigendSig) + state->Emulate = CHANGEMODE; /* Force ARMulator to notice these now. */ } - return (ARMul_DONE); + + return ARMul_DONE; } @@ -106,15 +121,30 @@ 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; - state->Emulate = TRUE; /* force ARMulator to notice these now ! */ + + + if (p != state->prog32Sig + || d != state->data32Sig + || l != state->lateabtSig + || b != state->bigendSig) + state->Emulate = CHANGEMODE; /* Force ARMulator to notice these now. */ } - return (TRUE); + + return TRUE; } diff --git a/sim/arm/armdefs.h b/sim/arm/armdefs.h index bce638dfe4..b23f26f51f 100644 --- a/sim/arm/armdefs.h +++ b/sim/arm/armdefs.h @@ -200,16 +200,17 @@ struct ARMul_State * Mode and Bank Constants * \***************************************************************************/ -#define USER26MODE 0L -#define FIQ26MODE 1L -#define IRQ26MODE 2L -#define SVC26MODE 3L -#define USER32MODE 16L -#define FIQ32MODE 17L -#define IRQ32MODE 18L -#define SVC32MODE 19L +#define USER26MODE 0L +#define FIQ26MODE 1L +#define IRQ26MODE 2L +#define SVC26MODE 3L +#define USER32MODE 16L +#define FIQ32MODE 17L +#define IRQ32MODE 18L +#define SVC32MODE 19L #define ABORT32MODE 23L #define UNDEF32MODE 27L +#define SYSTEMMODE 31L #define ARM32BITMODE (state->Mode > 3) #define ARM26BITMODE (state->Mode <= 3) @@ -225,6 +226,10 @@ struct ARMul_State #define ABORTBANK 4 #define UNDEFBANK 5 #define DUMMYBANK 6 +#define SYSTEMBANK 7 + +#define BANK_CAN_ACCESS_SPSR(bank) \ + ((bank) != USERBANK && (bank) != SYSTEMBANK && (bank) != DUMMYBANK) /***************************************************************************\ * Definitons of things in the emulator * diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c index d890cda259..acbcb75295 100644 --- a/sim/arm/armemu.c +++ b/sim/arm/armemu.c @@ -2864,6 +2864,9 @@ ARMul_Emulate26 (register ARMul_State * state) if (state->Emulate == ONCE) state->Emulate = STOP; + /* If we have changed mode, allow the PC to advance before stopping. */ + else if (state->Emulate == CHANGEMODE) + continue; else if (state->Emulate != RUN) break; } @@ -2872,7 +2875,8 @@ ARMul_Emulate26 (register ARMul_State * state) state->decoded = decoded; state->loaded = loaded; state->pc = pc; - return (pc); + + return pc; } /* Emulate 26/32 in instruction based mode */ diff --git a/sim/arm/arminit.c b/sim/arm/arminit.c index 3e75b478b6..0105c17c0f 100644 --- a/sim/arm/arminit.c +++ b/sim/arm/arminit.c @@ -85,7 +85,8 @@ ARMul_NewState (void) } for (i = 0; i < 7; i++) state->Spsr[i] = 0; - state->Mode = 0; + + state->Mode = USER26MODE; state->CallDebug = FALSE; state->Debug = FALSE; @@ -156,18 +157,23 @@ void ARMul_Reset (ARMul_State * state) { state->NextInstr = 0; + if (state->prog32Sig) { state->Reg[15] = 0; state->Cpsr = INTBITS | SVC32MODE; + state->Mode = SVC32MODE; } else { state->Reg[15] = R15INTBITS | SVC26MODE; state->Cpsr = INTBITS | SVC26MODE; + state->Mode = SVC26MODE; } + ARMul_CPSRAltered (state); state->Bank = SVCBANK; + FLUSHPIPE; state->EndCondition = 0; diff --git a/sim/arm/armos.c b/sim/arm/armos.c index 67dd51c16a..958d4cde6f 100644 --- a/sim/arm/armos.c +++ b/sim/arm/armos.c @@ -165,6 +165,7 @@ ARMul_OSInit (ARMul_State * state) ARMul_SetReg (state, SVC32MODE, 13, ADDRSUPERSTACK); /* and for supervisor mode */ ARMul_SetReg (state, ABORT32MODE, 13, ADDRSUPERSTACK); /* and for abort 32 mode */ ARMul_SetReg (state, UNDEF32MODE, 13, ADDRSUPERSTACK); /* and for undef 32 mode */ + ARMul_SetReg (state, SYSTEMMODE, 13, ADDRSUPERSTACK); /* and for system mode */ instr = 0xe59ff000 | (ADDRSOFTVECTORS - 8); /* load pc from soft vector */ for (i = ARMul_ResetV; i <= ARMFIQV; i += 4) ARMul_WriteWord (state, i, instr); /* write hardware vectors */ diff --git a/sim/arm/armsupp.c b/sim/arm/armsupp.c index 154d520d21..5c18ddd3b0 100644 --- a/sim/arm/armsupp.c +++ b/sim/arm/armsupp.c @@ -42,7 +42,7 @@ void ARMul_R15Altered (ARMul_State * state); ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode); -static ARMword ModeToBank (ARMul_State * state, ARMword mode); +static ARMword ModeToBank (ARMword mode); unsigned ARMul_NthReg (ARMword instr, unsigned number); @@ -87,7 +87,7 @@ ARMul_GetReg (ARMul_State * state, unsigned mode, unsigned reg) { mode &= MODEBITS; if (mode != state->Mode) - return (state->RegBank[ModeToBank (state, (ARMword) mode)][reg]); + return (state->RegBank[ModeToBank ((ARMword) mode)][reg]); else return (state->Reg[reg]); } @@ -101,7 +101,7 @@ ARMul_SetReg (ARMul_State * state, unsigned mode, unsigned reg, ARMword value) { mode &= MODEBITS; if (mode != state->Mode) - state->RegBank[ModeToBank (state, (ARMword) mode)][reg] = value; + state->RegBank[ModeToBank ((ARMword) mode)][reg] = value; else state->Reg[reg] = value; } @@ -233,11 +233,12 @@ ARMul_FixCPSR (ARMul_State * state, ARMword instr, ARMword rhs) ARMword ARMul_GetSPSR (ARMul_State * state, ARMword mode) { - ARMword bank = ModeToBank (state, mode & MODEBITS); - if (bank == USERBANK || bank == DUMMYBANK) - return (CPSR); - else - return (state->Spsr[bank]); + ARMword bank = ModeToBank (mode & MODEBITS); + + if (! BANK_CAN_ACCESS_SPSR (bank)) + return CPSR; + + return state->Spsr[bank]; } /***************************************************************************\ @@ -247,8 +248,9 @@ ARMul_GetSPSR (ARMul_State * state, ARMword mode) void ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) { - ARMword bank = ModeToBank (state, mode & MODEBITS); - if (bank != USERBANK && bank != DUMMYBANK) + ARMword bank = ModeToBank (mode & MODEBITS); + + if (BANK_CAN_ACCESS_SPSR (bank)) state->Spsr[bank] = value; } @@ -259,7 +261,7 @@ ARMul_SetSPSR (ARMul_State * state, ARMword mode, ARMword value) void ARMul_FixSPSR (ARMul_State * state, ARMword instr, ARMword rhs) { - if (state->Bank != USERBANK && state->Bank != DUMMYBANK) + if (BANK_CAN_ACCESS_SPSR (state->Bank)) { if (BITS (16, 19) == 9) SETPSR (state->Spsr[state->Bank], rhs); @@ -282,11 +284,14 @@ ARMul_CPSRAltered (ARMul_State * state) if (state->prog32Sig == LOW) state->Cpsr &= (CCBITS | INTBITS | R15MODEBITS); + oldmode = state->Mode; + if (state->Mode != (state->Cpsr & MODEBITS)) { state->Mode = ARMul_SwitchMode (state, state->Mode, state->Cpsr & MODEBITS); + state->NtransSig = (state->Mode & 3) ? HIGH : LOW; } @@ -317,7 +322,6 @@ ARMul_CPSRAltered (ARMul_State * state) else state->Reg[15] = ECC | ER15INT | EMODE | R15PC; } - } /***************************************************************************\ @@ -355,23 +359,30 @@ ARMword ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) { unsigned i; - - oldmode = ModeToBank (state, oldmode); - state->Bank = ModeToBank (state, newmode); - if (oldmode != state->Bank) + ARMword oldbank; + ARMword newbank; + + oldbank = ModeToBank (oldmode); + newbank = state->Bank = ModeToBank (newmode); + + if (oldbank != newbank) { /* really need to do it */ - switch (oldmode) + switch (oldbank) { /* save away the old registers */ + case SYSTEMBANK: + /* The System mode uses the USER bank. */ + oldbank = USERBANK; + /* Fall through. */ case USERBANK: case IRQBANK: case SVCBANK: case ABORTBANK: case UNDEFBANK: - if (state->Bank == FIQBANK) + if (newbank == FIQBANK) for (i = 8; i < 13; i++) state->RegBank[USERBANK][i] = state->Reg[i]; - state->RegBank[oldmode][13] = state->Reg[13]; - state->RegBank[oldmode][14] = state->Reg[14]; + state->RegBank[oldbank][13] = state->Reg[13]; + state->RegBank[oldbank][14] = state->Reg[14]; break; case FIQBANK: for (i = 8; i < 15; i++) @@ -381,20 +392,25 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) for (i = 8; i < 15; i++) state->RegBank[DUMMYBANK][i] = 0; break; - + default: + abort (); } - switch (state->Bank) + + switch (newbank) { /* restore the new registers */ + case SYSTEMBANK: + newbank = USERBANK; + /* Fall through. */ case USERBANK: case IRQBANK: case SVCBANK: case ABORTBANK: case UNDEFBANK: - if (oldmode == FIQBANK) + if (oldbank == FIQBANK) for (i = 8; i < 13; i++) state->Reg[i] = state->RegBank[USERBANK][i]; - state->Reg[13] = state->RegBank[state->Bank][13]; - state->Reg[14] = state->RegBank[state->Bank][14]; + state->Reg[13] = state->RegBank[newbank][13]; + state->Reg[14] = state->RegBank[newbank][14]; break; case FIQBANK: for (i = 8; i < 15; i++) @@ -404,9 +420,12 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) for (i = 8; i < 15; i++) state->Reg[i] = 0; break; + default: + abort (); } /* switch */ } /* if */ - return (newmode); + + return newmode; } /***************************************************************************\ @@ -415,21 +434,24 @@ ARMul_SwitchMode (ARMul_State * state, ARMword oldmode, ARMword newmode) \***************************************************************************/ static ARMword -ModeToBank (ARMul_State * state ATTRIBUTE_UNUSED, ARMword mode) +ModeToBank (ARMword mode) { - static ARMword bankofmode[] = { USERBANK, FIQBANK, IRQBANK, SVCBANK, + static ARMword bankofmode[] = + { + USERBANK, FIQBANK, IRQBANK, SVCBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, - USERBANK, FIQBANK, IRQBANK, SVCBANK, + USERBANK, FIQBANK, IRQBANK, SVCBANK, DUMMYBANK, DUMMYBANK, DUMMYBANK, ABORTBANK, - DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK + DUMMYBANK, DUMMYBANK, DUMMYBANK, UNDEFBANK, + DUMMYBANK, DUMMYBANK, DUMMYBANK, SYSTEMBANK }; - if (mode > UNDEF32MODE) - return (DUMMYBANK); - else - return (bankofmode[mode]); + if (mode >= (sizeof (bankofmode) / sizeof (bankofmode[0]))) + return DUMMYBANK; + + return bankofmode[mode]; } /***************************************************************************\ @@ -650,9 +672,11 @@ ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) unsigned cpab; cpab = (state->MCR[CPNum]) (state, ARMul_FIRST, instr, source); + while (cpab == ARMul_BUSY) { ARMul_Icycles (state, 1, 0); + if (IntPending (state)) { cpab = (state->MCR[CPNum]) (state, ARMul_INTERRUPT, instr, 0); @@ -661,6 +685,7 @@ ARMul_MCR (ARMul_State * state, ARMword instr, ARMword source) else cpab = (state->MCR[CPNum]) (state, ARMul_BUSY, instr, source); } + if (cpab == ARMul_CANT) ARMul_Abort (state, ARMul_UndefinedInstrV); else diff --git a/sim/arm/configure b/sim/arm/configure index 2720d6b5d3..2c574e4cd9 100755 --- a/sim/arm/configure +++ b/sim/arm/configure @@ -3534,6 +3534,7 @@ fi done +COPRO=armcopro.o trap '' 1 2 15 @@ -3744,6 +3745,7 @@ s%@sim_stdio@%$sim_stdio%g s%@sim_trace@%$sim_trace%g s%@sim_profile@%$sim_profile%g s%@EXEEXT@%$EXEEXT%g +s%@COPRO@%$COPRO%g CEOF EOF diff --git a/sim/arm/configure.in b/sim/arm/configure.in index 033b0bc161..cbfac44e4c 100644 --- a/sim/arm/configure.in +++ b/sim/arm/configure.in @@ -7,4 +7,7 @@ SIM_AC_COMMON AC_CHECK_HEADERS(unistd.h) +COPRO=armcopro.o +AC_SUBST(COPRO) + SIM_AC_OUTPUT diff --git a/sim/arm/wrapper.c b/sim/arm/wrapper.c index 003dec6d59..8fca85df14 100644 --- a/sim/arm/wrapper.c +++ b/sim/arm/wrapper.c @@ -205,13 +205,11 @@ sim_create_inferior (sd, abfd, argv, env) else ARMul_SetPC (state, 0); /* ??? */ -#if 1 /* JGS */ /* We explicitly select a processor capable of supporting the ARM - 32bit mode, and then we force the simulated CPU into the 32bit - User mode: */ + 32bit mode. JGS */ ARMul_SelectProcessor (state, ARM600); + /* And then we force the simulated CPU into the 32bit User mode. */ ARMul_SetCPSR (state, USER32MODE); -#endif if (argv != NULL) { @@ -359,7 +357,7 @@ sim_open (kind, ptr, abfd, argv) { sim_kind = kind; if (myname) free (myname); - myname = xstrdup (argv[0]); + myname = (char *) xstrdup (argv[0]); sim_callback = ptr; /* Decide upon the endian-ness of the processor. -- 2.34.1