SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: Resolving “Uses VFP Register Arguments” Errors when Compiling for Cortex-M3
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

Resolving “Uses VFP Register Arguments” Errors when Compiling for Cortex-M3

Eileen David
Last updated: September 27, 2023 2:05 pm
Eileen David 11 Min Read
Share
SHARE

When compiling code for the ARM Cortex-M3 processor, you may encounter an error like “uses VFP register arguments, target CPU does not support ARM mode” or “Target does not support Thumb double precision hardfloat ABI”. This error occurs because the Cortex-M3 does not support passing floating point arguments directly in VFP registers like some other ARM processors. However, there are ways to work around this limitation and still utilize floating point code on the Cortex-M3.

Contents
The IssueSolutions1. Disable hardware floating point2. Use soft-float ABI3. Use hard-float ABI with softfp functions4. Use floating point emulationDetailed ExplanationARM EABI ConventionsSoft-float ABIHard-float ABICortex-M3 LimitationsCausing the VFP Register ErrorDetailed Solutions1. Disable hardware floating point2. Use soft-float ABI3. Hard-float ABI with softfp functions4. Use floating point emulationOther ConsiderationsConclusion

The Issue

The Cortex-M3 CPU implements the Thumb-2 instruction set and only supports the Thumb interworking and Thumb2 instruction sets. It does not support ARM or ThumbEE instructions. The Thumb-2 instruction set does not include instructions for passing arguments directly in VFP registers for floating point values. Instead, the Cortex-M3 follows the standard ARM EABI conventions for passing floats and doubles in integer registers or on the stack.

This means if you have any floating point arguments in a function declaration, the compiler will try to pass them directly in VFP registers instead of integer registers. Since the Cortex-M3 does not support this, you get an error. For example: void foo(float arg1, double arg2);

Here the compiler will try to pass arg1 in s0 and arg2 in d0/d1 VFP registers, which the Cortex-M3 does not support.

Solutions

There are a few possible solutions to resolve this VFP register argument error when compiling for Cortex-M3:

1. Disable hardware floating point

One option is to disable hardware floating point support entirely in your compiler/linker settings. Without hardware floating point support enabled, the compiler will instead pass floats and doubles through integer registers like r0-r3 or on the stack according to the EABI conventions. This may reduce performance but will compile without errors.

2. Use soft-float ABI

You can specify the “-mfloat-abi=soft” option in GCC/Clang to use the soft-float ABI. This tells the compiler to pass floats in integer registers instead of trying to use VFP registers. The soft-float ABI works but loses some performance compared to hardware floating point.

3. Use hard-float ABI with softfp functions

This is the recommended approach to get good floating point performance on Cortex-M3. You can enable the hard-float ABI but compile individual functions with -mfloat-abi=softfp to pass floats in integer registers. This gives you hardware floating point when possible but falls back to soft-float ABI when needed.

For example: // Compiler settings: -mfloat-abi=hard -mfpu=fpv4-sp-d16 // Function definitions void foo(float f) __attribute__ ((pcs(“aapcs-vfp”))) { // … } void bar(float f) __attribute__ ((pcs(“aapcs”)) { // … }

Here foo() will use the hard-float ABI while bar() uses the soft-float ABI. bar() will work on Cortex-M3 while foo() will work on other ARM chips with full VFP support.

4. Use floating point emulation

Some toolchains like DS-5 and Arm Compiler 6 support software floating point emulation when compiling for Cortex-M3. This emulates VFP instructions using integer operations. It works but is slower than hardware floating point on supported chips.

Detailed Explanation

To understand why the “uses VFP register arguments” error occurs, we need to dive deeper into how the ARM EABI conventions handle floating point arguments and return values.

ARM EABI Conventions

The ARM EABI specifications define how functions arguments and return values are passed in registers or on the stack. There are two main variants supported by the EABI:

  • Soft-float ABI: Floating point args are passed in integer registers
  • Hard-float ABI: Floating point args are passed directly in VFP registers

The compiler follows these conventions to know where to put arguments when calling a function and where to expect arguments when defining a function.

Soft-float ABI

With the soft-float ABI, floats are passed in integer registers like r0-r3 while doubles use two registers. For example: void func(float f, double d);

This would pass f in r0 and d in r1:r2. No VFP registers are used.

Hard-float ABI

The hard-float ABI passes floats and doubles directly in VFP registers. For example: void func(float f, double d);

This would pass f in s0 and d in d0/d1 VFP registers instead of integer registers.

Cortex-M3 Limitations

The Cortex-M3 CPU implements the Thumb-2 instruction set, which does not include instructions for accessing the VFP registers directly. Therefore, it does not support the hard-float ABI for passing arguments directly in s0-s15 and d0-d7 registers.

