Patchwork [ARM] Fix prologue and epilogue for interrupt function

login
register
mail settings
Submitter Jie Zhang
Date July 7, 2010, 5:46 a.m.
Message ID <4C3414CE.8010606@codesourcery.com>
Download mbox | patch
Permalink /patch/58079/
State New
Headers show

Comments

Jie Zhang - July 7, 2010, 5:46 a.m.
ARM GCC will save r3 to the stack when it tries to align the stack to 
double-word. But it can only do so when r3 will not be saved. Otherwise 
there will be inconsistent information about how many registers will be 
saved and how much the stack will be adjusted. This patch fixes it.

Tested on arm-none-eabi. No regressions are found. Is it OK?


Regards,
Paul Brook - July 7, 2010, 1:49 p.m.
> ARM GCC will save r3 to the stack when it tries to align the stack to
> double-word. But it can only do so when r3 will not be saved. Otherwise
> there will be inconsistent information about how many registers will be
> saved and how much the stack will be adjusted. This patch fixes it.
> 
> Tested on arm-none-eabi. No regressions are found. Is it OK?

Your test fails for Thumb multilibs.

Other than that, ok.

Paul

Patch


	* config/arm/arm.c (arm_get_frame_offsets): Don't use r3 to
	align the stack when it's going to be saved.

	testsuite/
	* gcc.target/arm/interrupt-1.c: New test.
	* gcc.target/arm/interrupt-2.c: New test.

Index: testsuite/gcc.target/arm/interrupt-1.c
===================================================================
--- testsuite/gcc.target/arm/interrupt-1.c	(revision 0)
+++ testsuite/gcc.target/arm/interrupt-1.c	(revision 0)
@@ -0,0 +1,13 @@ 
+/* Verify that prologue and epilogue are correct for functions with
+   __attribute__ ((interrupt)).  */
+/* { dg-do compile } */
+/* { dg-options "-O0" } */
+extern void bar (int);
+extern void foo (void) __attribute__ ((interrupt("IRQ")));
+
+void foo ()
+{
+  bar (0);
+}
+/* { dg-final { scan-assembler "stmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, lr}" } } */
+/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, fp, ip, pc}\\^" } } */
Index: testsuite/gcc.target/arm/interrupt-2.c
===================================================================
--- testsuite/gcc.target/arm/interrupt-2.c	(revision 0)
+++ testsuite/gcc.target/arm/interrupt-2.c	(revision 0)
@@ -0,0 +1,16 @@ 
+/* Verify that prologue and epilogue are correct for functions with
+   __attribute__ ((interrupt)).  */
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+extern void bar (int);
+extern void test (void) __attribute__((__interrupt__));
+
+int foo;
+void test()
+{
+  funcptrs(foo);
+  foo = 0;
+}
+
+/* { dg-final { scan-assembler "stmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, lr}" } } */
+/* { dg-final { scan-assembler "ldmfd\tsp!, {r0, r1, r2, r3, r4, r5, ip, pc}\\^" } } */
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 161865)
+++ config/arm/arm.c	(working copy)
@@ -14690,7 +14690,8 @@  arm_get_frame_offsets (void)
 	     generates better code on Thumb-2 by avoiding the need to
 	     use 32-bit push/pop instructions.  */
 	  if (!crtl->tail_call_emit
-	      && arm_size_return_regs () <= 12)
+	      && arm_size_return_regs () <= 12
+	      && (offsets->saved_regs_mask & (1 << 3)) == 0)
 	    {
 	      reg = 3;
 	    }