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
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:
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
subir30,lo8(-(PowerOf2Tab))
2
sbcir31,hi8(-(PowerOf2Tab))
3
ldr20,Z
4
ldr24,X+
5
ldr25,X
6
sbiwr26,1
7
mulr20,r18
8
movwr18,r0
9
clrr1
10
comr18
11
comr19
12
mulr20,r21
13
movr20,r0
14
clrr1
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: