http://bugs.winehq.org/show_bug.cgi?id=28810
--- Comment #2 from Dan Kegel dank@kegel.com 2011-11-19 07:34:35 CST --- I'm not sure this is related. I reduced your case to
#include <stdio.h> int main(int argc, char **argv) { int ivalue = 0x1ffffff; float res = ivalue; printf("%f %f\n", res, (float)ivalue); }
$ gcc -m32 buggy8.c $ ./a.out 33554432.000000 33554431.000000 $ gcc -m64 buggy8.c $ ./a.out 33554432.000000 33554432.000000 $ gcc -mfpmath=387 -m64 buggy8.c $ ./a.out 33554432.000000 33554431.000000 $ gcc -mfpmath=387 -ffloat-store -m64 buggy8.c $ ./a.out 33554432.000000 33554432.000000
$ perl -e 'print 0x1ffffff' 33554431
So: single precision floats aren't big enough to hold that integer precisely, but doubles are. You get the value 33554432.000000 whenever you really go through a single precision float. You get the value 33554431.000000 when the value stays as a double the whole way through, which it will in 387 mode if the compiler doesn't see any reason to reduce precision. I think.
You can get a mixed source and assembly listing if you want with gcc -m32 -Wa,-adhln -g buggy8.c