avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?


From: Don Kinzer
Subject: Re: [avr-gcc-list] When does the Stack Frame Pointer (Y) get setup?
Date: Tue, 3 Jul 2012 15:40:02 -0700

>Is the frame pointer guaranteed to be preserved from the time it is set in 
>.init2 until it is used in main() [...]
The *stack pointer* is initialized in .init2 but the *frame pointer*
is not.  Rather, the frame pointer is set up in the prologue for each
function that needs it (i.e. has local storage or takes the address of
one or more parameters).  The "naked" attribute tells the compiler to
omit the function prologue and epilogue which, apparently, also causes
the frame pointer setup to be omitted as well. It would be useful to
add a caveat to the documentation about using local
variables in naked functions.

One way to work around the problem is to create a separate helper
function to do the work and then call it from the .init8 function.
You'll need to ensure that the helper function is *not* static to
avoid having the compiler inline the code.  You may also have to
adjust the compiler options to prevent the compiler from inlining the
code.  The output below (resulting from code derived from your
example) was obtained using the default call cost and inline size
option settings.

Don Kinzer

--- Example Code ---
void id_filter_init8( void ) __attribute__ ((naked))
__attribute__((section(".init8")));
void id_filter_init8( void )
{
  98:   07 d0           rcall   .+14            ; 0xa8 <bar>
  9a:   03 d0           rcall   .+6             ; 0xa2 <main>
  9c:   2a c0           rjmp    .+84            ; 0xf2 <_exit>
...
void bar(void)
{
  a8:   df 93           push    r29
  aa:   cf 93           push    r28
  ac:   cd b7           in      r28, 0x3d       ; 61
  ae:   de b7           in      r29, 0x3e       ; 62
  b0:   c0 58           subi    r28, 0x80       ; 128
  b2:   d0 40           sbci    r29, 0x00       ; 0
  b4:   0f b6           in      r0, 0x3f        ; 63
  b6:   f8 94           cli
  b8:   de bf           out     0x3e, r29       ; 62
  ba:   0f be           out     0x3f, r0        ; 63
  bc:   cd bf           out     0x3d, r28       ; 61
  be:   fe 01           movw    r30, r28
  c0:   31 96           adiw    r30, 0x01       ; 1
  uint8_t ff_u8[128U];

  /* memset() should really be used here */
  for( uint16_t idx_u16 = 0U; idx_u16 < (uint16_t) sizeof( ff_u8 ); idx_u16++)
  c2:   ce 01           movw    r24, r28
  c4:   8f 57           subi    r24, 0x7F       ; 127
  c6:   9f 4f           sbci    r25, 0xFF       ; 255
  {
    ff_u8[ idx_u16 ] = 0U;
  c8:   11 92           st      Z+, r1
void bar(void)
{
  uint8_t ff_u8[128U];

  /* memset() should really be used here */
  for( uint16_t idx_u16 = 0U; idx_u16 < (uint16_t) sizeof( ff_u8 ); idx_u16++)
  ca:   e8 17           cp      r30, r24
  cc:   f9 07           cpc     r31, r25
  ce:   e1 f7           brne    .-8             ; 0xc8 <bar+0x20>
  {
    ff_u8[ idx_u16 ] = 0U;
  }
  foo(ff_u8[ val ]);  // <-- this is to prevent the code above from
being optimized away
  d0:   80 91 00 01     lds     r24, 0x0100
  d4:   fe 01           movw    r30, r28
  d6:   e8 0f           add     r30, r24
  d8:   f1 1d           adc     r31, r1
  da:   81 81           ldd     r24, Z+1        ; 0x01
  dc:   e1 df           rcall   .-62            ; 0xa0 <foo>
}
  de:   c0 58           subi    r28, 0x80       ; 128
  e0:   df 4f           sbci    r29, 0xFF       ; 255
  e2:   0f b6           in      r0, 0x3f        ; 63
  e4:   f8 94           cli
  e6:   de bf           out     0x3e, r29       ; 62
  e8:   0f be           out     0x3f, r0        ; 63
  ea:   cd bf           out     0x3d, r28       ; 61
  ec:   cf 91           pop     r28
  ee:   df 91           pop     r29
  f0:   08 95           ret



reply via email to

[Prev in Thread] Current Thread [Next in Thread]