Using fp64lib with long double

The upcoming release of gcc 10 (which is currently in is testing phase) supports long double with 64 bits as a configurable option*. Using long double eliminates the need for explicit fp64lib calls, as the compiler will translate the usual operations +, -, … into calls to the appropriate routines fp64_add, fp64_sub, … . So, instead of

float64_t a, b, c, d, e;
a = fp64_add(a, fp64_mul(b, fp64_div(c, fp64_sub(d, e)))) 

you just write

long double a, b, c, d, e;
a = a + b * c / (d-e)

The following describes what is needed to get a copy of gcc 10 up and running and how to link & compile an avr-program with long doubles.

This description is for a linux system running Ubuntu. Most of the commands are also valid for Debian.

*gcc 10 could also be configured with double as 64 bit (instead of the currently selected 32 bits). However, as now for several years most Arduino programmers are used to double = float = 32 bits, the default configuration in gcc 10 is to keep double as 32 bits.

1. Prerequisites

Install all the tools necessary for setting up a compilation environment:

$ sudo apt-get update
$ sudo apt-get install build-essential
$ sudo apt-get install flex bison
$ sudo apt-get install binutils-avr

2. Get gcc source

Setup a directory (I use ~/gcc-10) and clone the gcc source code:

$ mkdir ~/gcc-10
$ git clone git://gcc.gnu.org/git/gcc.git ~/gcc-10

3. Create a target directory

Setup a directory (I use ~/avr) where the binaries and avr-libraries should be placed into:

$ PREFIX=~/avr
$ mkdir $PREFIX

4. Configure

Setup a directory inside the gcc directory (I use ~/gcc-10/build) and start the configuration process:

$ mkdir ~/gcc-10/build

Important: You have to create a seperate directory and run the configure command from within that directory. Otherwise the following step will fail with some weird/unexplainable error messages.

$ cd ~/gcc-10/build
$ ../configure --prefix=$PREFIX --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --with_dwarf2 --with-libf7=no

The option –with-libf7 comes new with gcc10. It is another IEEE 754 comptabile library, which uses for internal operation 10 bytes. Therefore, it consumes more memory and is slower than fp64lib, but offers up to 56 bits of precision.

If you omit the –with-libf7=no option, gcc 10 will be configured to use libf7 with long double, thus implicit calling of fp64lib functions is not guaranteed.

5. make avr-gcc

Stay in the same directory to start make:

$ make

Depending on your machine, this may take a while. make does not automatically use all processors of your machine, you may use the -j option to increase the number of parallel jobs, i.e.

$ make -j4

This will speed up the compilation process, however I had some runs, where the jobs did not properly synchronize. So, if make stops with an error, rerun it without the -j option.

6. Install the compiler

The following command copies the tools to the target directory, e.g. ~/avr:

$ make install

Include new gcc into your search path and check whether the correct version is called:

$ $ PATH=$PREFIX/bin:$PATH
$ avr-gcc --version

Now, the fist line should read similar to the following

avr-gcc (GCC) 10.0.1 20200313 (experimental)

If a different version number shows up, check your $PATH and check, whether $PREFIX/bin has a avr-gcc in it.

7. Install AVR LibC

Download the latest version of AVR LibC from http://download.savannah.gnu.org/releases/avr-libc/, e.g. avr-libc-2.0.0.tar.bz2

$ cd ~
$ gunzip -c avr-libc-<version>.tar.gz | tar xf - $ cd avr-libc-<version>
$ ./bootstrap $ ./configure --prefix=$PREFIX --build=`./config.guess` --host=avr $ make $ make install

8. Install fp64lib

Download the latest version of fp64lib from http://download.savannah.gnu.org/releases/avr-libc/, e.g. fp64lib-1.1.13

$ cd ~
$ gunzip -c fp64lib-1.1.<version>| tar xf - $ cd fp64lib-<version> $ make

8. A small test program

Write the following minimal test program with the editor of your choice, e.g. vim test.c:

#include <avr/io.h>
main(void) {
long double x = 0.0;
long double n = 1.0;
while(1) {
x += 1.0 / n;
}
}

Now try to compile the program

$ avr-gcc -mrelax --mmcu=atmega328p -o test.elf ./test.c libfp64.a

With the following command you can verify that routines from fp64lib are called:

$ grep fp64 test.elf

9. Warning: experimental support

Please be aware, that gcc 10 is not yet officially released and fp64lib support for gcc 10 is also not yet tested fully. So, errors may occur.

If you find any error, please report it as an issue in the fp64 github https://github.com/fp64lib/fp64lib/issues.