Porównanie efektywności AVR (ATMega) i 51: optymalizacja rozkazów i użycie rejestrów w GCC
avr czy 51?? gcc??
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
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
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
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
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_ ;-))
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
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