mikrocontroller.net

Forum: Compiler & IDEs GCC, Word statt Byte Zugriffe, Optimierung?


Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erst mal sorry für den komplizierten Betreff, aber mir fiel nix besseres
ein.
Ich erleichtere mir oft das Layout, indem ich die Port-Pins nach
gutdünken verteile und nachher in Software entsprechend darauf
zugreife. Das funktioniert sowohl in C als auch in Assembler bestens
(solange man natürlich nichts zeitkritisches vor hat).
Mir ist nun beim GCC aufgefallen, daß bei der Umsetzung unnötigerweise
einige Byte-Operationen als Word ausgeführt werden. Zum Beispiel:

void set_outputs(uint8_t data)
{
  PORTC = (PORTC & 0xF7) | ((data & 0x01)<<3);
  PORTD = (PORTD & 0x03) | ((data & 0x7E)<<1);
  PORTB = (PORTB & 0xFE) | ((data & 0x80)>>7);
}


Hierbei wird der erste Befehl folgendermaßen umgesetzt:

10:         PORTC = (PORTC & 0xF7) | ((data & 0x01)<<3);
IN      R18,0x15         In from I/O location
ANDI    R18,0xF7         Logical AND with immediate
MOV     R20,R24          Copy register
CLR     R21              Exclusive OR
MOVW    R24,R20          Copy register pair
ANDI    R24,0x01         Logical AND with immediate
ANDI    R25,0x00         Logical AND with immediate
LDI     R22,0x03         Load immediate
LSL     R24              Add without carry
ROL     R25              Add with carry
DEC     R22              Decrement
BRNE    -0x04            Branch if status flag cleared
OR      R18,R24          Logical OR
OUT     0x15,R18         Out to I/O location

Warum werden denn hier die logischen Operationen mit 16 Bit ausgeführt
(R24/R25) wenn ich doch nur 8 Bit brauche? In diesem Code könnte man
ohne weiteres knapp 50% wegoptimieren.
Ich bin noch grün hinter den Ohren, was C betrifft - mache ich etwas
falsch oder ist das einfach so?
Prinzipiell könnte ich schon mit diesem Overhead leben - aber wenns
nicht unbedingt sein muß, verzichte ich auch gerne drauf ;)

Gruß
Thomas

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daß die logischen Operationen mit 16 Bits ausgeführt werden, wird daran
liegen, daß die von Dir verwendeten Konstanten vom Compiler als
16-Bit-Konstanten (genaugenommen: int) behandelt werden.

Du musst durch ein geeignetes Suffix mitteilen, daß die Konstante einen
anderen Datentyp haben soll.

Allerdings hab' ich keines gefunden, das auf 8-Bit-unsigned verweist.

Unsigned generell wird durch Anhängen eines U signalisiert:

  wert = 1234U;

Long (32 Bit) wird durch Anhängen eines L signalisiert

  wert = 1234L;


Alternativ könntest Du mal ausprobieren, was geschieht, wenn Du mit
char-Konstanten arbeitest:

  void set_outputs(uint8_t data)
  {
    PORTC = (PORTC & '\xF7') | ((data & '\x01')<<3);
    PORTD = (PORTD & '\x03') | ((data & '\x7E')<<1);
    PORTB = (PORTB & '\xFE') | ((data & '\x80')>>7);
  }

Autor: Jörg Wunsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Typecast auf uint8_t sollte besser sein.

In der Tat könnte der GCC hier besser optimieren (das darf er, solange
dabei dasselbe rauskommt wie bei der type promotion auf 16 bits), hier
zeigt sich, dass die meiste Arbeit im GCC eben auf 32- und 64-bit
Architekturen gemacht wird, wo man sowas gar nicht erst bemerkt.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
danke für eure Tipps - jetzt weiß ich auch, was ein "typecast" ist
;)

Mit der folgenden Änderung der Zeile:

PORTC = (uint8_t)(PORTC & 0xF7) | (uint8_t)((data & 0x01)<<3);

wird nun dieser Code produziert - das gefällt mir wesentlich besser.

 in  r25, 0x15  ; 21
 andi  r25, 0xF7  ; 247
 andi  r24, 0x01  ; 1
 add  r24, r24
 add  r24, r24
 add  r24, r24
 or  r25, r24
 out  0x15, r25  ; 21

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.