[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*)&dd;
>    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