[avr-gcc] Call-saved registers in main()

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

I have a quick question. Can main() freely use r2–r17 and r28–r29 and not worry about saving them or having a called function clobber them?

 

It appears that avr-gcc 4.8.1 believes that:

 

avr-gcc-4.8.1 -g -Wall -mmcu=attiny24 -nostartfiles -nodefaultlibs -Os \
-DAVR -DOSCCAL_VAL=`awk '/^001 /{print $2}' osccal.txt` -x c -S ../main.c
main:                                ..........  ..........  ..........  ..
        ldi r24,lo8(127)             ..........  ..........  ..........  ..
        out 0x1b,r24                 ..........  ..........  ....4.....  ..
        ldi r24,lo8(-33)             ..........  ..........  ..........  ..
        mov r12,r24                  ..........  ..........  ....4.....  ..
        ldi r25,lo8(-33)             ..........  ..2.......  ..........  ..
        mov r11,r25                  ..........  ..2.......  .....5....  ..
        ldi r18,lo8(16)              ..........  .12.......  ..........  ..
        mov r10,r18                  ..........  .12.....8.  ..........  ..
        ldi r19,lo8(7)               ..........  012.......  ..........  ..
        mov r9,r19                   ..........  012......9  ..........  ..
        clr r8                       .........9  012.......  ..........  ..
        dec r8                       ........89  012.......  ..........  ..
        ldi r16,0                    ........89  012.......  ..........  ..
        ldi r17,0                    ........89  012...6...  ..........  ..
        ldi r20,lo8(24)              ........89  012...67..  ..........  ..
        mov r7,r20                   ........89  012...67..  0.........  ..
        ldi r21,lo8(13)              .......789  012...67..  ..........  ..
        mov r6,r21                   .......789  012...67..  .1........  ..
        ldi r22,lo8(-97)             ......6789  012...67..  ..........  ..
        mov r14,r22                  ......6789  012...67..  ..2.......  ..
        ldi r22,lo8(110)             ......6789  012.4.67..  ..........  ..
        mov r15,r22                  ......6789  012.4.67..  ..2.......  ..
.L2:                                 ......6789  012.4567..  ..........  ..
        clr __zero_reg__             ......6789  012.4567..  ..........  ..
        out __SP_L__,r11             .1....6789  012.4567..  ..........  ..
        out 0x1a,r10                 .1....6789  012.4567..  ..........  ..
        out 0x17,r9                  .1....6789  012.4567..  ..........  ..
        out 0x36,r8                  .1....6789  012.4567..  ..........  ..
        rcall test_flash             .1....6789  012.4567..  ..........  ..
        sbi 0x19,4                   .1....6789  012.4567..  ..........  ..
        ldi r24,lo8(1)               .1....6789  012.4567..  ..........  ..
        rcall initialize_hardware    .1....6789  012.4567..  ....4.....  ..
        rcall wait_for_serial_idle   .1....6789  012.4567..  ..........  ..
        mov r13,__zero_reg__         .1....6789  012.4567..  ..........  ..
.L3:                                 ......6789  01234567..  ..........  ..
        movw r24,r16                 ......6789  01234567..  ..........  ..
.L4:                                 ......6789  01234567..  ....45....  ..
        movw r28,r24                 ......6789  01234567..  ....45....  ..
        subi r28,-23                 ......6789  01234567..  ........89  ..
        sbci r29,111                 ......6789  01234567..  ........89  ..
        rcall receive_serial_nibble  ......6789  01234567..  ........89  ..
        clr __zero_reg__             ......6789  01234567..  ........89  ..
        out __SP_L__,r12             ......6789  01234567..  ........89  ..
        ldi r24,0                    ......6789  01234567..  ........89  ..
        rcall initialize_hardware    ......6789  01234567..  ....4...89  ..
        rcall receive_serial_nibble  ......6789  01234567..  ........89  ..
        sbrs r24,5                   ......6789  01234567..  ....4...89  ..
        rjmp .L5                     ......6789  01234567..  ....4...89  ..
        sbrs r24,4                   ......6789  01234567..  ....4.....  ..
        rjmp .L3                     ......6789  01234567..  ..........  ..
        rjmp .L2                     ......6789  012.4567..  ..........  ..
