Forum: Compiler & IDEs Registerattribut


von Peter (Gast)


Lesenswert?

Hallo,

gibt es irgendeine Möglichkeit, eine Variable fest an ein Register zu 
binden, so dass der avr-gcc sich da strikt dran hält?
Mit der Zuweisung
1
register uint8_t test asm("r5")
schaffe ich es zwar, dass der compiler die Variable da rein lädt, aber 
er lagert sie trotzdem wohl mal ins Sram aus. Das Problem an der Sache 
ist, dass ich einen modifizierten Atmel habe, bei dem Register breiter 
sind, als das SRAM, was bedeutet, dass Daten verlorengehen, wenn sie 
ausm Register geschoben werden.
Printf besipielsweise schluckt ja sehr viele Register...

Falls es noch keine Möglichkeit gibt, meint ihr es ist möglich, dem 
COmpiler ein neues Attribut beizubringen, welches dann eben wirklich 
bindend ist?
Danke schonmal =)

Gruß Peter

von Bernhard R. (barnyhh)


Lesenswert?

Es reicht nicht aus, die Hardware zu modifizieren. Schreibe bitte den 
GCC entsprechend um, daß er Deine Hardware unterstützt. Dann gibt es 
nicht nur eine Portierung für den AVR, sondern auch eine Portierung für 
Deine HW.

Bernhard

von Peter (Gast)


Lesenswert?

Ja, das wäre natürlich ideal.
Gibt es da Dokumentationen zu?
Also es wurden schon Modifikationen an Opcodes vorgenommen, also neue 
integriert in den assembler, die die HW unterstützt. Das einzige was 
eben noch fehlt ist das mit den Registern.
Ich durchsuche die ganze Zeit schon alle Sources des Gcc nach den 
entsprechenden Stellen, aber bis jetz noch erfolglos.
Also ich finde weder die Definition der Registerbreite in den Quellen, 
noch die Definition von Attributen, wie eben die vom Typ "Register".
Wie schon erwähnt wäre es perfekt, ein neues Attribut zu definieren, das 
eine Variable einem Register zuweist und zwar bindend!

Irgendein Tipp, oder ein Verweis auf entsprechende Dokus wäre super und 
würde mir unglaublich helfen, da ich schon sehr lange an dem Problem 
hänge.

Viele Grüße, und danke für die bisherige Antwort!

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> er lagert sie trotzdem wohl mal ins Sram aus. Das Problem an der Sache
> ist, dass ich einen modifizierten Atmel habe, bei dem Register breiter
> sind, als das SRAM, was bedeutet, dass Daten verlorengehen, wenn sie
> ausm Register geschoben werden.

Was muss man sich darunter vorstellen?

Eventuell gibt es ja eine Lösung, bei der man nicht den Compiler 
modifizieren muss. Aber ich kann mir mit deiner Beschreibung der 
Modifikation nichts darunter vorstellen.

von Peter (Gast)


Lesenswert?

Die Regs sind breiter gemacht worden, um für bestimmte anwendungen 
schneller zu sein.

Also beispielsweise haben die jetz 32 bit Breite.
Dann wird in der SW eine Variable reingeladen, meinetwegen noch ne 
zweite und die addiere ich jetz zb.
Dann schieb ich die in ein Array aus 8bit Elementen, um das ganze dann 
schöne ausgeben zu können.
Wenn ich jetz allerdings andere Befehle zwischen Berechnung und Asugabe 
schreibe, speziell printf, passiert folgendes:
Weil printf wohl viele Regs braucht, wird das 32 Bit ergebnis aus dem 
Reg ins SRAM gerettet. Und sobald printf durch is, wieder in mein Reg 
geschoben.
Aaaaber, das SRAM is ja nur 8 bit breit, das heisst es konnte auch nur 
die unteren 8bit retten.
Wenn ich dann mein ergebnis ausgebe, das sich im Reg befindet, hab ich 
die unteren 8bit korrekt. Aber die üblichen sind nun 0, weil sich die 
niemand gemerkt hat...

Eigentlich soll das Register attribut ja dafür sorgen, dass des gewählte 
Register dem Compiler gar nich mehr zugänglich gemacht wird, aber leider 
macht er in der Realität ja doch was er will.

von Peter (Gast)


Lesenswert?

wenn er nur 8bit von dem Register gerettet und wieder zurück geschrieben 
werden müsste doch alles stimmen? Die restelichen 24Bit bleiben doch wo 
sie sind oder etwas nicht?

von Grrr (Gast)


Lesenswert?

Es wäre extrem hilfreich wenn Du uns die Art und die Methode der 
"Modifikation" andeuten könntest.


Biiiittttttttttteeeeeeeeeeeeeee!

von Grrr (Gast)


Lesenswert?

Na toll. Von Hamburg VHDL nen AVR geladen, dran rumgebastelt und nun 
steckt er in der Sch...

von Klaus F. (kfalser)


Lesenswert?

Peter schrieb:
> Dann wird in der SW eine Variable reingeladen, meinetwegen noch ne
> zweite und die addiere ich jetz zb.

Woher kommen denn die Werte beim reinladen? Diese müssen doch auch 
irgendwie aus dem SRAM kommen, oder? Die Lade-Operation muss dann doch 
auch 32 Bit sein?

Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um 
Register zu retten, heißen push und pop.
Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch 
push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Wäre es nicht besser gewesen, einen ARM-Core zu benutzen, wenn du
breitere Register haben willst (oder irgendeinen anderen 32-bit-Core)?

Der AVR-Port des GCC ist nun ohnehin nicht wirklich optimal, wenn
du ihn jetzt noch mit sowas vermurksen willst, kommst du doch vom
hundertsten ins tausendste...

von nop (Gast)


Lesenswert?

Warum nicht gleich ein 32 Bit Prozessor... ???

Nur den GCC zu ändern reicht sowieso nicht, die ganzen Libs müssen 
wahrscheinlich auch noch geändert werden.

Das führt zu nix...außer einem riesen Batzen Entwicklungsarbeit.
Und wenn printf das einzige Problem ist... warum verzichtet man nicht 
einfach darauf ?

Aber wenn es nur um 32-Bit additionen oder ähnlichen Kleinkram geht, und 
das ganze auf einem FPGA stattfindet, gibt es da auch ganz andere 
Lösungswege.

von Peter (Gast)


Lesenswert?

Kernfrage:
Neues Attribut definieren? Doku? Welche Stelle genau? Beispieldef vom 
typ "Register"?
Wollte doch gar keine riesen Diskussion auslösen =)
Danke für alle hinweise, aber mir geht es um die punkte oben.

von Grrr (Gast)


Lesenswert?

Peter schrieb:
> Kernfrage:

Grrr schrieb:
> Art und die Methode der
> "Modifikation"

von Bernhard R. (barnyhh)


Lesenswert?

Dokumentation zum GCC: läßt sich finden.

In einem Teil des GCC wird die verwendete Hardware auf der Ebene RTL 
beschrieben. Das ist Dein Ansatzpunkt. Ich gehe davon aus, daß dieser 
Teil gut dokumentiert ist: Jeder, der neue HW in den GCC einfügt, hat 
sich dort auszukennen.

Bernhard

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Die Regs sind breiter gemacht worden, um für bestimmte anwendungen
> schneller zu sein.

Ich hab dich immer noch nicht.
Wie kann man Register breiter machen?

> Na toll. Von Hamburg VHDL nen AVR geladen, dran rumgebastelt
> und nun steckt er in der Sch...

Stimmt diese Vermutung?
Wenn ja, dann hast du im Grunde ja keinen AVR mehr vor dir liegen, 
sondern einen anderen Prozessor. Da drafst du dich nicht wundern, wenn 
der gcc damit nicht klar kommt.

