Demnächst wird SDCC 3.6.0 erscheinen. Es gibt nun einen RC1 (siehe auch NEWS unter http://sdcc.sourceforge.net/). Das ist somit die letzte Gelegenheit, noch Bugs in der aktuellen Version zu finden, bevor 3.6.0 erscheint. Besonders schwerwiegende oder einfach zu behebende Bugs könntne dann noch rechtzeitig vor 3.6.0 behoben werden. Philipp P.S.: Von SDCC gibt es üblicherweise ein Release pro Jahr, das dann auch in Distributionen wie Debian eingeht.
Welche neuen Features darf man denn bei 3.6 erwarten? Bei welchen Architekturen hat sich was getan? Irgendwie habe ich das ChangeLog nicht gefunden... Jens
Jens schrieb: > Welche neuen Features darf man denn bei 3.6 erwarten? > Bei welchen Architekturen hat sich was getan? > Irgendwie habe ich das ChangeLog nicht gefunden... > > Jens Das volle Changelog gibe es in den Quellen: https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/ChangeLog Aber das ist halt sehr lang, weil da jeder kleine Bugfix auftaucht. Eine Übersicht der wichtigsten Änderungen seit 3.5.0 findet sich unten auf http://sdcc.sourceforge.net/mediawiki/index.php/SDCC_3.6.0_Release Philipp
Vielen Dank für Eure Arbeit! Philipp Klaus K. schrieb: > Das volle Changelog gibe es in den Quellen: > https://sourceforge.net/p/sdcc/code/HEAD/tree/trunk/sdcc/ChangeLog > Aber das ist halt sehr lang, weil da jeder kleine Bugfix auftaucht. Dafür kann man ganz gut drin suchen. Jens
Ich hab jetzt ein Problem (CC2541->MCS51) beim SDCC 3.6.0 festgestellt, welches beim 3.5.0 nicht vorhanden war. Aus
1 | while(SEMAPHORE_0==0){}; |
entsteht im Listing:
1 | 00003E 1144 00101$: |
2 | 00003E 90 61 8A [24] 1145 mov dptr,#_SEMAPHORE_0 |
3 | 000041 E0 [24] 1146 movx a,@dptr |
4 | 000042 E0 [24] 1147 movx a,@dptr |
5 | 000043 60 F9 [24] 1148 jz 00101$ |
Da bei MOVX kein Flag gesetzt wird, kann das Ganze m.E. nicht richtig funktionieren. Jörg
Hallo Jörg, soweit ich mich erinnere hat MCS51 kein Zero-Flag. Zum JZ-Sprung wird der momentane Inhalt des Accu geprüft. Soweit wäre das schon in Ordnung. Aber warum wird die Speicherzelle zwei mal gelesen? Auch wenn deine Variable 16Bit breit ist, macht das so keinen Sinn. Gruß. Tom
Stimmt, das ist mir in dem Moment nicht eingefallen. Das Problem scheint wohl eine andere Ursache zu haben und hier muss ich erst mal ein Testprogramm schreiben. Denn derzeit werden fast alle Unterfunktionen durch eine Bibliothek bereitgestellt und nur dazugelinkt. Momentan bin ich wieder auf 3.5.0 zurück gewechselt, da habe ich das Problem nicht. Jörg
Joerg W. schrieb: > Das Problem scheint > wohl eine andere Ursache zu haben Weißt Du schon genaueres? Philipp
Ich hatte es inzwischen ein bisschen aus den Augen verloren, aber heute früh kam mir dann die "Erleuchtung". Ich hab dazu ein kleines Testprogramm geschrieben. Und es liegt doch an dem doppelten "movx a,@dptr".
1 | 1189 ; src/main.c:18: while(SEMAPHORE_0 == 0); |
2 | 00005F 1190 00101$: |
3 | 00005F 90 61 8A [24] 1191 mov dptr,#_SEMAPHORE_0 |
4 | 000062 E0 [24] 1192 movx a,@dptr |
5 | 000063 E0 [24] 1193 movx a,@dptr |
6 | 000064 60 F9 [24] 1194 jz 00101$ |
Die Semaphoren gehen nach "0", wenn man sie bei "1" liest, Durch das doppelte Lesen geht aber die "1" vom ersten Lesen verloren und "while(SEMAPHORE_0 == 0);" landet immer in einer Endlosschleife. Der SDCC3.5.0 macht an der Stelle:
1 | 1190 ; src/main.c:18: while(SEMAPHORE_0 == 0); |
2 | 00005F 1191 00101$: |
3 | 00005F 90 61 8A [24] 1192 mov dptr,#_SEMAPHORE_0 |
4 | 000062 E0 [24] 1193 movx a,@dptr |
5 | 000063 FF [12] 1194 mov r7,a |
6 | 000064 60 F9 [24] 1195 jz 00101$ |
Hier wird nur einmal gelesen was ja OK ist. Bei anderen Registern macht das doppelte Lesen nichts aus, bei den Semaphoren aber schon. Jörg
:
Bearbeitet durch User
Wie ist SEMAPHORE_0 deklariert? Hättest Du noch ein kompilierbares Minimalbeispiel, bei dem das Problem sichtbar ist? Philipp
SEMAPHORE_0 ist als __xdata volatile unsigned char deklariert. Anbei das Beispiel, das Makefile muss halt noch an die richtige Toolchain angepasst werden. Die while-Schleife steht bei mir normalerweise am Anfang der Radio-Initialisierung. Jörg
Mit SDCC 3.6.0 konnte ich das Problem reproduzieren. Ich meine mich erinnern, das so etwas ähnliches vor ein paar Monaten schon 'mal irgendwo (eine der SDCC-Mailinglisten?) auftauchte, und behoben wurde. In aktuellen Entwicklerversionen (3.6.4 #9802 und 3.6.4 #9811 die ich eh' gerade da hatte), ist der generierte Code zwar auch nicht unbedingt schön, aber immerhin korrekt. Damit wird das Problem wohl auch in SDCC 3.7.0 nicht wieder auftauchen. Philipp
Hi, sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar jetzt auf int gesetzt? Ich musste da etliche Fehlermeldung bei meinem Z80 Oldie-Dampf-Board ausbügeln, weil ich die beiden Funktionen überschrieben habe, um eine RS232 Ausgabe auf ein Terminal zu erzeugen. Tat das Not? es ist halt ärgerlich wenn bei jeder neuen Version immer wieder neue Komplierfehler auftauchen, die vorher nicht da waren. gruss, Christian
Christian J. schrieb: > sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar > jetzt auf int gesetzt? Vermutlich, weil das mit der C-Standardlibrary dann auch übereinstimmt. Die hat dort deswegen int und nicht char, weil man dann auch Sachen wie EOF oder sonstige Fehler zurückbekommen kann. Mit char ginge das nicht, weil alle Werte von 0-255 ja gültige Datenwerte sind.
Nop schrieb: > Christian J. schrieb: > >> sag mll Philipp, wieso habt ihr die Datentypen bei putchar und getchar >> jetzt auf int gesetzt? > > Vermutlich, weil das mit der C-Standardlibrary dann auch übereinstimmt. > Die hat dort deswegen int und nicht char, weil man dann auch Sachen wie > EOF oder sonstige Fehler zurückbekommen kann. Mit char ginge das nicht, > weil alle Werte von 0-255 ja gültige Datenwerte sind. So ist es. Oder wie ich für die Release Notes geschrieben habe: "Changed putchar() prototype from void putchar(char) to int putchar(int) to improve standard-compliance and allow error reporting." (http://sdcc.sourceforge.net/mediawiki/index.php/SDCC_3.7.0_Release). > es ist halt ärgerlich wenn bei jeder neuen Version immer wieder neue > Komplierfehler auftauchen, die vorher nicht da waren. > gruss, > Christian Die alte Situation, in der die Kompilierfehler bei standardkonformem Code auftraten war aber noch unschöner. Philipp
Philiiiiiiip........ habt ihr schon wieder am sdcc rumgespielt? Naa...... ? Aslink Warning-Undefined Global ::sdcc_heap_init referened by module crt0 Lief vorher, jetzt nicht mehr.... weder mit 1 noch mit 2 _ ich brauche den Heap aber unbedingt. Wenigstens 512 Bytes. Bin wieder im Z80 Fieber diese 2014 zusammen gefrickelte Kiste zum Leben zu bringen.
1 | ;-------------------------------------------------------------------------- |
2 | ; crt0.s - Generic crt0.s for a Z80 |
3 | ;
|
4 | ; Minimum Z80 System mit Mostek 3801 Multi I/O Chip |
5 | ;
|
6 | ; 1. Leeres RAM nullen |
7 | ; 2. Evtl direkt ins Userprogramm rein |
8 | ; 3. Interrupt Tabelle (32 Bytes) nach $4040 kopieren |
9 | ; 4. Mode 2 einschalten Register und MK3801 (IM2) |
10 | ; 5. I Register auf RAM Tabelle legen |
11 | ; 6. Keine Ints zulassen |
12 | ;-------------------------------------------------------------------------- |
13 | |
14 | .module crt0 ; Modul Name für den Linker |
15 | |
16 | ; Memory Map Adressen der Zeropage (vom Benutzer definierbar) |
17 | ; Definitions |
18 | |
19 | offset .equ 0x0000 ; Basisadresse des Codes |
20 | reset_vector .equ offset |
21 | stack .equ 0x0000 ; Stack |
22 | adr_vec_table .equ 0x40 ; Mode 2 Vektor Tabelle für STI Mostek Multi I/O |
23 | adr_nmi .equ 0x66 ; NMI Reset Vektor |
24 | adr_copyright .equ 0x80 |
25 | ram_prog .equ 0x4000 ; Beginn des Userprogrammes im RAM |
26 | heap_size .equ 512 ; Benutzer definierte Heap Groesse |
27 | |
28 | ; Globale Funktionen und Variablen für das C-Programm |
29 | |
30 | .globl _main |
31 | .globl _nmi_vint ; Funktion des NMI Handlers |
32 | .globl __sdcc_heap_init |
33 | .globl _vector_table |
34 | |
35 | ; Interruptroutinen für den Mostek MK3801 Multi I/O Baustein |
36 | ; Manual STI Baustein MK3801 Figure 7 |
37 | .globl _vector_table |
38 | .globl _int_sti_gpi_0 ; General Purpose Interrupt 0 |
39 | .globl _int_sti_gpi_1 ; General Purpose Interrupt 1 |
40 | .globl _int_sti_gpi_2 ; General Purpose Interrupt 2 |
41 | .globl _int_sti_gpi_3 ; General Purpose Interrupt 3 |
42 | .globl _int_sti_timer_d |
43 | .globl _int_sti_timer_c |
44 | .globl _int_sti_gpi_4 ; General Purpose Interrupt 4 |
45 | .globl _int_sti_gpi_5 ; General Purpose Interrupt 5 |
46 | .globl _int_sti_timer_b |
47 | .globl _int_sti_transmit_error |
48 | .globl _int_sti_transmit_buffer_empty |
49 | .globl _int_sti_receive_error |
50 | .globl _int_sti_receive_buffer_full |
51 | .globl _int_sti_timer_a |
52 | .globl _int_sti_gpi_6 ; General Purpose Interrupt 6 |
53 | .globl _int_sti_gpi_7 ; General Purpose Interrupt 7 |
54 | |
55 | .globl l__INITIALIZER |
56 | .globl s__INITIALIZER |
57 | .globl s__INITIALIZED |
58 | |
59 | ; ------------------------------------------------------------- |
60 | |
61 | .area _HEADER (ABS) |
62 | |
63 | ; Reset vector bei Kaltstart und Sprung ins User Programm |
64 | .org reset_vector |
65 | jp init |
66 | |
67 | |
68 | ; Tabelle der RST Vektoren für Software Interrupts auf RAM umlegen |
69 | .org 0x08 |
70 | jp ram_prog+0x0008 |
71 | .org 0x10 |
72 | jp ram_prog+0x0010 |
73 | .org 0x18 |
74 | jp ram_prog+0x0018 |
75 | .org 0x20 |
76 | jp ram_prog+0x0020 |
77 | .org 0x28 |
78 | jp ram_prog+0x0028 |
79 | .org 0x30 |
80 | jp ram_prog+0x0030 |
81 | .org 0x38 |
82 | jp ram_prog+0x0038 |
83 | |
84 | ;/////////////////////////////////////////////////////////// |
85 | ; Tabelle der Mode 2 Int Vektoren auf die Handler Funktionen im C Modul |
86 | ; Reihenfolge beachten !!! Siehe Manual Mostek 3801, Interrupt Tabelle |
87 | |
88 | .org adr_vec_table |
89 | _vector_table: |
90 | .dw (_int_sti_gpi_0) |
91 | .dw (_int_sti_gpi_1) |
92 | .dw (_int_sti_gpi_2) |
93 | .dw (_int_sti_gpi_3) |
94 | .dw (_int_sti_timer_d) |
95 | .dw (_int_sti_timer_c) |
96 | .dw (_int_sti_gpi_4) |
97 | .dw (_int_sti_gpi_5) |
98 | .dw (_int_sti_timer_b) |
99 | .dw (_int_sti_transmit_error) |
100 | .dw (_int_sti_transmit_buffer_empty) |
101 | .dw (_int_sti_receive_error) |
102 | .dw (_int_sti_receive_buffer_full) |
103 | .dw (_int_sti_timer_a) |
104 | .dw (_int_sti_gpi_6) |
105 | .dw (_int_sti_gpi_7) |
106 | |
107 | ;/////////////////////////////////////////////////////////// |
108 | ; NMI Interrupt 0x66, muss mit retn abgeschlossen werden |
109 | .org adr_nmi |
110 | jp _nmi_vint ; Aufruf Handler im C Modul main.c |
111 | retn
|
112 | |
113 | ; ////////////////////////////////////////////////////////// |
114 | .org adr_copyright |
115 | .asciz "(C) 02.2015 by C.Julius" |
116 | |
117 | ;/////////////////////////////////////////////////////////// |
118 | ; Anordung der Segmente fuer den Linker, ab hier nur relative |
119 | ; Adressen |
120 | |
121 | .area _CODE |
122 | .area _INITIALIZER |
123 | .area _HOME |
124 | .area _GSINIT |
125 | .area _GSFINAL |
126 | .area _DATA |
127 | .area _INITIALIZED |
128 | .area _BSEG |
129 | .area _BSS |
130 | .area _HEAP |
131 | |
132 | ; --- Defintion der Heap Groesse |
133 | __sdcc_heap_start:: |
134 | .ds heap_size |
135 | |
136 | .area _HEAP_END |
137 | __sdcc_heap_end:: |
138 | .ds 1 |
139 | |
140 | ;/////////////////////////////////////////////////////////// |
141 | ;; ------- Start des Init Codes ab hier ----------- |
142 | |
143 | .area _CODE |
144 | init: |
145 | |
146 | ld sp,#stack ;; Stack an Spitze des RAM legen |
147 | |
148 | ; Pruefe, ob ein Programm im RAM liegt |
149 | ld a, (ram_prog) ; Lade Start des RAM 0x4000 |
150 | cp #0xC3 ; vergleiche mit "C3" = JP Befehl |
151 | jp Z, init2 ; Ja, dann nicht nullen |
152 | |
153 | ; Sonst Ram ausnullen |
154 | xor a ; clear a and carry |
155 | ld bc,#(0xffff-ram_prog) ; ram size left |
156 | ld hl,#ram_prog ; starting from 4000 |
157 | ld de,#ram_prog+1 |
158 | ld (hl),a ; 0 -> (4000) |
159 | ldir ; (HL) -> (DE) |
160 | |
161 | ; Normaler Programmstart ab hier |
162 | init2: |
163 | ld sp,#stack ; Stack an Spitze des RAM legen |
164 | call gsinit ; Static Variablen |
165 | ; ------------------------------------------- |
166 | jp _main ; Hauptprogramm aufrufen |
167 | ; ------------------------------------------- |
168 | |
169 | ; -----Globale Initialisierungen (Code liegt hinter Code Segment)------------ |
170 | |
171 | .area _GSINIT |
172 | |
173 | gsinit: ; Initialisiere globale Variablen im RAM |
174 | call __sdcc_heap_init ; Initialisiere den HEAP |
175 | |
176 | ld bc, #l__INITIALIZER |
177 | ld a, b |
178 | or a, c |
179 | jr Z, weiter |
180 | ld de, #s__INITIALIZED |
181 | ld hl, #s__INITIALIZER |
182 | ldir
|
183 | |
184 | weiter: |
185 | |
186 | ; // Hier muss ein ret rein |
187 | .area _GSFINAL |
188 | ret
|
189 | ;Markiert das Ende des Programmes |
190 | .ascii "Z80END" |
@Philipp: Hast Du evtl noch eine Version vom sdcc von 2015 ? Wo alles noch so war wie als ich das Projekt angefangen habe? Also Also void putchar (char) und nur 1 Unterstrich bei Heap Global? Ich glaube damit werde ich glücklicher, es funktionierte ja schliesslich auch. Aktuell ärger ich mch nur herum 4 ganze Projekte irgendwie wieder ans Laufen zu bekommen. Habe leider keine in den snapshots mehr gefunden, die sind alle neu. Gruss, Christian
Christian J. schrieb: > @Philipp: > > Hast Du evtl noch eine Version vom sdcc von 2015 ? Wo alles noch so war > wie als ich das Projekt angefangen habe? Also Also void putchar (char) > und nur 1 Unterstrich bei Heap Global? > > Ich glaube damit werde ich glücklicher, es funktionierte ja schliesslich > auch. > Aktuell ärger ich mch nur herum 4 ganze Projekte irgendwie wieder ans > Laufen zu bekommen. Habe leider keine in den snapshots mehr gefunden, > die sind alle neu. > > Gruss, > Christian 3.5.0 ist von 2015. Als Quellen hier: https://sourceforge.net/projects/sdcc/files/sdcc/3.5.0/ Binärdateien für diverse Systeme mit ein paar weiteren Klicks von: https://sourceforge.net/projects/sdcc/files/ Philipp
Christian J. schrieb: > Philiiiiiiip........ > > habt ihr schon wieder am sdcc rumgespielt? Naa...... ? > > Aslink Warning-Undefined Global ::sdcc_heap_init referened by module > crt0 Das war aber schon im Oktober 2015. Aus den Release Notes von 3.6.0: "New memory management with lower overhead". Um die Größe des Heap für z80 auf etwas anderes als 1KB zu ändern: heap.s anpassen und dazulinken. In der crt0 findet sich nun nichts mehr zum Heap. Philipp
Hi, ok. Kann ich also im Startup alles weglassen was den Heap betrifft und er ist dann 1kg gross? Das ginge natürlich auch. Die AREA liegt ja ganz oben, er müsste dann also unter dem Stack zu liegen kommen und über den Variablen (BSS). edit: Klasse, mit dem 2015er alles wieder wie gehabt :-) Gruss, Christian
Hallo, ist das normal, dass so eine Funktion vom Compiler nicht eleminiert wird? Im Asm Code finde ich trotz maximaler Optimierung ständig Aufrufe der "eingepackten" Funktion. Dabei wäre es doch einfach die umgebenden Verpackung komplett weg zu lassen. Die ist nur aus Gründen der Übersichtlichkeit da. static void mcurses_putc (uint8_t ch) { putchar (ch); } 4E42 104 _mcurses_putc: 105 ;mcurses.c:70: putchar (ch); 4E42 21 02 00 [10] 106 ld hl, #2+0 4E45 39 [11] 107 add hl, sp 4E46 7E [ 7] 108 ld a, (hl) 4E47 F5 [11] 109 push af 4E48 33 [ 6] 110 inc sp 4E49 CD 7A 43 [17] 111 call _putchar 4E4C 33 [ 6] 112 inc sp 4E4D C9 [10] 113 ret Hier steht was davon, dass der GCC für Z80 portiert werden soll, wäre natürlich stark wenn die Leistungsfähigkeit des GCC für Z80 da wäre aber vermutlich sind da wieder tausend andere Hürden "compiler spezifischer Erweiterungen". Nur bisher keine Files hinterlegt. https://sourceforge.net/projects/z80gcc/
Christian J. schrieb: > Hier steht was davon, dass der GCC für Z80 portiert werden soll, Die Chance, dass der gcc jemals ein Z80-Backend bekommen wird, schätze ich als äußerst gering ein. Für den LLVM stehen die Chancen ein wenig besser, siehe z.B. https://olduino.wordpress.com/2014/12/30/llvm-for-the-z80-another-source-of-inspiration/ Aber ob diese Backends jemals die Reife vom SDCC erreichen, hängt davon ab, ob die Retro-Welle lange genug anhält. ;-)
S. R. schrieb: > Aber ob diese Backends jemals die Reife vom SDCC erreichen, hängt davon > ab, ob die Retro-Welle lange genug anhält. ;-) Der Verkauf von Plattenspielern und Vinyl Platten ist seit 2015 "explodiert". https://www.conrad.de/de/usb-plattenspieler-dual-dtj-3012-usb-direktantrieb-schwarz-1314095.html?gclid=Cj0KEQjww7zHBRCToPSj_c_WjZIBEiQAj8il5JtIMrpnW_oQozN1Y8228Ni0vMDIIqXhv3mPwODah_EaAjFS8P8HAQ&insert_kz=VQ&hk=SEM&WT.srch=1&WT.mc_id=google_pla&s_kwcid=AL!222!3!190748622382!!!g!!&ef_id=Vzv9rQAABPfxu2cz:20170413165922:s Da ist es doch zu hoffen, dass auch hier eine "Entschleunigung" eintritt, weg vom MIPS und Cortex, hin zum Kaffee kochen beim Compilieren und dem leisen Stampfen der Takte im Zylinder des CPU Cores..... wenn ich mein Ohr an die Z80 lege höre ich es ganz deutlich! ticker...ticker....ticker...klick :-)
Wäre es programmtechnisch möglich, dass der SDCC auch mehrere Cores nutzt, so wie der GCC auch? Und ihr es irgendwie hinkriegt, dass er nicht benutzten Code auch eliminiert? Der Unterschied von --max-allocs-per-node 10000 zu 1 Mio beträgt 500 Bytes auf 12kb Code aber die Laufzeit steigt von 1 Minute auf ca 15 Minuten.
Christian J. schrieb: > Wäre es programmtechnisch möglich, dass der SDCC auch mehrere Cores > nutzt, so wie der GCC auch? Das ist nicht so einfach, wie du dir das vorstellst... und davon abgesehen für die meisten Anwendungsfälle sinnfrei. Mir wäre es neu, dass der gcc mehrere Kerne nutzt. Üblicherweise besteht ein Projekt nämlich aus mehreren Dateien, und "make" ist in der Lage, automatisch mehrere Compilerinstanzen parallel laufen zu lassen. Aber dazu müsste man sich ja in die verwendete Technologie einarbeiten, was du ja gerne und lautstark vermeidest.
Christian J. schrieb: > Wäre es programmtechnisch möglich, [… dass …] ihr es irgendwie > hinkriegt, dass er nicht benutzten Code auch eliminiert? Da sind 3 Fälle zu unterscheiden: 1) Ungenutzer Code in Funktionen, wo sich ohne Kenntnis der anderen Funktionen erkennen lässt, dass der Code ungenutzt ist. Das ist die klassische Dead Code Elimination, die der SDCC beherrscht (aber natürlich ließe sich die noch effektiver machen, z.B. durch bessere Zeigeranalyse oder durch Intervallanalyse). 2) Nicht aufgerufene Funktionen, die static oder inline (aber nicht inline und extern zugleich) sind. Das erfordert zwar deutliche Änderungen im Compiler, ist aber vorgesehen (aber erst für irgendwann nach SDCC 3.7.0). Siehe auch den Thread "Keeping functions (and maybe other things) 'to be emitted later'? Multiple passes?" auf sdcc-devel. 3) Andere nicht aufgerufene Funktionen. Das erfordert Änderungen an Compiler und Linker. Das ist etwas, das wir zwar gern hätten, allerdings gibt es erstmal zuviel wichtigeres zu tun, so dass es wohl länger dauern wird. Es gibt hier allerdings einen Workaround: Wenn alle Funktionen in einer.rel nicht aufgerufen werden, und die .rel zuerst in eine Bibliothek eingebunden wird, und dann die Bibliothek zum Rest des Programms gelinkt wird, funktioniert es schon. Wenn man also die Fuktione sinnvoll gruppert auf C-Dateien aufteilt, lässt sich das Gewünschte erzielen. Di Standardbibliothek ist z.B. so aufgeteilt, und somit werden nur die wirklich benötigten Teile der Standardbibliothek eingebunden. Philipp
Hallo Philipp, danke für Dein Feedback. Wäre so ein Compiler nicht so ein extrem komplexes Werk würde ich da schon lange mitmachen wollen. Ich habe Respekt vor denjenigen, die ihre Freizeit dafür opfern da erstens durchzusteigen und zweitens noch jene im Nacken zu haben, die gern alles anders hätten. Mir ist zb aufgefallen, dass keine Elimination ganz kleiner Funktionen stattfindet, sondern dass wirklich stur jede Funktion mit Call und Registersicherung abgearbeitet wird, auch wenn sie nur 3 Befehle enthält. Ein Multithreading muss ja nicht sein, ich habe es nur zufällig gesehen dass der GCC es kann bzw der Linker beim Kompilieren des sdcc. Wie man eigene Libs erzeugt muss ich mir erst noch anschauen. Habe das noch nie gemacht in 25 Jahren C Programmieren. Der erzeugte Z80 Code ist aber klasse, sieht wirklich alles sehr optimal aus! Man merkt sofort wo man selbst noch Hand anlegen muss bei der Durchsicht der .lst Dateien.
Christian J. schrieb: > Mir ist zb aufgefallen, dass keine Elimination ganz kleiner Funktionen > stattfindet, sondern dass wirklich stur jede Funktion mit Call und > Registersicherung abgearbeitet wird, auch wenn sie nur 3 Befehle > enthält. Zu entscheiden, dass in solchen Fällen die durch inline-Ersetzung wegoptimiert werden, wäre Aufgabe der inlining-Heuristik. Die von GCC würde das machen. Und auch für den SDCC ist es vorgeshen, so etwas (also eine inlining-Heuristik, die inline-Ersetzung beim Aufruf sehr kleiner Funktionen vornimmt) nach 3.7.0 zu implementieren. Auch dafür werden die in "Keeping functions (and maybe other things) 'to be emitted later'? Multiple passes?" besprochenen Änderungen gebraucht. Zur Zeit berücksichtigt die inlining-Heuristik in SDCC die Größe der aufgerufenen Funktionen nicht: inline-Ersetzung von Funktionsaufrufen in SDCC findet genau dann statt, wenn der Funktionsaufruf nicht über Funktionszeiger erfolgt, die Funktion eine feste Anzahl an Argumenten hat, und die Funktion mit dem Schlüsselwort inline definiert ist. Philipp
Christian J. schrieb: > Hallo, > > ist das normal, dass so eine Funktion vom Compiler nicht eleminiert > wird? Im Asm Code finde ich trotz maximaler Optimierung ständig Aufrufe > der "eingepackten" Funktion. Dabei wäre es doch einfach die umgebenden > Verpackung komplett weg zu lassen. Die ist nur aus Gründen der > Übersichtlichkeit da. > > static void mcurses_putc (uint8_t ch) > { > putchar (ch); > } > > 4E42 104 _mcurses_putc: > 105 ;mcurses.c:70: putchar (ch); > 4E42 21 02 00 [10] 106 ld hl, #2+0 > 4E45 39 [11] 107 add hl, sp > 4E46 7E [ 7] 108 ld a, (hl) > 4E47 F5 [11] 109 push af > 4E48 33 [ 6] 110 inc sp > 4E49 CD 7A 43 [17] 111 call _putchar > 4E4C 33 [ 6] 112 inc sp > 4E4D C9 [10] 113 ret Irgendwann nach 3.7.0 soll das automatisch optimiert werden. Zur Zeit klappt es nur, wenn da (statt oder zusätzlich zu "static") auch "inline" steht. Philipp
Christian J. schrieb: > Hi, > > ok. Kann ich also im Startup alles weglassen was den Heap betrifft und > er ist dann 1kg gross? Das sollte gehen; der Heap wäre dann 1 KB groß. Philipp
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.