Porównanie efektywności AVR (ATMega) i 51: optymalizacja rozkazów i użycie rejestrów w GCC

avr czy 51?? gcc??





Poprzedni Następny
Wiadomość
Spis treści
From: "Mister" <_NOSPAM_wojpie_at_nospam_bielsko.evatronix.com.pl>
Subject: avr czy 51?? gcc??
Date: Fri, 21 Jun 2002 11:52:45 +0200


Witam,

1.Czy istnieje w avr (npATMega) rozkaz typu JB P1.0, cos_tam

coś się mi wydaje ze pod tym względem 51 jest efektywniejsza.
Aby porównać piąty bit PORTE robię tak:

in r24,1
sbrs r24,5
rjmp .L264
.................
czyli trwa to ponad 3 takty, czyli prawie tyle samo co w 51 i niepotrzebnie
modyfikuję rejestr.

2.Nie mogę zrozumiec dlaczego w przerwaniu w którym tylko wstawiam nop
jest tyle niepotrzebnych rzeczy:
push _zero_reg_
push _tmp_reg_
in _tmp_reg_, _SREG_
push _tmp_reg_
clr _zero_reg_
nop
pop _tmp_reg_
out _SREG_, _tmp_reg_
pop _tmp_reg_
pop _zero_reg_
reti
???
Czy to można jakoś optymalizować?
3.I jeszcze jedna sprawa czy można nakazać kompilatorowi gcc aby nigdy nie
używał pewnych rejestrów np. Z?

Pozdrawiam
Mister




Poprzedni Następny
Wiadomość
Spis treści
From: "gajer" <gajeronline_at_nospam_poczta.onet.pl>
Subject: Re: avr czy 51?? gcc??
Date: Fri, 21 Jun 2002 12:48:21 +0200



Użytkownik "Mister" <_NOSPAM_wojpie_at_nospam_bielsko.evatronix.com.pl> napisał w
wiadomości news:aeut0v$oum$1_at_nospam_news.tpi.pl...
Witam,

1.Czy istnieje w avr (npATMega) rozkaz typu JB P1.0, cos_tam

coś się mi wydaje ze pod tym względem 51 jest efektywniejsza.
Aby porównać piąty bit PORTE robię tak:

in r24,1
sbrs r24,5
rjmp .L264
.................
czyli trwa to ponad 3 takty, czyli prawie tyle samo co w 51 i
niepotrzebnie
modyfikuję rejestr.

2.Nie mogę zrozumiec dlaczego w przerwaniu w którym tylko wstawiam nop
jest tyle niepotrzebnych rzeczy:
push _zero_reg_
push _tmp_reg_
in _tmp_reg_, _SREG_
push _tmp_reg_
clr _zero_reg_
nop
pop _tmp_reg_
out _SREG_, _tmp_reg_
pop _tmp_reg_
pop _zero_reg_
reti
???
Czy to można jakoś optymalizować?
3.I jeszcze jedna sprawa czy można nakazać kompilatorowi gcc aby nigdy nie
używał pewnych rejestrów np. Z?

Pozdrawiam
Mister


W pliku makefile mozesz nakazac kompilatorowi zby nie uzywal pewnych
rejestrow oto przyklad:
CPFLAGS
= -g -Os -Wall -Wstrict-prototypes -Wa,-ahlms=$(<:.c=.lst) -ffixed-r18 -ffix
ed-r2

Aby porównać piąty bit PORTE robię tak:

in r24,1
sbrs r24,5
rjmp .L264
a w Medze 161 tak: (sbic - skip if bit is clear)
sbic PINB, 5
rjmp .L264

Pozdrawiam Sławek






Poprzedni Następny
Wiadomość
Spis treści
From: marekmSPAM_at_nospam_amelek.gda.pl (Marek Michalkiewicz)
Subject: Re: avr czy 51?? gcc??
Date: Fri, 21 Jun 2002 13:02:42 +0000 (UTC)


Mister <_NOSPAM_wojpie_at_nospam_bielsko.evatronix.com.pl> wrote:

1.Czy istnieje w avr (npATMega) rozkaz typu JB P1.0, cos_tam

W każdym AVR, ale tylko dla pierwszych 32 rejestrów I/O - dwa rozkazy:

