Für ne Berechnung auf nem ATtiny26 benötige ich ne große Dynamik, aber float paßt ja nicht rein. Da dachte ich, nimmste einfach long long (64Bit), dürfte ja nur doppelt soviel Code sein, wie long (32Bit). Aber Pustekuchen, das ist total verschwenderisch programmiert (noch viel teurer als float). Ne Division kostet etwa 5kB !!! Also Finger weg von long long, wenns unter nem ATmega16 ist ! Nun wollte ich mir ne Divisionsfunktion in Assembler schreiben (35 Words = 70Byte), also 2 Parameter übergeben (r25..r18, r17..10 -> r25..18). Aber wieder Pustekuchen, die Parameter werden gepusht, dann mein Assembler ausgeführt und dann die Parameter gepopt, also meine Berechnung weggeschmissen, schöne Scheiße. Obendrein wird noch gemeckert, daß kein Returnwert da ist. Ich bin mit meinem Latein am Ende :-( Hat überhaupt schonmal jemand erfolgreich Assembler mit Parameter und Returnwert in ne Funktion integrieren können ? Peter
Hallo, Peter, bei einem anderen Prozessor (Toshiba TLCS-900-Umgebung) habe ich es so gemacht: ich habe einen Funktionsrumpf in C geschrieben (gleiche Parameter und Rückgabe wie bei meiner späteren Assembler-Funktion, minimale Funktionalität in der Funktion), habe mir dann den Assembler-Code angeschaut, den der Compiler daraus macht (quasi abkopiert), und dann meine Funktionalität in die Assembler-Funktion eingebaut. Bei den AVR's habe ich keine Erfahrung mit Assembler, aber es könnte hier ja genauso gehen? Günter
Peter Dannegger wrote: > Ne Division kostet etwa 5kB !!! Das ist mehr oder weniger ein known issue. Da werden nur die generischen (in C geschriebenen) Funktionen der libgcc.a benutzt, für 64 bit gibt's keine handoptimierten Varianten. Du kannst ja gern mithelfen, in Assembler kennst du dich aus, warum schlägst du nicht mal einen Patch für die libgcc.a vor? Einziger Wermutstropfen: damit er von GNU akzeptiert wird, musst du deren Lizenzabkommen unterschreiben (Abtretung der Rechte aus dem Copyright an die FSF), ohne das akzeptieren sie keine Patches für den GCC, die mehr als `trivial patches' sind. (Bitte keine weitere Baustelle wie bei floating point schaffen, bei der die avr-libc die Funktionen aus der libgcc.a ersetzt. Das ist Sch***e und führt dazu, dass entsprechende Bugreports bei GCC nicht ernst genommen werden, auch dann, wenn sie eigentlich echte Bugs sind.) > Aber wieder Pustekuchen, die Parameter werden gepusht, dann mein > Assembler ausgeführt und dann die Parameter gepopt, also meine > Berechnung weggeschmissen, schöne Scheiße. > Obendrein wird noch gemeckert, daß kein Returnwert da ist. Dann hast du wohl irgendwas flasch deklariert, die Warnung passt ja wohl gut zum Verhalten des Compilers, den Rückkehrwert dann auch zu ignorieren. > Hat überhaupt schonmal jemand erfolgreich Assembler mit Parameter > und Returnwert in ne Funktion integrieren können ? Na klar, macht die avr-libc haufenweise: % find ~/src/avr-libc/lib* -name \*.c | wc -l 61 % find ~/src/avr-libc/lib* -name \*.S | wc -l 126 Doppelt so viele Assemblerquellen wie in C geschriebene. Ich mag jetzt nicht zählen, wie viele davon Werte zurückgeben, ist mir zu müßig.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Daraus wird generiert:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
Zugegebenermaßen ist das Umspeichern von x über r2...r9 nach r18...r25 alles andere als optimal, aber das Ergebnis wird ordentlich nach z abgespeichert. Bitte nicht mehr als 2 uint64_t übergeben: da gibt's einen offenen GCC-Bug dafür, für den noch keiner eine richtige Lösung parat hat. Der Fehler scheint im generischen GCC-Teil zu liegen, tritt aber nur bei nicht-mainstream-CPUs wie dem AVR zu Tage, da die anderen ihre eigenen Parameterübergaberoutinen haben. Das führt leider dazu, dass bei GCC daraus eine recht geringe Priorität resultiert. :-(
Gast
#423064
Mit dem Qualifier naked kann man ja beim GCC für ARM und AVR den Prolog und Epilog von Funktionen unterdrücken. http://www.delorie.com/gnu/docs/gcc/gcc_55.html Hilft dir das vielleicht bei deinem Push/Pop Problem weiter?
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.