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
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.
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
Wenns ganz schnell gehen soll und 1792 oder 2048 Byte Flash übrig sind, kann man das auch mit einem Tabellen-Lookup machen...
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
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!!!
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:
1 | i = PowerOf2Tab[7-i]; |
2 | tmpDaten._int = ((uint8_t)Daten * (uint8_t)i); |
3 | 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:
1 | subi r30,lo8(-(PowerOf2Tab)) |
2 | sbci r31,hi8(-(PowerOf2Tab)) |
3 | ld r20,Z |
4 | ld r24,X+ |
5 | ld r25,X |
6 | sbiw r26,1 |
7 | mul r20,r18 |
8 | movw r18,r0 |
9 | clr r1 |
10 | com r18 |
11 | com r19 |
12 | mul r20,r21 |
13 | mov r20,r0 |
14 | 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
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:
1 | #define MulByteByte(a,b,c) asm volatile("mul %1,%2" "\n\t"\
|
2 | "movw %A0,__tmp_reg__" "\n\t"\
|
3 | "clr __zero_reg__" "\n\t"\
|
4 | :"=r" (c) \
|
5 | :"r"(a),"r" (b))
|
und was er mir daraus macht:
1 | subi r30,lo8(-(PowerOf2Tab)) |
2 | sbci r31,hi8(-(PowerOf2Tab)) |
3 | ld r20,Z |
4 | ld r24,X+ |
5 | ld r25,X |
6 | sbiw r26,1 |
7 | /* #APP */
|
8 | mul r20,r18 |
9 | movw r18,__tmp_reg__ |
10 | clr __zero_reg__ |
11 | |
12 | /* #NOAPP */
|
13 | and r25,r18 |
14 | and r24,r19 |
15 | /* #APP */
|
16 | mul r20,r21 |
17 | movw r20,__tmp_reg__ |
18 | clr __zero_reg__ |
19 | |
20 | /* #NOAPP */
|
21 | or r25,r20 |
22 | or r24,r21 |
23 | st X+,r24 |
24 | st X,r25 |
Bis Später, stefan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.