On Tuesday 13 January 2026 16:09:09 LIU Hao wrote:
> 在 2025-12-28 02:32, Pali Rohár 写道:
> > x87 fldcw instruction triggers pending x87 exception. So if there is a
> > pending x87 exception and __mingw_setfp() is trying to disable some other
> > x87 type then it will trigger pending exception.
> >
> > There is no non-waiting variant of x87 fldcw instruction. So for setting
> > new control word use x87 fldenv instruction like for setting new status
> > word. For using x87 fldenv instruction it is first need to load whole
> > x87 env via x87 fnstenv instruction.
> >
> > Optimize code to not use x87 fnstenv when it is known that x87 fldenv would
> > not be used - when cw_mask or sw_mask is empty (used just for quering
> > cw/sw).
> > ---
> > mingw-w64-crt/misc/mingw_setfp.c | 63 +++++++++++++++++++-------------
> > 1 file changed, 38 insertions(+), 25 deletions(-)
> >
> > diff --git a/mingw-w64-crt/misc/mingw_setfp.c
> > b/mingw-w64-crt/misc/mingw_setfp.c
> > index fb03781292ce..2298515128b5 100644
> > --- a/mingw-w64-crt/misc/mingw_setfp.c
> > +++ b/mingw-w64-crt/misc/mingw_setfp.c
> > ...
> > + if ((!sw || sw_mask == 0) && (!cw || cw_mask == 0))
> > + {
> > + /* Fast path: when we are not going to change sw/cw which is
> > indicated
> > + * by zero mask then load sw/cw via fast fnstsw/fnstcw instruction.
> > + */
> > + if (sw && sw_mask == 0)
> > + __asm__ __volatile__( "fnstsw %0" : "=m" (newsw) );
> > + if (cw && cw_mask == 0)
> > + __asm__ __volatile__( "fnstcw %0" : "=m" (newcw) );
> > + }
> > + else
> > + {
> > + /* Slow path: when we are going to change sw/cw or we do not know
> > yet then
> > + * load whole x87 env via slow fnstenv as it is needed for
> > changing sw/cw.
> > + */
> > + __asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
> > + newsw = fenv.status_word;
> > + newcw = fenv.control_word;
> > + }
> > +
> > if (sw)
> > {
> > - __asm__ __volatile__( "fnstsw %0" : "=m" (newsw) );
> > oldsw = newsw;
> >
> At a first glance this doesn't look quite correct: When `sw` is null, `cw`
> is non-null and `cw_mask` is non-zero, this takes the slow path, and leaves
> `newsw` as zero, and eventually zeroes the status word.
>
> Since the use of FLDENV is subject to a change in either word, it's
> necessary to initialize {old,new}{cw,sw} unconditionally.
Yes, you are right. I tried to make the change minimal but forgot about that.
> I'm testing this series of patches with this change for now:
>
>
> diff --git a/mingw-w64-crt/misc/mingw_setfp.c
> b/mingw-w64-crt/misc/mingw_setfp.c
> index 229851512..dcd767d9a 100644
> --- a/mingw-w64-crt/misc/mingw_setfp.c
> +++ b/mingw-w64-crt/misc/mingw_setfp.c
> @@ -144,10 +144,8 @@ void __mingw_setfp( unsigned int *cw, unsigned int
> cw_mask,
> /* Fast path: when we are not going to change sw/cw which is
> indicated
> * by zero mask then load sw/cw via fast fnstsw/fnstcw instruction.
> */
> - if (sw && sw_mask == 0)
> - __asm__ __volatile__( "fnstsw %0" : "=m" (newsw) );
> - if (cw && cw_mask == 0)
> - __asm__ __volatile__( "fnstcw %0" : "=m" (newcw) );
> + __asm__ __volatile__( "fnstsw %0" : "=m" (newsw) );
> + __asm__ __volatile__( "fnstcw %0" : "=m" (newcw) );
> }
> else
> {
> @@ -159,10 +157,11 @@ void __mingw_setfp( unsigned int *cw, unsigned int
> cw_mask,
> newcw = fenv.control_word;
> }
>
> + oldsw = newsw;
> + oldcw = newcw;
> +
> if (sw)
> {
> - oldsw = newsw;
> -
> flags = 0;
> if (newsw & 0x1) flags |= _SW_INVALID;
> if (newsw & 0x2) flags |= _SW_DENORMAL;
> @@ -184,8 +183,6 @@ void __mingw_setfp( unsigned int *cw, unsigned int
> cw_mask,
>
> if (cw)
> {
> - oldcw = newcw;
> -
> flags = 0;
> if (newcw & 0x1) flags |= _EM_INVALID;
> if (newcw & 0x2) flags |= _EM_DENORMAL;
>
>
>
>
> --
> Best regards,
> LIU Hao
>
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public