Forum: Digitale Signalverarbeitung / DSP / Machine Learning ARM GCC Assembler: VMOV.F32 #immediate


von Stephan (Gast)


Lesenswert?

Hallo zusammen,

ich spiele mit dem ARM-Assembler unter DAVE4 für einen Cortex M4f.
Ich versuche mit VMOV eine Konstante zu laden, dabei stoße ich auf 
folgendes Problem:

VMOV.F32  s1, #0.25 // funktioniert!
VMOV.F32  s1, #0.26 // funktioniert nicht!

Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32 
nachbilden lässt.

Gibt es einen Trick, mit dem man dem Assembler mitteilt, dass der die 
nächstmögliche F32-Darstellung der Zahl verwendet?
Ich habe das Manual so interpretiert, dass er das auch ohne zusätzliche 
Anweisung machen würde, tut er aber wohl nicht...
Also habe ich habe nach einer Art Rundungsderektive gesucht, bin aber 
nur auf die gleiche Frage gestoßen.

Wie ist der Trick hierfür?

Gruß Stephan

von Jochen (Gast)


Lesenswert?

Eine immer wieder gern gestellte Frage, aber immer noch sinnvoll: Was 
genau heisst denn, das es "nicht funktioniert"?

von Dr. Sommer (Gast)


Lesenswert?

Stephan schrieb:
> Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32
> nachbilden lässt.
Kleine Pingeligkeit: Es lässt sich überhaupt nicht mit 
Binär-Floating-Point darstellen, egal wie viele Bits ;-) Ist so wie 1/3 
sich nicht mit Dezimalzahlen darstellen lässt, egal wie viele...

von Jochen (Gast)


Lesenswert?

Also, lautet die Analyse so:

1. Die Zahl ist in den Beschränkungen des Assemblers nicht als Float 
darstellbar. +/– n * 2–r,where n and r are integers, 16 <= n <= 31, 0 <= 
r <= 7

2. Der C-Preprozessor ist zwar verwendbar, kann aber nicht mit Floats 
umgehen. Daraus folgt, dass es auch kein Macro geben kann, dass diese 
Rundung durchführt.

Das ist also vermutlich unter "funktioniert nicht" zu verstehen.

Man könnte also allenfalls (das ist nur so eine Idee) der Nachkommateil 
als Integer darstellen und damit was basteln. D.h. aus 0.26 die Zahl 26 
machen und dem Macro noch den Faktor mitgeben (also 100).

Die nächstliegenden Zweierpotenzen sind 64 und 128 - für 0.01; den Teil 
der 1/100 entsprich.

1/64 = 0.0156
1/128 = 0.00781

Die Differenz zu 0.01 ist bei 1/128 geringer. Also nimmt man das.

Voilà.

Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem 
enspricht, was man "programmieren" nennt, erspare ich mir.

von Stephan (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Stephan schrieb:
>> Ich denke, dass es daran liegt, dass sich 0.26 nicht genau mit einem F32
>> nachbilden lässt.
> Kleine Pingeligkeit: Es lässt sich überhaupt nicht mit
> Binär-Floating-Point darstellen, egal wie viele Bits ;-) Ist so wie 1/3
> sich nicht mit Dezimalzahlen darstellen lässt, egal wie viele...

Widerspruch: 1/4, 1/2, 1.0 u.v.m. lassen sich sowohl im Dezimalsystem 
als auch im IEEE-Float32-Format mit einer endlichen Anzahl an Stellen 
exakt abbilden. :-)

Das Problem ist, dass der Assembler die Befehlszeile nicht akzeptiert 
und den Fehler "garbage following instruction" wirft.

Im ARM-Infocenter für den ARM Compiler habe ich die Fußnote
"Any number that can be expressed as +/-n * 2-r, where n and r are 
integers, 16 <= n <= 31, 0 <= r <= 7." gefunden.
Das bestätigt schonmal die Annahme bzgl. der Ursache...

