1  /* Test epilogue of a realigned interrupt handler. */
       2  /* { dg-do run } */
       3  /* { dg-options "-mthumb -Os -mgeneral-regs-only" } */
       4  /* { dg-skip-if "" { ! { arm_thumb1_ok || arm_thumb2_ok } } } */
       5  /* { dg-require-effective-target arm_cortex_m } */
       6  /* { dg-require-effective-target arm_eabi } */
       7  
       8  extern __attribute__((noreturn)) void abort(void);
       9  extern int snprintf(char *, int, const char *, ...);
      10  
      11  #define BUFF_LEN 256
      12  char buff[BUFF_LEN];
      13  
      14  char *get_buffer(void)
      15  {
      16  	return buff;
      17  }
      18  
      19  void __attribute__((interrupt)) foo(void)
      20  {
      21          char *msg = get_buffer();
      22          snprintf(msg, BUFF_LEN, "%d %p", 1, buff+BUFF_LEN);
      23  }
      24  
      25  volatile void * save_sp;
      26  int main()
      27  {
      28  	register volatile void * sp asm("sp");
      29  	/* Check stack pointer before/after calling the interrupt
      30           * handler. Not equal means that handler doesn't restore
      31           * stack correctly.  */
      32  	save_sp = sp;
      33  	foo();
      34  	/* Abort here instead of return non-zero. Due to wrong sp, lr value,
      35  	 * returning from main may not work.  */
      36  	if (save_sp != sp)
      37  	{
      38  		sp = save_sp;
      39  		abort();
      40  	}
      41  	return 0;
      42  }