www.mikrocontroller.net

Forum: Compiler & IDEs GCC Funktionen "umbiegen"


Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich benutze eine Nios2-System mit einem Coprozessor-Modul. Dabei will 
ich jetzt bestimmte Funktionen, zb eine double-Multiplikation so 
verbiegen, dass nicht mehr die Software-Routinen aufgerufen werden, 
sondern eine von mir zu schreibende Funktion, die den Coprozessor 
verwendet.
Das ganze soll für den Benutzer transparent sein, so dass im Code weiter 
c=a*b geschrieben werden kann.
Leider habe ich dazu nirgends etwas gefunden.

Ich wäre für einen Ansatzpunkt sehr dankbar!

Gruss, Andreas

p.s. Meine ursprüngliche Idee, einfach den * Operator zu überladen geht 
nicht, weil ich nur neue Funktionen hinzufügen darf aber vorhandene 
nicht neu definieren. Jedenfalls soweit ich das verstanden habe, kann 
mir das jemand bestätigen?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die sauberste Variante wäre es natürlich, das dem GCC richtig zu
sagen und einen eigenen Port davon anzufertigen.

Je nachdem, wie viel davon in RTL implementiert ist und wie viel in
Hilfsfunktionen, kannst du zumindest die Hilfsfunktionen einfach
durch deine eigenen überladen (die werden sonst aus der libgcc.a
gelinkt).  Wenn aber Dinge wie die Grundrechenarten direkt in RTL
implementiert sind, dann generiert der Compilerpass letzlich die
dafür notwendigen Assembleranweisungen intern, da kannst du nichts
mehr reinklinken.

Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein eigener Port von GCC kommt eigentlich nicht in Frage, da ich dann 
bei jedem Update seitens Altera die neue GCC-Version wieder anpassen 
muss. Daher sollte das möglichst unabhängig davon sein.

Die Hardware hat keine FPU, und der Compiler weiss momentan nichts 
davon. Jegliche float und double Operationen werden somit aus der 
libgcc.a geholt.

Was ich brauche ist irgend eine Methode, damit der Compiler automatisch 
aus c = a*b eine Funktion c = fmul(a,b) aufruft. Darin kümmere ich mich 
dann um die Multiplikation und gebe das Ergebnis zurück. Leider ist mir 
völlig unklar, wie ich diesen Schritt bewerkstelligen soll.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AG wrote:

> Jegliche float und double Operationen werden somit aus der
> libgcc.a geholt.

Dann kannst du stattdessen deine eigenen in einer Bibliothek
hinterlegen.  Da deine Bibliothek vor der libgcc.a gelinkt wird,
werden die darin enthaltenen Funktionen benutzt.

Die Namen dieser Funktionen sind etwas kryptisch, aber die
Bildungsregel sollte irgendwo in der GCC-Doku stehen.

Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok, hört sich sinnvoll an.

Für die double Addition sollte die entsprechende Funktion aus der 
libgcc.a __adddf3 sein.

Diese Funktion habe ich jetzt mit einer .h und .c Datei nue definiert. 
Nicht ganz unüberassched beschwert sich jetzt der Linker, dass die 
Funktion schon vorhanden ist:
Linking hello_world_0.elf...
/cygdrive/c/altera/72/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/
   mcustom-fpu-cfg=60-2//libgcc.a(_addsub_df.o)(.text+0x330): In function `__adddf3':
/build/nios2eds-gnutools-win32-7.2/bin/nios2-gnutools/src/gcc/gcc/config/nios2/nios2-dp-bit.c:731: 
   multiple definition of `__adddf3'
obj/dpfpu.o(.text+0x0):../dpfpu.c:15: first defined here
/cygdrive/c/altera/72/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/
   ../../../../nios2-elf/bin/ld: Warning: size of symbol `__adddf3' changed from 84 in obj/dpfpu.o
   to 108 in /cygdrive/c/altera/72/nios2eds/bin/nios2-gnutools/H-i686-pc-cygwin/bin/../lib/gcc/nios2-elf/3.4.1/
   mcustom-fpu-cfg=60-2//libgcc.a(_addsub_df.o)
collect2: ld returned 1 exit status

Wie umgehe ich das Problem? Muss ich dazu eine .a Datei erzeugen und das 
dem Compiler mitteilen?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Modul, der aus der libgcc.a gelinkt wird, heißt _addsub_df.o.
Das suggeriert, dass er noch weitere Symbole außer __adddf3 enthält.
Offensichtlich wurde der Modul aus der libgcc.a reingezogen, da eins
der weiteren Symbole noch nicht definiert war.  Bei dieser Gelegenheit
hat er aber die Doppeldefinition für __adddf3 mit eingeschleppt.

Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Heisst das, dass ich alle Funktionen, die in der _addsub_df.o drin sind 
in meine eigenen Library auch einbauen muss?

nm -a _addsub_df.o liefert mir folgende Ausgabe:
00000000 b .bss
00000000 n .comment
00000000 d .data
00000000 N .debug_abbrev
00000000 N .debug_aranges
00000000 N .debug_frame
00000000 N .debug_info
00000000 N .debug_line
00000000 N .debug_pubnames
00000000 N .debug_ranges
00000000 N .debug_str
00000000 t .text
00000330 T __adddf3
         U __negdi2
         U __pack_d
0000039c T __subdf3
         U __thenan_df
         U __unpack_d
00000000 t _fpadd_parts
00000000 a nios2-dp-bit.c

Langsam glaube ich, dass es doch einfacher wäre, die libgcc.a zu patchen 
und neu zu kompilieren. Nur konnte ich durch trotz langem Suchen bisher 
nicht herausfinden, welches die Quellen sind, aus denen diese Datei 
compiliert wird.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
AG wrote:

