The compiler usually generates FPA11 floating point instructions for floating point math operations with float, double and long double types. It assumes an FPA11 floating point unit or an emulator is available.
It is possible to force the compiler to assume no floating point hardware or an emulator exists. To do this compile with the -msoft-float compiler flag. The compiler then generates function calls instead of floating point instructions. No changes are needed to program code, just recompilation. This means a library is needed to satisfy the references to the function calls generated by the compiler. This library is not provided by the compiler, it only defines the interface; each port is expected to provide its own implementation. On the NetWinder, this library is libfloat. This was ported to ARM Linux by Phil Blundell, based on work Neil Carson did for a similar library for NetBSD. libfloat depends on SoftFloat for the implmentation of the IEEE floating point algorithms.
The latest version of libfloat can be found at: ftp://ftp.netwinder.org/users/s/scottb/libfloat/libfloat-990616.tar.gz.
Code compiled with -msoft-float should not linked with code that wasn't. The compiler follows APCS (ARM Procedure Call Standard) rules when generating floating point code. This uses the registers r0-r3 for the first four arguements (integer and floating point), and the stack for the rest. A floating point value can end up entirely in a register or multiple registers. It can even be split between the registers and the stack. A floating point return value is placed in f0. If the -msoft-float flag is used, then the compiler uses r0-r2, to return floating point values. Which registers are used depends on the size of the floating point numbers. Mixing object modules built with -msoft-float with those built is not really possible due to this difference in calling conventions.