Forum: Compiler & IDEs Verdacht auf GCC / Library Fehler ARM - Toolchain


von Thilo H. (thaala)


Lesenswert?

Hallo Forum,

ich habe auf dem Bugzilla - Howto vom GCC gelesen, das die meisten 
falsch gemeldeten Fehler zum Thema GCC im zusammenhang mit 
Fließkommazahlen gemacht werden. Damit gemeint sind Beobachtungsfehler, 
Rundungsfehler usw.

Ich möchte gerne vermeiden als Idiot dazustehen und hätte gerne zuerst 
eure Meinung dazu.

Ich nutze das STM32F4 - Discovery Board zu Testzwecken und versuche nun 
die FPU einzubinden:
1
main {
2
   int32_t maxY;
3
   double base_y;
4
5
   init_fpu();
6
7
   base_y = 168.0;
8
   maxY = (int32_t)base_y;
9
....
10
}

leider enthält die Variable maxY den Wert 0 statt 168.

Disassembly der Zeile "maxY = (int32_t)base_y;":

    08028f5c:   vldr d0, [sp, #40]      ; 0x28
    08028f60:   bl 0x8000a40 <__fixdfsi>

Ohne Nutzung der FPU:
    08029de2:   ldrd r0, r1, [sp, #40]  ; 0x28
    08029de6:   bl 0x8000a40 <__fixdfsi>

Getestet habe ich es bisher mit den drei mir bekannten Toolchains:
Codesourcery, Yagarto und Germia.

Ich habe es mit dem Betriebssystem Chibios versucht, als auch mit der 
BlinkLED - Demo - App von MMVisual.

Hier das Topic bei Chibios-Support:
http://forum.chibios.org/phpbb/viewtopic.php?f=2&t=337

Immer mit dem gleichen negativen Ergebnis.

FPU - CompilerOtionen:
-ggdb -fomit-frame-pointer -falign-functions=16 -mhard-float 
-mfpu=fpv4-sp-d16 -fsingle-precision-constant
MCU = cortex-m4

Was sagt Ihr ?
Könnt Ihr den Fehler nachvollziehen ?
Gibt es sonstige Hints - z.B. doubles darfst du nicht verwenden o.Ä. ?

gruß Thilo

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Der Code, d.g. die jeweils 2 Zeilen Disassembly sehen doch gut aus. Der 
Fehler ist also entweder hier:

> ....

oder in der Verwendung/Configury der Tools.

Und wiese "negatives Ergebnis": Wieso ist 0 negativ?

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:

> Der Code, d.g. die jeweils 2 Zeilen Disassembly sehen doch gut aus.

Vorausgesetzt er erwischt die richtige Lib, und damit eine 
Implementierung der Funktion __fixdfsi, die den Parameter in D0/D1 statt 
R0/R1 erwartet.

Im anderen Thread schreibt er allerdings

"this lib function is linked from Codesourcery (both variant use same 
library)
__fixdfsi 
d:/winarm/sourcery_codebench_lite_for_arm_eabi/bin/../lib/gcc/arm-none-e 
abi/4.6.1/thumb2\libgcc.a(_arm_fixdfsi.o)"

und das kann natürlich nicht funktionieren.

von (prx) A. K. (prx)


Lesenswert?

Johann L. schrieb:

> Und wiese "negatives Ergebnis": Wieso ist 0 negativ?

Manchmal ist sogar negativ = positiv. Wenn das eine der Laborbefund beim 
Arzt ist und das andere die Stimmung des Patienten nachher. ;-)

von Thilo H. (thaala)


Lesenswert?

Hallo Helfer,

>>> Und wiese "negatives Ergebnis": Wieso ist 0 negativ?
ich meine wenn man den Wert 168 erwartet und 0 kommt raus - ist das 
negativ.

library) __fixdfsi 
d:/winarm/sourcery_codebench_lite_for_arm_eabi/bin/../lib/gcc/arm-none-e 
abi/4.6.1/thumb2\libgcc.a(_arm_fixdfsi.o)"
>>> und das kann natürlich nicht funktionieren.

warum sagst Du das ?
meinst du den Thumb2 - Befehlssatz ?

Wer ist verantwortlich für die Auswahl der "richtigen" libs ?
Ich war der Ansicht, dass der Linker gesteuert wird über die 
Command-line switches..... Insbesondere der -mhard-float 
-mfpu=fpv4-sp-d16 müsste doch die Verwendung der FPU - Libs 
"einschalten".
Liege ich da falsch ?

>>> Vorausgesetzt er erwischt die richtige Lib, und damit eine
>>> Implementierung der Funktion __fixdfsi, die den Parameter in D0/D1
>>> statt R0/R1 erwartet.
D0 ist die 64 Bit Bezeichnung der zuammengefassten 32-Bit FPU Register 
S0 und S1. Davon gibt es dann 16 Stück.... D0 ist also ein Äquivalent zu 
R0/R1

