Simon K. wrote:
> Ich versteh noch nicht so ganz wo du drauf hinaus willst.
>
> Du kannst doch auch
> [...]
> benutzen.
Natürlich kann ich das. Ich weiß, wie ich als Anwender guten Code aus
gcc + Inline asm rausbekomme und kenne die DOs und DONTs.
Momentan sehe ich das Thema aber aus der Sicht des Compilers und da
stellt sich die Frage: Wie kann man sowas effektiv umsetzen?
Aus Sicht des Compilers ist die libc ja auch "nur" ein Anwender, und die
anvisierten Builtins würden so benutzt werden wie die Inline-asm Makros
aus der libc. Für den Anwender würde sich also nichts ändern.
Der Vorteil eines Builtins ist, daß man dem Compiler auf algebraischer
Ebene sagen kann, was im Code geschieht. Ein asm hingegen ist eine
BlackBox die dem Compiler bis auf deren Wirkung auf die Welt
verschlossen ist. Was im asm selbst passiert, kann er nicht wissen und
von daher auch nicht optimieren oder gewinnbringend verwenden.
Aus Sicht einer Optimierung interessant ist die Möglichkeit des
post-increment und die Weiterverwendung von Z. Das wird zwar auch durch
meine obigen Makros erreicht, aber
-- der Code wird dadurch nicht hübscher
-- man muss sich von hand drum kümmern wann man das einsetzt oder nicht
-- gcc weiß immer noch nicht was abgeht
Bei mehreren zu lesenden Daten erfordert das pgm_read_dword die
Einführung einer Union; krumme Anzahlen sind nicht effektiv behandelbar.
Nehmen wir mal an, du willst 4 aufeinander folgende Bytes lesen ohne die
Sachen in ne Union (in ner Union müssen die Sachen zudem genauso stehen
wie im Flash) zu packen:
1 | x = pgm_read_byte (p++);
|
2 | y = pgm_read_byte (p++);
|
3 | k = pgm_read_byte (p++);
|
4 | v = pgm_read_byte (p++);
|
Und freu dich an dem Code, den avr-gcc daraus macht.
Der Königsweg neuer (Target-abhängiger) Qualifier wie "flash" oder
"pgmspace" wird gcc -- wenn das überhaupt jemals unterstützt wird --
nicht in absehbarer Zeit liefern.
Damit gingen dann Sachen wie
1 | char foo (const pgmspace char * p)
|
2 | {
|
3 | return *p; // Kein pgm_read-Zeugs mehr
|
4 | }
|
5 |
|
6 | const pgmspace mytype_t ding =
|
7 | {
|
8 | char c;
|
9 | const pgmspace char * string;
|
10 | };
|
11 |
|
12 | char bar (const pgmspace mytype_t * p)
|
13 | {
|
14 | return p->c + p->string[4];
|
15 | }
|
und gcc könnte die passenden Dereferenzierungen erzeugen. Zurzeit gibt
es nur ein Attribut, keinen Qualifier.