John Hauser has written a package that implements the basic arithmetic functions for 32 and 64 bit and 80 and 128 bit floating point. The package is called SoftFloat and is available on the web at http://www.jhauser.us/arithmetic/SoftFloat.html. This is a full IEC/IEEE implementation and provides all arithmetic functions including square root. It unfortunately does not include conversions from ASCII strings.
I have taken this code and ported the 32 and 64 bit sections to the Atmel AVR processors using WinAvr. While it works very well indeed, the library takes nearly 63K using -Os. There would be much work to do reducing this to something manageable so I have gone no further.
Apart from re-defining his int32, float32 and float64 to match the names in avr-libc and removing references to FLOATX80 and FLOAT128, the code is original. The makefile uses a Mega2560 as an example processor so the code would fit using -O0 in the early debugging stages. So far only tested in Atmel Studio.
The files with changes are: millieu.h, softfloat.c, softfloat-macros and softfloat.h. The AVRs are bigendian, so the SPARC-gcc.h file was edited and renamed AVR.h with an added include for the avr-gcc file called stdint.h where the standard types are defined. For AVR SoftFloat the types become:
typedef int flag; typedef int uint8; typedef int int8; typedef int uint16; typedef int int16; typedef uint32_t uint32; typedef long int32; #ifdef BITS64 typedef uint64_t uint64; typedef int64_t int64; #endif
and the bit masks become:
typedef unsigned char bits8; typedef signed char sbits8; typedef uint16_t bits16; typedef int sbits16; typedef uint32 bits32; typedef int32 sbits32; #ifdef BITS64 typedef uint64_t bits64; typedef int64_t sbits64; #endif
The macro INLINE which Hauser has used to flag specific functions for inline compilation has been re-defined as static, as inlining in avr-gcc produces a register spill and would, in any case, considerably increase the compiled size.
The TestSoftFloat.c file contains some examples of using the SoftFloat functions in avr-gcc:
int32 a1, a2, a3;
float64 b1, b2, b3;
float32 c1;
int main(void)
{
// Add test cases as required...
//
a1 = 1234;
b1 = int32_to_float64(a1); // i32 -> f64
c1 = float64_to_float32(b1); // f64 -> f32
a2 = float64_to_int32(b1); // f64 -> i32
a3 = float32_to_int32(c1); // f32 -> i32
a2 = 2;
b2 = int32_to_float64(a2); // i32 -> f64
b3 = float64_add(b1, b2); // f64 + f64
a3 = float64_to_int32(b3); // f64 -> i32
a1 = 152399025;
b1 = int32_to_float64(a1); // i32 -> f64
b2 = float64_sqrt(b1); // sqrt(f64)
a2 = float64_to_int32(b2); // f64 -> i32
a1 = -369;
b1 = int32_to_float64(a1); // i32 -> f64
a2 = 9874;
b2 = int32_to_float64(a2); // i32 -> f64
b3 = float64_mul(b1, b2); // f64 * f64
a3 = float64_to_int32(b3); // f64 -> i32
b3 = float64_div(b2, b1); // f64 / f64
a3 = float64_to_int32(b3); // f64 -> i32
return 0;
}
Download the AVR SoftFloat zipped files.
Ron Kreymborg. 24/12/2008