www.mikrocontroller.net

Forum: Compiler & IDEs Optimierung bei Multiplikation


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!


Ich verwende bei eine Treiber für ein T6963 Display eine Multiplikation 
für das linksschieben

Optimiert wird mit -Os auf einemn ATMega128

Ungefähr so

<code>

i = PowerOf2Tab[7-i];
tmpDaten._int = ((uint8_t)Daten * (uint8_t)i);

<code/>

Wobei tmp_Daten._int eine Union von größe int ist, welches dann je als 
Byte in nem Cache Abgelegt wird und dann zum LCD Geschickt.

i ist PowerOf2 für schieben.

der Gcc optiemiert diesen vorgan auch recht ordentlich, nämlich so.

        andi r24,lo8(7)
  ldi r30,lo8(7)
  ldi r31,hi8(7)
  sub r30,r24
  sbc r31,__zero_reg__
  subi r30,lo8(-(PowerOf2Tab))
  sbci r31,hi8(-(PowerOf2Tab))
  ld r24,Z
  mul r18,r24
  movw r18,r0
  clr r1

Jetzt habe ich das Problem, das ich 2 Multiplikationen der gleichen art 
durchführen muss. Nämlich einmal mit den Daten und einmal mit einer Bit 
Maske für die Breite der Daten


Das sieht dann So aus

        i = PowerOf2Tab[7-i];
  tmpDaten._int = ((uint8_t)Daten * (uint8_t)i);
  tmpMask._int = ((uint8_t)Bits * (uint8_t)i);

Normalerweise würde ich davon ausgehen, das der Gcc nur nochma eine 
Multiplikation durchführt, er macht aber das daraus

        andi r24,lo8(7)
  ldi r30,lo8(7)
  ldi r31,hi8(7)
  sub r30,r24
  sbc r31,__zero_reg__
  subi r30,lo8(-(PowerOf2Tab))
  sbci r31,hi8(-(PowerOf2Tab))
  ld r24,Z
  clr r25
  mov r20,r19
  clr r21
  movw r22,r20
  mul r22,r24
  movw r20,r0
  mul r22,r25
  add r21,r0
  mul r23,r24
  add r21,r0
  clr r1
  clr r19
  movw r22,r18
  mul r22,r24
  movw r18,r0
  mul r22,r25
  add r19,r0
  mul r23,r24
  add r19,r0
  clr r1


Hatt von euch vielleicht jemand eine Idee warum er das macht, und wie 
mann ihm das austreiben könnte ???

Vielen Dank im Vorraus


Stefan

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nimmst du nicht den Shiftbefehl << statt einer Multiplikation und 
dem Klimmzug mit PowerOf2Tab[7-i]?

Beispiel:

   int i = 1 << 3;

i hat dann den Wert 8.

Autor: Μαtthias W. (matthias) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

weil die Anzahl der zu shiftenden Stellen erst zur Laufzeit bekannt ist. 
Und das dürfte dann in einer recht ineffizienten ein Bit schiebe 
Schleife resultieren. Mit der Tabellen/Multiplikationsmethode erzwingt 
man eine Multiplikation was auf Controllern mit Hardwaremultiplikator 
und ohne Barrelshifter deutlich effizienter und berechenbarer ist 
(Laufzeit O(1) statt O(n))

Was der GCC da macht ist mir aber auch nicht klar.

Matthias

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenns ganz schnell gehen soll und 1792 oder 2048 Byte Flash übrig sind, 
kann man das auch mit einem Tabellen-Lookup machen...

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Für mich sieht es ja so aus aals wenn er nicht mehr 8 bit sondern 16 bit 
multiplieziert, also den Typcast vergisst. Warum was so ist ist mir aber 
volkommen schleierhaft.


Gruß Stefan

Autor: Peter S. (psavr)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie ist Bits definiert?

Wenn es eine Präprozessor-Konstante ist (z.B. #define Bits 0xF0) dann 
behandelt der AVR-GCC diese defaultmässig als 16-Bit int, selbst wenn Du 
die Konstante explizit als 8-Bit Werd castest...

Ist eigentlich schade, dass der AVR-GCC den Typecast für Konstanten 
ignoriert, hier wird sehr viel an Code-Effizienz verschenkt!!!

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter!

Bits ist die Übergebene Maske der Funktion, also keineKonstante

Was mich nur wunder ist halt, das wenn er eine Multiplikation ausführt 
er es schön knapp hält, und bei genau 2 mal das gleiche so aufbläßt.

wenn ich z.b. Diesen machen würde:

 i = PowerOf2Tab[7-i];
  tmpDaten._int = ((uint8_t)Daten * (uint8_t)i);
  tmpMask._int = (uint8_t)(((uint8_t)Bits * (uint8_t)i));


Also eine Multiplikation als voll 8 bit ausführen bläßte er eine zwar 
nicht ganz so auf, aber vergisst bei der anderen ein byte wie es sein 
sollte
ungefährt so:

        subi r30,lo8(-(PowerOf2Tab))
  sbci r31,hi8(-(PowerOf2Tab))
  ld r20,Z
  ld r24,X+
  ld r25,X
  sbiw r26,1
  mul r20,r18
  movw r18,r0
  clr r1
  com r18
  com r19
  mul r20,r21
  mov r20,r0
  clr r1




Leider kann ich es nicht so machen, das er es knapp und vollständig 
hält.


Jemand vielleicht eine Idee oder Vorschlag???


Gruß Stefan

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!


Da ich trotz aller versuche es nicht geschafft habe, es im reinen C auf 
eine 8*8 bit multiplikation zu beschränken, habe ichnun mit inline 
Assambler gearbeitet. Damit geht mir zwar die Portierbarkeit verlohren, 
aber es funktioniert wie ich will. Hier das Makro:

#define MulByteByte(a,b,c) asm volatile("mul %1,%2"    "\n\t"\
                    "movw %A0,__tmp_reg__"  "\n\t"\
                    "clr __zero_reg__"    "\n\t"\
                    :"=r" (c)    \
                    :"r"(a),"r" (b))



und was er mir daraus macht:

subi r30,lo8(-(PowerOf2Tab))
  sbci r31,hi8(-(PowerOf2Tab))
  ld r20,Z
  ld r24,X+
  ld r25,X
  sbiw r26,1
/* #APP */
  mul r20,r18
  movw r18,__tmp_reg__
  clr __zero_reg__
  
/* #NOAPP */
  and r25,r18
  and r24,r19
/* #APP */
  mul r20,r21
  movw r20,__tmp_reg__
  clr __zero_reg__
  
/* #NOAPP */
  or r25,r20
  or r24,r21
  st X+,r24
  st X,r25



Bis Später, stefan

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.