Hallo zusammen,
schaut euch mal bitte folgenden Code an:
1
if(my16bitpointer>=(constant)){
2
13e: 80 e0 ldi r24, 0x00 ; 0
3
140: ef 37 cpi r30, 0x7F ; 127
4
142: f8 07 cpc r31, r24
5
144: 10 f0 brcs .+4 ; 0x14a <__vector_13+0x3a>
Hier soll der AVR den 16 Bit pointer vergleichen; dabei belegt er aber
R24 mit einer Null obwohl R0 schon diesen Wert enthält. Es wäre viel
geschickter, stat R24 R0 zum verlgeichen zu nehmen. Man spart ohne viel
aufwand 1 Register und ein Befehl.
Kann man das dem GCC irgendwie beibringen? (Bin leider absolut
inkompentent im Compilerbau!)
Grüße
Michael
Da es um einem Pointer geht nehme ich an, dass die Konstante eine
Adresse ist. Deren Wert kennt erst der Linker. Der Compiler kennt ihn
nicht, weiss also nicht, dass das obere Byte davon 0 ist.
Nur indem du den Wert der Adresse dort angibst. Also
if(my16bitpointer>=(sonstwas *)0x7F){
Wär natürlich besser, wenn das auch in der nächsten Version immer noch
0x7F ist, sonst...
Stop, es sollte doch gehen! Der AVR hat per Definiton (Tiny24) nur 8
Bitram Adressen. Also müsste es der Compiler doch auch wissen. Aber das
ist wohl aufwendiger als das Ergebnis.
Diese Manuelle Konstruktion halte ich für ein Spiel mit dem Feuer. Wehe,
das ist dann nachher nicht mehr so...
Gibt es eine Möglichkeit, die 16 Bit Pointer auf 8 Bit Pointer zu
reduzieren? (da der AVR nur 128 Byte Ram hat)
Michael H. schrieb:
> Stop, es sollte doch gehen! Der AVR hat per Definiton (Tiny24) nur 8> Bitram Adressen. Also müsste es der Compiler doch auch wissen. Aber das> ist wohl aufwendiger als das Ergebnis.
Ok, du hast Recht. Nur müsste sich jetzt noch jemand finden, der für die
paar Tinys mit Datenadressraum bis 256 Bytes den Compiler auf den Kopf
stellt.
> Gibt es eine Möglichkeit, die 16 Bit Pointer auf 8 Bit Pointer zu> reduzieren? (da der AVR nur 128 Byte Ram hat)
Aber sicher. Der GCC Quellcode ist bekanntlich offen. Es hindert dich
niemand daran, eine avr-gcc Version zu stricken, die für Pointer nur 8
Bits verwendet. Allerdings wird Datenzugriff auf das ROM dann noch etwas
umständlicher als er ohnehin schon ist, denn auch diese Pointer sind
dann 8 Bit "breit".
Okay, ich glaube das war ein Overkill. Ich kapituliere.
Noch eine Frage, gibt es eine Möglichkeit den Prolog zu überarbeiten?
Z.B. würde ich gerne __do_copy_data oder das rcall durch ein rjmp
ersetzen. Das würde ich mir in Assembler zutrauen.
Der Compiler weiß nicht, auf was ein Pointer zeigt. Es kann genauso gut
wie RAM eine Adresse im Flash sein, und da reichen 8 Bit nicht.
Einen Pointer, der nur auf Ram zeigen kann, gibt es in AVR-GCC nicht.
Hc Zimmerer schrieb:
> Einen Pointer, der nur auf Ram zeigen kann, gibt es in AVR-GCC nicht.
Andersrum. Von Funktionszeigern mal abgesehen gibt es, was den Compiler
angeht, nur solche Pointer. Deshalb kann man ja das Flash auch nur mit
Murks wie pgm_read_byte erreichen.
Was mich stört ist der überzogene Prolog.
Wie kann ich den optimieren?
@Flo: Das problem ist, wenn ich alles in ASM schreibe, verliere ich den
Überblick.
@prx: Ich habe halt meinen Spass am optimieren. Ich empflinde das nicht
als Krampf.
Nein. pgm_read_byte brauchst Du nur beim Dereferenzieren eines
Pointers. Für den Pointer selbst ist es egal, ob er ins Rom zeigt oder
ins Ram. C kennt keine solche Unterscheidung.
Ob ROM oder RAM ist ihm egal, ob Codespace oder Dataspace nicht. Bei
AVRs ist dieser Unterschied allerdings deckungsgleich.
Ein Compiler, der bei einer C-konformen Dereferenzierung jene
Prozessor-Befehle verwendet, die RAM/Dataspace ansprechen, versteht
einen solchen Pointer offenkundig als Pointer auf RAM/Dataspace. Auch
wenn C diese Unterscheidung nicht kennt, der AVR-Compiler als Brücke
zwischen C und Maschine kennt sie.
Dass man einem solchen Pointer auch Adressen im ROM/Codespace oder im
EEPROM zuweisen kann, das ist genau genommen ein absichtlich übersehener
Fehler beim Linken.
A. K. schrieb:
> Auch wenn C diese Unterscheidung nicht kennt, der AVR-Compiler als> Brücke zwischen C und Maschine kennt sie.
Nein, der Compiler kennt sie eben nicht, zumindest im Falle von gcc. Das
ist ja das Problem. Als Krücken zur Unterscheidung dienen
Bibliotheksfunktionen und Tricks im Linkerskript.
> Dass man einem solchen Pointer auch Adressen im ROM/Codespace oder im> EEPROM zuweisen kann, das ist genau genommen ein absichtlich> übersehener Fehler beim Linken.
Dem Linker sind Zeigerwerte eigentlich ziemlich egal.