Hi folks!
In case I would find the function
int __attribute__((noreturn)) func(void) { char str[16]; asm volatile("nop" :: "e" (str) : "r17","r16","r15","r14","r13","r12","r11","r10","r9","r8","r7","r6"); for(;;); }
useful, should the calling functions frame pointer (r28,r29) be pushed to stack in this functions prologue?
When using the attached files, GCC 4.2.2, and no call prologues I get:
00000092: int __attribute__((noreturn)) func(void) { 92: df 93 push r29 94: cf 93 push r28 96: cd b7 in r28, 0x3d ; 61 98: de b7 in r29, 0x3e ; 62 9a: 60 97 sbiw r28, 0x10 ; 16 9c: 0f b6 in r0, 0x3f ; 63 9e: f8 94 cli a0: de bf out 0x3e, r29 ; 62 a2: 0f be out 0x3f, r0 ; 63 a4: cd bf out 0x3d, r28 ; 61 char str[16]; asm volatile("nop" :: "e" (str) : "r17","r16","r15","r14","r13","r12","r11","r10","r9","r8","r7","r6"); a6: fe 01 movw r30, r28 a8: 31 96 adiw r30, 0x01 ; 1 aa: 00 00 nop ac: ff cf rjmp .-2 ; 0xac
Can func() rely in some situation on the fact that r28 and r29 are pushed to the stack?
The reason I'm asking this is in the assembly listing generated with call prologues enabled:
00000092: int __attribute__((noreturn)) func(void) { 92: a0 e1 ldi r26, 0x10 ; 16 94: b0 e0 ldi r27, 0x00 ; 0 96: ef e4 ldi r30, 0x4F ; 79 98: f0 e0 ldi r31, 0x00 ; 0 9a: 0c 94 61 00 jmp 0xc2 ; 0xc2 <__prologue_saves__+0x8> char str[16]; asm volatile("nop" :: "e" (str) : "r17","r16","r15","r14","r13","r12","r11","r10","r9","r8","r7","r6"); 9e: fe 01 movw r30, r28 a0: 31 96 adiw r30, 0x01 ; 1 a2: 00 00 nop a4: ff cf rjmp .-2 ; 0xa4 . . . 000000ba <__prologue_saves__>: ba: 2f 92 push r2 bc: 3f 92 push r3 be: 4f 92 push r4 c0: 5f 92 push r5 c2: 6f 92 push r6 c4: 7f 92 push r7 c6: 8f 92 push r8 c8: 9f 92 push r9 ca: af 92 push r10 cc: bf 92 push r11 ce: cf 92 push r12 d0: df 92 push r13 d2: ef 92 push r14 d4: ff 92 push r15 d6: 0f 93 push r16 d8: 1f 93 push r17 da: cf 93 push r28 dc: df 93 push r29 de: cd b7 in r28, 0x3d ; 61 e0: de b7 in r29, 0x3e ; 62 e2: ca 1b sub r28, r26 e4: db 0b sbc r29, r27 e6: 0f b6 in r0, 0x3f ; 63 e8: f8 94 cli ea: de bf out 0x3e, r29 ; 62 ec: 0f be out 0x3f, r0 ; 63 ee: cd bf out 0x3d, r28 ; 61 f0: 09 94 ijmp
All those clobbered call saved registers are being pushed despite the fact that we will never return. Out of intrest I decided to take a peek inside the compiler source and make a quick fix for it, but I don't know if I really should push the frame pointer into stack or not...
This problem seems to be present in GCC trunk as well even though the compiler code has been rewritten. As far as I can see, using __attribute__((OS_task)) would do the trick for new code, but any existing code would need updating... Can I safely make the assumtion that OS_task equals noreturn in functionality?