SDCC 3.6.0 RC1

#4599781
Lesenswert?

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.
#4603109
Lesenswert?

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
#4804944
Lesenswert?

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
Gast #4805005
Lesenswert?

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
#4805325
Lesenswert?

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
#4817067
Lesenswert?

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
#4817792
Lesenswert?

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
Gast #4917298
Lesenswert?

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
Gast #4917721
Lesenswert?

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.
#4917966
Lesenswert?

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
Gast #4969694
Lesenswert?

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"
Gast #4969699
Lesenswert?

@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
#4970503
Lesenswert?

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
#4970513
Lesenswert?

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
Gast #4970715
Lesenswert?

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
Gast #4974581
Lesenswert?

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/
#4974646
Lesenswert?

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. ;-)
Gast #4974658
Lesenswert?

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 :-)
Gast #4977560
Lesenswert?

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.
Angehängte Dateien:
#4977591
Lesenswert?

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.
#4977757
Lesenswert?

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
Gast #4978138
Lesenswert?

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.
#4978293
Lesenswert?

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
#4978316
Lesenswert?

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

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