Trouble with long double support on arm

Ian Lepore freebsd at damnhippie.dyndns.org
Mon Apr 9 20:09:31 UTC 2012


A collegue at work has just run into trouble with printf() and long
double with softfloat on arm.  It looks like C++ stream output has the
same problem.  It appears that the math itself works correctly, but
attempting to print the value gives wrong output.

We're pretty sure that this is a problem only with coverting long double
values to ascii.  In all other ways, long double seems to be properly
handled the same as double (which you'd expect given the defines in
float.h for arm).  We use long double types in a few places in our
products where wrong results would lead to in-your-face wrong behavior,
and we've never seen anything like that.  This was noticed in some debug
logging which is normally disabled but he happened to be looking at it
closely today.

This simple program:

        #include <float.h>
        #include <stdio.h>
        #include <iostream>
        
        int main(int argc, char **argv)
        {
            printf("Long Double Test\n");
            printf("sizeof(double): %d\n", sizeof(double));
            printf("sizeof(long double): %d\n", sizeof(long double));
        
            double f = 9999999.898991832509637;
            long double lf = f;
        
            printf("double as double: %f\n", f);
            printf("long double as double: %f\n", lf);
            printf("double as long double: %Lf\n", f);
            printf("long double as long double: %Lf\n", lf);
            std::cout << "long double via cout " << lf << std::endl;
            printf("double as hex double: %A\n", f);
            printf("long double as hex long double: %LA\n", lf);
        
            return 0;
        }
        
Produces this output:
        
        # /usr/tsc/bin/testsimple 
        Long Double Test
        sizeof(double): 8
        sizeof(long double): 8
        double as double: 9999999.898992
        long double as double: 9999999.898992
        double as long double: 1611391.898991
        long double as long double: 1611391.898991
        long double via cout 1.61139e+06
        double as hex double: 0X1.312CFFCC48A85P+23
        long double as hex long double: 0X1.312CFFCC48A85P+23
        
I get the same output on 8.2 and 9.0.  You'd expect the "double as long
double" case to be wrong, but it seems like it might be a clue that the
"long double as long double" case is the same value.

I pointed him at the twisty maze of lib/libc, lib/msun, and contrib/gcc,
and he's currently trying to track down which function actually gets
called to handle %Lf, but I figured I'd ask here as well in case
somebody has already fought this battle and knows what's going on.

-- Ian




More information about the freebsd-arm mailing list