> Eigentlich soll das Register attribut ja dafür sorgen, dass des gewählte
> Register dem Compiler gar nich mehr zugänglich gemacht wird, aber leider
> macht er in der Realität ja doch was er will.

Und das ist in der überwiegenden Mehrzahl der Fälle auch gut so.
Mit 'register' ist in der Vergangenheit ziemlich viel Humbug betrieben 
worden. Compiler sind dazu übergegangen ihrer eigenen Datenflussanalyse 
mehr zu vertrauen als dem was der Programmierer sich ausdenkt.

von Mark B. (markbrandis)


Lesenswert?

Karl heinz Buchegger schrieb:
> Wie kann man Register breiter machen?

Indem man die Wortbreite (und die Busbreite) vergrößert. Am besten 
funktioniert dies durch Multiplikation mit einer Potenz von zwei :-)

von Peter (Gast)


Lesenswert?

Ja, die Modi ist in vhdl realisiert.
Ich weiss, es ist prinzipiell ein anderer Prozessor, aber wiederum auch 
nicht, weil bis auf die Breite nix verändert wurde.
Und prinzipiell macht der Compiler ja auch brav das was er soll.
Wäre es dann prinzipiell eine Möglichkeit einen alten avr-gcc zu 
verwenden?

Hat denn schonmal jemand von euch am Compiler selbst rumgeschraubt? Also 
sowas in der Richtung von eigenen Attributen hinzufügen?

Wäre natürlich am schönsten, wenn das so irgendwie ginge, damit die 
Entwicklungszeit in einem vertretbaren Rahmen bliebe...

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Ja, die Modi ist in vhdl realisiert.

Na endlich!
Das man da aber immer erst alles 5 mal nachfragen und aus der Nase 
ziehen muss.

> Ich weiss, es ist prinzipiell ein anderer Prozessor, aber wiederum auch
> nicht, weil bis auf die Breite nix verändert wurde.

Doch ist es.
WinAvr geht von gewissen Eigenschaften des Prozessors aus, wenn du ihm 
einen AVR unterjubelst. Da dein Proz diese Eigenschaften nicht hat, ist 
es ein anderer Proz.

> Wäre natürlich am schönsten, wenn das so irgendwie ginge, damit die
> Entwicklungszeit in einem vertretbaren Rahmen bliebe...

Der war gut!
Den 'vertretbaren Rahmen' hast du in dem Moment verlassen, indem du 
beschlossen hast, deine eigene CPU zu kreieren.

von Karl H. (kbuchegg)


Lesenswert?

Klaus Falser schrieb:

> Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um
> Register zu retten, heißen push und pop.
> Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch
> push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.

Und beten, dass der gcc nicht auf die Idee kommt, Arithmetik mit dem 
Stackpointer zu betreiben. Das geht dann mit Sicherheit das eine oder 
andere mal ins Auge.
Die ganze indirekte Adressierung von lokalen Variablen, die am Stack 
angelegt wurden, wird dann nicht mehr stimmen, etc.

von Peter (Gast)


Lesenswert?

Sorry, da ich nicht zuviele details preisgeben darf(!) wollte ich mich 
nunmal auf den Knackpunkt beschränken.
Ich hab das alles ja gar nich beschlossen! Ich darf nur Entscheidungen 
anderer ausbaden (wie wir alle eigentlich immer) ;-) Ich hab eben die 
genannte Problemstellung und muss nun eine Lösung dafür finden! Bin also 
nur der Depp vom Dienst auf den ihr nich nur draufhauen sollt ;-)

Bin immer noch für jeden Vorschlag offen, da immer noch genauso rat- und 
hilflos...

Viele Grüße

von Klaus F. (kfalser)


Lesenswert?

Karl heinz Buchegger schrieb:
> Klaus Falser schrieb:
>
>> Die Operationen, die printf oder ein anderes Unterprogramm aufrufen um
>> Register zu retten, heißen push und pop.
>> Wenn die Lade-Operationen 32 Bit breit sind, dann kannst Du doch auch
>> push und pop verändern, sodass push und pop mit 32 Bit werten arbeiten.
>
> Und beten, dass der gcc nicht auf die Idee kommt, Arithmetik mit dem
> Stackpointer zu betreiben. Das geht dann mit Sicherheit das eine oder
> andere mal ins Auge.
> Die ganze indirekte Adressierung von lokalen Variablen, die am Stack
> angelegt wurden, wird dann nicht mehr stimmen, etc.

Naja, so ganz ernst war meine Antwort nicht gemeint, und in der 
Zwischenzeit haben Ihm ja alle freudlichst klar gemacht, worauf er sich 
einläßt :-)

von Grrr (Gast)


Lesenswert?

Peter schrieb:
> Ja, die Modi ist in vhdl realisiert.

Na endlich!

>Bin immer noch für jeden Vorschlag offen, da immer noch genauso rat- und
hilflos...

Also, da fällt mir ein Märchen ein. Gestern gesehen.
Ein armes Bauernmädchen wird aufgefordert einem Stein die Haut 
abzuziehen.
Sie willigt ein, wenn der Prinz erstmal dem Stein das Blut rauslässt, 
weil sie eben kein Blut sehen kann.

Ebenso hier: Derjenige der die Entscheidung getroffen hat, den AVR so zu 
verändern das die Register breiter werden, soll noch die Entscheidung 
treffen, den GCC so umzuarbeiten, das er mit dem neuen Prozessor 
arbeitet.
An sich müssten die Entscheidungen sowieso im selben Zuge getroffen 
werden, wenn sowas gemacht wird.

von Grrr (Gast)


Lesenswert?

Rechne ein paar Mann-Monate, wenn Du gcc gut kennst.
Vielleicht ein paar Wochen um mal irgendwas übersetzen zu können.

Ich gehe mal davon aus, das der Prozessor auch mal eben so larifari 
"erweitert" worden ist und die ganze Arithmetik uswusf. wohl noch mal 
angeguckt werden muss.

von Karl H. (kbuchegg)


Lesenswert?

Handelt es sich eigentlich nur um 1 derartiges Register, oder sind alle 
betroffen?

Wenn es nur 1 ist, dann würde ich mal dahingehend überlegen, dieses 
Register vor dem gcc zu verstecken. Zb indem man es als r33 einführt und 
dann alle Spezialoperationen (von denen der gcc ja auch nichts weiß) 
mittels inline-Assembler zu realisieren. Bei Funktionsaufrufen muss man 
halt aufpassen, das nicht innerhalb der Funktion wieder dieses 
Spezialregister benutzt wird und im Notfall selbst um Push/Pop kümmern.

Also: keine Modifikation des AVR-Kerns sondern eine Erweiterung. Der AVR 
Kern, so wie er dem gcc bekannt ist, belibt unangetastet und die 
HW-Erweiterung wird über inline-Assembler angesprochen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:

> Ich hab eben die
> genannte Problemstellung und muss nun eine Lösung dafür finden!

Bist du wenigstens Informatiker?  Ich glaube, ansonsten hast du
ein ziemlich schweres Los, einen Compiler wie den GCC passend zu
modifizieren.  (Btw., ich bin keiner, und ich gucke in weiten Teilen
des GCC-Codes wie das berühmte Tier ins Uhrwerk. ;-)

Ich würde an deiner Stelle anfangen, den AVR-Code im GCC komplett
zu clonen, vielleicht in ein Target namens "myavr" (oder
"my_schools_avr" :), und den dann modifizieren.  Wenn du dir da
wirklich nur ein paar Register frei halten willst, die du dann
ausschließlich via Assemblercode beackerst, mag das vielleicht
gehen, wenn du dem register allocator im GCC einfach beibiegst,
dass er diese Register gar nicht erst kennen möge.  Allzu viele
Register wirst du sicher nicht ohne größere architekturelle
Umbauten frei bekommen auf diese Weise, aber vielleicht genügen
dir ja ein paar.

Allerdings sehe ich schwarz, dass es irgendwie möglich ist, dass
man ihm ,,mal schnell'' beibringt, dass verschiedene Register in
unterschiedlicher Breite existieren.

Wie schon geschrieben, das ganze Projekt hätte man wohl lieber gleich
mit einem 32-bit-Core beginnen sollen, das wäre deutlich effektiver
gewesen, als hier die Zeit in schrägen Compilerhacks zu verplempern,
die nachher rettungslos verloren sind, weil sowas natürlich keiner
`upstream' im GCC einpflegen wird, sodass sie lediglich mit der
Compilerversion benutzbar sind, die du manuell gepatcht hast.  Drei
GCC-Versionen weiter passt das niemand mehr mal einfach so an, damit
werden die entsprechenden Bits ganz schnell verrotten.

von Karl H. (kbuchegg)


Lesenswert?

Jörg Wunsch schrieb:

> Bist du wenigstens Informatiker?  Ich glaube, ansonsten hast du
> ein ziemlich schweres Los, einen Compiler wie den GCC passend zu
> modifizieren.  (Btw., ich bin keiner, und ich gucke in weiten Teilen
> des GCC-Codes wie das berühmte Tier ins Uhrwerk. ;-)

Ich bin einer.

Und ich hab mal vor Jahren versucht (zugegeben: nicht sehr intensiv) zu 
verstehen, wie das funktioniert.
Ich habe nur 'Schienengebundenes öffentliches Verkehrsmittel 
Haltestelle' verstanden und bin dagestanden wie das 'männliche 
zeugungsunfähige Rindvieh vor der Öffnung, die der Maurer in der Wand 
gelassen hat'

Ich hab dann für mich entschieden: Das ist sinnlos und auch nicht 
zielführend.

Da schreibe ich lieber meinen eigenen Compiler. Das geht schneller, auch 
wenn ich am Anfang nicht soviele Optimierungen drauf haben werde wie der 
gcc.

von Volker Z. (vza)


Lesenswert?

Wenn man keinen 32Bit-Core implementieren will, würde ich eine art 
CO-Prozessor schreiben, der dir deine 32Bit-Berechnungen macht. Den 
sprichst du über deinen Speicher-Bus an.
Das ist (meistens, kommt auf deine Aufwendige Berechnung an) schneller 
als die emulation von 32bit auf 8Bit-Cores.

ciao Volker

von Peter (Gast)


Lesenswert?

Nee, kein Info, sondern E-techniker ;-)
Sie sind nich 32 Bit breit, sondern noch mehr. Und es sind alle 32 Stück 
verbreitert worden.
Wie schon erwähnt, im Prinzip funltioniert alles wunderbar! Ich habe 
auch Routinen drin, die mir die Reg-Werte retten in die 8-Bit arrays. 
Was jedoch wieder einige Rechenschritte kostet und der ganze clou an dem 
system ist ja die Geschwindigkeit. Ich soll das ganze in C 
programmierbar hinterlassen. Mit Assembler kriegt man das alles ganz gut 
in den Griff, aber der Knackpunkt is halt der C-compiler.

Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden, 
die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell 
schon oder?
Fallen euch spontan noch andere Funktionen ein, die haufenweise Register 
zuballern?

Danke für all die Infos und Mühen =)

von Grrr (Gast)


Lesenswert?

Volker Zabe schrieb:
> die emulation von 32bit auf 8Bit-Cores

Darum geht es hier nicht.

Peter schrieb:
> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!

Wieviel Arbeit steckt da jetzt schon drin?

Peter schrieb:
> Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden,
> die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell
> schon oder?

Nicht im Kontext mit

> Ich soll das ganze in C programmierbar hinterlassen.

Das ist alles bloss Gefrickel.

D.h. irgendwie würgt man das schon hin. Aber es hat keinen Zeck. Der 
Entscheider wird halt in den sauren Apfel beissen müssen.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Nee, kein Info, sondern E-techniker ;-)

Na super.
Wer kommt eigentlich auf solche Ideen?

> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!

Kann ich mir nicht wirklich vorstellen.
Das Attribut "wunderbar" würde ich dem nicht zugestehen.

> Ich habe
> auch Routinen drin, die mir die Reg-Werte retten in die 8-Bit arrays.
> Was jedoch wieder einige Rechenschritte kostet und der ganze clou an dem
> system ist ja die Geschwindigkeit. Ich soll das ganze in C
> programmierbar hinterlassen.

Das wirst du so nie hinkriegen.

> Wäre es eine Möglichkeit, statt printf eine eigene Routine zu verwenden,
> die dann die Rettung durchführt bevor printf gestartet wird? Prinzipiell
> schon oder?

Prinzipiell ja.
printf ist auch nicht sonderlich schwer zu schreiben.

Aber printf ist nur die halbe Miete.
Im Grunde musst du durch die komplette Runtime Library durch und alle 
Funktionen neu schreiben (bzw. anpassen).

Wenn du dem gcc 1 oder 2 Register mittels 'register' klaust, reicht es 
im Prinzip aus, die Runtime Library mit genau dieser Einstellung neu zu 
compilieren um die Benutzung dieses Register exclusiv deinem Programm 
(und nur deinem Programm) zu erlauben.

Wie sinnvoll das ist, ist eine andere Frage.
Den Zeitgewinn an einer Stelle erkaufst du dir damit, dass dem gcc an 
anderer Stelle dafür die Register ganz schnell ausgehen und er wie wild 
Register jonglieren muss.

Mal ganz davon abgesehen, dass das dann eine Runtime Library ist, die 
ganz speziell für ein Programm (oder einen Programmtyp) angepasst wurde.

> Fallen euch spontan noch andere Funktionen ein, die haufenweise Register
> zuballern?

Es ghet nicht nur darum, ob sie 'haufenweise' Register zuballern. Es 
geht darum welche sie zuballern. Eines reicht schon, wenn es das 
richtige ist.

von Grrr (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Na super.
> Wer kommt eigentlich auf solche Ideen?

Ganz klar. Einer der auf keinen Fall gefeuert wird, es sei denn es ist 
der TO selbst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:

> Sie sind nich 32 Bit breit, sondern noch mehr. Und es sind alle 32 Stück
> verbreitert worden.

Schönen Schrank auch.  Und dafür nimmt man sich ausgerechnet einen
AVR als Original?  Der GCC ist ursprünglich vor allem für 32-bit-
CPUs vorgesehen gewesen, das ganze Gefummel, was der AVR-GCC als
Hacks für die kleine 8-bit-CPU macht, hätte man sich hier komplett
klemmen können.  Von mir aus auch 64 bits.  (Weiß nicht, wie schwer
es wäre, ihn auch auf noch breitere Architekturen zu portieren.)

Karl heinz Buchegger schrieb:
> Das Attribut "wunderbar" würde ich dem nicht zugestehen.

Geht mir auch so.

Peter, tut mir echt leid für dich.  Hat man dich mit Geld bedroht,
dass du dir so einen <censored>-Job hast andrehen lassen? ;-)

Lieber würde ich meine Energie in eine Portierung auf einen ATtiny10
stecken, als mir eine derartige Krücke freiwillig aufzuladen.  Sorry,
wenn das jetzt hart klingt.

von Grrr (Gast)


Lesenswert?

Tut mir leid, Peter.
Muss sich ganz schön blöd anfühlen, falls das nicht Deine Idee war.

von Peter (Gast)


Lesenswert?

:-)
Danke für euer Mitleid =)
Nee, noch nichmal Geld is drin ;-) das ganze nennt sich diplomarbeit =)

von Peter D. (peda)


Lesenswert?

Volker Zabe schrieb:
> Wenn man keinen 32Bit-Core implementieren will, würde ich eine art
> CO-Prozessor schreiben, der dir deine 32Bit-Berechnungen macht. Den
> sprichst du über deinen Speicher-Bus an.

Das sehe ich auch als die einzige Möglichkeit an.

Wenn man einen vorhandenen Compiler benutzen will, muß man sich 
sklavisch exakt, bis auf I-Tüpfelchen, 100%-ig an den original 
Befehlssatz halten, da führt kein Weg dran vorbei.
Ändert man das Verhalten auch nur eines Bits, produziert der Compiler 
nur noch Schrott.


Für memory mapped Zusatzfunktionen brauchst Du dann nur alle nötigen 
Zugriffsfunktionen schreiben und kannst sie dann in C aufrufen.
Compiler Internas werden damit nicht gestört. Er kann weiterhin richtig 
rechnen, den Speicher verwalten und Bedingungen testen.


Peter

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> Wie schon erwähnt, im Prinzip funltioniert alles wunderbar!

Das kannst Du vielleicht jemandem erzählen, der sich die Hose mit der 
Kneifzange anzieht.

Schon eine simple Adreßberechnung läuft gegen die Wand, wenn die 
Register nicht 8-bittig sind:
Der Compiler addiert den low-Index zu ZL und erwartet bei >255 einen 
Übertrag, den er dann mit dem high-Index zu ZH addiert. Und dann springt 
er an die richtige Stelle, aber bei Dir springt er in den Wald.


Peter

von Peter (Gast)


Lesenswert?

Auch wenn Ihr euch das nich vorstellen könnt, es klappt wirklich alles 
sehr gut. Also alle Berechnungen werden brav durchgeführt mit den neuen 
Regs.
Die Angepasste Breite und die neue Rechnerarchitektur ist nicht das 
Problem.
Das einzige Problem ist ungewünschte Auslagerung der Regs. Wenn die 
nicht wäre, wären alle Beteiligten zufrieden.

Aber lassen wir das drumherum mal kurz beiseite =)

Ich habe versucht mehr Infos über den Ablauf der printf routine zu 
bekommen, aber leider finde ich da keine... im dissassembler wird ja 
auch nur die subroutine gecallt und ich erhalte keinen Einblick, was da 
jetzt genau passiert und eben in meinem Fall schiefgeht...
Und im Netz finde ich das ganze auch nicht in den gcc sources auch 
nicht.

Was ich eben auch nicht verstehe, ist, was hier auch schon angemerkt 
wurde, wieso und wobei werden die oberen Bits 0 gesetzt. Der Compiler 
denkt ja mein Reg is 8Bit breit, dh er rettet doch nur 8 Bit ins SRAM 
und dürfte die oberen ja gar nicht anrühren?!?
Außerdem sehe ich nicht, ob er sie überhaupt ins SRAm rettet, da ich ja 
nur rcall printf sehe im Assemb... Und im restlichen Code werden die ja 
gar nicht angerührt.

Naja, wahrscheinlich ist das ganze zu speziell und vielleicht auch zu 
ungeschickt durchgeführt um es von außen nachvollziehen zu können. Ich 
kann leider nicht genauer auf die Implementation des Ganzen eingehen, da 
ich sonst riskiere Ärger zu bekommen, wegen Vertraulichkeitsgedöhns :(

Vielen Dank für alle GEdanken die Ihr euch wegen mir schon gemacht habt 
=)
Und wie gesagt, ich kann nix dafür sondern muss es nur ausbaden ;-)
Viele Grüße

von Volker Z. (vza)


Lesenswert?

Wenn sich C und eurer superdupererweiterterasemblercode nicht vertragen, 
dann mischt sie auch nicht.
Definiere ein Interface zwischen C und erweitertem Asembler.
Und haltet euch sauber daran.

Das Konzept bleibt aber Mist.

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> Der Compiler
> denkt ja mein Reg is 8Bit breit, dh er rettet doch nur 8 Bit ins SRAM
> und dürfte die oberen ja gar nicht anrühren?!?

PUSH/POP sind ja nicht die einzigen Befehle, der Compiler braucht die 
Register hauptsächlich zum Rechnen!

Was passiert denn bei den Befehlen, werden z.B. immer nur die unteren 
8Bit addiert und das Carry beim 8Bit gesetzt?
Du wirst ja die Befehle auf 32Bit erweitert haben und genau deswegen 
knirscht es.

Solange wird Deine Änderungen im Befehlssatz nicht kennen, stochern wir 
alle nur im Nebel.

Falls Du kein Genie bist, daß eben mal schnell nen Compiler aus dem 
Boden stampft, wirst Du Dich damit abfinden müssen, daß nur purer 
Assembler auf Deiner Kiste läuft.


Peter

von (prx) A. K. (prx)


Lesenswert?

Apropos Compiler: Wer sich vom GCC Quellcode erschlagen fühlt, der kann 
sich mal meinen alten Bekannten ansehen, den Portable C Compiler (Google 
hilft). Der ist zwar mittlerweile ca. 35 Jahre alt, aber zu meiner 
Überraschung wieder aus dem Grabe auferstanden. Ist sehr viel einfacher 
als GCC, optimiert aber natürlich auch nicht ganz so gut.

von Bernhard R. (barnyhh)


Lesenswert?

@ Peter:

Dein Problem läßt sich recht einfach lösen, und ich wundere mich, daß Du 
nicht selbst darauf gekommen bist. Schließlich zeigt eine Diplomarbeit, 
daß ihr Ersteller wissenschaftlich arbeiten kann.

Die Sourcen der GCC-Library-Funktionen sind öffentlich. Du kannst 
hingehen und sie an die Bedürfnisse Deines Environments anpassen - sei 
es durch Modifikation des Source-Codes, sei es durch entsprechende 
Compiler-Optionen.

Bernhard

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, er hat's ja noch nichtmal geschafft, die avr-libc zu finden.

Wenn er sie findet, wird seine Welt aber auch nicht besser sein:
der ganze Code von stdio ist ja in C geschrieben, das heißt, wenn
da irgendwas mit seinem gehackten Professor nicht richtig läuft,
ist es doch wieder der C-Compiler, an dem er sich vergreifen muss...

von Peter D. (peda)


Lesenswert?

Eine Möglichkeit wäre noch, alle original Atmel Befehle 100% identisch 
zu implementieren und Befehle für erweiterte Register nur über noch 
freie Befehlskombinationen zu machen. Ich glaube bei den 
Doppelwordbefehlen ist noch viel frei.
Dann läuft der Compiler wieder richtig.

Aber die erweiterten Befehle mußt Du dann als Opcode hinschreiben, also 
weder C noch Assembler.


Peter

von Peter (Gast)


Lesenswert?

Also es gibt ja mehrere neue Befehle, die mit den langen Regs arbeiten.
Es gibt dann eben die ein oder andere Routine, speziell die zum retten 
der Regs in ein Array, hierbei werden dann 8Bit stücke nacheinander 
gespeichert.
Oder eben das Laden eines Regs aus dem 8-Bit Array.
Aber wie schon erwähnt, das ganze andere Handling klappt prima. 
Problematisch wird es eben ab dem Moment, in dem der Compiler die Regs 
anders nutzt.
ALU usw klappen einwandfrei...

Ja die Sourcen sind öffentlich und ja ich habe sie auf dem Rechner und 
mache seit Tagen nichts anderes, als diese zu durchforsten. Aber die 
grundlegende Definition von beispielsweise printf besipielsweise finde 
ich dort nicht. Auch die Maschinenbeschreibung vom Atmel ist ja da zu 
finden mit Registeranzahl usw.. Aber wirklich was anfangen kann ich 
damit nicht, bin wohl doch kein Genie ;-) Das Thema Compilerbau ist halt 
eben doch sehr komplex und ich habe im moment keinen richtigen 
Anfangspunkt und bin wohl auch zu doof um in den GCC Dokus die richtigen 
Stellen zu finden, um den COmpiler an neue HW anzupassen.

Werde mir mal den portable anschauen, vllt bekomme ich da eher nen 
durchblick, danke für den tipp =)

Ansonsten wird die Marschrichtung wohl sein, die Funktionen und Routinen 
zu bestimmen, bei denen der Fehler vorkommt und diese zu ersetzen durch 
andere, die zuerst noch eine sicherung der gefährdeten Register 
durchführen.
Oder ich finde raus, wann es passiert, dass die eigentlich unbekannten 
oberen Bits 0 gesetzt werden, denn wenn diese erhalten blieben während 
einer Routine, wäre das Problem ja auch schon gelöst, egal was Ihr alle 
von der Implementation haltet ;-)

Danke nochmal für alles =)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Aber die
> grundlegende Definition von beispielsweise printf besipielsweise finde
> ich dort nicht.
1
int
2
printf(const char *fmt, ...)
3
{
4
        va_list ap;
5
        int i;
6
7
        va_start(ap, fmt);
8
        i = vfprintf(stdout, fmt, ap);
9
        va_end(ap);
10
11
        return i;
12
}

vfprintf ist dann das eigentliche Arbeitspferd der gesamten Familie,
steht in libc/stdio/vfprintf.c.

Da das aber alles in C geschrieben ist bedeutet das, wenn diese
Funktionen in deinem Prozessor Mist machen, dass dann auch jede
x-beliebige andere Funktion genauso Mist machen kann.  Bis auf
einen kleinen inline-assembler-Makro, der dynamisch entscheidet,
ob ein bestimmter Zeiger als Zeiger auf den RAM oder Flash-ROM
zu interpretieren ist, ist das alles stinknormaler C-Code, wie
er auch in jeder Nutzer-Applikation auftreten könnte.

von Peter (Gast)


Lesenswert?

@Peter:
Das wurde auch genauso gemacht, neue Opcodes, neue Befehle usw...
Und die klappen durch die Mnemonics ja auch wunderbar in assembler, und 
durch inline asms auch wunderbar in C.
Das alles ist ja nich das Problem!

@Jörg: Naja, ich hab die Libs schon gefunden und durchgesehn, aber ne 
extern int printf(bla,blubb) deklaration bringt mich eben auch nich 
weiter....

Naja, es wird schon irgendwie klappen...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:

> @Jörg: Naja, ich hab die Libs schon gefunden und durchgesehn, ...

Offenbar nicht, denn so klein, dass dir die 714 Zeilen Implementierung
für vfprintf einfach so durch die Lappen rutschen könnten, ist sie ja
nun wirklich nicht.  Aber wie schon gesagt, eben (fast) stinknormaler
C-Code, das heißt, wenn das nicht geht, bist du wieder bei "LOS!" und
darfst dir den Compiler vorknöpfen, denn es könnte dir für jede andere
Funktion genauso passieren.

Was u. U. hilft, das Problem zu triggern ist, dass printf() eine
"variadic function" ist, d. h. Argumente können (bis auf den
Formatstring) nur über den Stack übergeben werden.  Du kannst das
Problem vermutlich auch mit einer variadic function innerhalb deiner
Applikation dann triggern.

von Peter (Gast)


Lesenswert?

Ja, tut mir leid, ich gebe zu damit begebe ich mich grad aufs 
halbwissen-glatteis...

Also nochmal langsam, wenn ich von QUellen rede meine ich die Gcc 4.4.3 
Quellen. Darin enthalten sind doch genau die sources, mit denen der gcc 
gebaut wird?

von (prx) A. K. (prx)


Lesenswert?

Das ja, aber dort findest du keine Definition von printf, sondern 
allenfalls die GCC-spezifische aber hier nutzlose Heurikstik, in der 
Formatstring und Parametertypen gegengecheckt werden um ggf. zu warnen.

Sorry, aber mit deinen Kenntnissen bewaffnet solltest du dich auf die 
Hardware konzentrieren und die Softwareseite auf dem Verhandlungsweg 
lösen. Du willst die Arbeit doch bestimmt noch dieses Jahr abgeben.

Denn bevor man sich in einen C Compiler stürzt, egal welchen, sollte man 
C wenigstens gut verstanden haben.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Oder eben das Laden eines Regs aus dem 8-Bit Array.
> Aber wie schon erwähnt, das ganze andere Handling klappt prima.

Du meinst:
Du hast nur noch nicht die ganzen anderen C-Fälle gefunden, in denen es 
nicht funktioniert und ein kleines Problem lauert, das nur darauf wartet 
rausgelassen zu werden und zu einem großen Problem zu mutieren.

> grundlegende Definition von beispielsweise printf besipielsweise finde
> ich dort nicht.

Ich würde mal erwarten, dass printf so implementiert ist
1
int printf(const char * fmt, ...)
2
(
3
  int res;
4
  va_list args;
5
6
  va_start( args, fmt );
7
  res = vfprintf( stdout, fmt, args );
8
  va_end( args );
9
10
  return res;
11
}

Das könnte auch dein Ansatzpunkt sein, an dem du dein spezielles 
Registerhandling vor und nach der eigentlichen Funktionalität einbringen 
kannst.
(Die 3 Punkte sind hier übrigens nicht das Zeichen dafür, dass ich da 
etwas ausgelassen habe. Die gehören da hin und müssen da sein)

Wenn du mit obiger printf-Funktion allerdings nicht klarkommst, rate ich 
dir von der ganzen Sache ab. Du begibst dich da in eine Situation, in 
der du nur verlieren kannst.

> Denn bevor man sich in einen C Compiler stürzt, egal welchen,
> sollte man C wenigstens gut verstanden haben.

Full ACK!
Und zwar auch in den 'dunklen Ecken von C'!

von Peter (Gast)


Lesenswert?

=)
Ok, Das trifft den Nagel wohl auf den Kopf!

von Peter (Gast)


Lesenswert?

Das war auf die bescheidenen Kentnisse bezogen.

Ja, printf war bisher nur ein Beispiel was schiefgehen kann. Wollte auch 
nie bezweifeln, dass es bei vielen adneren genauso schiefgeht.
Deshalb war der ursprüngliche Gedanke ja, de gefährdeten Regs dem 
Zugriff des Compuilers zu entziehen. ICh hatte ja hoffnung, dass das zu 
machen wäre.
Aber ich sehe ja ein, dass die ganze Problematik extrem viel komplexer 
ist als erhofft.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> Deshalb war der ursprüngliche Gedanke ja, de gefährdeten Regs dem
> Zugriff des Compuilers zu entziehen. ICh hatte ja hoffnung, dass das zu
> machen wäre.

Wenn es sich nur um 1 oder 2 spezielle Register handeln würde, ja dann 
würde das gehen. Ganz im Gegenteil: Anstatt an den vorhandenen Registern 
rumzuwerken, hätte man die beiden Register als Erweiterung zu den 
bestehenden gemacht, von denen der Compiler nichts weiß.
Dazu noch die Spezialbefehle, die zum Ansprechen dieser Erweiterung 
notwendig sind, schön verpackt in inline-Assembler Funktionen, und im 
Grunde wärs das gewesen.
Man kommt dem Compiler nicht ins Gehege (*) und muss ihn auch nicht 
austricksen. Jeder tut das was er am besten kann: Der Compiler kümmert 
sich um die AVR Architektur und die Assembler Funktionen bedienen die 
Erweiterung.

Aber nein, statt dessen musste es ja gleich ein Rundumschlag sein (ich 
weiß, du kannst nichts dafür), damit man sich nur ja richtig in die 
Schei... reinreitet.

(*) Das kann man durchaus auch als Aufforderung verstehen:
"Man kommt dem Compiler nicht ins Gehege!"
Das tut man einfach nicht, denn man kann dabei nur verlieren. Compiler 
sind nicht mehr die einfachen linearen Programme, die mit 2 mal schief 
ansehen verstehbar sind. Jede noch so kleine Änderung kann unabsehbare 
Konsequenzen nach sich ziehen.
Und es gilt immer noch das Dogma: Der Compiler hat immer recht! Immer? 
Immer!

von Peter (Gast)


Lesenswert?

Ja, der Gedanke mit Extra-Registern drängt sich förmlich auf.
Sollte das so nich akzeptiert werden, werde ich versuchen, einfach durch 
try&error kritische Funktionen zu ermitteln und diese dann an eine 
Rettung der Regs knüpfen mit entsprechenden Vorschriften für potentielle 
Programmierer.

Also in jedem Falle, ein herzliches Dankeschön fürs Augen öffnen und 
Grenzen (auch persönliche ;-) ) aufzeigen =)
P.S.: wäre das schön, wenn es ein bindendes Registerattribut gäbe ;-)

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:

> P.S.: wäre das schön, wenn es ein bindendes Registerattribut gäbe ;-)


Überleg mal.
So etwas kann es im Allgemeinen nicht geben!
Dein Code ist nicht der einzige der auf der Maschine läuft. Du hast 
immer noch einen gewissen Anteil an Funktionen aus der Runtime-Library 
mit dabei. Die sind vorcompiliert und wissen nichts von deiner 
Registerabzwackerei.

von (prx) A. K. (prx)


Lesenswert?

Wie KHB oben schon erwähnte gibt es im GCC über das globale asm("r2") 
die Möglichkeit, ihn komplett von der Verwendung bestimmter Register 
abzubringen. Allzu viele dürfen es natürlich nicht sein und es kommen 
auch nicht alle in Frage.

Damit das aber funktioniert, muss der gesamte Code mit dieser 
Definition des Registers frisch übersetzt werden und damit sind auch die 
Bibliotheksfunktionen gemeint. Es kann dann auch nötig werden, einzelne 
in Assembler implementierte Bibliotheksfunktionen daraufhin zu 
überprüfen, ob sie diese Register verwenden.

Wenn man sich mit solchen Registern sehr zurückhält und nur am selten 
genutzen Rand knabbert, dann werden nur wenige Bibliotheksfunktionen ein 
Problem bereiten. Es kann dann helfen, das printf komplett selbst zu 
implementieren und mit etwas Lust am Risiko die vorhandene Bibliothek 
trotzdem für den Rest zu verwenden. Andere Problemkandidaten wären 
Funktionen, die 64-Bit Integer verwenden bzw. deren Arithmetik 
implementieren.

von Peter D. (peda)


Lesenswert?

Peter schrieb:
> @Peter:
> Das wurde auch genauso gemacht, neue Opcodes, neue Befehle usw...
> Und die klappen durch die Mnemonics ja auch wunderbar in assembler, und
> durch inline asms auch wunderbar in C.
> Das alles ist ja nich das Problem!

Dann kann das Problem nur sein, daß bei der Implementierung der original 
Befehle ein Fehler gemacht wurde und die Register sich nicht 8bittig 
verhalten.
Dafür kann man aber nicht dem Compiler die Schuld in die Schuhe 
schieben.

Da mußt Du Dir erstmal ein Testprogramm schreiben, was sämtliche 
original Register-Befehle testet.
Also auch die Flagsetzung, bedingte Sprünge, indirekte Adressierung usw.
Und nicht die 16Bit Befehle vergessen (MOVW, ADIW, ..).
Das kann schon in richtig Arbeit ausarten.


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
> Die sind vorcompiliert und wissen nichts von deiner
> Registerabzwackerei.

Wenn man an irgendwas wie dem ABI rumschraubt ist es eigentlich
Pflicht, dass man als mindestes erstmal die run-time lib komplett
mit dem gleichen Compiler und den gleichen Compilerschrauben selbst
compiliert.

von Peter (Gast)


Lesenswert?

Ok, das klingt natürlich auch vernünftig..
Bitte nicht hauen, aber ..ähhm... wie würde ich das anfangen? diese 
nochmal selber zu compilieren in deckung geh

von Bernhard R. (barnyhh)


Lesenswert?

Und wenn Du dann die Runtime-Lbrary neu compilierst, dann hast Du die 
Möglichkeit, jede einzelne Funktion anhand des jeweiligen 
Assembler-Listings auf unerwartete Registerbenutzung u.ä. 
Inkompatibilitäten mit Deinem Prozessor zu prüfen. Du besitzt dann die 
Freiheit, diese Funktionen mit angepaßten Compiler-Optionen (z.B. -O0) 
zu compilieren bzw. nicht erforderliche Teile (z.B. Float-Unterstützung 
bei der ..printf-Familie) zu eliminieren. Das liegt alles in Deiner 
Hand.

Bernhard

von Karl H. (kbuchegg)


Lesenswert?

Bernhard R. schrieb:
> Und wenn Du dann die Runtime-Lbrary neu compilierst, dann hast Du die
> Möglichkeit, jede einzelne Funktion anhand des jeweiligen
> Assembler-Listings auf unerwartete Registerbenutzung u.ä.
> Inkompatibilitäten mit Deinem Prozessor zu prüfen. Du besitzt dann die
> Freiheit, diese Funktionen mit angepaßten Compiler-Optionen (z.B. -O0)
> zu compilieren bzw. nicht erforderliche Teile (z.B. Float-Unterstützung
> bei der ..printf-Familie) zu eliminieren. Das liegt alles in Deiner
> Hand.

Und wehe, deine Kapazunder kommen auf die Idee, in einem halben Jahr auf 
die neueste Version upzugraden (sowohl Compiler als auch Runtime 
Library).
Dann geht das ganze Spielchen von vorne los :-)

Also am besten jede Modifikation dokumentieren, warum sie notwendig war 
und was die Modifikation bewirkt.

Auf die Assembler Anteile in der Runtime Library nicht vergessen (wurde 
weiter oben schon einmal erwähnt)

von Bernhard R. (barnyhh)


Lesenswert?

Letzter Hinweis:

Hier ( http://www.nongnu.org/avr-libc/ ) ist die Runtime-Library für die 
AVR-Portierung des GCC. Es ist alles vorhanden: C-Files, H-Files, 
Makefiles, Dokumentation.

Bernhard

von Peter D. (peda)


Lesenswert?

Ich vermisse in den letzten Postings die Ironie-Tags.

Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über 
Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.


Peter

von (prx) A. K. (prx)


Lesenswert?

Wie ich schon schrieb geht das nicht mit allen Registern. Ganz besonders 
nicht mit R0 und R1.

von Peter (Gast)


Lesenswert?

Ok, super =)

Dann hab ich ja jetz erstmal ordentlich was zu tun =)
Sorry, wegen der Build-Frage war mir nich ganz sicher, ob ich dafür auch 
die ganzen schritte über Unix-Umgebungen gehen muss, aber es gibt ja zum 
glück das avr-libc manual =)

Also ich kann nur noch einmal betonen:
Vielen, vielen Dank für den ganzen Input und eure ganze Nachsicht mit 
Laien =)

Viele Grüße
vllt melde ich mich ja nochmal wenn alles geklappt hat, oder ihr als 
Zeugen auftreten müsst, wenn ich ne schlechte Note kriegen soll =)

von Karl H. (kbuchegg)


Lesenswert?

> Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über
> Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.

A.K. hat schon geschrieben, dass R0,R1 nicht geht. Und bei den 
Registern, die zum Argumentpassing abegstellt sind, wirds wohl auch 
Schwierigkeiten geben (aus dem Bauch heraus geschätzt).

Aber im Grunde kann man das bei anderen Registern schon machen.

Die Frage ist halt immer: wie sinnvoll ist es, dem Registerallokator 
seine Arbeitsgrundlage zu entziehen. Das ist ungefähr so sinnvoll, wie 
einem Klavierbauer zu sagen, er möge alle Tasten ausser C,D,E,F,G,A,H,C 
weglassen, weil was anderes braucht man nicht für 'Hänschen klein'. Will 
man nur 'Hänschen klein' spielen und andere Stücke, die mit diesen Noten 
auskommen, dann ist das perfekt. Aber wehe, wenn nicht.

Irgendwann bezahlt man dafür. Und dann hat man die paradoxe Situation, 
dass diese vermeintliche Beschleunigung eine Verschlechterung darstellt, 
weil der Geschwindigkeitsvorteil an einer Stelle durch massive 
Verschlechterung an anderen Stellen (durch die dort fehlenden Register) 
mehr als aufgefressen wird.

Ausserdem muss man sich immer überlegen, ob es schlau es ist, eine 
speziell privat angepasste Runtime Library im Projekt zu haben. Wenns 
nicht anders geht, ist es ja ok. Nur sollte man auch die Konsequenzen 
für die Zukunft berücksichtigen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Karl heinz Buchegger schrieb:
>> Wenn das wirklich so einfach ist, könnt ich mir ja mal schnell über
>> Mittag nen WINAVR ohne das R0,R1-Geraffel basteln.
>
> A.K. hat schon geschrieben, dass R0,R1 nicht geht.

Wobei ich das noch nicht so absolut sehen würde.  Für eine rein
private Version geht das sicher, sie ist eben nur komplett ABI-
inkompatibel zu allem anderen, und man muss jedes Stück Assembler-
code (einschließlich inline asm) einzeln begutachten.

Ob man komplett ohne _zero_reg_ auskommt, weiß ich nicht, aber
auf ein anderes Register umlegen müsste man das wirklich können.

Eine Mittagspause wird nicht reichen, ein Wochenende schon, wenn
man ungefähr weiß, wo man was suchen will, und wenn man wenigstens
die Buildumgebung schon hat.

von Peter (Gast)


Lesenswert?

Eine Frage hab ich dann aber doch noch:
Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die 
globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen 
inline assembler routinen usw, zu den runtime-libs inzufügen und dann 
das ganze builden?

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

>> A.K. hat schon geschrieben, dass R0,R1 nicht geht.
>
> Wobei ich das noch nicht so absolut sehen würde.

Ich bezog mich dabei auf die vorher beschriebene Variante asm("r0") zur 
Reservierung eines Registers.

R0,R1 komplett frei zu bekommen ist sicherlich möglich, erfordert aber 
signifikante Änderungen am maschinenabhängigen Teil des Compilers und in 
Assembler-Routinen der Lib. Zudem müssen denn Multiplikationen entweder 
mit abgeschalteten Interrupts oder ohne die entsprechenden Befehle 
ausgeführt werden.

von Karl H. (kbuchegg)


Lesenswert?

Peter schrieb:
> Eine Frage hab ich dann aber doch noch:
> Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die
> globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen
> inline assembler routinen usw, zu den runtime-libs inzufügen und dann
> das ganze builden?

Mach dir ein Header File, in welches die extern-'Reservierung' (und nur 
diese) hineinkommt.
Diesen Header includierst du dann quer durch die Bank in allen *.c 
Files, damit auch alle wissen, das diese Register tabu sind.
Ich kenne jetzt den Aufbau der Runtime Lib nicht. Eventuell gibt es dort 
ja schon ein Header File, welches wirklich überall includiert wird. Das 
wäre dann ein guter Platz.

von (prx) A. K. (prx)


Lesenswert?

Peter schrieb:

> Wenn ich alles neubaue, an welcher Stelle werden "reserviere" ich die
> globalen Reg-variablen? Soll ich dann einfach die eigene .h mit meinen
> inline assembler routinen usw, zu den runtime-libs inzufügen und dann
> das ganze builden?

Du benötigst eine zentrale .h mit deinen register asm("rX") Statements 
drin, die in allen C-Quellcodes der Lib included wird.

Sehr viele Register sollten das aber nicht sein, sonst besteht die 
Gefahr, dass der Compiler öfter mal nicht weiter weiss und verzweifelt 
die Segel streicht, insbesondere wenn registerfressende 64-Bit Integers 
verwendet werden.

von Peter (Gast)


Lesenswert?

Super danke =)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:

> R0,R1 komplett frei zu bekommen ist sicherlich möglich, erfordert aber
> signifikante Änderungen am maschinenabhängigen Teil des Compilers

Das ist in 1...2 Stunden erledigt.  Wie gesagt, in der Annahme, dass
man stur r0/r1 durch r2/r3 ersetzt.  Das sind einige wenige Stellen,
das meiste dabei ist relativ zentral definiert.

> und in
> Assembler-Routinen der Lib.

Das ist der größere Aufwand, das würde den restlichen ersten Tag
des genannten Wochenendes in Beschlag nehmen. ;-)

> Zudem müssen denn Multiplikationen entweder
> mit abgeschalteten Interrupts oder ohne die entsprechenden Befehle
> ausgeführt werden.

Nein, man muss eigentlich dem Compiler nur beibringen, dass die
Multiplikationsbefehle diese beiden Register benötigen, sodass eine
ISR sie als geändert betrachten muss, wenn solche Befehle benutzt
werden.  Entsprechend müssen sie dann nur noch bei Bedarf gesichert
werden, wie alle anderen Register, die nicht immer gesichert werden
müssen.  Dem Compiler das beizubringen wäre der zweite Tag des
Wochenendes. :-)

von Peter D. (peda)


Lesenswert?

Mein Posting sollte auch nur ironisch gemeint sein:

Beitrag "Re: Registerattribut"

Die R0,R1 Sache hat nix mit dem "Peter (Gast)" zu tun.
Vergeßt es einfach.


Peter

P.S.:
Immerhin interessant, daß es für den Kundigen in 2 Tagen zu schaffen 
wäre.

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

> Nein, man muss eigentlich dem Compiler nur beibringen, dass die
> Multiplikationsbefehle diese beiden Register benötigen, sodass eine
> ISR sie als geändert betrachten muss, wenn solche Befehle benutzt
> werden.

Vorausgesetzt, man verwendet in ISRs keine Funktionen, die auf die 
betroffenen Registervariablen angewiesen sind. Denn deren Werte sind 
dann unauffindbar irgendwo im Stack versteckt.

von (prx) A. K. (prx)


Lesenswert?

Peter Dannegger schrieb:

> Immerhin interessant, daß es für den Kundigen in 2 Tagen zu schaffen
> wäre.

Für die erste Alpha-Version könnte das passen. Aber du bist wohl lange 
genug in der Branche um zu wissen, was man mit ersten optimistischen 
Aufwandseinschätzungen tun muss ;-).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:

> Vorausgesetzt, man verwendet in ISRs keine Funktionen, die auf die
> betroffenen Registervariablen angewiesen sind.

Häh?  Hier verstehe ich dich nicht mehr...

Nimm an, dein Hauptprogramm benutzt einen MUL-Befehl, das Ergebnis
steht in r0/r1.  Jetzt kommt ein Interrupt rein.  Die ISR benutzt
selbst auch MUL und rettet daher r0/r1 (was sie sonst nun nicht
mehr müsste).  Danach hat sie das normale Ergebnis vorliegen, aber
was soll sie jetzt mit den "betroffenen Registervariablen" wollen
(welchen überhaupt)?

Wenn die ISR zurückkehrt restauriert sie r0/r1, und das Hauptprogramm
sammelt aus diesen dann das Ergebnis der vorangegangenen Multi-
plikation auf.

Die ISR muss natürlich immer noch r2 retten (scratch register),
allerdings darf sie nun davon ausgehen, dass niemand mehr jemals
die 0 aus r3 entfernt, daher muss sie das weder retten noch neu
ausnullen.  Sollte eine Assemblerfunktion jemals r3 benutzen
wollen, ist sie natürlich dafür verantwortlich, für diese Zeit
die Interrupts zu sperren.

von (prx) A. K. (prx)


Lesenswert?

Jörg Wunsch schrieb:

> Häh?  Hier verstehe ich dich nicht mehr...

Es ging um globale Variablen der Form:
  register uint8_t status asm("r0");

Eine Multiplikation muss R0 verwenden, wird es also vorher sichern. Wenn 
nun eine ISR auf "status" zugreifen will, aber grad eine Multiplikation 
unterbrochen hat, dann war's das. Nix geht mehr. Der Wert liegt irgendwo 
im Stack oder einem beliebigen anderen Register.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. schrieb:

>> Häh?  Hier verstehe ich dich nicht mehr...
>
> Es ging um globale Variablen der Form:
>   register uint8_t status asm("r0");

Ja, es ist ja wohl klar, dass dann r0 bis r3 komplett tabu sind für
eine explizite Registerzuweisung.  r0 und r1 wegen der Multiplikation,
r2 und r3 wegen ihrer Sonderbedeutung.

von Peter (Gast)


Lesenswert?

Hm, also habe die ganze Build-Umgebung..
Hat alles soweit gut funktioniert.
Wenn ich jetz allerdings avr-libc builden will mit der angegebenen 
congigure anweisung, bekome ich einen:
1
tee: invalid option -- c
2
Try `tee --help' for more information.

