16Bit x 16Bit = 32Bit schnelle Multiplikation für 8Bit AVR in C

OP #881013
Lesenswert?

Hier ein C-Code für die Multiplikation von 16Bit Zahlen und als Ergebnis 
erhält man eine 32Bit Zahl:
uint32_t mul16(uint16_t, uint16_t) ersetzt folgenden Ausdruck:
32Bit = 16Bit * 16Bit
Mit Optimierung -0s dauert die Multiplikation 37 Taktzyklen (inklusive 
pop und push der Register). Der Quellcode enthält Inline-Assembler 
Anteile, was die Multiplikatin beschleunigt.
Damit ist es mögliche alle Arten von Zahlen (Ganzzahl und 
Fließkommahzahlen bis 255) zu rechnen die 16Bit brauchen.
Um Fließkommazahlen zu multiplieren müssen diese natürlich erst ins 
Binäre umgerechnet werden. Dies wird so durchgeführt:
Den Ganzzahlligen Dezimalwert in die oberen 8Bit hineinschreiben und den 
Dezimalen Kommawert mit 2^8 multiplizieren und diesen Wert in die 
unteren 8Bit hinein schreiben. Anschließend steht im 32Bit Ergebnis in 
den oberen 16Bit die Ganzzahl und in den unteren 16Bit die Kommazahl. 
Der Kommawert ist aber nicht Dezimal. Dieser wird Dezimal dadurch 
dargestellt, dass der Kommawert mit 1/(2^16) multipliziert wird.
Als Beispiel: Die Zahl 1,1 gibt in Hex: 0x0119 = 1 im oberen Byte und 25 
im niederen Byte.
Dadurch hat man zwar eine Auflösung von nur 0,0039 in Dezimal, aber für 
viele Regelungstechnische Aufgaben oder Filter reicht es aus. Da hier 
die Geschwindigkeit im vordergrund steht.
Verbesserungen und Optimierungen sind erwünscht.
Gruß Alex.
Angehängte Dateien:
Persönliche Seite #882209
Lesenswert?

Oder gleich in avr-gcc einbauen :-)
1
(define_insn "umulhisi3"
2
  [(set (match_operand:SI 0 "register_operand" "=&r")
3
        (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "r"))
4
                 (zero_extend:SI (match_operand:HI 2 "register_operand" "r"))))]
5
  "AVR_HAVE_MUL && !(optimize_size)"
6
  "mul %B1,%B2
7
   movw %C0,r0
8
   mul %A1,%A2
9
   movw %A0,r0
10
   mul %B1,%A2
11
   add %B0,r0
12
   adc %C0,r1
13
   clr __zero_reg__
14
   adc %D0,__zero_reg__
15
   mul %A1,%B2
16
   add %B0,r0
17
   adc %C0,r1
18
   clr __zero_reg__
19
   adc %D0,__zero_reg__"
20
  [(set_attr "length" "14")
21
   (set_attr "cc" "clobber")])

Wobei bei solch langen Pattern irgendwann die Schmerzgrenze erreicht 
ist...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren