I have a very simple Interrupt Service Routine(ISR) written for the atmega328 and compiled with avrgcc (using -Os) using AVR studio.
ISR (TIMER0_OVF_vect) {
txofcnt++; //count overflows and store in uint16_t
}
If you note the assembly generated (below), it uses r24, r25 to get the job incrementing the volatile uint16_t txofcnt, but it also push-write-pop r1, r28, r29 without ever reading them. It also has an extra push/pop of r0 without ever using it in between.
I flat out don't understand why r1 is pushed, cleared and then finally poped. But also why does gcc feel the need to load EIMSK and GPIOR0 into registers and then not use them. Bonus points if you can tell me what GPIOR0 is even for, the datasheet says it exists but has no 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
r28
andr29
in case the ISR code swaps to an interrupt stack? But I'm just guessing. – Michael Burr