I'm looking at the avr-gcc assembly generated code for small C programs. The following is supposed to allocate a 100 byte local array on the stack.
extern void foo(char [], int);
void bar()
{
char t[100];
foo(t,100);
}
and of course it does, by subtracting 100 from the stack pointer.
I understand that, as the avr is a 8 bit machine, changing the 16bit stack pointer takes 2 steps (changing SPH and SPL). Also, it is a good idea to provide some atomicity by disabling interrupts. It is done by the sequence
in r28,__SP_L__
in r29,__SP_H__ ; get SP
subi r28,100 ; new SP in R29:R28 = OLD -100
sbc r29,__zero_reg__
in __tmp_reg__,__SREG__ ; save status to r0
cli ; disable interrupts
out __SP_H__,r29 ; update SPH
out __SREG__,__tmp_reg__ ; restore status -- why here ?
out __SP_L__,r28 ; update SPL
what I'm not convinced yet is the position of the restore status instruction.
Why is it not done after updating SPL ?
Maybe there is a guarantee that after (re)enabling interrupts, no interrupt will be taken into accounts before the next instruction has completed?