# 1 "irq.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "irq.c"
extern void add_irq(int, void (*irq)(void)); extern void do_something(void); static __attribute__ ((interrupt("IRQ"))) void irq(void) { unsigned long ints; ints = (*(volatile unsigned long *)(0x00000000)); ints &= ~(*(volatile unsigned long *)(0x00000004)); if (ints & 0x1) do_something(); (*(volatile unsigned long *)(0x00000000)) = ints; } void init(void) { add_irq(0, irq); } When compiled with -Os using gcc 4.5.0 (arm-none-eabi), the generated assembly for irq() subtracts 4 from the stack pointer immediately prior to calling do_something() but never adds 4 back before the function exits. This results in the program counter (and all registers saved at the start of the function) being loaded with incorrect values. This doesn't happen with 4.5.0 when compiled with no optimisation (-O0) or with 4.4.2 (arm-elf) with any optimisation level. It appears to only be a problem when the function is defined as an interrupt handler as when defined as a normal function (with standard entry/exit wrappers) the generated assembly looks correct. Target: arm-none-eabi Configured with: ../gcc-4.5.0/configure --target=arm-none-eabi --prefix=/home/ya garto/install --disable-nls --disable-shared --disable-threads --with-gcc --with -gnu-ld --with-gnu-as --with-dwarf2 --enable-languages=c,c++ --enable-interwork --enable-multilib --with-newlib --with-headers=../newlib-1.18.0/newlib/libc/incl ude --disable-libssp --disable-libstdcxx-pch --disable-libmudflap --disable-libg omp -v Thread model: single gcc version 4.5.0 (GCC) COLLECT_GCC_OPTIONS='-mcpu=arm7tdmi-s' '-std=gnu99' '-Wall' '-c' '-fno-common' '-Os' '-o' -- Summary: Stack pointer corruption within interrupt routine when compiled with -Os Product: gcc Version: 4.5.0 Status: UNCONFIRMED Severity: major Priority: P3 Component: target AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rob dot thornburrow at adder dot com GCC target triplet: arm-none-eabi http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44888