Klar muss __fixdfsi zur Verwendung von "vldr d0, [sp, #40]" passen, 
evtl. könnt Ihr mir ja mal ein paar command line switches nennen, die 
mehr Auskunft über die verwendeten Libs geben ?

Danke im voraus.
Gruß Thilo

von (prx) A. K. (prx)


Lesenswert?

Thilo Haala schrieb:

> Liege ich da falsch ?

Vermutlich schon, das steuert m.W. nur die Codegenerierung des 
Compilers, nicht aber die Auswahl der Library.

> D0 ist die 64 Bit Bezeichnung der zuammengefassten 32-Bit FPU Register
> S0 und S1.

Ok.

> Davon gibt es dann 16 Stück.... D0 ist also ein Äquivalent zu
> R0/R1

Nur ist R0 nicht identisch mit S0, d.h. mit VLDR landet der Parameter in 
FPU-Register(n) und mit LDRD in Integer-Registern.

von (prx) A. K. (prx)


Lesenswert?

Probiers mal mit -mfloat_abi=softfp statt -mhard-float. FPU Support 
gibts damit trotzdem, aber die Aufrufkonvention entspricht dann Soft-FP 
und __fixdfsi wird korrekt aufgerufen.

von Thilo H. (thaala)


Lesenswert?

>>> Probiers mal mit -mfloat_abi=softfp statt -mhard-float. FPU Support
hab ich gemacht.
Gerechnet wir richtig, aber FPU - Support scheint weg zu sein.
1
    dy = 168.0;
2
    fx = (float)dy;
3
    dy = 202.0;
4
    double d = dy * fx;
5
    intx = (int)fx;
6
    inty = (int)dy;
7
    intz = (int)d;