sbic port,bit
rjmp cos_tam

Trwa 2 takty gdy skok nie wykonany, 3 gdy wykonany, rejestr niepotrzebny.
Od niedawna GCC (aktualne źródła z CVS) potrafi sam zrobić z tego użytek
bez wstawek asemblerowych.

2.Nie mog? zrozumiec dlaczego w przerwaniu w kt?rym tylko wstawiam nop
jest tyle niepotrzebnych rzeczy:

Bo na ogół w przerwaniu robi się coś więcej niż tylko NOP :)

Na upartego można by to próbować zoptymalizować, sprawdzając czy
gdziekolwiek w funkcji wykorzystuje się _zero_reg_ (r1) - ale
byłoby z tym trochę zachodu (GCC nic nie wie o tym rejestrze).
Proste funkcje obsługi przerwań zawsze można pisać w asemblerze.

A po co wpisywac zero do _zero_reg_, skoro już tam powinno być?
W przerwaniu nie musi (gdy trafi na właściwy moment), bo _zero_reg_
jest również w paru miejscach rejestrem tymczasowym (nie trzeba go
zachowywać i odtwarzać - wystarczy "clr r1" na końcu). Na przykład
po "mul" (wynik w r1:r0), zanim wynik będzie przepisany gdzie trzeba.
Też się kiedyś dziwiłem :)

3.I jeszcze jedna sprawa czy mo?na nakaza? kompilatorowi gcc aby nigdy nie
u?ywa? pewnych rejestr?w np. Z?

Akurat Z (r31:r30) to może być problem (niektóre instrukcje wymagają
tylko tego rejestru i żadnego innego, więc kompilator zgłosi błąd),
ale jak najbardziej można definiować zmienne globalne w rejestrach,
umieszczając coś takiego we wspólnym pliku *.h:

register int x asm ("r2"); /* zmienna globalna x w rejestrach r3:r2 */

Można w ten sposób przydzielać rejestry "call saved" (r2-r17), najlepiej
zaczynając od dołu (bo sam kompilator przydziela od góry).

Marek


Poprzedni Następny
Wiadomość
Spis treści
From: zielpro_at_nospam_cavern.pl (ziel)
Subject: RE: avr czy 51?? gcc??
Date: 21 Jun 2002 23:51:11 +0200


Akurat Z (r31:r30) to może być problem (niektóre instrukcje wymagają
tylko tego rejestru i żadnego innego, więc kompilator zgłosi błąd),
ale jak najbardziej można definiować zmienne globalne w rejestrach,
umieszczając coś takiego we wspólnym pliku *.h:

register int x asm ("r2"); /* zmienna globalna x w rejestrach r3:r2 */

Można w ten sposób przydzielać rejestry "call saved" (r2-r17), najlepiej
zaczynając od dołu (bo sam kompilator przydziela od góry).

Marek

O! Widzę fachwca. ;-)
To się zapytam.
Czy avrgcc obsługuje wskażniki (poitner)?
pzdr
Artur


--
Archiwum grupy: http://niusy.onet.pl/pl.misc.elektronika


Poprzedni Następny
Wiadomość
Spis treści
From: Ireneusz Niemczyk <i.niemczyk_at_nospam_multispedytor.com.pl>
Subject: Re: avr czy 51?? gcc??
Date: Sat, 22 Jun 2002 01:40:48 +0200


O! Widzę fachwca. ;-)
To się zapytam.
Czy avrgcc obsługuje wskażniki (poitner)?

C bez wskaźników????


--
PZD, Irek.N.
To nie może być _yogurt_ ;-))



Poprzedni Następny
Wiadomość
Spis treści
From: "Mister" <_NOSPAM_wojpie_at_nospam_bielsko.evatronix.com.pl>
Subject: Re: avr czy 51?? gcc??
Date: Mon, 24 Jun 2002 15:52:31 +0200


sbic port,bit
rjmp cos_tam
Dzięki!

Bo na ogół w przerwaniu robi się coś więcej niż tylko NOP :)
Jasne chodziło mi raczej o pokazanie iż pewne rejestry są wkładane na stos
niepoczebnie, gdyż nie są używane. A nop tylko po to aby kompilator
przesadnie nie zopymalizował kodu i nie wyciął obsługi przerwania. Chodzi
mi o bardzo szybką reakcję na przerwanie w postaci zapisania pod wskaznik
pewnej wartości i inkrementacji tego wskaźnika .