Instead, the Cortex-M3 follows the soft-float ABI convention of passing floats in integer registers r0-r3 and doubles in r0:r1 or r2:r3 register pairs. When compiling for the Cortex-M3, the compiler needs to follow the soft-float ABI and avoid trying to pass floats in VFP registers.

Causing the VFP Register Error

The “uses VFP register arguments” error happens when you enable hardware floating point but the compiler tries to use the hard-float ABI with VFP registers instead of the soft-float ABI. This is an invalid combination on Cortex-M3.

For example, enabling “-mfpu=fpv4-sp-d16” tells the compiler that full VFPv4 hardware floating point is available. So it assumes it can use the hard-float ABI and pass floats directly in VFP registers. But on Cortex-M3 this results in an invalid instruction error when it tries to pass floats in s0-s15 registers that don’t exist.

Detailed Solutions

Now that we understand the issue, here are the detailed solutions again:

1. Disable hardware floating point

Passing the -mfloat-abi=soft compiler option disables hardware floating point support entirely. This forces the compiler to use the soft-float ABI convention of passing floats and doubles in integer registers and on the stack.

While this works, it disables hardware floating point support and loses any performance benefit. Code will run but all floating point is done in software instead.

2. Use soft-float ABI

Specifying -mfloat-abi=soft tells the compiler to always use the soft-float ABI, even with hardware floating point enabled. This passes all arguments in integer registers but allows the rest of the floating point code to still use the hardware. arm-none-eabi-gcc -mcpu=cortex-m3 -mfpu=fpv4-sp-d16 -mfloat-abi=soft

This gives you hardware floating point performance while avoiding the VFP argument error on Cortex-M3.

3. Hard-float ABI with softfp functions

This approach allows mixing both hard-float and soft-float ABIs in one program. The compiler uses hard-float ABI by default for hardware floating point support. But individual functions can be marked soft-float to pass args in integer registers when needed.

For example, compiling with: arm-none-eabi-gcc -mcpu=cortex-m3 -mfpu=fpv4-sp-d16 -mfloat-abi=hard

Tells the compiler to use hard-float ABI. Then marking specific functions soft-float: void foo(float f) __attribute__ ((pcs(“aapcs-vfp”))) { // Uses hard-float ABI } void bar(float f) __attribute__ ((pcs(“aapcs”)) { // Uses soft-float ABI }

This gives the best of both – optimized floating point code along with compatibility with Cortex-M3 limitations.

4. Use floating point emulation

Some toolchains allow compiling Cortex-M3 with full software floating point emulation. This emulates the VFP instructions using integer operations when compiling.

For example, with DS-5: armcc -mcpu=cortex-m3 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mfp16-format=ieee

The -mfp16-format=ieee setting enables the floating point emulation. This is slower but can compile hard-float code for Cortex-M3.

Other Considerations

There are a few other things to keep in mind when working with floating point code on Cortex-M3:

  • Try to isolate floating point code in separate source files or libraries. This makes it easier to apply the __attribute__ tags to selectively use soft-float ABI.
  • Mark any interrupt handlers or context switch code as soft-float to avoid saving VFP registers.
  • Some RTOSes like FreeRTOS provide hooks for switching between hard-float and soft-float modes in different threads.
  • Test code thoroughly after making ABI changes to ensure proper argument passing.
  • Using hard-float ABI can result in smaller code size since float arguments don’t take integer register space.

Conclusion

The “uses VFP register arguments” error occurs due to a mismatch between the hard-float ABI assumptions and the Cortex-M3 limitations. By either disabling hardware floating point entirely, forcing soft-float ABI, or selectively marking soft-float functions, we can work around this issue and utilize floating point on Cortex-M3. Isolating floating point code and testing thoroughly for ABI issues is recommended when mixing hard-float and soft-float code.

Understanding the ARM EABI conventions for passing arguments in registers and how the compiler interacts with the CPU is key to resolving these kinds of ABI issues with Cortex-M3 and other ARM processors. Following the recommendations outlined in this article will help you properly utilize floating point capabilities in your Cortex-M3 programs.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article Tips for ARM Cortex-M3 Multitasking
Next Article ARM gcc Compiler Flags: mcpu vs mfloat-abi vs mfpu Explained
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

ARM Exception Return

The ARM exception return is a key mechanism that allows…

6 Min Read

Cortex-M4 Debug Registers

The Cortex-M4 processor from ARM includes several debug registers that…

8 Min Read

Influence Factors That Affect Interrupt Latency

Interrupt latency refers to the time it takes for an…

10 Min Read

Cortex M0+ Image for MSP3

The Cortex-M0+ is an ultra-low power 32-bit ARM processor core…

11 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account