heraus kommt:
1
08029bb2:   add r3, pc, #404        ; (adr r3, 0x8029d48 <main+424>)
2
08029bb4:   ldrd r2, r3, [r3]
3
08029bb8:   strd r2, r3, [sp, #64]  ; 0x40
4
08029bbc:   ldrd r0, r1, [sp, #64]  ; 0x40
5
08029bc0:   bl 0x8000a90 <__truncdfsf2>
6
08029bc4:   mov r3, r0
7
08029bc6:   str r3, [sp, #60]       ; 0x3c
8
08029bc8:   add r3, pc, #388        ; (adr r3, 0x8029d50 <main+432>)
9
08029bca:   ldrd r2, r3, [r3]
10
08029bce:   strd r2, r3, [sp, #64]  ; 0x40
11
08029bd2:   ldr r0, [sp, #60]       ; 0x3c
12
08029bd4:   bl 0x8000458 <__extendsfdf2>
13
08029bd8:   mov r2, r0
14
08029bda:   mov r3, r1
15
08029bdc:   mov r0, r2
16
08029bde:   mov r1, r3
17
08029be0:   ldrd r2, r3, [sp, #64]  ; 0x40
18
08029be4:   bl 0x8000500 <__muldf3>
19
08029be8:   mov r2, r0
20
08029bea:   mov r3, r1
21
08029bec:   strd r2, r3, [sp, #48]  ; 0x30
22
08029bf0:   vldr s15, [sp, #60]     ; 0x3c
23
08029bf4:   vcvt.s32.f32 s15, s15
24
08029bf8:   vmov r3, s15
25
08029bfc:   str r3, [sp, #44]       ; 0x2c
26
08029bfe:   ldrd r0, r1, [sp, #64]  ; 0x40
27
08029c02:   bl 0x8000a40 <__fixdfsi>
28
08029c06:   mov r3, r0
29
08029c08:   str r3, [sp, #40]       ; 0x28
30
08029c0a:   ldrd r0, r1, [sp, #48]  ; 0x30
31
08029c0e:   bl 0x8000a40 <__fixdfsi>

da ist noch nicht einmal ein fpu - register mehr im Spiel...

Heiße Frage - wie kann ich die Verwendung der Libs steuern ?
Gruß,
Thilo

von Thilo H. (thaala)


Lesenswert?

Korrektur:

irgendwas hab ich übersehen:
1
08029bf0:   vldr s15, [sp, #60]     ; 0x3c
2
08029bf4:   vcvt.s32.f32 s15, s15
3
08029bf8:   vmov r3, s15

is das nun meine Multiplikation ?

von (prx) A. K. (prx)


Lesenswert?

Thilo Haala schrieb:

> 08029bf0:   vldr s15, [sp, #60]     ; 0x3c
> 08029bf4:   vcvt.s32.f32 s15, s15
> 08029bf8:   vmov r3, s15

> da ist noch nicht einmal ein fpu - register mehr im Spiel...

Ach nee...

Was hast du denn erwartet? Dass die single precision FPU deines CM4 auf 
einmal Flügel kriegt und zu einer double precision FPU wird? In deinem 
Code ist m.E. exakt eine reine single precision Operation drin und die 
wurde auch in FPU-Befehle umgesetzt.

> Heiße Frage - wie kann ich die Verwendung der Libs steuern ?

Sinnlos, gibt im CS keine Lib für 64-Bit Softfloat und 32-Bit Hardfloat. 
Ich hatte da noch irgendwelche früheren ARM Compiler-Packages mit einem 
Dutzend Libs für alle Varianten von Byteorder und FP-Support in 
Erinnerung.

von (prx) A. K. (prx)


Lesenswert?

Thilo Haala schrieb:

> is das nun meine Multiplikation ?

Nö. Das ist
  intx = (int)fx;

Deine Multiplikation ist das da, erst wird fx zu double konvertiert, 
dann mit Laufzeitfunktion in double precision multipliziert:

08029bd2:   ldr r0, [sp, #60]       ; 0x3c
08029bd4:   bl 0x8000458 <__extendsfdf2>
08029bd8:   mov r2, r0
08029bda:   mov r3, r1
08029bdc:   mov r0, r2
08029bde:   mov r1, r3
08029be0:   ldrd r2, r3, [sp, #64]  ; 0x40
08029be4:   bl 0x8000500 <__muldf3>
08029be8:   mov r2, r0
08029bea:   mov r3, r1
08029bec:   strd r2, r3, [sp, #48]  ; 0x30

Wenn du die FPU nutzen willst, dann nimm "float". Durchgängig. Bei 
"double" besteht effektiv kein Unterschied zwischen deinem CM4 und einem 
CM3 ohne FPU, du kriegst die gleichen Softfloat Operationen.

von Thilo H. (thaala)


Lesenswert?

Hallo prx,

is ja gut... hau doch nicht gleich so auf mich ein...8-)
Ich hatte ja Eingangs gefragt ob man in diesem Kontext überhaupt 
"double" verwenden darf.

als kleine Abwandlung:
1
    dy = 168.0;
2
    fx = (float)dy;
3
    dy = 202.0;
4
    float d = (float)dy * fx;
5
    intx = (int)fx;
6
    inty = (int)dy;
7
    intz = (int)d;

der hier entstandene Code gibt Dir Recht:
1
08029bb2:   add r3, pc, #396        ; (adr r3, 0x8029d40 <main+416>)
2
08029bb4:   ldrd r2, r3, [r3]
3
08029bb8:   strd r2, r3, [sp, #56]  ; 0x38
4
08029bbc:   ldrd r0, r1, [sp, #56]  ; 0x38
5
08029bc0:   bl 0x8000a90 <__truncdfsf2>
6
08029bc4:   mov r3, r0
7
08029bc6:   str r3, [sp, #52]       ; 0x34
8
08029bc8:   add r3, pc, #380        ; (adr r3, 0x8029d48 <main+424>)
9
08029bca:   ldrd r2, r3, [r3]
10
08029bce:   strd r2, r3, [sp, #56]  ; 0x38
11
08029bd2:   ldrd r0, r1, [sp, #56]  ; 0x38
12
08029bd6:   bl 0x8000a90 <__truncdfsf2>
13
08029bda:   vmov s14, r0
14
08029bde:   vldr s15, [sp, #52]     ; 0x34
15
08029be2:   vmul.f32 s15, s14, s15
16
08029be6:   vstr s15, [sp, #48]     ; 0x30
17
08029bea:   vldr s15, [sp, #52]     ; 0x34
18
08029bee:   vcvt.s32.f32 s15, s15
19
08029bf2:   vmov r3, s15
20
08029bf6:   str r3, [sp, #44]       ; 0x2c
21
08029bf8:   ldrd r0, r1, [sp, #56]  ; 0x38
22
08029bfc:   bl 0x8000a40 <__fixdfsi>

Danke für deine Mühe.
Offensichtlich ist der Switch -mfloat_abi=softfp die Lösung des 
Problems.
Unabhängig davon ob die FPU genutzt wird oder nicht sollte das richtige 
Ergebins ja schon rauskommen...

Gruß Thilo

von (prx) A. K. (prx)


Lesenswert?

Thilo Haala schrieb:

> is ja gut... hau doch nicht gleich so auf mich ein...8-)

Sorry, passiert manchmal.

> Ich hatte ja Eingangs gefragt ob man in diesem Kontext überhaupt
> "double" verwenden darf.

Dürfen schon. Hat aber Konsequenzen.

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.