I have a very simple interrupt service routine (ISR) written for atmega328 and compiled using avrgcc (using -Os) using the AVR studio.
ISR (TIMER0_OVF_vect) { txofcnt++; //count overflows and store in uint16_t }
If you notice the assembly generated (see below), it uses r24, r25 to get the job increasing volatile uint16_t txofcnt, but also push-write-pop-r-r1, r28, r29 without reading them. It also has an extra push / pop of r0, without using it between them.
I do not understand why r1 is pushed, cleaned, and then unloaded. But also why gcc feels the need to load EIMSK and GPIOR0 into registers and then not use them. Bonus points, if you can tell me what GPIOR0 is suitable for, the data table indicates that it exists, but does not have a description.
00000258 <__vector_16>: ISR (TIMER0_OVF_vect) { 258: 1f 92 push r1 25a: 0f 92 push r0 25c: 00 90 5f 00 lds r0, 0x005F 260: 0f 92 push r0 262: 11 24 eor r1, r1 264: 8f 93 push r24 266: 9f 93 push r25 268: cf 93 push r28 26a: df 93 push r29 26c: cd b7 in r28, 0x3d ; 61 reads register EIMSK 26e: de b7 in r29, 0x3e ; 62 reads register GPIOR0 txofcnt++; 270: 80 91 0a 01 lds r24, 0x010A 274: 90 91 0b 01 lds r25, 0x010B 278: 01 96 adiw r24, 0x01 ; 1 27a: 90 93 0b 01 sts 0x010B, r25 27e: 80 93 0a 01 sts 0x010A, r24 } 282: df 91 pop r29 284: cf 91 pop r28 286: 9f 91 pop r25 288: 8f 91 pop r24 28a: 0f 90 pop r0 28c: 00 92 5f 00 sts 0x005F, r0 290: 0f 90 pop r0 292: 1f 90 pop r1 294: 18 95 reti
source share