.L5:                                 ......6789  01234567..  ....4...89  ..
        cpi r28,-71                  ......6789  01234567..  ....4...89  ..
        sbci r29,72                  ......6789  01234567..  ....4....9  ..
        brne .L8                     ......6789  01234567..  ....4.....  ..
        wdr                          ......6789  01234567..  ....4.....  ..
        out 0x21,r7                  ......6789  01234567..  ....4.....  ..
        out 0x21,r6                  ......6789  01234567..  ....4.....  ..
        cbi 0x1b,4                   ......6789  01234567..  ....4.....  ..
        com r13                      ......6789  01234567..  ....4.....  ..
        out 0x36,r13                 ......6789  01234567..  ....4.....  ..
.L8:                                 ......6789  012.4567..  ....4.....  ..
        movw r28,r14                 ......6789  012.4567..  ....4.....  ..
        andi r24,lo8(15)             ......6789  012.4567..  ....4...89  ..
        mov r13,r24                  ......6789  012.4567..  ....4...89  ..
        rcall receive_serial_nibble  ......6789  01234567..  ........89  ..
        rcall test_flash             ......6789  01234567..  ........89  ..
        rcall receive_serial_nibble  ......6789  01234567..  ........89  ..
        sbrs r24,4                   ......6789  01234567..  ....4...89  ..
        rjmp .L9                     ......6789  01234567..  ....4...89  ..
        sbrs r24,5                   ......6789  01234567..  ....4.....  ..
        rjmp .L3                     ......6789  01234567..  ..........  ..
        rjmp .L2                     ......6789  012.4567..  ..........  ..
.L9:                                 ......6789  01234567..  ....4...89  ..
        swap r24                     ......6789  01234567..  ....4...89  ..
        andi r24,lo8(-16)            ......6789  01234567..  ....4...89  ..
        or r13,r24                   ......6789  01234567..  ....4...89  ..
        movw r24,r28                 ......6789  01234567..  ........89  ..
        subi r24,-3                  ......6789  01234567..  ....45....  ..
        sbci r25,-75                 ......6789  01234567..  ....45....  ..
        rjmp .L4                     ......6789  01234567..  ....45....  ..

I just wanted to make sure. Thanks for your help!

- John

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

jfiresto wrote:
Can main() freely use r2–r17 and r28–r29 and not worry about saving them or having a called function clobber them?
The code you've shown never returns so it is free to use any registers it wants without regard to the call-saved convention.  If you modify it so that it does return you may see a different result.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

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

Thanks, that helped clear things up. All the pushes and pops appeared in magnificent abundance after I made main() return and removed the __attribute__((naked)) I have been sticking before main() for the past dozen years or so, hidden in a macro I had forgotten about.

 