fehler in msys... google hilft leider nicht...
configure:
1
        ./configure \
2
            --host=avr \
3
            --prefix=$installdir \
4
            --enable-doc \
5
            --disable-versioned-doc \
6
            --enable-html-doc \
7
            --enable-pdf-doc \
8
            --enable-man-doc \
9
            --mandir=$installdir/man \
10
            --datadir=$installdir \
11
            2>&1 | tee $package-configure.log

von Peter (Gast)


Lesenswert?

achso, mein OS is leider vista premium

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:

> tee: invalid option -- c

>             2>&1 | tee $package-configure.log

Wo auch immer du das her genommen hast...  Die Variable "package"
ist bei dir einfach leer, sodass das da oben zu

2>&1 | tee -configure.log

erweitert.  Damit würdest du dem tee-Kommando die Optionen -c,
-o, -n, -f, -i, -g, -u, -r, -e, -., -l, -o und -g übergeben
wollen, wovon er sich bereits bei der ersten beschwert. ;-)

Schreib einfach: »... | tee logfile.txt«  (Dein Windows würde mit dem
Suffix .log ohnehin nichts anfangen können, denn Windows hat sich
ja mit sowas ziemlich eigen.)

> achso, mein OS is leider vista premium

Nein, dein OS ist Windows, die Version ist Vista Premium.  Ich
sage dir doch auch nicht, dass mein OS 8.0-stable ist und impliziere
dass du weißt, dass damit ein FreeBSD gemeint ist. ;-)

