Attribute noreturn and frame pointer

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Define the routine as "naked":

void black_hole( void ) __attribute__ ((naked));

void black_hole( void ) {
...
}

This will issue no prologue at all. Just be sure that you know what you're doing, though.

Stu

edit 1: PS: Note that I define the return value as void (no value returned). That way you don't need to worry about doing some bogus "return 0" at the end of the routine to make the compiler happy.

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Note that I define the return value as void (no value returned).
I left that int there accidentally. It used to be the main() of this testcase...

__attribute__((naked)) would probably be otherwise fine, but in a general case I don't want to count myself how many bytes should be reserved from the stack for local arrays and other stuff. That's what I'm trying to convince the compiler to do :wink: . I'm just giving it a hint.