If you have a series of modifications to make to a particular peripheral, like:#include <avr/io.h>
void individ_regs() {
USART0_CTRLA = 0x12;
USART0_CTRLB = 0x34;
USART0_CTRLC = 0x56;
USART0_CTRLD = 0x78;
USART0_BAUDL = 0x9A;
USART0_BAUDH = 0;
}
int main()
{
individ_regs();
VPORTA_OUT |= 8;
USART0.CTRLA = 0x12;
USART0.CTRLB = 0x34;
USART0.CTRLC = 0x56;
USART0.CTRLD = 0x78;
USART0.BAUDL = 0x9A;
USART0.BAUDH = 0;
}
the second form will end up producing a bit less code, because the compiler is able to load the peripheral base address once and use a sequence of (2 byte) "STD Z+x, rNN" instructions instead of having to implement each store separately with a (4-byte) "STS addr, rNN" instruction:void individ_regs() {
USART0_CTRLA = 0x12;
b8: 82 e1 ldi r24, 0x12
ba: 80 93 05 08 sts 0x0805, r24
USART0_CTRLB = 0x34;
be: 84 e3 ldi r24, 0x34
c0: 80 93 06 08 sts 0x0806, r24
USART0_CTRLC = 0x56;
c4: 86 e5 ldi r24, 0x56
c6: 80 93 07 08 sts 0x0807, r24
USART0_CTRLD = 0x78;
ca: 88 e7 ldi r24, 0x78
cc: 80 93 0a 08 sts 0x080A, r24
USART0_BAUDL = 0x9A;
d0: 8a e9 ldi r24, 0x9A
d2: 80 93 08 08 sts 0x0808, r24
USART0_BAUDH = 0;
d6: 10 92 09 08 sts 0x0809, r1
da: 08 95 ret
int main()
{
individ_regs();
dc: 0e 94 5c 00 call 0xb8 ; 0xb8 <individ_regs>
VPORTA_OUT |= 8;
e0: 0b 9a sbi 0x01, 3 ; 1
USART0.CTRLA = 0x12;
e2: e0 e0 ldi r30, 0x00
e4: f8 e0 ldi r31, 0x08
e6: 82 e1 ldi r24, 0x12
e8: 85 83 std Z+5, r24
USART0.CTRLB = 0x34;
ea: 84 e3 ldi r24, 0x34
ec: 86 83 std Z+6, r24
USART0.CTRLC = 0x56;
ee: 86 e5 ldi r24, 0x56
f0: 87 83 std Z+7, r24
USART0.CTRLD = 0x78;
f2: 88 e7 ldi r24, 0x78
f4: 82 87 std Z+10, r24
USART0.BAUDL = 0x9A;
f6: 8a e9 ldi r24, 0x9A
f8: 80 87 std Z+8, r24
USART0.BAUDH = 0;
fa: 11 86 std Z+9, r1 ; 0x09
}
fc: 80 e0 ldi r24, 0x00
fe: 90 e0 ldi r25, 0x00
100: 08 95 ret