Gibt es bei den GCC keine Hilfsfunktion, die die (fehlerträchtige) 
Konvertierung/Rundung einer Zahl in eine vom Assembler akzeptierte 
Hex/Bin-Darstellung übernimmt?
Der GCC-C-Compiler muss das bei "float32_t K = 0.26" schließlich auch 
vornehmen.

Stephan

von Stephan (Gast)


Lesenswert?

"Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem
enspricht, was man "programmieren" nennt, erspare ich mir."

Du tust gut daran! Davon auszugehen, dass für ein Standardprobleme, die 
sehr fehlerträchtig sein können, die Lösung nicht bereits in dem 
verwendeten Werkzeug vorhanden ist, führt oft zu massiven Fehlern und 
stellt einen nicht unerheblichen Zeitaufwand dar.

von Jochen (Gast)


Lesenswert?

Stephan schrieb:
> "Die Bemerkung, dass, sich sowas auszudenken im wesentlichen dem
> enspricht, was man "programmieren" nennt, erspare ich mir."
>
> Du tust gut daran! Davon auszugehen, dass für ein Standardprobleme, die
> sehr fehlerträchtig sein können, die Lösung nicht bereits in dem
> verwendeten Werkzeug vorhanden ist, führt oft zu massiven Fehlern und
> stellt einen nicht unerheblichen Zeitaufwand dar.

Ja, ja, Meister. Du hast nur gefragt, weil Du Langeweile hattest. Schon 
klar.

von Stephan (Gast)


Lesenswert?

Für alle, die diesen Beitrag irgendwann mal ausgraben:

Const_1: .float 0.26
...
VLDR.32     s1, Const_1

Hier wird der Wert der Konstante zwar aus dem Speicher geladen und nicht 
als Immediate, dafür bleibt der Quellcode gut lesbar; man muss nicht mit 
den Hex-Darstellungen der Floats hantieren.
http://infocenter.arm.com/help/topic/com.arm.doc.dui0553a/CHDICEDI.html

Der Assembler des ARM-Toolchains für NEON kennt eine gleichnamige 
Pseudo-Anweisung

VLDR.32     s0,=const

die (falls möglich) in eine einzelne VMOV-Anweisung übersetzt wird.
http://infocenter.arm.com/help/topic/com.arm.doc.dui0489f/CIHGGHHA.html

Der GCC-Assembler von DAVE4 scheint dies nicht zu tun. Unabhägig vom 
Wert der Konstanten wurde bei mir

VLDR.32     s0,=const (Quelltext)

stets in

vldr s0, [r0]

übersetzt.

Evtl. hilft es jemand...

Gruß Stephan

von Sascha (Gast)


Lesenswert?

Danke Stefan,
vor vielen Jahren habe ich die FPU auch zum ersten mal eingesetzt und 
muste auch feststellen, dass nicht jede Zahl als direkte Angabe 
funktioniert.
Mann muss nur in der Dokumentation bei ARM nachlesen, dann sieht man 
sofort, das es sehr eingeschränkt ist.
Also bleibt nur das laden eines Prozessorregister in ein FPU-Register 
oder die elegantere Art, die Stefan zeigt übrig. Das indirekte laden 
PC+rel ist durchaus sehr gut.
Nur nicht vergessen, irgendwo müssen die Daten dann auch im ROM sein.
deshalb am Ende der Routine noch ein .LTORG setzen, ab da werden dann 
die Daten gespeichert.

Übrigens finde ich die FPU sehr gelungen, auch für DSP übrigens spitze 
zu verwenden.

Werde mal diese Woche die FPU eines CM7 von ST mit 64 Bit ausprobieren. 
Mal sehen wie schnell die ist?

Gruß Sascha

FPU in Assembler ist einfach wie ein Gedicht....

von Sascha (Gast)


Lesenswert?

Sorry Stephan, ist keine Absicht habe deinen Namen falsch geschrieben.

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.