Binary, do you use Hard-Float or Soft-Float?

Many cost-sensitive ARM Cortex-M devices like the M0+ do not have a hardware floating point unit, and some like the M4 only has an optional single-precision floating point unit (FPU). As outlined in “Be aware: Floating Point Operations on ARM Cortex-M4F“, using floating point operations without a hardware unit can be costly.

Looking at the disassembly for sure will tell you if the hardware is handling the float or double operation or not:

Disassembly showing runtime routines

But who wants check the all the disassembly? With the GNU tools there is an easier way: readelf.

Readelf

readelf‘ or ‘arm-none-eabi-readelf’ is part of the GNU binutils and part of the ARM GNU toolchain. It displays information about ELF object files. I’m using here the following version:

GNU readelf (Arm GNU Toolchain 12.3.Rel1 (Build arm-12.35)) 2.40.0.20230627

This version has the option -A

-A --arch-specific Display architecture specific information (if any)

This option checks the binary and tells me if any hardware is used for floating point operation. For example for an ARM Cortex-M0+ (LPC845) which does not have any ARM FPU hardware shows this:

readelf -A AEMBS_LPC845.axf
Attribute Section: aeabi
File Attributes
Tag_CPU_name: "6S-M"
Tag_CPU_arch: v6S-M
Tag_CPU_arch_profile: Microcontroller
Tag_THUMB_ISA_use: Thumb-1
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: small
Tag_ABI_optimization_goals: Prefer Speed

The Tag_ABI_FP_number_model tells that it is using the standard IEEE 754 format.

Running it on a ARM Cortex M4F (Kinetis K22) with single precision FPU shows this:

Attribute Section: aeabi
File Attributes
Tag_CPU_name: "7E-M"
Tag_CPU_arch: v7E-M
Tag_CPU_arch_profile: Microcontroller
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: VFPv4-D16
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_enum_size: small
Tag_ABI_HardFP_use: SP only
Tag_ABI_VFP_args: VFP registers
Tag_ABI_optimization_goals: Aggressive Debug
Tag_CPU_unaligned_access: v6

The one we are looking for is this:

  Tag_ABI_HardFP_use: SP only

It tells that the hardware is only used for single precision (SP) floating point.

Finally, below an example of a Cortex-M7 with a double-precision FPU (VFPv5):

File Attributes
Tag_CPU_name: "7E-M"
Tag_CPU_arch: v7E-M
Tag_CPU_arch_profile: Microcontroller
Tag_THUMB_ISA_use: Thumb-2
Tag_FP_arch: FPv5/FP-D16 for ARMv8
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: small
Tag_ABI_VFP_args: VFP registers
Tag_ABI_optimization_goals: Aggressive Debug
Tag_CPU_unaligned_access: v6

MCUXpresso IDE

The NXP MCUXpresso IDE has even a context option to run readelf on a file:

readelf binary utility in MCUXpresso IDE

This then shows the information:

Output of readelf in MCUXpresso IDE

The command can be configured in the workspace here:

Setting to configure Information Command in MCUXpresso IDE

Summary

To find out if a binary (object file, ELF/Dwarf file) is using hardware or software for the floating point operation, the GNU readelf utility can dump the necessary information. This is especially helpful for checking binaries which I do not build myself.

The only caveat is that readelf will not tell you if floating point data types are used or not: for this I still need to produce disassembly files and grep for things like __aeabi_dmul.

Happy floating 🙂

Links

6 thoughts on “Binary, do you use Hard-Float or Soft-Float?

    • It all depends of course of the application and the capabilities of the MCU. In many lower-end embedded applications one can use fixed point arithmetic which is more efficient.
      But the issue might start if someone is not familiar with the drawbacks of floating point data types (precision, value distribution, NaN, …) and the performance impact of using it.
      Or that for whatever reason you want/need to use a third party library which uses it.

      Like

  1. Integer divide is also not present on most MCUs, so any use of division or modulus is problematic. Even with hardware float support, double precision float is rarely available in hardware on MCUs. I’ve seen plenty of unnecessary use of doubles in my work.

    Like

    • Integer divide is not present on M0/M0+. ARM told me once that this would have increased the code size of the core too much (~30%?), so decided against it for cost reasons. With the result that many vendors added a ‘hardware integer divide’ to their peripherals, but you have to use macros or libraries to use it :-(.
      The M4 can have an optional FPU (only single precision), and double needs to be handled with software. You need to be very careful not to use double (see https://mcuoneclipse.com/2019/03/29/be-aware-floating-point-operations-on-arm-cortex-m4f/). M7/M33 can have optionally both single and double precision FPU, but most I see on the market only have a single precision.

      Like

    • Not sure if Azure RTOS has a future without big support behind it. Microsoft would have had the power and money. Now to me it is very uncertain if ThreadX/Azure will be able to survive. Sure there will be always users, especially the ones who used ThreadX for a long time. But for the lower end, FreeRTOS has a better ecosystem, and Zephyr is taking over the middle end more and more. To me, Microsoft seems to de-invest (again) from the embedded space, and making things open source does not help if the project is not adequately funded and moved forward. Just my 1 cent.

      Liked by 1 person

Leave a reply to bitbank Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.