There is a feature of the ARM architecture that can be a bit confusing to engineers that haven’t worked with ARM processors before.  It has to do with floating-point calculations, and whether they are done in hardware or software.

You can do quite a lot with a microprocessor using only integers.  For example, you can calculate a memory offset, count the occurrences of an event, or encode a state in a state machine.  You can also do integer calculations, of course, but even calculations involving fractional numbers can be done as long as you also keep track of decimal places.  So why dedicate hardware to floating-point calculations if you can do it all using integers?  Well, the performance gains from a dedicated floating-point unit (FPU) can be significant, but the downside is an increase in die size, cost, and power usage.  The RZ and ARM designers accommodate for this trade-off by making the FPU optional.

As you might expect, the compiler needs to know whether it can include FPU-specific opcodes when compiling a program.  But the FPU also has its own set of registers, which actually has a larger impact on the compilation process.  If those registers exist, then the functions written to either accept or return floating-point numbers can do so via those registers.  Otherwise, floating-point numbers must be passed via the normal CPU registers or put on the call stack.

The expectations regarding what goes in registers, and when, as well as what goes on the call stack when one function calls another is called the “ABI”.  (This stands for “application binary interface”.)  And because the FPU and its registers are optional, there are two ABIs defined for ARM processors.  Confusingly though, there are three choices the compiler can make, but I will explain those next.

If the compiler is targeting ARM microprocessors that do not have an FPU, then it will compile all floating-point code by transparently calling software routines that perform those calculations using integer operations.  This is called the “soft” ABI.  Code compiled this way will run just fine on a processor without an FPU; it will just run slower than it could have.

If the compiler is targeting processors that do have an FPU, then it has two choices.  Obviously, it could compile all of its code assuming that the FPU and its registers exists.  This is called the “hard” ABI.  However, code compiled this way is incompatible with code compiled using the soft ABI, due to the different assumptions made regarding the existence of the FPU registers.  So there is a third option that is used sometimes.  It is called the “softfp” ABI, though to be precise it is not actually a different ABI.  It works by taking advantage of the fact that as long as floating-point numbers are passed in and out of functions using the soft ABI--remaining compatible with code compiled for FPU-less processors--the code is free to use the FPU however it would like within a function.

So why would you compile with the softfp pseudo-ABI?  Well, don’t, if you can help it.  (The overhead of ignoring those FPU registers is significant!)  All it takes is recompile if the source code is available.  But, if you can’t, then the softfp ABI allows you to link to soft ABI code but still take partial advantage of the FPU and its registers.

How does this apply to the ARM processors available from Renesas?  Well, as I write this, every ARM processor available, as part of the RZ family, have an FPU.  This makes sense, given that they are intended for applications that most likely involve a significant amount of floating-point calculations.  So use the hard ABI, if you can.  Otherwise, the softfp ABI is an excellent second choice.The soft ABI should only be chosen when there are either minimal floating point calculations or none at all.