von Peter (Gast)


Lesenswert?

Ach tut mir leid, aber ich bin zu unfähig! Weder Google, noch Su-Fu 
haben geholfen, deswegen nerv ich euch schon wieder :-(

Also habe mich genau an die Anleitung von
http://www.nongnu.org/avr-libc/user-manual/install_tools.html
gehalten.

Die Tools haben ja dann sich auch installen lassen.
Configuren von avr-libc hat dann auch funktioniert, dank Jörg ;-)

Aber wenn ich dann den make install Befehl durchführe passiert 
folgendes:
1
make[5]: Entering directory `/c/msys/1.0/avr-libc-1.6.7/avr/lib/avr2'
2
avr-gcc -DHAVE_CONFIG_H -I. -I../../.. -I../../../common -I../../../include -g -Wall -W -Wstrict-pro
3
totypes -D__COMPILING_AVR_LIBC__ -mcall-prologues -Os -x assembler-with-cpp -Wa,-gstabs -D__COMPILIN
4
G_AVR_LIBC__ -c -o eerd_block_at90s1200.o       \
5
    -mmcu=              \
6
    ../../../libc/misc/eerd_block.S
7
cc1.exe: error: missing argument to "-mmcu="
8
make[5]: *** [eerd_block_at90s1200.o] Error 1
9
make[5]: Leaving directory `/c/msys/1.0/avr-libc-1.6.7/avr/lib/avr2'
10
make[4]: *** [all-recursive] Error 1
11
make[4]: Leaving directory `/c/msys/1.0/avr-libc-1.6.7/avr/lib/avr2'
12
make[3]: *** [all-recursive] Error 1
13
make[3]: Leaving directory `/c/msys/1.0/avr-libc-1.6.7/avr/lib'
14
make[2]: *** [all-recursive] Error 1
15
make[2]: Leaving directory `/c/msys/1.0/avr-libc-1.6.7/avr'
16
make[1]: *** [all-recursive] Error 1
17
make[1]: Leaving directory `/c/msys/1.0/avr-libc-1.6.7'
18
make: *** [all] Error 2

