The C compiler generates wrong assembler code for functions with  __attribute__
((interrupt ("IRQ"))). Link register lr in interrupt function is decremented
two times before it is loaded back to the program counter pc. It is decremented
at the beginning of interrupt routime (sub     lr, lr, #4) and again at the end
(subs    pc, lr, #4). It should be decremented only once. Such a bug was also
reported previously (ID 16634, ID 25428). Here is the complete example:


PROGRAM bug.c:

void function( void )
{
        volatile unsigned int *a;

        a = (unsigned int *)2000;
        *a = 1;
        *a = 0;
}

void IRQ_Handler( void ) __attribute__ ((interrupt ("IRQ")));
void IRQ_Handler( void )
{
        volatile unsigned int s, *a;


        a = (unsigned int *)2500;
        s = *a;

        function();

}

COMPILATION OUTPUT:

arm-4.1.1-eabi-gcc -v -save-temps -Wall -c -O  -o bug.o bug.c
Using built-in specs.
Target: arm-none-eabi
Configured with: ./configure --target=arm-none-eabi
--program-prefix=arm-4.1.1-eabi-
Thread model: single
gcc version 4.1.1
 /usr/local/packages/arm411/bin/../libexec/gcc/arm-none-eabi/4.1.1/cc1 -E
-quiet -v -iprefix
/usr/local/packages/arm411/bin/../lib/gcc/arm-none-eabi/4.1.1/
-D__USES_INITFINI__ bug.c -Wall -O -fpch-preprocess -o bug.i
ignoring nonexistent directory
"/usr/local/packages/arm411/bin/../lib/gcc/arm-none-eabi/4.1.1/../../../../arm-none-eabi/sys-include"
ignoring nonexistent directory "/usr/local/lib/gcc/arm-none-eabi/4.1.1/include"
ignoring nonexistent directory "/usr/local/lib/../arm-none-eabi/sys-include"
ignoring nonexistent directory "/usr/local/lib/../arm-none-eabi/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/packages/arm411/bin/../lib/gcc/arm-none-eabi/4.1.1/include

/usr/local/packages/arm411/bin/../lib/gcc/arm-none-eabi/4.1.1/../../../../arm-none-eabi/include
End of search list.
 /usr/local/packages/arm411/bin/../libexec/gcc/arm-none-eabi/4.1.1/cc1
-fpreprocessed bug.i -quiet -dumpbase bug.c -auxbase-strip bug.o -O -Wall
-version -o bug.s
GNU C version 4.1.1 (arm-none-eabi)
        compiled by GNU C version 4.1.1 20060525 (Red Hat 4.1.1-1).
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128878
Compiler executable checksum: 8b248e68ff58c0b76da33bbc4bade307

/usr/local/packages/arm411/bin/../lib/gcc/arm-none-eabi/4.1.1/../../../../arm-none-eabi/bin/as
-meabi=4 -o bug.o bug.s

ASSEMBLER OUTPUT:
        .file   "bug.c"
        .text
        .align  2
        .global function
        .type   function, %function
function:
        @ Function supports interworking.
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        @ lr needed for prologue
        mov     r3, #0
        mov     r2, #1
        str     r2, [r3, #2000]
        str     r3, [r3, #2000]
        bx      lr
        .size   function, .-function
        .align  2
        .global IRQ_Handler
        .type   IRQ_Handler, %function
IRQ_Handler:
        @ Interrupt Service Routine.
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 0, uses_anonymous_args = 0
        sub     lr, lr, #4
        stmfd   sp!, {r0, r1, r2, r3, ip, lr}
        sub     sp, sp, #8
        mov     r3, #0
        ldr     r3, [r3, #2500]
        str     r3, [sp, #4]
        bl      function
        add     sp, sp, #8
        ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
        subs    pc, lr, #4
        .size   IRQ_Handler, .-IRQ_Handler
        .ident  "GCC: (GNU) 4.1.1"


Best regards,
Jurij Kotar


-- 
           Summary: Bug in generation of interrupt function code for ARM
                    processor
           Product: gcc
           Version: 4.1.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: jurij dot kotar at gmail dot com
 GCC build triplet: i386-redhat-linux
  GCC host triplet: i386-redhat-linux
GCC target triplet: arm-none-eabi


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27859

Reply via email to