Proste funkcje obsługi przerwań zawsze można pisać w asemblerze.
3.I jeszcze jedna sprawa czy mo?na nakaza? kompilatorowi gcc aby nigdy
nie
u?ywa? pewnych rejestr?w np. Z?
Właśnie, chciałbym np. zablokować rejestr Z dla kodu w C i przeznaczyć go
na wskaźnik który byłby modyfikowany we wstawce asemblerowej obsługującej
przerwanie. I pytanie, jak podpiąć się z tym asemblerem pod przerwanie aby
kompilator nie dołączył rozkazów o których była mowa poprzednio?
Oraz pytanie do Marka, od którego należałoby chyba zacząć: gdzie znaleźć
opis avrgcc tj. sposoby konfiguracji, opis zmiennych, typów , przekazywanie
parametrów współpracę z asemblerem itp.

Pozdrawiam
Mister



Poprzedni Następny
Wiadomość
Spis treści
From: marekmSPAM_at_nospam_amelek.gda.pl (Marek Michalkiewicz)
Subject: Re: avr czy 51?? gcc??
Date: Mon, 24 Jun 2002 15:51:28 +0000 (UTC)


Mister <_NOSPAM_wojpie_at_nospam_bielsko.evatronix.com.pl> wrote:
Jasne chodzi?o mi raczej o pokazanie i? pewne rejestry s? wk?adane na stos
niepoczebnie, gdy? nie s? u?ywane. A nop tylko po to aby kompilator
przesadnie nie zopymalizowa? kodu i nie wyci?? obs?ugi przerwania. Chodzi
mi o bardzo szybk? reakcj? na przerwanie w postaci zapisania pod wskaznik
pewnej warto?ci i inkrementacji tego wska?nika .

Jest problem o tyle, że zarówno X jak i Z są rejestrami "call used" czyli
mogą być zmieniane przy wywołaniu funkcji (również tych z bibliotek!).
Natomiast Y jest "call saved", ale za to używany jako wskaźnik zmiennych
lokalnych (jeśli są na stosie, bo zabrakło miejsca w rejestrach).
Czyli wskaźnik jako taki musi niestety być w jakichś innych rejestrach,
powiedzmy r3:r2 (i na czas operacji kopiowany do X lub Z).

W?a?nie, chcia?bym np. zablokowa? rejestr Z dla kodu w C i przeznaczy? go
na wska?nik kt?ry by?by modyfikowany we wstawce asemblerowej obs?uguj?cej
przerwanie. I pytanie, jak podpi?? si? z tym asemblerem pod przerwanie aby
kompilator nie do??czy? rozkaz?w o kt?rych by?a mowa poprzednio?

Kod asemblerowy umieścić w osobnym pliku costam.S wyglądającym np. tak:

#include <io.h>

.global SIG_INTERRUPT0 ; przykładowo
SIG_INTERRUPT0:
push r26
push r27
movw r26,r2 ; wskaźnik jako zmienna globalna w r3:r2
st X+,r4 ; powiedzmy że w r4 jest ta wartość do wpisania
movw r2,r26 ; nowy wskaźnik zwiększony o 1
pop r27
pop r26
reti

Skompilować costam.S do costam.o:

avr-gcc -mmcu=... -x assembler-with-cpp -c costam.S

Po zlinkowaniu całości sprawdzić (avr-objdump -d) czy na pewno jest
skok do obsługi przerwania we właściwym miejscu tablicy wektorów.

Oraz pytanie do Marka, od kt?rego nale?a?oby chyba zacz??: gdzie znale??
opis avrgcc tj. sposoby konfiguracji, opis zmiennych, typ?w , przekazywanie
parametr?w wsp??prac? z asemblerem itp.

Nie ma jednego opisu w którym jest wszystko, ale:
- wstawki asemblerowe są opisane w gcc.info (trzeba to jednak uważnie
przeczytać kilka razy...)
- w avr-libc jest plik register-usage.txt który kiedyś napisałem i jest
wciąż aktualny (jak są przekazywane parametry itp.)
- do wszystkiego są źródła :)

Marek