diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 14723eb314a..7c0c7b52be8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2011-08-19 Matthew Gretton-Dann + + PR target/49437 + * config/arm/arm.c (arm_output_epilogue): Properly handle epilogue + when stack was realigned in interrupt handler prologue. + 2011-08-18 Joseph Myers * c-decl.c (shadow_tag_warned): Check for _Noreturn. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d1a349049f8..3162b30582e 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -15230,6 +15230,7 @@ arm_output_epilogue (rtx sibling) && !crtl->calls_eh_return && bit_count(saved_regs_mask) * 4 == count && !IS_INTERRUPT (func_type) + && !IS_STACKALIGN (func_type) && !crtl->tail_call_emit) { unsigned long mask; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3f286ed5d13..0cadc3ccb7d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-08-19 Joey Ye + + PR target/49437 + * gcc.target/arm/handler-align.c: New test. + * lib/target-supports.exp (check_effective_target_arm_cortex_m): + New Function. + 2011-08-19 Joey Ye * gcc.c-torture/execute/20101011-1.c (DO_TEST): Skip on ARM. diff --git a/gcc/testsuite/gcc.target/arm/handler-align.c b/gcc/testsuite/gcc.target/arm/handler-align.c new file mode 100644 index 00000000000..6c5187b2028 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/handler-align.c @@ -0,0 +1,42 @@ +/* Test epilogue of a realigned interrupt handler. */ +/* { dg-do run } */ +/* { dg-options "-mthumb -Os" } */ +/* { dg-skip-if "" { ! { arm_thumb1_ok || arm_thumb2_ok } } } */ +/* { dg-require-effective-target arm_cortex_m } */ +/* { dg-require-effective-target arm_eabi } */ + +extern __attribute__((noreturn)) void abort(void); +extern int snprintf(char *, int, const char *, ...); + +#define BUFF_LEN 256 +char buff[BUFF_LEN]; + +char *get_buffer(void) +{ + return buff; +} + +void __attribute__((interrupt)) foo(void) +{ + char *msg = get_buffer(); + snprintf(msg, BUFF_LEN, "%d %p", 1, buff+BUFF_LEN); +} + +volatile void * save_sp; +int main() +{ + register volatile void * sp asm("sp"); + /* Check stack pointer before/after calling the interrupt + * handler. Not equal means that handler doesn't restore + * stack correctly. */ + save_sp = sp; + foo(); + /* Abort here instead of return non-zero. Due to wrong sp, lr value, + * returning from main may not work. */ + if (save_sp != sp) + { + sp = save_sp; + abort(); + } + return 0; +} diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 28dedc97d32..54dc6b60bd5 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -2116,6 +2116,19 @@ proc check_effective_target_arm_thumb2 { } { } ""] } +# Return 1 if this is an ARM cortex-M profile cpu + +proc check_effective_target_arm_cortex_m { } { + return [check_no_compiler_messages arm_cortex_m assembly { + #if !defined(__ARM_ARCH_7M__) \ + && !defined (__ARM_ARCH_7EM__) \ + && !defined (__ARM_ARCH_6M__) + #error FOO + #endif + int i; + } "-mthumb"] +} + # Return 1 if the target supports executing NEON instructions, 0 # otherwise. Cache the result.