Bug 12080 - arm-elf-gcc-3.2 generates wrong interrupt code w/o optimizations on
Summary: arm-elf-gcc-3.2 generates wrong interrupt code w/o optimizations on
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 3.2
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2003-08-27 15:21 UTC by James Lamanna
Modified: 2003-09-01 09:27 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2003-08-28 01:24:03


Attachments
Smaller C file showing the same problems. (143 bytes, application/octet-stream)
2003-08-27 15:25 UTC, James Lamanna
Details
bug.i, from compiling bug.c (177 bytes, application/octet-stream)
2003-08-27 15:25 UTC, James Lamanna
Details

Note You need to log in before you can comment on or make changes to this bug.
Description James Lamanna 2003-08-27 15:21:31 UTC
arm-elf-gcc-3.2 seems to generate bad interrupt code when compiling w/o any 
optimizations.




Gcc Version:


arm-elf-gcc (GCC) 3.2




Compiling with:


arm-elf-gcc -S -g -I. -mcpu=arm7dmi -Wall -save-temps timer_test.c




yields the following asm code for an interrupt handler:


timer2_int:


.LFB3:


.LM25:


    @ Interrupt Service Routine.


    @ args = 0, pretend = 0, frame = 0


    @ frame_needed = 1, uses_anonymous_args = 0


    str ip, [sp, #-4]!


    mov ip, sp


.LCFI7:


    sub lr, lr, #4


    stmfd   sp!, {r2, r3, fp, ip, lr, pc}


.LCFI8:


    sub fp, ip, #4


.LCFI9:


.LM26:


    mvn r3, #3776


    sub r3, r3, #15


    mov r2, #0


    str r2, [r3, #0]


.LM27:


    ldmea   fp, {r2, r3, fp, ip, pc}^




As you can see, the last line of this is bogus.


It should not be LDMing from fp, but instead from sp.




Compiling with:


arm-elf-gcc -S -g -I. -O2 -mcpu=arm7dmi -Wall -save-temps timer_test.c


fixes the problem:




.LM49:


    @ Interrupt Service Routine.


    @ args = 0, pretend = 0, frame = 0


    @ frame_needed = 0, uses_anonymous_args = 0


    @ link register save eliminated.


    stmfd   sp!, {r2, r3}


.LCFI2:


.LM50:


    mov r2, #0


    mvn r3, #3776


.LM51:


    @ lr needed for prologue


.LM52:


    str r2, [r3, #-15]


    ldmfd   sp!, {r2, r3}    <--- This line is correct here.


    subs    pc, lr, #4
Comment 1 James Lamanna 2003-08-27 15:25:05 UTC
Created attachment 4664 [details]
Smaller C file showing the same problems.
Comment 2 James Lamanna 2003-08-27 15:25:48 UTC
Created attachment 4665 [details]
bug.i, from compiling bug.c
Comment 3 James Lamanna 2003-08-27 15:27:26 UTC
Using the above attachment, you can see the problem compiling with:


arm-elf-gcc -S -g -I. -mcpu=arm7dmi -Wall -save-temps bug.c


vs.


arm-elf-gcc -S -g -I. -Os -mcpu=arm7dmi -Wall -save-temps bug.c
Comment 4 Andrew Pinski 2003-08-27 15:36:24 UTC
On the mainline (20030806) I get this:

        str     ip, [sp, #-4]!
        mov     ip, sp
        stmfd   sp!, {r3, fp, ip, lr, pc}
        sub     fp, ip, #4
        sub     sp, sp, #4
        mvn     r3, #65280
        sub     r3, r3, #199
        ldr     r3, [r3, #0]
        str     r3, [fp, #-20]
        ldmea   fp, {r3, fp, sp, lr}
        ldmfd   sp!, {ip}
        subs    pc, lr, #4
But I think the load from fp is okay since fp is set above to fp-4, above that fp = ip, before the 
store to sp (which increments sp), ip = sp. The load is still there in the mainline.
What do you think?
Comment 5 Richard Earnshaw 2003-08-27 15:43:02 UTC
Subject: Re:  arm-elf-gcc-3.2 generates wrong interrupt code 
 w/o optimizations on

All versions of gcc prior to 3.3.1 have known problems with interrupt code.

R.

Comment 6 James Lamanna 2003-08-27 22:16:56 UTC
I would say that this instruction:


ldmea   fp, {r3, fp, sp, lr}


is very bad.




Restoring fp from fp?


who knows what the value of fp would be.




Also, the fact that after that you only have:


ldmfd   sp!, {ip} means that your stack pointer doesn't get restored to what it 
was at function entry.


So after enough interrupts, your stack will be entirely gone.




Oh, I have just cross-compiled gcc-3.3.1, and I have seen the same problem, even 
with the -Os and -O2 optimizations.




If I am misinterpreting this assmbly please let me know, but it just looks bad 
to me.


Comment 7 James Lamanna 2003-08-27 23:00:09 UTC
Here's an analysis of the code you posted:


lets say, on entry, sp = 0x1000




        str     ip, [sp, #-4]!


@ ip -> [0xFFC], sp = 0xFFC


        mov     ip, sp


@ ip = 0xFFC


        stmfd   sp!, {r3, fp, ip, lr, pc}


@ r3 -> [0xFF8]


@ fp -> [0xFF4]


@ ip -> [0xFF0]


@ lr -> [0xFEC]


@ pc -> [0xFE8]


@ sp = 0xFE8


        sub     fp, ip, #4


@ fp = 0xFF8


        sub     sp, sp, #4


@ sp = 0xFE4


        mvn     r3, #65280


        sub     r3, r3, #199


        ldr     r3, [r3, #0]


        str     r3, [fp, #-20]


        ldmea   fp, {r3, fp, sp, lr}


@ r3 <- [0xFFC]


@ fp <- [0x1000] (who knows what fp is at this point)


@ sp <- ????


@ lr <- ???? 


        ldmfd   sp!, {ip}


        subs    pc, lr, #4




So looking that that code, it seems horribly broken.


And besides, there is no ^ operator after the ldm** operations, so the CPSR 
never gets restored.


I don't think I want the rest of program executing in IRQ mode.
Comment 8 James Lamanna 2003-08-28 00:49:13 UTC
I realized I made a couple of mistakes:
@ r3 -> [0xFF8]
@ fp -> [0xFF4]
@ ip -> [0xFF0]
@ lr -> [0xFEC]
@ pc -> [0xFE8]
should be in reverse order:
@ pc -> [0xFF8]
@ lr -> [0xFF4] etc...

And I think the example code has a typo.
Did you mean:
str     r3, [fp, #-20]!
instead of:
str     r3, [fp, #-20]

In that case, offseting fp by -20 makes the ldmea make everything work out ok.
But the ldmea still needs the ^ at the end
Comment 9 Andrew Pinski 2003-08-28 01:24:03 UTC
Thanks for you anlysis, the asm I copied was a direct copy of the outputed asm so this is 
still a problem (I do not read ARM asm that well), thanks.
Comment 10 Richard Earnshaw 2003-09-01 09:27:20 UTC
Your analysis of the 3.3.1 generated code is invalid.  You really should read up
on how the ldm and stm instructions work.  In particular how the instruction
suffixes affect its behaviour.