Kiedy kompiluję kod C z moim krzyżowym toolchainem, linker drukuje strony z ostrzeżeniami mówiącymi, że mój plik wykonywalny używa hard floats, ale mój libc używa soft floats. Co za różnica?Jaka jest różnica pomiędzy liczbami zmiennoprzecinkowymi twardymi i miękkimi?
Odpowiedz
Twarde pływaki używają jednostki zmiennoprzecinkowej na chipie. Soft floats emulują jeden w oprogramowaniu. Różnica polega na szybkości. Dziwne jest to, że obie są używane w tej samej docelowej architekturze, ponieważ chip ma albo jednostkę FPU, albo nie. Możesz włączyć miękki zmiennoprzecinkowy w GCC za pomocą -msoft-float. Możesz chcieć przekompilować swoją bibliotekę libc, aby używać sprzętowego punktu zmiennoprzecinkowego, jeśli go używasz.
"Dziwnie jest widzieć oba używane w tej samej docelowej architekturze" Może to mieć sens dla biblioteki być niezależnym od maszyny i dokładnym bitem (miękki pływak) w częściach o dużej dokładności i szybkich (twarde pływaki) w częściach, w których małe odchylenia nie mają znaczenia. – PhilLab
Wygląda na to, że twoja biblioteka libc została zbudowana dla operacji zmiennoprzecinkowych w oprogramowaniu, podczas gdy twój exe został skompilowany przy założeniu obsługi sprzętu dla zmiennoprzecinkowej. W krótkim okresie można wymusić miękkie pływaki jako flagę kompilatora. (jeśli używasz gcc, myślę, że to -msoft-float)
Dłuższy okres, jeśli procesor twojego celu ma sprzętową obsługę operacji zmiennoprzecinkowych, zazwyczaj chcesz zbudować lub znaleźć krzyżowy zestaw narzędzi z włączonym spławem sprzętowym dla prędkość. Niektóre rodziny procesorów mają warianty modeli, niektóre z nich, a niektóre bez wsparcia sprzętowego. Na przykład, po prostu mówienie, że twój procesor jest ARM jest niewystarczające, aby wiedzieć, czy masz sprzętową obsługę zmiennoprzecinkowej.
Istnieją trzy sposoby, aby zrobić zmiennoprzecinkowych arytmetycznych:
- instrukcjach użyto pływak jeśli procesor posiada FPU. (szybki)
- Niech twój kompilator przetłumaczy arytmetykę zmiennoprzecinkową na arytmetykę całkowitą. (powolny)
- Używaj instrukcji pływaka i procesora bez FPU. Twój procesor wygeneruje wyjątek (instrukcja zarezerwowana, instrukcja niezaimplementowana lub podobne), a jeśli jądro systemu operacyjnego zawiera emulator zmiennoprzecinkowy, będzie emulować te instrukcje (najwolniej).
Obliczenia można wykonać za pomocą sprzętu zmiennoprzecinkowego lub oprogramowania opartego na arytmetyce całkowitej.
Robiąc to w sprzęcie jest znacznie szybciej, ale wiele mikrokontrolerów nie ma sprzętu zmiennoprzecinkowego. W takim przypadku możesz albo unikać używania zmiennoprzecinkowego (zwykle najlepsza opcja), albo polegać na implementacji w oprogramowaniu, które będzie częścią biblioteki C.
W niektórych rodzinach kontrolerów, na przykład ARM, sprzęt zmiennoprzecinkowy występuje w niektórych modelach rodziny, ale nie w innych, więc gcc dla tych rodzin obsługuje oba. Twój problem polega na tym, że pomieszałeś dwie opcje.
Ściśle mówiąc, wszystkie te odpowiedzi wydają mi się błędne.
Kiedy kompiluję kod C za pomocą mojego krzyżowego toolchaina, linker drukuje strony z ostrzeżeniami mówiącymi, że mój plik wykonywalny używa hard floats, ale mój libc używa soft floats. Co za różnica?
Debian VFP wiki posiada informacje na temat trzech opcji dla -mfloat-abi
,
soft
- to czysta oprogramowaniesoftfp
- ten obsługuje FPU sprzętu, ale ABI jest miękka kompatybilne.hard
- ABI używa rejestrów float lub VFP.
Błąd łącznika (modułu ładującego) wynika z tego, że masz wspólną bibliotekę, która będzie przekazywać wartości zmiennoprzecinkowe w rejestrach całkowitych. Nadal możesz skompilować swój kod za pomocą -mfpu=vfp
, itp., Ale powinieneś użyć -mfloat-abi=softfp
, więc jeśli libc potrzebuje float, jest przekazywany w sposób zrozumiały dla biblioteki.
Jądro Linux może obsługiwać emulację instrukcji VFP. Oczywiście lepiej jest skompilować ten kod z -mfpu=none
i mieć kompilator bezpośrednio generujący kod, zamiast polegać na emulacji jądra Linuksa. Uważam jednak, że błąd PO nie jest w rzeczywistości związany z tym problemem. Jest oddzielny i należy go również załatwić razem z -mfloat-abi
.
Armv5 shared library with ArmV7 CPU jest przeciwieństwem tego; the libc był trudny, ale aplikacja była tylko miękka. Jest kilka sposobów na obejście problemu, ale rekompilacja z odpowiednimi opcjami jest zawsze najłatwiejsza.
Inną kwestią jest to, że jądro Linux musi obsługiwać zadania VFP (lub dowolny inny zmienny punkt ARM), aby zapisać/przywrócić rejestry w przełączniku kontekstu.
Nowoczesne wersje GCC (~ 4.8 +) obsługują "multi-lib", które mają biblioteki twarde i miękkie. Wcześniejsze wersje wymagały kompilatora zbudowanego w określonej wersji. Czasami ścieżka do właściwej biblioteki jest potrzebna podczas łączenia z dystrybucją gcc "multi-lib", ponieważ istnieje kilka wersji bibliotek (wymagające dłuższego czasu na kompilację). Nazwy katalogów mogą mieć postać "hf", "hardf", "libhf" lub "hard-float", ale zwykle znajdują się pod zwykłym "miękkim" katalogiem lub w pobliżu. –
To jest właściwa odpowiedź. Konwersja wywołań dla elementów pływających musi pasować do kodu i biblioteki libc. Może nadal działać z niedopasowaniem, jeśli nigdy nie będziesz wywoływał żadnych funkcji zmiennoprzecinkowych libc. –
- 1. assert_eq! z liczbami zmiennoprzecinkowymi i deltami
- 2. Jaka jest różnica pomiędzy $ (this) i to
- 3. Jaka jest różnica pomiędzy Cp i -classpath
- 4. Jaka jest różnica pomiędzy $ .each (selektor) i $ (selektor) .each()
- 5. Jaka jest różnica pomiędzy poleceniami Döcker: biegać, budować i tworzyć
- 6. Jaka jest różnica pomiędzy skrzyniami "serializuj" i "rustc-serialize"?
- 7. Jaka jest różnica pomiędzy rzutem (void *) i (void (*) (typ argumentu))?
- 8. Jaka jest różnica pomiędzy $ (document) .ready (function() i $ (function()
- 9. jaka jest różnica pomiędzy $ _ENV, $ _SESSION i $ _COOKIE
- 10. Jaka jest dokładna różnica pomiędzy stanami MEM_RESERVE i MEM_COMMIT?
- 11. Jaka jest różnica pomiędzy realizacją i skompilować w Gradle
- 12. Jaka jest różnica między USUŃ i USUŃ?
- 13. Różnica pomiędzy * i + regex
- 14. Jaka jest różnica pomiędzy wartością lub Promise.resolve powracającego z potem()
- 15. Jaka jest różnica pomiędzy zmienną a @zmienna w MySQL
- 16. Jaka jest różnica pomiędzy poziomami śledzenia ALL & DEBUG w LOG4NET
- 17. Jaka jest różnica pomiędzy komórkami statycznymi a dynamicznymi prototypami?
- 18. Jaka jest różnica między? : i ||
- 19. Jaka jest różnica między $ i $$?
- 20. Różnica pomiędzy MKOl wiosennym i wiosennym AOP
- 21. Różnica pomiędzy + i - metody w Objective-C
- 22. JavaScript Random Integer Pomiędzy dwoma liczbami
- 23. jquery - różnica pomiędzy $ .functionName i $ .fn.FunctionName
- 24. Jaka jest różnica między "mutex" i "lock"?
- 25. różnica pomiędzy wybrać i gdzie w LINQ
- 26. Różnica pomiędzy AVX instrukcji vxorpd i vpxor
- 27. Regex usunąć spacje pomiędzy liczbami tylko
- 28. Różnica pomiędzy "100" i "100px" html
- 29. Jaka jest różnica między ścieżki i drogi w pliku GPX
- 30. jaka jest różnica między dodawaniem i [] w operacjach słownikowych
Jeśli jest to architektura ARM, proszę umieścić to w tagach :-) –
@Nils Pipenbrinck: Chipy MIPS również mają ten problem – Javier