> Heisst das, dass ich alle Funktionen, die in der _addsub_df.o drin sind
> in meine eigenen Library auch einbauen muss?

Ja.

> nm -a _addsub_df.o liefert mir folgende Ausgabe:
>
>
> 00000000 b .bss
> 00000000 n .comment
> 00000000 d .data
> 00000000 N .debug_abbrev
> 00000000 N .debug_aranges
> 00000000 N .debug_frame
> 00000000 N .debug_info
> 00000000 N .debug_line
> 00000000 N .debug_pubnames
> 00000000 N .debug_ranges
> 00000000 N .debug_str
> 00000000 t .text
> 00000330 T __adddf3
>          U __negdi2
>          U __pack_d
> 0000039c T __subdf3
>          U __thenan_df
>          U __unpack_d
> 00000000 t _fpadd_parts
> 00000000 a nios2-dp-bit.c
> 

Das macht dann (wie der Name des Moduls erwarten ließe) außer __adddf3
nur noch __subdf3, was du da mit reinpacken musst.  _fpadd_parts ist
eine interne (static) Funktion, die von den anderen beiden nur in
der libgcc-Implementierung benutzt wird, und die Us sind global
undefined, d. h. Referenzen auf andere Funktionen.

Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, mittlerweile funktionierts genau so wie ich mir das gewünscht habe. 
Zuerst mal herzlichen Dank an Jörg für die kompetente Hilfe!

Folgende Schritte waren nötig:

.h und .c Datei mit den Funktionen erzeugen, die ersetzt werden sollen. 
Die dazugehörigen Namen sind in den GCC Internals (Datei gccint.info 
oder hier: http://stderr.org/doc/gcc-4.2-doc/gccint.html, 4.2 Routines 
for floating point emulation) zu finden. In meinem Fall sind dies:
double __adddf3 (double, double);
double __subdf3 (double, double);
double __muldf3 (double, double);
double __divdf3 (double, double);

Zu beachten ist hierbei, dass die Funktionen in der libgcc.a in mehreren 
.o Dateien verteilt sind. Es müssen immer alle Funktionen, die in einer 
bestimmten .o Datei drin sind, ersetzt werden.
Dazu:
- mit ar die .o Dateien aus der libgcc.a auspacken
- mit nm (siehe oben) die Funktionen in der relevanten .o Datei anzeigen

Infos hierzu sind auch in 
http://www.network-theory.co.uk/docs/gccintro/index.html zu finden.

Beim ausprobieren ist noch darauf zu achten, dass die ersetzten Sachen 
auch von anderen (System-) Routinen aufgerufen werden, so gibt zum 
Beispiel printf nur Müll aus wenn man die double Addition zu a+b = a 
umdefiniert :-)

Andreas

Autor: Martin Cibulski (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

könnte man so dem AVRGCC echtes double-Format (64 bit) beibringen ?

Zusätzlich müsste man dem GCC noch sagen, dass double 64 bit lang ist.
Wo kann man das machen ?

Hintergrund meiner Frage ist, dass ich eine ASM-Bibliothek für 64 bit 
double auf dem AVR geschrieben habe, diese aber bisher nur in Assembler 
nutzen kann.

Gruß,
Martin

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nm kann übrigens auch direkt auf .a-Archiven arbeiten.

Autor: AG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> könnte man so dem AVRGCC echtes double-Format (64 bit) beibringen ?

Ich vermute (ohne es zu wissen), dass der double auch beim AVRGCC 64 bit 
hat, nur die Rechenoperationen in der Library nur 32bit rechnen.

Wenn das tatsächlich so ist, kannst du mit der Beschreibung oben die 
entsprechenden Funktionen abfangen und durch deinen Assembler-Code 
ersetzen. Ich würds einfach mal ausprobieren, du kannst in der Funktion 
ja auch Ausgabe statt ner Addition implementieren und damit dann einfach 
mal nachschauen ob 32 oder 64 bit ankommen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin Cibulski wrote:

> könnte man so dem AVRGCC echtes double-Format (64 bit) beibringen ?

Nein, das braucht auch schon noch ein wenig RTL-Code.  Das erklärt
dann auch die Frage, wo man dem Compiler sagt, wie groß die Typen
sind.  Der größere Anteil an Code steckt aber ganz sicher in der
libgcc, keine Frage.

Außerdem braucht es schließlich noch jemanden, der dafür eine libm.a
zimmert

Aber nur zu!  Wir suchen schon lange jemanden, der sich des Themas
mal annimmt.  Falls jemand ernsthaft die Absicht hat, würde ich ihm
erstens raten, sich auf der avr-gcc-list einzutragen (dort lesen
zumindest alle diejenigen noch mit, die in den letzten Jahren irgend-
was am AVR-Teil des GCC gezimmert haben) und zweitens nicht zu spät
damit zu beginnen, die Copyright-Übertragung an die FSF in die Wege
zu leiten, da die FSF darauf besteht und das Ganze nur mit Sackpost
erledigt werden kann.  (Die ist für unserereinen ansonsten komplett
gegenstandslos, da man als Deutscher das Copyright sowieso niemandem
übertragen kann...)

Wenn sich das jemand ernsthaft auf die Fahnen schreibt, würde ich
übrigens für eine Lösung wie bei -mint8 plädieren: der Default sollte
sizeof(double) = 8 werden (weil nur das konform mit dem C99-Standard
geht), aber es sollte eine Option, nennen wir sie -mdouble32, geben,
die dem Compiler mitteilt, den Code wie bisher zu generieren.  Die
ausgelieferten Makefile-Templates könnten diese Option dann standard-
mäßig mit auswählen, damit sich gegenüber dem bisherigen Verhalten
nichts ändert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.