Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-05 Thread Houder

On 2018-08-03 14:00, Houder wrote:

On 2018-08-03 12:39, Corinna Vinschen wrote:

On Aug  3 11:27, Houder wrote:

On 2018-08-03 09:36, Corinna Vinschen wrote:

[snip]


> In terms of x86_64, do we have to change the fenv stuff completely
> to use only SSE opcodes?  Does that make sense at all?

Ho! I have to disappoint you here! I am not an expert at all.


Thanks all the same for your detailed description.  A quick search in
glibc shows that x86_64 FP exceptions in fact work somewhat different 
in

that it additionally reads and writes from the SSE control register,
e.g. sysdeps/x86_64/fpu/fesetenv.c:

__asm__ ("fnstenv %0\n"
   "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr));
[...]
  __asm__ ("fldenv %0\n"
   "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));


? ... uhm, this also happens in Korn's implementation (Cygwin). Only
Dave Korn verifies if SSE is present (does the machine have SSE?).

Both implementations both manage SSE and x87 FPU simultaneously.

For instance fetestexcept(), i.e. show me the status flags, return

status flag in SSE | status flag in x87 FPU
(bit-wise "OR" of both "status registers")

Both Korn and Jaeger try to hide that there are in fact two devices
that do "floating-point".

Can gcc generate code for both devices at the same time? Possibly!

Did it in case of my _tiny_ STC? ("double d = 1.0; long l = d + 0.4")

No (as far as I tell).

On Linux and Cygwin 64-bits, the SSE was used. On WoW the x87 FPU was
used.

As far as I tell, it is neither the machine nor "fenv" that devices
to switch from x87 FPU to SSE ...

Why gcc prefers x87 FPU in case of WoW, I cannot tell (Yes, I a bit
outspoken here; though that is my hypothesis).


As a last note on this topic:

My hypothesis was correct.

By default gcc "uses" the x87 FPU on WoW (32-bits) and SSE on x86_64.

It is NOT even possible to force gcc to use SSE on WoW (32-bits):

@@ gcc -Wall -mfpmath=sse -o STC-FENV STC-FENV.c
cc1: warning: SSE instruction set disabled, using 387 arithmetics

It is however possible to instruct gcc to use the x87 FPU on x86_64,
... resulting in an exception where one is not expected (on x86_64):

64-@@ gcc -Wall -mfpmath=387 -o stc-last stc-last.c
64-@@ ./stc-last
INITIALIZING !
Initializing fe_dfl_env
Initializing fe_nomask_env
Exception created! < exceptions STILL DISabled
obj->_fpu._fpu_cw= 037f
obj->_fpu._fpu_sw= 0004 <=== "zero-divide" flag set!
obj->_fpu._fpu_tagw  = 
obj->_fpu._fpu_ipoff = 40186f
obj->_fpu._fpu_ipsel = 0  obj->_fpu._fpu_opcde = 0
obj->_fpu._fpu_dpoff = cc10
obj->_fpu._fpu_dpsel = 
obj->_sse_mxcsr  = 1f80
Exceptions ENABLED!
Floating point exception (core dumped) <=== Whao!

(when SSE is used, an exception is not triggered in this case)

Regards,
Henri


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Corinna Vinschen
On Aug  3 14:00, Houder wrote:
> On 2018-08-03 12:39, Corinna Vinschen wrote:
> > On Aug  3 11:27, Houder wrote:
> > > On 2018-08-03 09:36, Corinna Vinschen wrote:
> [snip]
> 
> > > > In terms of x86_64, do we have to change the fenv stuff completely
> > > > to use only SSE opcodes?  Does that make sense at all?
> > > 
> > > Ho! I have to disappoint you here! I am not an expert at all.
> > 
> > Thanks all the same for your detailed description.  A quick search in
> > glibc shows that x86_64 FP exceptions in fact work somewhat different in
> > that it additionally reads and writes from the SSE control register,
> > e.g. sysdeps/x86_64/fpu/fesetenv.c:
> > 
> > __asm__ ("fnstenv %0\n"
> >"stmxcsr %1" : "=m" (*), "=m" (*__mxcsr));
> > [...]
> >   __asm__ ("fldenv %0\n"
> >"ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));
> 
> ? ... uhm, this also happens in Korn's implementation (Cygwin). Only
> Dave Korn verifies if SSE is present (does the machine have SSE?).

Oops.  Next time I check our code first.  Promised :}


Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Houder

On 2018-08-03 14:00, Houder wrote:
[snip]


As far as I tell, it is neither the machine nor "fenv" that devices
to switch from x87 FPU to SSE ...


s/devices/decides/

Sorry.


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Houder

On 2018-08-03 12:39, Corinna Vinschen wrote:

On Aug  3 11:27, Houder wrote:

On 2018-08-03 09:36, Corinna Vinschen wrote:

[snip]


> In terms of x86_64, do we have to change the fenv stuff completely
> to use only SSE opcodes?  Does that make sense at all?

Ho! I have to disappoint you here! I am not an expert at all.


Thanks all the same for your detailed description.  A quick search in
glibc shows that x86_64 FP exceptions in fact work somewhat different 
in

that it additionally reads and writes from the SSE control register,
e.g. sysdeps/x86_64/fpu/fesetenv.c:

__asm__ ("fnstenv %0\n"
   "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr));
[...]
  __asm__ ("fldenv %0\n"
   "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));


? ... uhm, this also happens in Korn's implementation (Cygwin). Only
Dave Korn verifies if SSE is present (does the machine have SSE?).

Both implementations both manage SSE and x87 FPU simultaneously.

For instance fetestexcept(), i.e. show me the status flags, return

status flag in SSE | status flag in x87 FPU
(bit-wise "OR" of both "status registers")

Both Korn and Jaeger try to hide that there are in fact two devices
that do "floating-point".

Can gcc generate code for both devices at the same time? Possibly!

Did it in case of my _tiny_ STC? ("double d = 1.0; long l = d + 0.4")

No (as far as I tell).

On Linux and Cygwin 64-bits, the SSE was used. On WoW the x87 FPU was
used.

As far as I tell, it is neither the machine nor "fenv" that devices
to switch from x87 FPU to SSE ...

Why gcc prefers x87 FPU in case of WoW, I cannot tell (Yes, I a bit
outspoken here; though that is my hypothesis).

Regards,
Henri


If you're still interested in this stuff, feel free to create more
patches :)


Thanks,
Corinna


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Corinna Vinschen
On Aug  3 11:27, Houder wrote:
> On 2018-08-03 09:36, Corinna Vinschen wrote:
> > Hi J.H.,
> > 
> > Pushed with tweaks.  The string in __asm__ statements works a
> 
> Bah! Must be the heat! I did a compare (sdiff), but missed it. You
> are correct: the '\n' is required.
> 
> > bit different and I made a slight change to the commit message.
> 
> No problem! (you could have gone even further; your command of the
> English language is far better than mine).
> 
> > In terms of x86_64, do we have to change the fenv stuff completely
> > to use only SSE opcodes?  Does that make sense at all?
> 
> Ho! I have to disappoint you here! I am not an expert at all.

Thanks all the same for your detailed description.  A quick search in
glibc shows that x86_64 FP exceptions in fact work somewhat different in
that it additionally reads and writes from the SSE control register,
e.g. sysdeps/x86_64/fpu/fesetenv.c:

__asm__ ("fnstenv %0\n"
   "stmxcsr %1" : "=m" (*), "=m" (*__mxcsr));
[...]
  __asm__ ("fldenv %0\n"
   "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));

If you're still interested in this stuff, feel free to create more
patches :)


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Houder

On 2018-08-03 11:27, Houder wrote:

I discovered a difference in behaviour between the x87 FPU and SSE.

When an exception is masked, a "default action" is carried out when
an exception occurs. At the same time the associated status flag is
set.
(the manual speaks about a "reasonable" default action, an action
 that is "sufficient" most of the times)

When the exception is enabled again, SSE is not bothered. However
the next _FPU_ statement will notice the status flag set, and will
set the "Exception Summary Bit" (in the FPU's status register).


To clarify:

SSE has a "control and status register". The x87 FPU has a control
register and a status register.

Flags are only set in x87 FPU's status register when FPU statements
are executed.

(the FPU is not "interested" in SSE's control and status register)

Henri


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Houder

On 2018-08-03 09:36, Corinna Vinschen wrote:

Hi J.H.,

Pushed with tweaks.  The string in __asm__ statements works a


Bah! Must be the heat! I did a compare (sdiff), but missed it. You
are correct: the '\n' is required.


bit different and I made a slight change to the commit message.


No problem! (you could have gone even further; your command of the
English language is far better than mine).


In terms of x86_64, do we have to change the fenv stuff completely
to use only SSE opcodes?  Does that make sense at all?


Ho! I have to disappoint you here! I am not an expert at all.

Basically, it was Anton Lavrentiev (Cygwin ML, July 9 2018) who got
me interested.

I created my little STC:

feenableexcept()
fegetenv()
fegetenv(FE_DFL_ENV) // to be switched on and off
operation to provoke exception
fesetenv()

I could not make "head or tail" of what was happening; especially
when I expected to see the exception triggered.

On WoW, but also on x86_64.

The standard (and manual page) that describe "fenv" is a disaster.
(too me far too abstract).

That is why I started comparing Cywgin with glibc. Comparing the
implementation by Dave Korn (Cygwin, some 8 years ago), and that
by Andreas Jaeger (glibc).

Only then, I started studying the manuals written by Intel. But
only as far as was required to get a grasp of what was going on.

First "code-wise", next to understand the behaviour of my STC.

Meaning, my focus of interest have been:

fe{en,dis}ableexcept
fe{get,set)env

and after the repair of fegetenv(), _feinitialise(), as Dave Korn
defines FE_ALL_EXCEPT different from Andreas Jaeger.
(in my test environment I used Jaeger's definition, which required
 a slight modification of _feinitialise() )

ONLY after the above was "out of the way", I moved my attention to
WoW: why did exceptions get triggered here, while they were NOT on
x86_64 ?

I discovered a difference in behaviour between the x87 FPU and SSE.

When an exception is masked, a "default action" is carried out when
an exception occurs. At the same time the associated status flag is
set.
(the manual speaks about a "reasonable" default action, an action
 that is "sufficient" most of the times)

When the exception is enabled again, SSE is not bothered. However
the next _FPU_ statement will notice the status flag set, and will
set the "Exception Summary Bit" (in the FPU's status register).

The next FPU statement after will trigger the exception! (Yes, the
triggering of the exception is "delayed", deferred).

You can read all this in Intel's manuals. Bottom-line, if the FPU
is used, and exceptions are enabled again, one must _first_ clear
all exceptions (again, not needed on SSE).

Returning to your question ...

From "a logical point of view", Korn's implementation is more or
less the same as Jaeger's implementation.

Why is there "a preference for the x87 FPU" on WoW, I cannot tell.

Why does "using double d = 1.0; long l = d + 0.4" on WoW result
in code that is executed on the x87 FPU ? (and why does the
reverse occur on x86_64)? (Yes, that is my hypothesis!)

I cannot tell.

Perhaps it is gcc ... I did not investigate any further.

Regards,

Henri


Re: [PATCH] Cygwin: fegetenv() in winsup/cygwin/fenv.cc should not disable exceptions!

2018-08-03 Thread Corinna Vinschen
Hi J.H.,

On Aug  3 01:45, J.H. van de Water wrote:
> fegetenv() in winsup/cygwin/fenv.cc
> 
> fnstenv MUST be followed by fldenv in fegetenv(), as the former disables all
> exceptions in the x87 FPU, which is not appropriate here (fegetenv() ).
> fldenv after fnstenv should reload the x87 FPU w/ the configuration that was
> saved by fnstenv, i.e. a configuration that might have exceptions enabled.
> 
> Note: x86_64 uses SSE for floating-point, not the x87 FPU. However, because
> feraiseexcept() attempts to provoke an exception using the x87 FPU, the bug
> in fegetenv() will make this attempt futile here (x86_64).
> 
> Note: WoW uses the x87 FPU for floating-point, not SSE. Here anything that
> would normally result in triggering an exception, not only feraiseexcept(),
> will not be able to, as result of the bug in fegetenv().
> ---
>  winsup/cygwin/fenv.cc | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/winsup/cygwin/fenv.cc b/winsup/cygwin/fenv.cc
> index bd3f904..eb5260c 100644
> --- a/winsup/cygwin/fenv.cc
> +++ b/winsup/cygwin/fenv.cc
> @@ -141,7 +141,10 @@ fegetexcept (void)
>  int
>  fegetenv (fenv_t *envp)
>  {
> -  __asm__ volatile ("fnstenv %0" : "=m" (envp->_fpu) : );
> +  /* fnstenv disables all exceptions in the x87 FPU; as this is not what is
> + desired here, reload the cfg saved from the x87 FPU, back to the FPU */
> +  __asm__ volatile ("fnstenv %0"
> +"fldenv %0" : "=m" (envp->_fpu) : );
>if (use_sse)
>  __asm__ volatile ("stmxcsr %0" : "=m" (envp->_sse_mxcsr) : );
>return 0;
> -- 
> 2.7.5

Thank you!

Pushed with tweaks.  The string in __asm__ statements works a
bit different and I made a slight change to the commit message.

In terms of x86_64, do we have to change the fenv stuff completely
to use only SSE opcodes?  Does that make sense at all?


Thanks,
Corinna

-- 
Corinna Vinschen  Please, send mails regarding Cygwin to
Cygwin Maintainer cygwin AT cygwin DOT com
Red Hat


signature.asc
Description: PGP signature