avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-gcc-list] push r1, pop r0


From: Szikra Istvan
Subject: [avr-gcc-list] push r1, pop r0
Date: Tue, 7 Nov 2017 20:36:09 +0100

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.

What do you think?

Üdvözlettel,
Szikra Istvan

reply via email to

[Prev in Thread] Current Thread [Next in Thread]