AVR-GCC: Zugriff auf Bytes in uint16, uint32.

Gast #845235
Lesenswert?
• ▲
▼
Hallo,

wenn ich unter avr-gcc (-O2) auf die Bytes in einem uint16_t (oder 
breiter) zugreifen möchte, um diese beispielsweise an eine (8-Bit) IO 
Adresse auszugeben, wird unnötiger Code generiert (siehe Beispiel).

Beispiel C (disassembly) (zugegeben, nicht besonders sinnvoll):
1
  uint16_t cnt=0;
2
  64:  20 e0         ldi  r18, 0x00  ; 0
3
  66:  30 e0         ldi  r19, 0x00  ; 0
4
  for(;;){
5
    PORTB=cnt>>0;//unteres Byte von cnt an PORTB
6
  68:  28 bb         out  0x18, r18  ; 24
7
    PORTB=cnt>>8;//zweites Byte von cnt an PORTB 
8
  6a:  83 2f         mov  r24, r19        ;bedingt notwendig
9
  6c:  99 27         eor  r25, r25        ;unnoetig
10
  6e:  88 bb         out  0x18, r24  ; 24
11
    cnt++;
12
  70:  2f 5f         subi  r18, 0xFF  ; 255
13
  72:  3f 4f         sbci  r19, 0xFF  ; 255
14
  74:  f9 cf         rjmp  .-14       ; 0x68
15
  }

im Anhang das gleiche Beispiel nochmal für uint32.

Wie kann ich dem Compiler beibiegen, bei Zuweisungen von 
(variable>>(n*8))-Konstrukten direkt auf die Register zuzugreifen, in 
denen die Werte liegen? Z.B. könnte an Adresse 0x6e einfacher stehen out 
0x18,r19 und die Befehle an Adressen 0x6a-0x6d wären unnötig. Und so 
weiter. Kann man das sicher mit C-Syntax erschlagen oder muss man da auf 
Assembler zurückgreifen?

Grüße, Sebastian
Angehängte Dateien:
Gast #846694
Lesenswert?
• ▲
▼
>> Wie kann ich dem Compiler beibiegen, bei Zuweisungen von
>> (variable>>(n*8))-Konstrukten direkt auf die Register zuzugreifen, in
>> denen die Werte liegen?

>Der Quellcode vom GCC ist öffentlich - niemand hindert dich.


Nein, aber mal im Ernst:

Gibt es eine Syntax, die das dem Compiler verklickert, dass er die 
Register direkt nimmt?
Ich habe das nämlich auch schon festgestellt.
Gast #846706
Lesenswert?
• ▲
▼
Der vielgescholtene GCC 4.3.0 macht aus dem 16-Bit-Beispiel folgendes:
1
  48:  80 e0         ldi  r24, 0x00  ; 0
2
  4a:  90 e0         ldi  r25, 0x00  ; 0
3
  uint16_t cnt=0;
4
  for(;;) {
5
    PORTB = cnt>>0;
6
  4c:  88 bb         out  0x18, r24  ; 24
7
    PORTB = cnt>>8;
8
  4e:  98 bb         out  0x18, r25  ; 24
9
    cnt++;
10
  50:  01 96         adiw  r24, 0x01  ; 1
11
  52:  fc cf         rjmp  .-8        ; 0x4c <sub+0x4>

Besser geht's nicht, oder?

Beim 32-Bit-Beispiel kommt allerdings das gleiche Code-Ungetüm heraus
wie bei dir.
#846778
Lesenswert?
• ▲
▼
Letzte Woche kam ja raus, dass die Optimierung hinter -fsplit-wide-types 
den Code auch mal aufbläst statt ihn zu reduzieren (ist als Bug in 
Arbeit aber noch ohne Lösung). Dieser Teil von GCC ist mit 4.3 neu 
hinzugekommen, vorher gab's das nicht.

Probiert hier mal -fno-split-wide-types aus: schwupps ist der 16bit Code 
so wie der 32bit Code. Hier also nützt dieser Teil der Optimierung 
etwas, zumindest bei 16bit Typen. Ist aber offenbar noch 
verbesserungsfähig. Beispielsweise funktioniert das auch nicht, wenn der 
16bit Typ ein Vorzeichen hat.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.