main:                                .......789  01234567..  ........89  ..
        push r7                      .......789  01234567..  ........89  ..
        push r8                      ........89  01234567..  ........89  ..
        push r9                      .........9  01234567..  ........89  ..
        push r10                     ..........  01234567..  ........89  ..
        push r11                     ..........  .1234567..  ........89  ..
        push r12                     ..........  ..234567..  ........89  ..
        push r13                     ..........  ...34567..  ........89  ..
        push r14                     ..........  ....4567..  ........89  ..
        push r15                     ..........  .....567..  ........89  ..
        push r16                     ..........  ......67..  ........89  ..
        push r17                     ..........  .......7..  ........89  ..
        push r28                     ..........  ..........  ........89  ..
        push r29                     ..........  ..........  .........9  ..
        ldi r24,lo8(127)             ..........  ..........  ..........  ..
        out 0x1b,r24                 ..........  ..........  ....4.....  ..
        ldi r24,lo8(-33)             ..........  ..........  ..........  ..
        mov r13,r24                  ..........  ..........  ....4.....  ..
        ldi r25,lo8(16)              ..........  ...3......  ..........  ..
        mov r11,r25                  ..........  ...3......  .....5....  ..
        ldi r18,lo8(7)               ..........  .1.3......  ..........  ..
        mov r10,r18                  ..........  .1.3....8.  ..........  ..
        clr r9                       ..........  01.3......  ..........  ..
        dec r9                       .........9  01.3......  ..........  ..
        ldi r16,0                    .........9  01.3......  ..........  ..
        ldi r17,0                    .........9  01.3..6...  ..........  ..
        ldi r19,lo8(-97)             .........9  01.3..67..  ..........  ..
        mov r14,r19                  .........9  01.3..67.9  ..........  ..
        ldi r19,lo8(110)             .........9  01.34.67..  ..........  ..
        mov r15,r19                  .........9  01.34.67.9  ..........  ..
        ldi r20,lo8(24)              .........9  01.34567..  ..........  ..
        mov r8,r20                   .........9  01.34567..  0.........  ..
        ldi r21,lo8(13)              ........89  01.34567..  ..........  ..
        mov r7,r21                   ........89  01.34567..  .1........  ..
.L2:                                 .......789  01.34567..  ..........  ..
        clr __zero_reg__             .......789  01.34567..  ..........  ..
        out __SP_L__,r13             .1.....789  01.34567..  ..........  ..
        out 0x1a,r11                 .1.....789  01.34567..  ..........  ..
        out 0x17,r10                 .1.....789  01.34567..  ..........  ..
        out 0x36,r9                  .1.....789  01.34567..  ..........  ..
        rcall test_flash             .1.....789  01.34567..  ..........  ..
        sbi 0x19,4                   .1.....789  01.34567..  ..........  ..
        ldi r24,lo8(1)               .1.....789  01.34567..  ..........  ..
        rcall initialize_hardware    .1.....789  01.34567..  ....4.....  ..
        rcall wait_for_serial_idle   .1.....789  01.34567..  ..........  ..
        mov r12,__zero_reg__         .1.....789  01.34567..  ..........  ..
.L3:                                 .......789  01234567..  ..........  ..
        movw r28,r16                 .......789  01234567..  ..........  ..
        subi r28,-23                 .......789  01234567..  ........89  ..
        sbci r29,111                 .......789  01234567..  ........89  ..
        rcall receive_serial_nibble  .......789  01234567..  ........89  ..
        clr __zero_reg__             .......789  01234567..  ........89  ..
        out __SP_L__,r13             .......789  01234567..  ........89  ..
        ldi r24,0                    .......789  01234567..  ........89  ..
        rcall initialize_hardware    .......789  01234567..  ....4...89  ..
        rcall receive_serial_nibble  .......789  01234567..  ........89  ..
        sbrs r24,5                   .......789  01234567..  ....4...89  ..
        rjmp .L4                     .......789  01234567..  ....4...89  ..
        sbrs r24,4                   .......789  01234567..  ....4.....  ..
        rjmp .L3                     .......789  01234567..  ..........  ..
        rjmp .L2                     .......789  01.34567..  ..........  ..
.L4:                                 .......789  01234567..  ....4...89  ..
        cpi r28,-71                  .......789  01234567..  ....4...89  ..
        sbci r29,72                  .......789  01234567..  ....4....9  ..
        brne .L7                     .......789  01234567..  ....4.....  ..
        wdr                          .......789  01234567..  ....4.....  ..
        out 0x21,r8                  .......789  01234567..  ....4.....  ..
        out 0x21,r7                  .......789  01234567..  ....4.....  ..
        cbi 0x1b,4                   .......789  01234567..  ....4.....  ..
        com r12                      .......789  01234567..  ....4.....  ..
        out 0x36,r12                 .......789  01234567..  ....4.....  ..
