diff options
-rw-r--r-- | sim/arm/ChangeLog | 6 | ||||
-rw-r--r-- | sim/arm/armemu.c | 35 | ||||
-rw-r--r-- | sim/arm/armemu.h | 11 | ||||
-rw-r--r-- | sim/arm/arminit.c | 41 |
4 files changed, 48 insertions, 45 deletions
diff --git a/sim/arm/ChangeLog b/sim/arm/ChangeLog index 06345b2..9e4bdc0 100644 --- a/sim/arm/ChangeLog +++ b/sim/arm/ChangeLog @@ -1,5 +1,11 @@ 2000-07-04 Alexandre Oliva <aoliva@redhat.com> + * armemu.h (INSN_SIZE): New macro. + (SET_ABORT): Save CPSR in SPSR and set LR. + * armemu.c (ARMul_Emulate, isize): Set to INSN_SIZE. + (WriteR15, WriteSR15): Do not discard bit 1 in Thumb mode. + * arminit.c (ARMul_Abort): Use new SETABORT and INSN_SIZE. + * armemu.c (LoadSMult): Use WriteR15() to discard the least significant bits of PC. diff --git a/sim/arm/armemu.c b/sim/arm/armemu.c index 43cd6dc..31bd327 100644 --- a/sim/arm/armemu.c +++ b/sim/arm/armemu.c @@ -299,14 +299,7 @@ ARMul_Emulate26 (register ARMul_State * state) do { /* just keep going */ -#ifdef MODET - if (TFLAG) - { - isize = 2; - } - else -#endif - isize = 4; + isize = INSN_SIZE; switch (state->NextInstr) { case SEQ: @@ -3104,8 +3097,15 @@ WriteR15 (ARMul_State * state, ARMword src) { /* The ARM documentation states that the two least significant bits are discarded when setting PC, except in the cases handled by - WriteR15Branch() below. */ - src &= 0xfffffffc; + WriteR15Branch() below. It's probably an oversight: in THUMB + mode, the second least significant bit should probably not be + discarded. */ +#ifdef MODET + if (TFLAG) + src &= 0xfffffffe; + else +#endif + src &= 0xfffffffc; #ifdef MODE32 state->Reg[15] = src & PCBITS; #else @@ -3122,15 +3122,26 @@ WriteR15 (ARMul_State * state, ARMword src) static void WriteSR15 (ARMul_State * state, ARMword src) { - src &= 0xfffffffc; #ifdef MODE32 - state->Reg[15] = src & PCBITS; if (state->Bank > 0) { state->Cpsr = state->Spsr[state->Bank]; ARMul_CPSRAltered (state); } +#ifdef MODET + if (TFLAG) + src &= 0xfffffffe; + else +#endif + src &= 0xfffffffc; + state->Reg[15] = src & PCBITS; #else +#ifdef MODET + if (TFLAG) + abort (); /* ARMul_R15Altered would have to support it. */ + else +#endif + src &= 0xfffffffc; if (state->Bank == USERBANK) state->Reg[15] = (src & (CCBITS | R15PCBITS)) | ER15INT | EMODE; else diff --git a/sim/arm/armemu.h b/sim/arm/armemu.h index ad89294..de836cb 100644 --- a/sim/arm/armemu.h +++ b/sim/arm/armemu.h @@ -73,6 +73,9 @@ extern ARMword isize; #define SETT state->TFlag = 1 #define CLEART state->TFlag = 0 #define ASSIGNT(res) state->TFlag = res +#define INSN_SIZE (TFLAG ? 2 : 4) +#else +#define INSN_SIZE 4 #endif #define NFLAG state->NFlag @@ -179,7 +182,13 @@ extern ARMword isize; state->Reg[15] = R15PC | ((s) & (CCBITS | R15INTBITS | R15MODEBITS)) ; \ ARMul_R15Altered (state) ; \ } -#define SETABORT(i,m) state->Cpsr = ECC | EINT | (i) | (m) +#define SETABORT(i,m,d) do { \ + int SETABORT_mode = (m); \ + ARMul_SetSPSR (state, SETABORT_mode, ARMul_GetCPSR (state)); \ + ARMul_SetCPSR (state, ((ARMul_GetCPSR (state) & ~(EMODE | TBIT)) \ + | (i) | SETABORT_mode)); \ + state->Reg[14] = temp - (d); \ +} while (0) #ifndef MODE32 #define VECTORS 0x20 diff --git a/sim/arm/arminit.c b/sim/arm/arminit.c index 0105c17..66e6dad 100644 --- a/sim/arm/arminit.c +++ b/sim/arm/arminit.c @@ -253,6 +253,7 @@ void ARMul_Abort (ARMul_State * state, ARMword vector) { ARMword temp; + int isize = INSN_SIZE; state->Aborted = FALSE; @@ -270,53 +271,29 @@ ARMul_Abort (ARMul_State * state, ARMword vector) switch (vector) { case ARMul_ResetV: /* RESET */ - state->Spsr[SVCBANK] = CPSR; - SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp; + SETABORT (INTBITS, state->prog32Sig ? SVC32MODE : SVC26MODE, 0); break; case ARMul_UndefinedInstrV: /* Undefined Instruction */ - state->Spsr[state->prog32Sig ? UNDEFBANK : SVCBANK] = CPSR; - SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (IBIT, state->prog32Sig ? UNDEF32MODE : SVC26MODE, isize); break; case ARMul_SWIV: /* Software Interrupt */ - state->Spsr[SVCBANK] = CPSR; - SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (IBIT, state->prog32Sig ? SVC32MODE : SVC26MODE, isize); break; case ARMul_PrefetchAbortV: /* Prefetch Abort */ state->AbortAddr = 1; - state->Spsr[state->prog32Sig ? ABORTBANK : SVCBANK] = CPSR; - SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize); break; case ARMul_DataAbortV: /* Data Abort */ - state->Spsr[state->prog32Sig ? ABORTBANK : SVCBANK] = CPSR; - SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; /* the PC must have been incremented */ + SETABORT (IBIT, state->prog32Sig ? ABORT32MODE : SVC26MODE, isize); break; case ARMul_AddrExceptnV: /* Address Exception */ - state->Spsr[SVCBANK] = CPSR; - SETABORT (IBIT, SVC26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (IBIT, SVC26MODE, isize); break; case ARMul_IRQV: /* IRQ */ - state->Spsr[IRQBANK] = CPSR; - SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (IBIT, state->prog32Sig ? IRQ32MODE : IRQ26MODE, isize); break; case ARMul_FIQV: /* FIQ */ - state->Spsr[FIQBANK] = CPSR; - SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE); - ARMul_CPSRAltered (state); - state->Reg[14] = temp - 4; + SETABORT (INTBITS, state->prog32Sig ? FIQ32MODE : FIQ26MODE, isize); break; } if (ARMul_MODE32BIT) |