Forum: Compiler & IDEs AVR-GCC: Zugriff auf Bytes in uint16, uint32.


von Sebastian (Gast)


Angehängte Dateien:

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

von Andreas K. (a-k)


Lesenswert?

Sebastian wrote:

> 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.

von Matthias L. (Gast)


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.

von yalu (Gast)


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.

von Andreas K. (a-k)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.