Hi all,
I have this interesting test case for you guys, and girls.
#include <avr/io.h>
unsigned int GetStackPointer()
{
volatile unsigned int sp = (SPH << 8) | SPL;
return sp;
}
int main(void)
{
while(1)
{
PORTA.OUT = GetStackPointer();
}
}
After building it with Atmel Studio 6.2 (default project settings, -mmcu=atxmega128a4u), AVR8/GNU C Compiler/Linker : 4.8.1 the .lss contains this gem:
unsigned int GetStackPointer()
{
21a: cf 93 push r28
21c: df 93 push r29
21e: 1f 92 push r1
220: 1f 92 push r1
222: cd b7 in r28, 0x3d ; 61
224: de b7 in r29, 0x3e ; 62
volatile unsigned int sp = (SPH << 8) | SPL;
226: 2e b7 in r18, 0x3e ; 62
228: 8d b7 in r24, 0x3d ; 61
22a: 90 e0 ldi r25, 0x00 ; 0
22c: 92 2b or r25, r18
22e: 89 83 std Y+1, r24 ; 0x01
230: 9a 83 std Y+2, r25 ; 0x02
return sp;
232: 89 81 ldd r24, Y+1 ; 0x01
234: 9a 81 ldd r25, Y+2 ; 0x02
}
236: 0f 90 pop r0
238: 0f 90 pop r0
23a: df 91 pop r29
23c: cf 91 pop r28
23e: 08 95 ret
(Atmel Studio 7 (Version: 7.0.1417), gcc version 5.4.0 (AVR_8_bit_GNU_Toolchain_3.6.0_1734) does the same.)
(If anyone interested I can attach the whole compressed project.)
I'm mostly interested in the push r1, pop r0 pairs.
Why? What are they doing? Who puts them there? Can someone "fix" the compiler/binutils?
This seems to be a bug for me.
AFAIK r1 is the zero reg, and r0 is temp reg, so this should not cause problems, so it's not a critical bug, only optimization issue.
(Unnecessary __tmp_reg__ =__zero_reg__ )
I know that a better implementation would be
unsigned int GetStackPointer()
{
unsigned int sp = (SPH << 8) | SPL;
21a: 2e b7 in r18, 0x3e ; 62
21c: 8d b7 in r24, 0x3d ; 61
21e: 90 e0 ldi r25, 0x00 ; 0
return sp;
}
220: 92 2b or r25, r18
222: 08 95 ret
(I'm not really sure why (SPH << 8) | SPL; isn't optimized correctly/fully, but it isn't the point here.)
And my optimal solution is
unsigned int GetStackPointer()
{
union { unsigned int w; unsigned char b[2];} w;
w.b[0] = SPL; w.b[1] = SPH;
21a: 8d b7 in r24, 0x3d ; 61
21c: 9e b7 in r25, 0x3e ; 62
return w.w;
}
21e: 08 95 ret
But the weird volatile issue is not the point here.
I see push r1, pop r0 in other functions, but this was the smallest test case that produced this anomaly.
Üdvözlettel,
Szikra Istvan