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

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

Re: [avr-gcc-list] Posible bug in avr-gcc-4.0.2 (inline asm)


From: David Brown
Subject: Re: [avr-gcc-list] Posible bug in avr-gcc-4.0.2 (inline asm)
Date: Thu, 6 Oct 2005 09:17:54 +0200

----- Original Message -----
From: "Anatoly Sokolov" <address@hidden>


> Hello.
>
> Studying avr-libc bug #14486 I have written the following test case.
>
> #define SFR (*(unsigned char *)(0x80))
>
> #define foo()                                   \
> ({                                              \
>     __asm__ __volatile__                        \
>     (                                           \
>         "sts %0, 0x00\n\t"                      \
>         : "=m" (SFR)                              \
>     );                                          \
> })
>

I haven't done much AVR assembly for a while, but there is no such
instruction format as "sts 0x80, 0x00" - you cannot store a value directly
in this way.  Add to that the fact that SFR cannot properly be coerced into
"m" format (it is a dereferenced pointer - "m" should be the pointer
itself), and you have given the compiler's peephole optomiser a challenge!

If you were instead using "sts %0, r0", then I think it is probably
perfectly reasonable for the compiler to re-arrange things to use the Z
pointer.  The compiler (and the assembler, IIRC) treat all stores the the
same way, and are happy with just "ST" rather than needing "STS" and "STD".
You told the "asm" command that your parameter was a memory address, which
could mean either an immediate address or a pointer (using "i" would mean
immediate).  This gives the compiler the freedom to put the address into a
pointer register and use that.

Of course, this leaves the question of *why* it choose to do so.  For
unoptomised code, it makes some sense - putting the address in a pointer is
the simple, natural, unoptomised way of handling "m" parameters.  For
optomised code, however, this looks like it might be bad peephole
optomisation (unless the address is used again later).  Loading Z first and
then doing two "ST Z, r0" takes the same number of instructions as "STS mem,
r0", but executes slower.

mvh.,

David



> int main (void)
> {
>     foo ();
>     foo ();
> }
>
> The avr-gcc version 4.0.2 with optimisation  (-O3 or -Os ) generates a
> following code:
> ...
> .LM2:
>  ldi r30,lo8(128)
>  ldi r31,hi8(128)
> /* #APP */
>  sts Z, 0x00
>
> .LM3:
>  sts Z, 0x00
>
> /* #NOAPP */
> ....
> It is not true, pointer register cannot be the first operand of sts
> instruction, only constant.
> If to leave only one foo in main:
>
> int main (void)
> {
>     foo ();
>     //foo ();
> }
> The correct code is generated;
> ...
> .LM2:
> /* #APP */
>  sts 128, 0x00
>
> /* #NOAPP */
> ...
>
> If to compile without optimization, again a mistake:
>
> int main (void)
> {
>     foo ();
>     //foo ();
> }
> ...
> .LM2:
>  ldi r30,lo8(128)
>  ldi r31,hi8(128)
> /* #APP */
>  sts Z, 0x00
>
> /* #NOAPP */
> ...
>
> The avr-gcc version 3.4.4 with and without optimisation generates a
correct
> code:
> ...
> .LBB2:
> .LM2:
> /* #APP */
>  sts 128, 0x00
>
> /* #NOAPP */
> .LBE2:
> .LBB3:
> .LM3:
> /* #APP */
>
>  sts 128, 0x00
>
> /* #NOAPP */
> ...
>
> It is a bug in the avr-gcc or it is erroneous to use "m" parameter with
the
> sts instruction?
>
> Anatoly.
>
>






reply via email to

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