On Sat, Nov 23, 2013 at 6:24 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
> On Sat, Nov 23, 2013 at 5:48 PM, Uros Bizjak <ubiz...@gmail.com> wrote:
>
>>> Thanks for lookin at this. I am a real newcomer to 387, and it took me a 
>>> long time perusing the Intel doc, as well as glibc sources, to come up with 
>>> that. The “reference” implementation of these FPU functions, the one I am 
>>> confident in, is that in config/fpu-glibc.h: i.e., the functions in 
>>> config/fpu-i387.h should have the same effect that config/fpu-glibc.h on 
>>> i386/x86_64 hardware.
>>>
>>> I’ll reply to your comments, but in some cases I was not sure exactly what 
>>> you were saying… thanks for your help, and patience!
>>>
>>>
>>>> @@ -136,16 +165,54 @@ set_fpu (void)
>>>>       __asm__ __volatile__ ("%vstmxcsr\t%0" : "=m" (cw_sse));
>>>>
>>>>       /* The SSE exception masks are shifted by 7 bits.  */
>>>> -      cw_sse |= _FPU_MASK_ALL << 7;
>>>> -      cw_sse &= ~(excepts << 7);
>>>> -
>>>> -      /* Clear stalled exception flags.  */
>>>> -      cw_sse &= ~_FPU_EX_ALL;
>>>>
>>>> You have to clear stalled SSE exceptions here. Their flags are in LSB
>>>> bits, so their position is different than the position of exception
>>>> mask bits in the control word.
>>>
>>> So, if I get you right, I should restore the "cw_sse &= ~_FPU_EX_ALL”, 
>>> which I had mistakenly removed.
>>> But I’m looking at glibc-2.18/sysdeps/x86_64/fpu/feenablxcpt.c and 
>>> fedisblxcpt.c, and it doesn’t seem to be done there.
>>
>> The idea was that since control word is changed, status word should be
>> cleared. But since stalled flags won't raise an exception, it actually
>> doesn't matter, although it looks nicer in a debugger. However, if you
>> remove SSE clear, you should also remove fnclex from x87 code.
>
> Actually, I was wrong. You have to clear stalled flags.
>
> Please consider following test:
>
> --cut here--
> #include <fenv.h>
>
> int main(void)
> {
>   unsigned short cw;
>
>   /* Raise FE_DIVBYZERO */
>   volatile float d = 0.0f;
>   volatile float r = 1.0f / d;
>
> #if GLIBC
>   feenableexcept (FE_DIVBYZERO);
> #else
>   __asm__ __volatile__ ("fstcw\t%0" : "=m" (cw));
>
>   cw |= FE_ALL_EXCEPT;
>   cw &= ~FE_DIVBYZERO;
>
>   __asm__ __volatile__ ("fnclex\n\tfldcw\t%0" : : "m" (cw));
> #endif
>
>   /* Raise FE_INEXACT */
>   d = 3.0f;
>   r = 1.0f / d;
>
>   return 0;
> }
>
> --cut here--
>
> The test (compiled with -m32 or -mfpmath=387 due to x87 assembly,
> linked against -lm will generate erroneous exception when -DGLIBC is
> added to compile flags.
>
> So, it looks to me that glibc has a bug here. Oh, and contrary to
> claims in glibc sources, the above test raises only FE_INEXACT
> exception.
>
> I have added Joseph to Cc due to glibc issues.

Now glibc Bug 16209 [1]

[1] https://sourceware.org/bugzilla/show_bug.cgi?id=16209

Uros.

Reply via email to