[OE-core] [RFC YOCTO #5248] core-image-lsb: Why FPU doesn't work correctly on qemux86-64
Hongxu Jia
hongxu.jia at windriver.com
Mon Sep 23 09:11:17 UTC 2013
On 09/23/2013 04:55 PM, Hongxu Jia wrote:
> *Preparation
> 1, vim local.conf
> ...
> DISTRO ?= "poky-lsb"
> MACHINE ?= "qemux86-64"
> ...
>
> *Problem
> 1, Build core-image-lsb
> ..
> bitbake core-image-lsb
> ..
>
> 2, Start qemux86-64, there are 21 LSB tcl test failures on
> qemux86-64, you could reproduce it by tcl interpreter:
> 1, On qemux86-64's terminal, start tcl interpreter
> root at qemux86-64:~# $ tclsh
> %
>
> 2, Run 'binary scan' to assign ieeeValues(-Subnormal)
> % binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d ieeeValues(-Subnormal)
> 1
>
> 3, Run 'puts' to output ieeeValues(-Subnormal), the result is '0.0'
> % puts $ieeeValues(-Subnormal)
> -0.0
>
> Expected:
> -1.1125369292536007e-308
>
> *Analysis
> 1, On the previous environment, add IMAGE_INSTALL_append = " tcl" to
> local.conf and build core-image-sato, the result is expected.
>
> 2, Trace tcl's source code, you could also reproduce the issue by
> compiling and executing the following C codes on core-image-lsb-sdk.
>
> 1) Build core-image-lsb-sdk, and Run qemux86-64.
> 2) On target's terminal, create a C source file:
> root at qemux86-64:~# cat >> test.c << EOF
> #include <stdio.h>
>
> int main(int argc, char *argv[])
> {
> double dd = 0;
> char *p = (char*)ⅆ
> p[0] = 0x00;
> p[1] = 0x00;
> p[2] = 0x00;
> p[3] = 0x00;
> p[4] = 0x00;
> p[5] = 0x00;
> p[6] = 0x08;
> p[7] = 0x00;
>
> if (dd == 0.0)
> printf("Incorrect equal 0.0\n");
> else
> printf("Expected not equal 0.0\n");
>
> return 0;
> }
> EOF
>
> 2) Compile test.c
> root at qemux86-64:~# gcc test.c -o test
>
> 3, Execute test
> $ root at qemux86-64:~# ./test
> Incorrect equal 0.0
>
> Expected:
> Expected not equal 0.0
>
> 3, It's about x86-64's FPU: the SSE MXCSR register.
> If you invoke 'feenableexcept(FE_INEXACT);' or
> 'feclearexcept(FE_INEXACT);' in the above C test,
> the issue will be fixed. In these two functions,
> the SSE MXCSR register has been handled.
vim eglibc-2.18/libc/sysdeps/x86_64/fpu/feenablxcpt.c
...
#include <fenv.h>
int
feenableexcept (int excepts)
{
unsigned short int new_exc, old_exc;
unsigned int new;
excepts &= FE_ALL_EXCEPT;
/* Get the current control word of the x87 FPU. */
__asm__ ("fstcw %0" : "=m" (*&new_exc));
old_exc = (~new_exc) & FE_ALL_EXCEPT;
new_exc &= ~excepts;
__asm__ ("fldcw %0" : : "m" (*&new_exc));
/* And now the same for the SSE MXCSR register. */
__asm__ ("stmxcsr %0" : "=m" (*&new));
/* The SSE exception masks are shifted by 7 bits. */
new &= ~(excepts << 7);
__asm__ ("ldmxcsr %0" : : "m" (*&new));
return old_exc;
}
...
//Hongxu
> *Solution
> Is it necessary to invoke 'feenableexcept(FE_INEXACT);' or
> 'feclearexcept(FE_INEXACT);' to handle SSE MXCSR register?
>
> Or any good idea about this issue.
>
> Thanks,
> Hongxu
>
>
>
>
More information about the Openembedded-core
mailing list