.L7:                                 .......789  01.34567..  ....4.....  ..
        movw r28,r14                 .......789  01.34567..  ....4.....  ..
        andi r24,lo8(15)             .......789  01.34567..  ....4...89  ..
        mov r12,r24                  .......789  01.34567..  ....4...89  ..
        rcall receive_serial_nibble  .......789  01234567..  ........89  ..
        rcall test_flash             .......789  01234567..  ........89  ..
        rcall receive_serial_nibble  .......789  01234567..  ........89  ..
        sbrs r24,4                   .......789  01234567..  ....4...89  ..
        rjmp .L8                     .......789  01234567..  ....4...89  ..
        sbrs r24,5                   .......789  01234567..  ....4.....  ..
        rjmp .L3                     .......789  01234567..  ..........  ..
        rjmp .L2                     .......789  01.34567..  ..........  ..
.L8:                                 ..........  ..........  ........89  ..
        subi r28,-3                  ..........  ..........  ........89  ..
        sbci r29,-75                 ..........  ..........  .........9  ..
        pop r29                      ..........  ..........  ..........  ..
        pop r28                      ..........  ..........  ..........  ..
        pop r17                      ..........  ..........  ..........  ..
        pop r16                      ..........  ..........  ..........  ..
        pop r15                      ..........  ..........  ..........  ..
        pop r14                      ..........  ..........  ..........  ..
        pop r13                      ..........  ..........  ..........  ..
        pop r12                      ..........  ..........  ..........  ..
        pop r11                      ..........  ..........  ..........  ..
        pop r10                      ..........  ..........  ..........  ..
        pop r9                       ..........  ..........  ..........  ..
        pop r8                       ..........  ..........  ..........  ..
        pop r7                       ..........  ..........  ..........  ..
        ret                          ..........  ..........  ..........  ..

- John

Last Edited: Sat. Aug 22, 2015 - 04:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But why would you want to return from main? And why use "naked" when you can use "noreturn"?

Regards,
Steve A.

The Board helps those that help themselves.

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

Koshchi wrote:

But why would you want to return from main?

I don't, and apparently haven't for at least a dozen years. smiley I was just playing with the compiler to debug my mental model.

 

Quote:
And why use "naked" when you can use "noreturn"?

It is old code that I wrote before there was "noreturn".

- John

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

Koshchi wrote:
But why would you want to return from main? And why use "naked" when you can use "noreturn"?
+1

 

The AVR target also supports attribute OS_main:

https://gcc.gnu.org/onlinedocs/gcc/AVR-Function-Attributes.html

OS_main

OS_task

On AVR, functions with the

OS_main

or

OS_task

attribute do not save/restore any call-saved register in their prologue/epilogue.

The OS_main attribute can be used when there is guarantee that interrupts are disabled at the time when the function is entered. This saves resources when the stack pointer has to be changed to set up a frame for local variables.

The OS_task attribute can be used when there is no guarantee that interrupts are disabled at that time when the function is entered like for, e.g. task functions in a multi-threading operating system. In that case, changing the stack pointer register is guarded by save/clear/restore of the global interrupt enable flag.

The differences to the naked function attribute are:

  • nakedfunctions do not have a return instruction whereas OS_main and OS_task functions have a RET or RETI return instruction.
  • nakedfunctions do not set up a frame for local variables or a frame pointer whereas OS_main and OS_task do this as needed.

Strictly, this may be better than 'noreturn':

noreturn

A few standard library functions, such as

abort

and

exit

, cannot return. GCC knows this automatically. Some programs define their own functions that never return. You can declare them

noreturn

to tell the compiler this fact. For example,

          void fatal () __attribute__ ((noreturn));
          
          void
          fatal (/* ... */)
          {
            /* ... */ /* Print error message. */ /* ... */
            exit (1);
          }

The noreturn keyword tells the compiler to assume that fatal cannot return. It can then optimize without regard to what would happen if fatal ever did return. This makes slightly better code. More importantly, it helps avoid spurious warnings of uninitialized variables.

The noreturn keyword does not affect the exceptional path when that applies: a noreturn-marked function may still return to the caller by throwing an exception or calling longjmp.

Do not assume that registers saved by the calling function are restored before calling the noreturn function.

It does not make sense for a noreturn function to have a return type other than void.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]