Als COnfigure Skrip hab ich das oben schon geschriebene verwendet, auch 
aus dem avr_liibc manual...

Sry, wenn ich zu sehr nerve!!!

von Peter (Gast)


Lesenswert?

Also ich habe bisher auch noch gar nix an irgendwelchen quellen 
verändert! Ich will den Build erwst einmal im Original durchführen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> cc1.exe: error: missing argument to "-mmcu="

Deine Version von GNU-make ist zu alt, du musst eine neuere benutzen
(3.81).

von Peter (Gast)


Lesenswert?

Hach... ich könnt Dich knutschen =)
KLappt, dankeschön =)

von Peter (Gast)


Lesenswert?

Ach Mann, ich könnte heulen...
Also wenn ich make install mache von avr-libc, dann passiert folgendes:

Er legt brav los und maked. Dann irgendwann beim 1500 make schritt, 
kommt ne windows fehlermeldung, dass der arbeitsspeciher belegt wäre, 
dann macht make trotzdem im schneckentempo weiter und dann brichts 
irgendwann ab, wegen ner Fehlermeldung, die irgednwas mit 
sync_with_child zu tun hat und auch irgendwas mit Mem.
Wenn ich im Taskmanager Prozesse anschaue, sehe ich dass wohl jeder make 
und hs.exe schritt nen eigenen Prozess hat, mit ca 1MB Speicher. So 
werden dann wohl schnell die 4GB ram zugemüllt.

