[erlang-bugs] io_lib_format:fwrite_g/1 on arm

Mikael Pettersson mikpe@REDACTED
Fri May 23 20:17:12 CEST 2008


George Bronnikov writes:
 > In recent versions (since R12B0?), io_lib_format:fwrite_g/1, which is
 > the default function for printing floats, analyzes its argument using
 > a bit pattern (mantissa_exponent is a helper function called from
 > fwrite_g):
 > 
 > mantissa_exponent(F) ->
 >     case <<F:64/float>> of
 >         <<_S:1, 0:11, M:52>> -> % denormalized
 >             E = log2floor(M),
 >             {M bsl (53 - E), E - 52 - 1075};
 >         <<_S:1, BE:11, M:52>> when BE < 2047 ->
 >             {M + ?BIG_POW, BE - 1075}
 >     end.
 > 
 > Unfortunately, on Linux/arm (at least in my configuration), a float
 > has its 32-bit words swapped, so the function produces garbage.
 > Reverting to the version from R11B-4 (which just calls fwrite_g/4 with
 > appropriate defaults) gets rid of the bug.
 > 
 > Configuration: iPaq3900, Familiar 0.8.4, Linux
 > 2.4.19-rmk6-pxa1-hh41.1, glibc 2.3.90, gcc-3.4.4.

My guess is that your system uses the FPA floating-point format,
and your CPU runs in big-endian mode.

The problem on ARM is that the architecture initially didn't
specify an FPU or the FP format. An early add-on FPU was the FPA,
which used the standard IEEE 64-bit format but made it always
little-endian even if the CPU was big-endian (I'm a bit
uncertain about the details, but that's the essence of it).
Only a minority of CPUs actually included the FPA, but the
pathetic FPA instruction set and its broken FP format became
standard, even for soft-float, at least in the Linux world.

Later on ARM added the VFP FPU to some models. The VFP is
much saner, and the FP format is standard IEEE 64-bit stored
in the same endianess as the CPU uses, much like any other
sane CPU.

The problem now is that unless you know which FPU model your
system is using (FPA or VFP; hard or soft doesn't matter),
you cannot reliably inspect the bit-level representation of
FP values.

Personally I'd either rip out this mantissa_exponent/1 thing,
or reimplement it in C where there are well-known preprocessor
symbols that tell you which FP format it's using.

/Mikael



More information about the erlang-bugs mailing list