This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

ARM sim exceptions: adjust LR properly in Thumb mode


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]