Wie gesagt, OS is Windows(!) Version Vista Premium 32-bit...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter schrieb:
> Wenn ich im Taskmanager Prozesse anschaue, sehe ich dass wohl jeder make
> und hs.exe schritt nen eigenen Prozess hat, mit ca 1MB Speicher. So
> werden dann wohl schnell die 4GB ram zugemüllt.

Da kannst du nur mal Eric Weddington fragen, wie er das dann schafft.
Dass Windows nicht sonderlich effizient im Anlegen neuer Prozesse
ist, ist bekannt (unter unixoiden Systemen ist das Anlegen eines
Threads praktisch genauso teuer wie das Anlegen eines Prozesses,
beide werden intern sehr ähnlich gehandhabt).  Aber dass man deshalb
gar nicht mehr compilieren kann, wundert mich schon, auch wenn die
avr-libc zugegebenermaßen ein ziemliches Mammutprojekt ist, was das
Compilieren angeht.

Kann natürlich sein, dass Eric von Windows Vista einfach mal die
Finger gelassen hat und bei XP als Version geblieben ist.

Du könntest noch versuchen, verzeichnisweise zu installieren,
wobei du mindestens die Verzeichnisse "include", "libc" und "libm"
installieren musst (also jeweils mit cd da hinein wechseln und dann
dort »make install« ausführen).

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
Noch kein Account? Hier anmelden.