avr-libc-dev
[Top][All Lists]
Advanced

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

Re: [avr-libc-dev] XMEGA


From: Erik Walthinsen
Subject: Re: [avr-libc-dev] XMEGA
Date: Mon, 07 Jun 2010 16:12:37 -0700
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100423 Thunderbird/3.0.4

On 06/07/2010 03:28 PM, Weddington, Eric wrote:
I would be very interested if someone shows conclusively that there are errors 
with the structure-and-dot-offset register definitions.

So here's my test:

int main () {
  while (1) {
    PORTC.OUT = 0x00;
    PORTC.OUT = 0xff;
  }
}

avr-gcc -O0 -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   5:test.c        ****   while (1) {
   6:test.c        ****     PORTC.OUT = 0x00;
 408                    .LM1:
 409 0008 E0E4                  ldi r30,lo8(1600)
 410 000a F6E0                  ldi r31,hi8(1600)
 411 000c 1482                  std Z+4,__zero_reg__
   7:test.c        ****     PORTC.OUT = 0xff;
 413                    .LM2:
 414 000e E0E4                  ldi r30,lo8(1600)
 415 0010 F6E0                  ldi r31,hi8(1600)
 416 0012 8FEF                  ldi r24,lo8(-1)
 417 0014 8483                  std Z+4,r24
 418 0016 00C0                  rjmp .L2
=====

avr-gcc -Os -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   5:test.c        ****   while (1) {
   6:test.c        ****     PORTC.OUT = 0x00;
 403                    .LM1:
 404 0000 E0E4                  ldi r30,lo8(1600)
 405 0002 F6E0                  ldi r31,hi8(1600)
   7:test.c        ****     PORTC.OUT = 0xff;
 407                    .LM2:
 408 0004 8FEF                  ldi r24,lo8(-1)
 409                    .L2:
   6:test.c        ****     PORTC.OUT = 0x00;
 411                    .LM3:
 412 0006 1482                  std Z+4,__zero_reg__
 414                    .LM4:
 415 0008 8483                  std Z+4,r24
 416 000a 00C0                  rjmp .L2
=====

avr-gcc -O2 -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   5:test.c        ****   while (1) {
   6:test.c        ****     PORTC.OUT = 0x00;
 403                    .LM1:
 404 0000 E0E4                  ldi r30,lo8(1600)
 405 0002 F6E0                  ldi r31,hi8(1600)
   7:test.c        ****     PORTC.OUT = 0xff;
 407                    .LM2:
 408 0004 8FEF                  ldi r24,lo8(-1)
 409                    .L2:
   6:test.c        ****     PORTC.OUT = 0x00;
 411                    .LM3:
 412 0006 1482                  std Z+4,__zero_reg__
 414                    .LM4:
 415 0008 8483                  std Z+4,r24
 416 000a 00C0                  rjmp .L2
=====

avr-gcc -O6 -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   5:test.c        ****   while (1) {
   6:test.c        ****     PORTC.OUT = 0x00;
 403                    .LM1:
 404 0000 E0E4                  ldi r30,lo8(1600)
 405 0002 F6E0                  ldi r31,hi8(1600)
   7:test.c        ****     PORTC.OUT = 0xff;
 407                    .LM2:
 408 0004 8FEF                  ldi r24,lo8(-1)
 409                    .L2:
   6:test.c        ****     PORTC.OUT = 0x00;
 411                    .LM3:
 412 0006 1482                  std Z+4,__zero_reg__
 414                    .LM4:
 415 0008 8483                  std Z+4,r24
 416 000a 00C0                  rjmp .L2
=====

In all cases there are two std's to Z+4. In fact, given the use of Z+4 to address into the register, there's the hope that it can be smart and load (1600) once and allow you to write to several registers in the structure that much faster. However, there appears to be an optimization fault here:

int main () {
  while (1) {
    PORTC.DIR = 0xff;
    PORTC.OUT = 0xff;
  }
}

avr-gcc -Os -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   5:test.c        ****   while (1) {
   6:test.c        ****     PORTC.DIR = 0xff;
 403                    .LM1:
 404 0000 E0E4                  ldi r30,lo8(1600)
 405 0002 F6E0                  ldi r31,hi8(1600)
 406 0004 8FEF                  ldi r24,lo8(-1)
 407                    .L2:
 408 0006 8093 4006             sts 1600,r24
   7:test.c        ****     PORTC.OUT = 0xff;
 410                    .LM2:
 411 000a 8483                  std Z+4,r24
 412 000c 00C0                  rjmp .L2
=====

For some unknown reason, even with -Os, it's insisting on doing a two-word instruction to store into 1600 even though it just loaded Z with the same value. All the optimization levels do this. Line 408 *should* read "st Z,r24"...

However, compare this to the _ version of the same:

avr-gcc -Os -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   4:test.c        ****   while (1) {
   5:test.c        ****     PORTC_DIR = 0xff;
 408                    .LM1:
 409 0008 E0E4                  ldi r30,lo8(1600)
 410 000a F6E0                  ldi r31,hi8(1600)
 411 000c 8FEF                  ldi r24,lo8(-1)
 412 000e 8083                  st Z,r24
   6:test.c        ****     PORTC_OUT = 0xff;
 414                    .LM2:
 415 0010 E4E4                  ldi r30,lo8(1604)
 416 0012 F6E0                  ldi r31,hi8(1604)
 417 0014 8FEF                  ldi r24,lo8(-1)
 418 0016 8083                  st Z,r24
 419 0018 00C0                  rjmp .L2
=====

avr-gcc -Os -g -mmcu=atxmega128a1 test.c -o test -Wa,-almshd=test.lst
=====
   4:test.c        ****   while (1) {
   5:test.c        ****     PORTC_DIR = 0xff;
 403                    .LM1:
 404 0000 8FEF                  ldi r24,lo8(-1)
 405                    .L2:
 406 0002 8093 4006             sts 1600,r24
   6:test.c        ****     PORTC_OUT = 0xff;
 408                    .LM2:
 409 0006 8093 4406             sts 1604,r24
 410 000a 00C0                  rjmp .L2
=====

Either way it's only as good as or inferior, which means that not only is the struct notation turning out fully correct (if not fully optimal), it even comes out potentially faster/smaller.



reply via email to

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