public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/43876]  New: [avr] Improper updating of struct members when written out of order from struct definition
@ 2010-04-24  9:02 justin at mattair dot net
  2010-04-27 19:52 ` [Bug target/43876] " justin at mattair dot net
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: justin at mattair dot net @ 2010-04-24  9:02 UTC (permalink / raw)
  To: gcc-bugs

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 4319 bytes --]

avr-gcc may improperly update members of a struct if:

1) The access to the members is in a different order than the struct was
defined and
2) The volatile modifier is used on the struct variable (instance) and
3) The target device is set to atxmega128a1 (possibly all xmega chips) and
4) Optimizations are enabled (I tested -Os)

The following code replicates the problem:

#include <avr/io.h>

typedef struct {
        uint16_t        year;
        uint8_t         month;
        uint8_t         mday;
        uint8_t         hour;
        uint8_t         min;
        uint8_t         sec;
} RTC_time_t;

volatile RTC_time_t t;

void rtc_init (void)
{
        t.sec = 0;
        t.min = 0;
        t.hour = 0;
        t.mday = 1;
        t.month = 1;
        t.year = 2010;
        //t.month = 1;
        //t.mday = 1;
        //t.hour = 0;
        //t.min = 0;
        //t.sec = 0;
}

void main(void)
{
        rtc_init();

        while (1);
}

The makefile used was the WinAVR Makefile Template written by Eric B.
Weddington, Jörg Wunsch, et al. with MCU = atxmega128a1. The problem does not
exist when using, for example, MCU = atmega32u2, or if the volatile modifier is
removed.

The problem can be seen in the disassembly of rtc_init(). The disassembly
without the problem:

      t.year = 2010;
    7a1c:   8a ed          ldi   r24, 0xDA   ; 218
    7a1e:   97 e0          ldi   r25, 0x07   ; 7
    7a20:   80 93 1b 2b    sts   0x2B1B, r24
    7a24:   90 93 1c 2b    sts   0x2B1C, r25
      t.month = 1;
    7a28:   81 e0          ldi   r24, 0x01   ; 1
    7a2a:   80 93 1d 2b    sts   0x2B1D, r24
      t.mday = 1;
    7a2e:   80 93 1e 2b    sts   0x2B1E, r24
      t.hour = 0;
    7a32:   10 92 1f 2b    sts   0x2B1F, r1
      t.min = 0;
    7a36:   10 92 20 2b    sts   0x2B20, r1
      t.sec = 0;
    7a3a:   10 92 21 2b    sts   0x2B21, r1 

which is pretty straightforward.

The disassembly of the nonworking version:

                t.sec = 0;
    7a1c:   10 92 21 2b    sts   0x2B21, r1
      t.min = 0;
    7a20:   e0 e2          ldi   r30, 0x20   ; 32
    7a22:   fb e2          ldi   r31, 0x2B   ; 43
    7a24:   10 82          st   Z, r1
      t.hour = 0;
    7a26:   12 92          st   -Z, r1
      t.mday = 1;
    7a28:   81 e0          ldi   r24, 0x01   ; 1
    7a2a:   82 93          st   -Z, r24
      t.month = 1;
    7a2c:   82 93          st   -Z, r24
      t.year = 2010;
    7a2e:   8a ed          ldi   r24, 0xDA   ; 218
    7a30:   97 e0          ldi   r25, 0x07   ; 7
    7a32:   31 97          sbiw   r30, 0x01   ; 1
    7a34:   81 93          st   Z+, r24
    7a36:   90 83          st   Z, r25
    7a38:   32 97          sbiw   r30, 0x02   ; 2 

As you can see, the high byte of t.year is being updated with the low byte of
2010. Then t.month is overwritten with the high byte of 2010. The compiler
should have subtracted 2 from Z (the first sbiw instruction), but it only
subtracts 1. It does manage to subtract 2 in the last instruction, which seems
rather pointless.

I have tested this using both avr-gcc 4.3.3 (built on Linux using the
"build-avr-gcc-4.3.3-binutils-2.20-libc-1.6.8-insight6.8-dude-5.10-insight-patch"
script available on avrfreaks.net), avr-gcc 4.3.4, as well as WinAVR20100110 on
Windows. The problem exists in all of these cases.


Using built-in specs.
Target: avr
Configured with: ../../source/gcc-4.3.4/configure -v --target=avr --disable-nls
--prefix=/usr/local/avr --with-gnu-ld --with-gnu-as --enable-languages=c,c++
--disable-libssp --with-dwarf2
Thread model: single
gcc version 4.3.4 (GCC)

Command Line: avr-gcc -c -mmcu=atxmega128a1 -I. -gdwarf-2 -DF_CPU=32000000UL 
-Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wundef -Wall -Wstrict-prototypes -Wa,-adhlns=test.lst 
-std=gnu99 -MD -MP -MF .dep/test.o.d test.c -o test.o


-- 
           Summary: [avr] Improper updating of struct members when written
                    out of order from struct definition
           Product: gcc
           Version: 4.3.4
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: justin at mattair dot net
GCC target triplet: avr-*-*


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43876


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2010-09-20 17:14 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-24  9:02 [Bug c/43876] New: [avr] Improper updating of struct members when written out of order from struct definition justin at mattair dot net
2010-04-27 19:52 ` [Bug target/43876] " justin at mattair dot net
2010-04-29  2:38 ` justin at mattair dot net
2010-06-09  2:13 ` eric dot weddington at atmel dot com
2010-09-20 17:14 ` eric dot weddington at atmel dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).