This is the mail archive of the
gdb-patches@sourceware.cygnus.com
mailing list for the GDB project.
ARM sim exceptions: adjust LR properly in Thumb mode
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: ARM sim exceptions: adjust LR properly in Thumb mode
- From: Alexandre Oliva <aoliva at redhat dot com>
- Date: 04 Jul 2000 03:51:42 -0300
- Organization: GCC Team, Red Hat
I'm checking this in, approved by Nick Clifton:
Index: sim/arm/ChangeLog
from 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.
Index: sim/arm/armemu.h
===================================================================
RCS file: /cvs/src/src/sim/arm/armemu.h,v
retrieving revision 1.6
diff -u -r1.6 armemu.h
--- sim/arm/armemu.h 2000/07/04 06:35:36 1.6
+++ sim/arm/armemu.h 2000/07/04 06:46:08
@@ -73,6 +73,9 @@
#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 @@
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
Index: sim/arm/armemu.c
===================================================================
RCS file: /cvs/src/src/sim/arm/armemu.c,v
retrieving revision 1.10
diff -u -r1.10 armemu.c
--- sim/arm/armemu.c 2000/07/04 06:39:39 1.10
+++ sim/arm/armemu.c 2000/07/04 06:46:08
@@ -299,14 +299,7 @@
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 @@
{
/* 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 @@
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
Index: sim/arm/arminit.c
===================================================================
RCS file: /cvs/src/src/sim/arm/arminit.c,v
retrieving revision 1.2
diff -u -r1.2 arminit.c
--- sim/arm/arminit.c 2000/05/30 17:13:37 1.2
+++ sim/arm/arminit.c 2000/07/04 06:46:08
@@ -253,6 +253,7 @@
ARMul_Abort (ARMul_State * state, ARMword vector)
{
ARMword temp;
+ int isize = INSN_SIZE;
state->Aborted = FALSE;
@@ -270,53 +271,29 @@
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)
--
Alexandre Oliva Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist *Please* write to mailing lists, not to me