Possibly ambiguous redefinition of _fpreset()?

Keith Marshall <[email protected]> Wed, 8 Feb 2017 22:30:15 +0000
Newsgroups gmane.comp.gnu.mingw.devel
Organization MinGW Project
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------060504060502040700080608
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Guys,

A recent bug report:
https://sourceforge.net/p/mingw/bugs/2326/

prompted me to revisit an idea I've been toying with for a while -- as
it grows bigger, there may be mileage in offering a dynamic linking
option for libmingwex.a.  However, when I try to create a DLL, I see:

  $ mingw32-gcc -shared -o libmingwex-0.dll -Wl,--whole-archive \
    libmingwex.a -Wl,--no-whole-archive -L.
  ./libmsvcrt.a(dgrcbs00324.o):(.text+0x0): multiple definition
   of `_fpreset'
  ./libmingw32.a(CRT_fp10.o):.../mingwrt/CRT_fp10.c:14: first
   defined here
  collect2: error: ld returned 1 exit status

The problem here is Danny Smith's stratagem for overriding the default
behaviour of MSVCRT.DLL's _fpreset() function, by shoving an alternative
function of the same name, but with somewhat different behaviour, (which
he implements in CRT_fp10.c), into libmingw32.a, whence it should be
statically linked ahead of -lmsvcrt; he then also provided a further
free-standing implementation, CRT_fp8.c, which attempts to redirect the
call back to the (*_imp__fpreset)() entry point in MSVCRT.DLL.

Am I over-thinking this?  Or is this as fragile as it appears?  Was
Danny off his game, when he wrote this stuff?  I guess it can't be too
serious a problem, since no issues have been reported in the 15 years
or so since Danny wrote it, but I can see the following possibilities:

1) User creates his own DLL, into which CRT_fp10.o is linked, and its
   _fpreset() symbol is re-exported; that now provides its own copy of
   (*_imp__fpreset)(), which neutralizes Danny's stratagem for calling
   the MSVCRT.DLL implementation.

2) User creates his own DLL, within which _fpreset() is called; user
   then links this DLL to his main program, which he also links with
   CRT_fp8.o; calls to _fpreset() in his DLL will still be resolved
   to whichever of CRT_fp10.o or CRT_fp8.o was linked into the DLL
   itself, ignoring the intent of linking the main program with
   CRT_fp8.o

Given that _fpreset() is strictly a Microsoft concept, conforming to no
known standard, I'd prefer to do away with this ambiguity, and leave it
to MSVCRT.DLL to resolve all references -- users who value standards,
and portability, should be using ISO-C99's fesetenv() function anyway.
Consequently, I've extensively revised Danny's implementation; would
anyone care to review the attached patch, before I commit it?

Of course, if the modified fesetenv() function continues to be linked
statically, from libmingwex.a, the potential for (non-deterministic)
behavioural ambiguity remains, spanning user created DLLs; that could
be mitigated by furnishing libmingwex-0.dll as an alternative to a
statically linked libmingwex.a, so that only a single fesetenv() need
exist within the process address space.

One final related issue: Danny's implementations of both CRT_fp10.c
and CRT_fp8.c defined fpreset(), (without leading underscore), as an
alias for each of his _fpreset() replacement implementations.  Given
the complete lack of any defining standard, that seems kind of pointless
to me.  Right now I've marked this as deprecated, but have retained a
__LIBIMPL__ stub for it, (reimplemented in terms of fesetenv()), but
it's messy, and I'd just as soon see it disappear altogether.

Any thoughts?
- -- 
Regards,
Keith.

Public key available from keys.gnupg.net
Key fingerprint: C19E C018 1547 DE50 E1D4 8F53 C0AD 36C6 347E 5A3F
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)

iQIcBAEBAgAGBQJYm5v3AAoJEMCtNsY0flo/kMoP/0hMLVflTgbCBHDGxGSUByND
rLZzeA/lD+X2mlB4yNGGVI+VUGFEAbkt20oQYVT9vJiBAHB3+qAUoq3s1/+MJ1gw
9uUQMUKr5yrLTmi1nyR1gAR/zPnpzLwVoMVvVP46oV0skjf8+Ais11/kbHVyTSPy
B4e3WzJWka1f1WSKab+BU1iIzCksCf3OxwANWefHCNxvDBJlR30Hu9cDjbBkf4J5
0Cy4p99OuXQERzlcPplXQG79rrdeHGcH2q5insw8pDNG64Tm7Bbo9Th3JKblyuN+
BiOHHH0b3wPJ/tzJUJt84KBzeAvpv9+7ywzX8bu4Y7wnSneof9sBB/XpG9r8kwG1
+FJRPlHJ9KtMy5wFYka7/GWwmzyMf8vtUxz6awaf46IkPomQZvlLcAMOruvdUu+u
y7hkg4FnAgtGyfIxdQ20LTZjCZ3R5AkNrrpxaHpxU9OHe9TdFk79AL07Sbn+MCh7
iVVdZx+R79rxzbuX1nMJ/YKIYmsZnY1FAJMnmj+5bDzRrgkHf5zAPLYyPnLDJGIy
HHh7PDSrX0TewATDwtCYXB1xOlMKTIPsHjLdHXYla1uXq6syaj9UGn5N0NPh7qsr
RFGQ/thrhkEqWto5MzSEEu0YSlOkLMh6fzZGhLQu7Fy+LpOkZJXtiAHJFoJJrPKK
IwNh8PQbSoDJVLkR5AdT
=M8C7
-----END PGP SIGNATURE-----

--------------060504060502040700080608
Content-Type: text/x-patch;
 name="fenv.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="fenv.patch"

# HG changeset patch
# Parent 9a1ff48b35250d65077697acc89a4c270b216f40
Make floating point environment more robust.

* CRT_fp8.c CRT_fp10.c: Delete them; both are replaced by...
* CRT_fenv.c: ...this new common source file; it implements...
(_CRT_fenv): ...this new global variable, with alternative definitions
evaluated during application start-up, to assign one or other of...
[FE_PC53_ENV, FE_PC64_ENV]: ...these, as the preferred default...
[FE_DFL_ENV]: ...represented by this; replacement linkage for...
(_fpreset): ...this MSVCRT.DLL function is no longer supported.

* Makefile.in: Add new static pattern rule, for compiling...
(CRT_fp8.$OBJEXT, CRT_fp10.$OBJEXT): ...each of these, from CRT_env.c

* crt1.c (_gnu_exception_handler, __mingw_CRTStartup): Do not call...
(_fpreset): ...this; its linkage was non-deterministically ambiguous.
(fesetenv): Use this, unambiguously, instead; initially configure the
floating point environment to the predefined state, as assigned to...
[_CRT_fenv]: ...this new global variable; thereafter, reset to...
[FE_DFL_ENV]: ...this ISO-C99 mandatory configuration.

* include/float.h: Assert copyright; tidy layout.
[_MINGW_FLOAT_H_]: Retain, but replace in guard macro usage by...
[_MINGW_FLOAT_H]: ...this, conforming to preferred naming convention.
[_BEGIN_C_DECLS, _END_C_DECLS]: Use them, as appropriate.
(_fpreset): Add _CRTIMP attribute; it is resolved by MSVCRT.DLL
(fpreset): Deprecate it; provide inline __LIBIMPL__ fall-back.

* include/fenv.h: Assert copyright; tidy layout.
[_FENV_H_]: Rename multiple inclusion guard macro, adopting...
[_FENV_H]: ...this preferred stylistic naming convention.
[_BEGIN_C_DECLS, _END_C_DECLS]: Use them, as appropriate.
(FE_INVALID, FE_DENORMAL, FE_DIVBYZERO, FE_OVERFLOW, FE_UNDERFLOW)
(FE_INEXACT, FE_ALL_EXCEPT, FE_TONEAREST, FE_DOWNWARD, FE_UPWARD)
(FE_TOWARDZERO): Redefine them, in terms of enumerated bit positions.
(FE_PD53_ENV, FE_PD64_ENV): New predefined environment selectors; they
serve as initialization-time aliases, causing redefinition of...
[FE_DFL_ENV]: ...this, as run-time alias for one or other of...
[FE_PC53_ENV, FE_PC64_ENV]: ...these, respectively.

* mingwex/fesetenv.c: Assert copyright; tidy layout.
(fesetenv) [FE_PD53_ENV || FE_PD64_ENV]: Handle them, assigning to...
(FE_DFL_ENV): ...this ISO-C99 mandatory configuration, representing...
(fenv_default): ...the value of this new static variable.
(_fpreset): Call it directly; now always resolved by MSVCRT.DLL, so...
(*_imp__fpreset): ...this indirection becomes unnecessary.

diff --git a/mingwrt/CRT_fenv.c b/mingwrt/CRT_fenv.c
new file mode 100644
--- /dev/null
+++ b/mingwrt/CRT_fenv.c
@@ -0,0 +1,63 @@
+/*
+ * CRT_fenv.c
+ *
+ * Specifies the default FPU configuration, in terms of one of the
+ * predefined floating point environments defined in <fenv.h>, via
+ * a global variable assignment, whence the specified selection will
+ * be copied to FE_DFL_ENV at application start-up.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <[email protected]>
+ * Copyright (C) 2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * This file replaces the two original files CRT_fp8.c, and CRT_fp10.c;
+ * compile it using each of the two commands:
+ *
+ *   gcc -c -D_CRT_FE_DFL_ENV=8  CRT_fenv.c -o CRT_fp8.o
+ *   gcc -c -D_CRT_FE_DFL_ENV=10 CRT_fenv.c -o CRT_fp10.o
+ *
+ * to create the complementary pair of object files, reproducing the
+ * intended effect of the original similarly named object file pair.
+ *
+ */
+#include <fenv.h>
+
+#ifndef _CRT_FE_DFL_ENV
+/* If the user neglects to specify this, assume that the intention is
+ * to reproduce, in FE_DFL_ENV, the effect of the original CRT_fp10.o
+ * object file.
+ */
+# define _CRT_FE_DFL_ENV  10
+#endif
+
+/* Initialize the "_CRT_fenv" global variable, based on compile time
+ * selection, to map FE_DFL_ENV to FE_PC53_env, (precision configured
+ * to 53-bits), or to FE_PC64_ENV, (precision configured to 64-bits),
+ * via initial FPU configuration to FE_PD53_ENV, (precision default
+ * 53-bits), or FE_PD64_ENV, (precision default 64-bits).
+ */
+const fenv_t *_CRT_fenv = (_CRT_FE_DFL_ENV == 8) ? FE_PD53_ENV : FE_PD64_ENV;
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/CRT_fp10.c b/mingwrt/CRT_fp10.c
deleted file mode 100644
--- a/mingwrt/CRT_fp10.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * CRT_FP10.c
- *
- * This defines _fpreset as asm ("fnint"). Calls to _fpreset
- * will set default floating point precesion to 64-bit mantissa
- * at app startup.
- *
- * Linking in CRT_FP10.o before libmingw.a will override the definition
- * set in CRT_FP8.o.
- */
-
-/* Override library  _fpreset() with asm fninit */
-void _fpreset (void)
-  { __asm__ ( "fninit" ) ;}
-
-#if defined(__PCC__)
-void _Pragma("alias _fpreset") fpreset(void);
-#else
-void __attribute__ ((alias ("_fpreset"))) fpreset(void);
-#endif
diff --git a/mingwrt/CRT_fp8.c b/mingwrt/CRT_fp8.c
deleted file mode 100644
--- a/mingwrt/CRT_fp8.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * CRT_FP8.c
- *
- * This forces calls of _fpreset to the MSVCRT function
- * exported from dll.  Effectively it make default
- * precison same as apps built with MSVC (53-bit mantissa).
-
- *
- * To change to 64-bit mantissa, link in CRT_FP10.o before libmingw.a.
- */
-
-/* Link against the _fpreset visible in import lib */
-
-extern void (*_imp___fpreset)(void) ;
-void _fpreset (void)
-{  (*_imp___fpreset)(); }
-
-#if defined(__PCC__)
-void _Pragma("alias _fpreset") fpreset(void);
-#else
-void __attribute__ ((alias ("_fpreset"))) fpreset(void);
-#endif
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -5,11 +5,11 @@
 
 PACKAGE_TARNAME := @PACKAGE_TARNAME@
 PACKAGE_VERSION := @PACKAGE_VERSION@
 
 # Written by Keith Marshall <[email protected]>
-# Copyright (C) 2014-2016, MinGW.org Project
+# Copyright (C) 2014-2017, MinGW.org Project
 #
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
 # copy of this software and associated documentation files (the "Software"),
 # to deal in the Software without restriction, including without limitation
@@ -237,15 +237,22 @@ all-deprecated-crt-objects install-depre
 vpath %.c ${mingwrt_srcdir}
 $(addsuffix .$(OBJEXT), crt1 dllcrt1): %.$(OBJEXT): %.c
 	$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -D__CRTDLL__ -o $@ $<
 
 # ...while, for the current build case, we need an explicit mapping
-# to identify the disparately named source file.
+# to identify the disparately named source file...
 #
 $(addsuffix .$(OBJEXT), crt2 dllcrt2): %2.$(OBJEXT): %1.c
 	$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
 
+# ...and for the pair of default FPU configuration selectors, we
+# need to pass the configuration specification to the compiler, when
+# compiling the common source for each of the two cases.
+#
+CRT_fp8.$(OBJEXT) CRT_fp10.$(OBJEXT): CRT_fp%.$(OBJEXT): CRT_fenv.c
+	$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -D_CRT_FE_DFL_ENV=$* -o $@ $<
+
 # The initialization hook for profiling code is inherited from Cygwin,
 # where it is built as gcrt0.$(OBJEXT); we build it, unmodified, as each
 # of gcrt1.$(OBJEXT) and gcrt2.$(OBJEXT), to satisfy the differing GCC
 # specs file dependencies for each of the (deprecated) CRTDLL build
 # and (current) MSVCRT build cases, respectively.
diff --git a/mingwrt/crt1.c b/mingwrt/crt1.c
--- a/mingwrt/crt1.c
+++ b/mingwrt/crt1.c
@@ -1,25 +1,48 @@
 /*
  * crt1.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
  *
- * Source code for the startup proceedures used by all programs. This code
- * is compiled to make crt1.o, which should be located in the library path.
+ * Source code for the startup procedures used by all programs.  This
+ * code is compiled to crt1.o, which is located in the library path.
+ *
+ * $Id$
+ *
+ * Written by Colin Peters <[email protected]>
+ * Copyright (C) 1997, 1999, 2002-2007, 2009, 2010, 2014, 2016,
+ *   2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
  */
-
-/* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
- * avoid problems with older GCC.
+#define __IN_MINGW_RUNTIME
+/* Hide the declaration of _fmode(), with its dllimport attribute in
+ * <stdlib.h>, to avoid problems with older GCC.
  */
-#define __IN_MINGW_RUNTIME
 #include <stdlib.h>
 #include <stdio.h>
 #include <io.h>
 #include <process.h>
-#include <float.h>
+#include <fenv.h>
+
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 #include <signal.h>
 
 #include "cpu_features.h"
@@ -81,12 +104,11 @@ extern void __getmainargs( int *, char *
  */
 extern void __GetMainArgs( int *, char ***, char ***, int );
 #endif
 
 void _mingw32_init_mainargs()
-{
-  /* This is the old start-up mechanism, in which we use a start-up
+{ /* This is the old start-up mechanism, in which we use a start-up
    * hook provided by Microsoft's runtime library to initialize the
    * argument and environment vectors.
    *
    * Note that the preferred method for accessing the environment
    * vector is via a direct pointer retrieved from the runtime DLL,
@@ -96,21 +118,21 @@ void _mingw32_init_mainargs()
    */
   char **dummy_envp;
 
 # define _CRT_GLOB_OPT  _CRT_glob & __CRT_GLOB_USE_MSVCRT__
 # ifdef __MSVCRT__
-    /* The MSVCRT.DLL start-up hook requires this invocation
-     * protocol...
-     */
-    _startupinfo start_info = { 0 };
-    __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
+  /* The MSVCRT.DLL start-up hook requires this invocation
+   * protocol...
+   */
+  _startupinfo start_info = { 0 };
+  __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
 
 # else
-    /* ...while a somewhat simpler protocol is applicable, in
-     * the case of the CRTDLL.DLL version.
-     */
-    __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
+  /* ...while a somewhat simpler protocol is applicable, in
+   * the case of the CRTDLL.DLL version.
+   */
+  __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
 # endif
 }
 
 /* TLS initialization hook.
  */
@@ -136,20 +158,19 @@ extern const PIMAGE_TLS_CALLBACK __dyn_t
 extern int _fmode;
 #ifdef __MSVCRT__
 extern int* __p__fmode(void); /* To access the dll _fmode */
 #endif
 
-/*
- * Setup the default file handles to have the _CRT_fmode mode, as well as
- * any new files created by the user.
+/* Setup the default file handles to have the _CRT_fmode mode,
+ * as well as any new files created by the user.
  */
 extern int _CRT_fmode;
 
 static void
 _mingw32_init_fmode (void)
-{
-  /* Don't set the std file mode if the user hasn't set any value for it.
+{ /* Don't set the std file mode if the user hasn't set any
+   * value for it.
    */
   if (_CRT_fmode)
   {
     _fmode = _CRT_fmode;
 
@@ -165,13 +186,13 @@ static void
   }
 
   /* Now sync the dll _fmode to the one for this .exe.
    */
 # ifdef __MSVCRT__
-    *__p__fmode() = _fmode;
+  *__p__fmode() = _fmode;
 # else
-    *_imp___fmode_dll = _fmode;
+  *_imp___fmode_dll = _fmode;
 # endif
 }
 
 /* This function will be called when a trap occurs.  Thanks to
  * Jacob Navia for this contribution.
@@ -182,46 +203,50 @@ static CALLBACK long
   void (*old_handler) (int);
   long action = EXCEPTION_CONTINUE_SEARCH;
   int reset_fpu = 0;
 
   switch (exception_data->ExceptionRecord->ExceptionCode)
-    {
+  {
     case EXCEPTION_ACCESS_VIOLATION:
-      /* test if the user has set SIGSEGV */
+      /* Test if the user has set SIGSEGV
+       */
       old_handler = signal (SIGSEGV, SIG_DFL);
       if (old_handler == SIG_IGN)
-	{
-	  /* this is undefined if the signal was raised by anything other
-	     than raise ().  */
-	  signal (SIGSEGV, SIG_IGN);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
+      { /* This is undefined if the signal was raised by
+	 * anything other than raise()
+	 */
+	signal (SIGSEGV, SIG_IGN);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
       else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGSEGV);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
+      { /* This means 'old_handler' is a user defined
+	 * function.  Call it
+	 */
+	(*old_handler) (SIGSEGV);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
       break;
 
     case EXCEPTION_ILLEGAL_INSTRUCTION:
     case EXCEPTION_PRIV_INSTRUCTION:
-      /* test if the user has set SIGILL */
+      /* Test if the user has set SIGILL
+       */
       old_handler = signal (SIGILL, SIG_DFL);
       if (old_handler == SIG_IGN)
-	{
-	  /* this is undefined if the signal was raised by anything other
-	     than raise ().  */
-	  signal (SIGILL, SIG_IGN);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
+      { /* This is undefined if the signal was raised by
+	 * anything other than raise()
+	 */
+	signal (SIGILL, SIG_IGN);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
       else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGILL);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
+      { /* This means 'old_handler' is a user defined
+	 * function.  Call it
+	 */
+	(*old_handler) (SIGILL);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
       break;
 
     case EXCEPTION_FLT_INVALID_OPERATION:
     case EXCEPTION_FLT_DIVIDE_BY_ZERO:
     case EXCEPTION_FLT_DENORMAL_OPERAND:
@@ -230,37 +255,61 @@ static CALLBACK long
     case EXCEPTION_FLT_INEXACT_RESULT:
       reset_fpu = 1;
       /* fall through. */
 
     case EXCEPTION_INT_DIVIDE_BY_ZERO:
-      /* test if the user has set SIGFPE */
+      /* Test if the user has set SIGFPE
+       */
       old_handler = signal (SIGFPE, SIG_DFL);
       if (old_handler == SIG_IGN)
-	{
-	  signal (SIGFPE, SIG_IGN);
-	  if (reset_fpu)
-	    _fpreset ();
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
+      {
+	signal (SIGFPE, SIG_IGN);
+	if (reset_fpu)
+	  fesetenv (FE_DFL_ENV);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
       else if (old_handler != SIG_DFL)
-	{
-	  /* This means 'old' is a user defined function. Call it */
-	  (*old_handler) (SIGFPE);
-	  action = EXCEPTION_CONTINUE_EXECUTION;
-	}
-      break;
-
-    default:
-      break;
-    }
+      { /* This means 'old_handler' is a user defined
+	 * function.  Call it
+	 */
+	(*old_handler) (SIGFPE);
+	action = EXCEPTION_CONTINUE_EXECUTION;
+      }
+  }
   return action;
 }
 
-/* The function mainCRTStartup is the entry point for all console programs.
+/* During application start-up, we establish the default configuration
+ * for the FPU.  MSVCRT.DLL provides the _fpreset() function to perform
+ * the appropriate initialization, but it sets the default operation to
+ * be in IEEE-754 8-byte mode, whereas we prefer IEEE-754 10-byte mode,
+ * to better support GCC's 10-byte long doubles; nevertheless, we offer
+ * the option, via the _CRT_fenv global variable, to establish either
+ * one of these modes as initial default, it should be set to either
+ * FE_PD64_ENV, (defined in <fenv.h>, reflecting the 64-bit precision
+ * of the 10-byte mode, and established as default for _CRT_fenv within
+ * the runtime library), or overridden by a setting of FE_PD53_ENV, in
+ * user code, like this:
+ *
+ *   #include <fenv.h>
+ *   const fenv_t *_CRT_fenv = FE_PD53_ENV;
+ *
+ * (or by linking with CRT_fp8.o), to select the 53-bit precision of
+ * the 8-byte mode.
+ *
+ * Whichever of these assignments, i.e. FE_PD64_ENV or FE_PD53_ENV, is
+ * in effect when the following __mingw_CRTStartup() function is invoked,
+ * will cause FE_DFL_ENV to be mapped to one or other of the predefined
+ * environments, FE_PC64_ENV or FE_PC53_ENV, respectively.
  */
-static void  __MINGW_ATTRIB_NORETURN
-__mingw_CRTStartup (void)
+extern const fenv_t *_CRT_fenv;
+
+/* The function mainCRTStartup(), (defined below), is the entry point
+ * for all console programs, it is, primarily, a wrapper around the
+ * following __mingw_CRTStartup() helper function.
+ */
+static __MINGW_ATTRIB_NORETURN  void __mingw_CRTStartup (void)
 {
   int nRet;
 
   /* Initialize TLS callback.
    */
@@ -272,23 +321,22 @@ static void  __MINGW_ATTRIB_NORETURN
    * Win32 SE is not 1-to-1, so caveat emptor.
    *
    */
   SetUnhandledExceptionFilter (_gnu_exception_handler);
 
-  /* Initialize floating point unit.
+  /* Initialize the floating point unit.
    */
-  __cpu_features_init ();	/* Do we have SSE, etc.*/
-  _fpreset ();			/* Supplied by the runtime library. */
+  __cpu_features_init ();	/* Do we have SSE, etc. */
+  fesetenv (_CRT_fenv); 	/* Supplied by the runtime library. */
 
   /* Set up __argc, __argv and _environ.
    */
   _setargv ();
 
-  /* Sets the default file mode.
-   * If _CRT_fmode is set, also set mode for stdin, stdout
-   * and stderr, as well
-   * NOTE: DLLs don't do this because that would be rude!
+  /* Set the default file mode.  If _CRT_fmode is set, also set mode
+   * for stdin, stdout and stderr, as well.  NOTE: DLLs don't do this
+   * because that would be rude!
    */
   _mingw32_init_fmode ();
 
   /* Adust references to dllimported data that have non-zero offsets.
    */
@@ -297,47 +345,47 @@ static void  __MINGW_ATTRIB_NORETURN
   /* Align the stack to 16 bytes for the sake of SSE ops in main
    * or in functions inlined into main.
    */
   asm  __volatile__  ("andl $-16, %%esp" : : : "%esp");
 
-   /* From libgcc.a, __main calls global class constructors via
-      __do_global_ctors, This in turn  registers  __do_global_dtors
-      as the first entry of the app's atexit table.  We do this
-      explicitly at app startup rather than rely on gcc to generate
-      the call in main's  prologue, since main may be imported from a dll
-      which has its own __do_global_ctors.  */
-    __main ();
+  /* From libgcc.a, __main() calls global class constructors via
+   * __do_global_ctors(); this in turn registers __do_global_dtors()
+   * as the first entry of the application's atexit() table.  We do
+   * this explicitly at application startup rather than rely on GCC
+   * to generate the call in main()'s prologue, since main() may be
+   * imported from a DLL which has its own __do_global_ctors()
+   */
+  __main ();
 
-  /* Call the main function. If the user does not supply one
+  /* Call the main() function. If the user does not supply one
    * the one in the 'libmingw32.a' library will be linked in, and
-   * that one calls WinMain. See main.c in the 'lib' dir
+   * that one calls WinMain().  See main.c in the 'lib' directory
    * for more details.
    */
   nRet = main (_argc, _argv, environ);
 
-  /* Perform exit processing for the C library. This means
-   * flushing output and calling 'atexit' registered functions.
+  /* Perform exit processing for the C library. This means flushing
+   * output and calling atexit() registered functions.
    */
   _cexit ();
 
   ExitProcess (nRet);
 }
 
-/*
- * The function mainCRTStartup is the entry point for all console programs.
+/* The function mainCRTStartup() is the entry point for all console
+ * programs.
  */
 void
 mainCRTStartup (void)
 {
 #ifdef __MSVCRT__
   __set_app_type (__CONSOLE_APP);
 #endif
   __mingw_CRTStartup ();
 }
 
-/*
- * For now the GUI startup function is the same as the console one.
+/* For now the GUI startup function is the same as the console one.
  * This simply gets rid of the annoying warning about not being able
  * to find WinMainCRTStartup when linking GUI applications.
  */
 void
 WinMainCRTStartup (void)
@@ -346,22 +394,17 @@ WinMainCRTStartup (void)
   __set_app_type (__GUI_APP);
 #endif
   __mingw_CRTStartup ();
 }
 
-/*
- *  We force use of library version of atexit, which is only
- *  visible in import lib as _imp__atexit
+/* We force use of library version of atexit(), which is only
+ * visible in import lib as _imp__atexit
  */
 extern int (*_imp__atexit)(void (*)(void));
-int atexit (void (* pfn )(void) )
-{
-  return ( (*_imp__atexit)(pfn));
-}
+int atexit (void (* pfn )(void)){ return (*_imp__atexit)(pfn); }
 
-/* Likewise for non-ANSI _onexit */
+/* Likewise for non-ANSI _onexit()
+ */
 extern _onexit_t (*_imp___onexit)(_onexit_t);
-_onexit_t
-_onexit (_onexit_t pfn )
-{
-  return (*_imp___onexit)(pfn);
-}
+_onexit_t _onexit (_onexit_t pfn){ return (*_imp___onexit)(pfn); }
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/include/fenv.h b/mingwrt/include/fenv.h
--- a/mingwrt/include/fenv.h
+++ b/mingwrt/include/fenv.h
@@ -1,107 +1,197 @@
-#ifndef _FENV_H_
-#define _FENV_H_
+/*
+ * fenv.h
+ *
+ * Structures and constants defining, and functions for management of,
+ * the floating point environment.
+ *
+ * $Id$
+ *
+ * Written by Danny Smith <[email protected]>
+ * Copyright (C) 2002, 2003, 2005-2007, 2017, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _FENV_H
+#pragma  GCC system_header
+#define _FENV_H
 
+/* All MinGW headers are required to include <_mingw.h>
+ */
 #include <_mingw.h>
 
-/* FPU status word exception flags */
-#define FE_INVALID	0x01
-#define FE_DENORMAL	0x02
-#define FE_DIVBYZERO	0x04
-#define FE_OVERFLOW	0x08
-#define FE_UNDERFLOW	0x10
-#define FE_INEXACT	0x20
-#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO \
-		       | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+/* FPU status word flags indicating exceptions.  Each is represented
+ * by a single bit, sequentially and contiguously assigned to the low
+ * order bits of the status word, enumerated from lowest:
+ */
+enum
+{ __FE_INVALID_EXCEPT_FLAG_SHIFT,
+  __FE_DENORMAL_EXCEPT_FLAG_SHIFT,
+  __FE_DIVBYZERO_EXCEPT_FLAG_SHIFT,
+  __FE_OVERFLOW_EXCEPT_FLAG_SHIFT,
+  __FE_UNDERFLOW_EXCEPT_FLAG_SHIFT,
+  __FE_INEXACT_EXCEPT_FLAG_SHIFT,
 
-/* FPU control word rounding flags */
-#define FE_TONEAREST	0x0000
-#define FE_DOWNWARD	0x0400
-#define FE_UPWARD	0x0800
-#define FE_TOWARDZERO	0x0c00
+  /* The final entry in the shift enumeration represents the order
+   * of the rightmost bit which does NOT represent an exception flag;
+   * we use it as a high water mark, for generation of the aggregate
+   * mask for ALL exception flags; arithmetically, this becomes the
+   * numeric value of a pseudo-flag placed at the high water mark,
+   * less one.
+   */
+  __FE_ALL_EXCEPT_HWM_SHIFT
+# define FE_ALL_EXCEPT		((0x01 << __FE_ALL_EXCEPT_HWM_SHIFT) - 1)
+};
 
-/* The MXCSR exception flags are the same as the
-   FE flags. */
-#define __MXCSR_EXCEPT_FLAG_SHIFT 0
+#define __FE_EXCEPT(__NAME__)	 (0x01 << __FE_##__NAME__##_EXCEPT_FLAG_SHIFT)
 
-/* How much to shift FE status word exception flags
-   to get the MXCSR exeptions masks,  */
-#define __MXCSR_EXCEPT_MASK_SHIFT 7
+#define FE_INVALID		  __FE_EXCEPT(INVALID)
+#define FE_DENORMAL		  __FE_EXCEPT(DENORMAL)
+#define FE_DIVBYZERO		  __FE_EXCEPT(DIVBYZERO)
+#define FE_OVERFLOW		  __FE_EXCEPT(OVERFLOW)
+#define FE_UNDERFLOW		  __FE_EXCEPT(UNDERFLOW)
+#define FE_INEXACT		  __FE_EXCEPT(INEXACT)
 
-/* How much to shift FE control word rounding flags
-   to get MXCSR rounding flags,  */
-#define __MXCSR_ROUND_FLAG_SHIFT 3
+/* FPU control word flags to specify rounding mode; this may be
+ * represented as a selection from a four-way enumeration...
+ */
+enum
+{ __FE_ROUND_TONEAREST,
+  __FE_ROUND_DOWNWARD,
+  __FE_ROUND_UPWARD,
+  __FE_ROUND_TOWARDZERO
+};
+/* ...with the actual flag bits offset 10-bits from the rightmost
+ * bit in the control word; hence, the rounding mode macros become:
+ */
+#define __FE_ROUND(__MODE__)	(__FE_ROUND_##__MODE__ << 10)
+
+#define FE_TONEAREST		 __FE_ROUND(TONEAREST)
+#define FE_DOWNWARD		 __FE_ROUND(DOWNWARD)
+#define FE_UPWARD		 __FE_ROUND(UPWARD)
+#define FE_TOWARDZERO		 __FE_ROUND(TOWARDZERO)
+
+/* The MXCSR exception flags are the same as those for the FPU...
+ */
+#define __MXCSR_EXCEPT_FLAG_SHIFT  0
+
+/* ...and the corresponding mask bits are offset by a further 7-bit
+ * shift to the left...
+ */
+#define __MXCSR_EXCEPT_MASK_SHIFT  7
+
+/* ...while the MXCSR rounding mode flags adopt the same enumeration,
+ * but are offset a further 3-bits to the left of those representing
+ * the FPU rounding mode selection flags.
+ */
+#define __MXCSR_ROUND_FLAG_SHIFT   3
 
 #ifndef RC_INVOKED
-/*
-  For now, support only for the basic abstraction of flags that are
-  either set or clear. fexcept_t could be  structure that holds more
-  info about the fp environment.
-*/
+/* For now, support only for the basic abstraction of flags that are
+ * either set or clear; fexcept_t could be a structure that holds more
+ * info about the fp environment.
+ */
 typedef unsigned short fexcept_t;
 
-/* This 32-byte struct represents the entire floating point
-   environment as stored by fnstenv or fstenv, augmented by
-   the  contents of the MXCSR register, as stored by stmxcsr
-   (if CPU supports it). */
-typedef struct
-{
-  unsigned short __control_word;
-  unsigned short __unused0;
-  unsigned short __status_word;
-  unsigned short __unused1;
-  unsigned short __tag_word;
-  unsigned short __unused2;
-  unsigned int	 __ip_offset;    /* instruction pointer offset */
-  unsigned short __ip_selector;
-  unsigned short __opcode;
-  unsigned int	 __data_offset;
-  unsigned short __data_selector;
-  unsigned short  __unused3;
-  unsigned int __mxcsr; /* contents of the MXCSR register  */
+typedef struct __fenv_t
+{ /* This 28-byte structure represents the entire floating point
+   * environment of the FPU, as stored by either the "fnstenv", or
+   * the "fstenv" instruction.
+   */
+  unsigned short	__control_word;
+  unsigned short	__unused0;
+  unsigned short	__status_word;
+  unsigned short	__unused1;
+  unsigned short	__tag_word;
+  unsigned short	__unused2;
+  unsigned int		__ip_offset;    /* instruction pointer offset */
+  unsigned short	__ip_selector;
+  unsigned short	__opcode;
+  unsigned int		__data_offset;
+  unsigned short	__data_selector;
+  unsigned short	__unused3;
+
+  /* The structure is extended, beyond the 28 byte requirement to
+   * store the FPU state, by 4 additional bytes, which then makes it
+   * sufficient to also store the contents of the MXCSR register, as
+   * stored by the "stmxcsr" instruction, (if the CPU supports it).
+   */
+  unsigned int		__mxcsr;	/* content of the MXCSR register */
 } fenv_t;
 
+/* The ISO-C99 standard, section 7.6 paragraph 8 requires us to define
+ * the FE_DFL_ENV macro; it specifies restoration of the FPU environment
+ * to its default state, as established at application start-up.
+ */
+#define FE_DFL_ENV    ((const fenv_t *)(0))
 
-/*The C99 standard (7.6.9) allows us to define implementation-specific macros for
-  different fp environments */
+/* Paragraph 9 of the same section of ISO-C99 provides for the definition
+ * of implementation-specific macros to identify alternative predefined
+ * FPU environment configuration; we exploit this licence to offer:
+ *
+ *   FP_PC64_ENV  --  Intel standard 80-bit (64-bit precision); this is
+ *		      consistent with IEEE-754 extended precision, and
+ *		      the configuration preferred by MinGW, because it
+ *		      matches the format of GCC's 80-bit long doubles.
+ *
+ *   FP_PC53_ENV  --  IEEE-754 64-bit (53-bit precision); consistent
+ *		      with Microsoft's preferred FPU configuration;
+ *		      (they offer no better than 64-bit long doubles).
+ */
+#define FE_PC64_ENV   ((const fenv_t *)(-1))
+#define FE_PC53_ENV   ((const fenv_t *)(-2))
 
-/* The default Intel x87 floating point environment (64-bit mantissa) */
-#define FE_PC64_ENV ((const fenv_t *)-1)
+/* The following pair of additional predefined environment macros serve
+ * as aliases for the preceding pair, respectively, with the added side
+ * effect that, when passed to fesetenv(), each causes its respective
+ * alias to become associated with FE_DFL_ENV in subsequent calls.
+ */
+#define FE_PD64_ENV   ((const fenv_t *)(-3))
+#define FE_PD53_ENV   ((const fenv_t *)(-4))
 
-/* The floating point environment set by MSVCRT _fpreset (53-bit mantissa) */
-#define FE_PC53_ENV ((const fenv_t *)-2)
-
-/* The FE_DFL_ENV macro is required by standard.
-  fesetenv will use the environment set at app startup.*/
-#define FE_DFL_ENV ((const fenv_t *) 0)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
 
 /*TODO: Some of these could be inlined */
-/* 7.6.2 Exception */
 
-extern int __cdecl __MINGW_NOTHROW feclearexcept (int);
-extern int __cdecl __MINGW_NOTHROW fegetexceptflag (fexcept_t * flagp, int excepts);
-extern int __cdecl __MINGW_NOTHROW feraiseexcept (int excepts );
-extern int __cdecl __MINGW_NOTHROW fesetexceptflag (const fexcept_t *, int);
-extern int __cdecl __MINGW_NOTHROW fetestexcept (int excepts);
+/* ISO-C99 section 7.6.2 -- Floating Point Exception Handling
+ */
+extern __cdecl __MINGW_NOTHROW  int feclearexcept (int);
+extern __cdecl __MINGW_NOTHROW  int fegetexceptflag (fexcept_t *, int);
+extern __cdecl __MINGW_NOTHROW  int feraiseexcept (int);
+extern __cdecl __MINGW_NOTHROW  int fesetexceptflag (const fexcept_t *, int);
+extern __cdecl __MINGW_NOTHROW  int fetestexcept (int);
 
-/* 7.6.3 Rounding */
+/* ISO-C99 section 7.6.3 -- Floating Point Rounding Mode Control
+ */
+extern __cdecl __MINGW_NOTHROW  int fegetround (void);
+extern __cdecl __MINGW_NOTHROW  int fesetround (int);
 
-extern int __cdecl __MINGW_NOTHROW fegetround (void);
-extern int __cdecl __MINGW_NOTHROW fesetround (int mode);
+/* ISO-C99 section 7.6.4 -- Floating Point Environment Configuration
+ */
+extern __cdecl __MINGW_NOTHROW  int fegetenv (fenv_t *);
+extern __cdecl __MINGW_NOTHROW  int fesetenv (const fenv_t *);
+extern __cdecl __MINGW_NOTHROW  int feupdateenv (const fenv_t *);
+extern __cdecl __MINGW_NOTHROW  int feholdexcept (fenv_t *);
 
-/* 7.6.4 Environment */
+_END_C_DECLS
 
-extern int __cdecl __MINGW_NOTHROW fegetenv (fenv_t * envp);
-extern int __cdecl __MINGW_NOTHROW fesetenv (const fenv_t * );
-extern int __cdecl __MINGW_NOTHROW feupdateenv (const fenv_t *);
-extern int __cdecl __MINGW_NOTHROW feholdexcept (fenv_t *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif	/* Not RC_INVOKED */
-
-#endif /* ndef _FENV_H */
+#endif	/* ! RC_INVOKED */
+#endif	/* !_FENV_H: $RCSfile$: end of file */
diff --git a/mingwrt/include/float.h b/mingwrt/include/float.h
--- a/mingwrt/include/float.h
+++ b/mingwrt/include/float.h
@@ -1,169 +1,227 @@
-#ifndef _MINGW_FLOAT_H_
 /*
  * float.h
  *
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
+ * Constants related to floating point arithmetic.  Also included here are
+ * some non-ANSI mechanisms for accessing the floating point controller.
  *
- * Constants related to floating point arithmetic.
+ * $Id$
  *
- * Also included here are some non-ANSI bits for accessing the floating
- * point controller.
+ * Written by Colin Peters <[email protected]>
+ * Copyright (C) 1997, 1999-2005, 2007, 2010, 2011, 2017, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
  *
  */
-#define _MINGW_FLOAT_H_
+#ifndef _MINGW_FLOAT_H
+#pragma  GCC system_header
+#define _MINGW_FLOAT_H
 /*
  * NOTE:
  *
  * GCC provides float.h, but it doesn't include the non-standard stuff for
  * accessing the fp controller.  We parse the GCC-supplied header, for its
  * standard content, and then define the MS-specific extensions here.
  *
  * In a MinGW standard Win32 hosted environment, this should be the float.h
  * found by a system include path search, but this can't be guaranteed; for
  * a cross-compiler setup, the GCC-supplied header, which is guarded by the
- * _FLOAT_H___ macro, may be found first, thus...
+ * _FLOAT_H___ macro, may be found first, thus, except when compiling any
+ * __LIBIMPL__ stub...
  *
  */
 #if !defined(_FLOAT_H___) && !defined(__FLOAT_H)
-
- /*
-  * ...when we didn't find the GCC-supplied header first, we want to pull
+ /* ...when we didn't find the GCC-supplied header first, we want to pull
   * it in now; include_next should achieve this, (and we must rely on the
   * GCC header maintainers to extend us the same courtesy, to get this one
   * pulled in, when the GCC-supplied header is found first).
-  *
   */
-# include_next <float.h>
+# define _MINGW_FLOAT_H_  1	/* GCC's <float.h> needs to see this */
+# include_next <float.h>	/* !__CRT_ALIAS __LIBIMPL__( FUNCTION = fpreset ) */
 #endif
 
-/* All the headers include this file. */
+/* All MinGW headers are required to include <_mingw.h>
+ */
 #include <_mingw.h>
 
-/*
- * Functions and definitions for controlling the FPU.
+/* Functions and definitions for controlling the FPU.
  */
-#ifndef	__STRICT_ANSI__
+#ifndef __STRICT_ANSI__
 
 /* TODO: These constants are only valid for x86 machines */
 
-/* Control word masks for unMask */
-#define	_MCW_EM		0x0008001F	/* Error masks */
-#define	_MCW_IC		0x00040000	/* Infinity */
-#define	_MCW_RC		0x00000300	/* Rounding */
-#define	_MCW_PC		0x00030000	/* Precision */
+/* Control word masks for unMask
+ */
+#define _MCW_EM 		0x0008001F	/* Error masks */
+#define _MCW_IC 		0x00040000	/* Infinity */
+#define _MCW_RC 		0x00000300	/* Rounding */
+#define _MCW_PC 		0x00030000	/* Precision */
 
-/* Control word values for unNew (use with related unMask above) */
-#define	_EM_INVALID	0x00000010
-#define	_EM_DENORMAL	0x00080000
-#define	_EM_ZERODIVIDE	0x00000008
-#define	_EM_OVERFLOW	0x00000004
-#define	_EM_UNDERFLOW	0x00000002
-#define	_EM_INEXACT	0x00000001
-#define	_IC_AFFINE	0x00040000
-#define	_IC_PROJECTIVE	0x00000000
-#define	_RC_CHOP	0x00000300
-#define	_RC_UP		0x00000200
-#define	_RC_DOWN	0x00000100
-#define	_RC_NEAR	0x00000000
-#define	_PC_24		0x00020000
-#define	_PC_53		0x00010000
-#define	_PC_64		0x00000000
+/* Control word values for unNew (use with related unMask above)
+ */
+#define _EM_INVALID		0x00000010
+#define _EM_DENORMAL		0x00080000
+#define _EM_ZERODIVIDE		0x00000008
+#define _EM_OVERFLOW		0x00000004
+#define _EM_UNDERFLOW		0x00000002
+#define _EM_INEXACT		0x00000001
+#define _IC_AFFINE		0x00040000
+#define _IC_PROJECTIVE		0x00000000
+#define _RC_CHOP		0x00000300
+#define _RC_UP			0x00000200
+#define _RC_DOWN		0x00000100
+#define _RC_NEAR		0x00000000
+#define _PC_24			0x00020000
+#define _PC_53			0x00010000
+#define _PC_64			0x00000000
 
-/* These are also defined in Mingw math.h, needed to work around
-   GCC build issues.  */
-/* Return values for fpclass. */
 #ifndef __MINGW_FPCLASS_DEFINED
-#define __MINGW_FPCLASS_DEFINED 1
-#define	_FPCLASS_SNAN	0x0001	/* Signaling "Not a Number" */
-#define	_FPCLASS_QNAN	0x0002	/* Quiet "Not a Number" */
-#define	_FPCLASS_NINF	0x0004	/* Negative Infinity */
-#define	_FPCLASS_NN	0x0008	/* Negative Normal */
-#define	_FPCLASS_ND	0x0010	/* Negative Denormal */
-#define	_FPCLASS_NZ	0x0020	/* Negative Zero */
-#define	_FPCLASS_PZ	0x0040	/* Positive Zero */
-#define	_FPCLASS_PD	0x0080	/* Positive Denormal */
-#define	_FPCLASS_PN	0x0100	/* Positive Normal */
-#define	_FPCLASS_PINF	0x0200	/* Positive Infinity */
+#define __MINGW_FPCLASS_DEFINED  1
+/* These are also defined in MinGW <math.h>; these duplicates are
+ * needed here, to work around GCC build issues.  FIXME: we should
+ * be able to factor this, at least to avoid any potential for the
+ * introduction of inconsistent definitions.
+ *
+ *
+ * Return values for fpclass.
+ */
+#define _FPCLASS_SNAN		    0x0001	/* Signaling "Not a Number" */
+#define _FPCLASS_QNAN		    0x0002	/* Quiet "Not a Number" */
+#define _FPCLASS_NINF		    0x0004	/* Negative Infinity */
+#define _FPCLASS_NN		    0x0008	/* Negative Normal */
+#define _FPCLASS_ND		    0x0010	/* Negative Denormal */
+#define _FPCLASS_NZ		    0x0020	/* Negative Zero */
+#define _FPCLASS_PZ		    0x0040	/* Positive Zero */
+#define _FPCLASS_PD		    0x0080	/* Positive Denormal */
+#define _FPCLASS_PN		    0x0100	/* Positive Normal */
+#define _FPCLASS_PINF		    0x0200	/* Positive Infinity */
+
 #endif /* __MINGW_FPCLASS_DEFINED */
 
-/* invalid subconditions (_SW_INVALID also set) */
-#define _SW_UNEMULATED		0x0040  /* unemulated instruction */
-#define _SW_SQRTNEG		0x0080  /* square root of a neg number */
-#define _SW_STACKOVERFLOW	0x0200  /* FP stack overflow */
-#define _SW_STACKUNDERFLOW	0x0400  /* FP stack underflow */
+/* Invalid subconditions (_SW_INVALID also set)
+ */
+#define _SW_UNEMULATED		    0x0040	/* unemulated instruction */
+#define _SW_SQRTNEG		    0x0080	/* square root of a neg number */
+#define _SW_STACKOVERFLOW	    0x0200	/* FP stack overflow */
+#define _SW_STACKUNDERFLOW	    0x0400	/* FP stack underflow */
 
-/*  Floating point error signals and return codes */
-#define _FPE_INVALID		0x81
-#define _FPE_DENORMAL		0x82
-#define _FPE_ZERODIVIDE		0x83
-#define _FPE_OVERFLOW		0x84
-#define _FPE_UNDERFLOW		0x85
-#define _FPE_INEXACT		0x86
-#define _FPE_UNEMULATED		0x87
-#define _FPE_SQRTNEG		0x88
-#define _FPE_STACKOVERFLOW	0x8a
-#define _FPE_STACKUNDERFLOW	0x8b
-#define _FPE_EXPLICITGEN	0x8c    /* raise( SIGFPE ); */
+/* Floating point error signals and return codes
+ */
+#define _FPE_INVALID		      0x81
+#define _FPE_DENORMAL		      0x82
+#define _FPE_ZERODIVIDE 	      0x83
+#define _FPE_OVERFLOW		      0x84
+#define _FPE_UNDERFLOW		      0x85
+#define _FPE_INEXACT		      0x86
+#define _FPE_UNEMULATED 	      0x87
+#define _FPE_SQRTNEG		      0x88
+#define _FPE_STACKOVERFLOW	      0x8A
+#define _FPE_STACKUNDERFLOW	      0x8B
+#define _FPE_EXPLICITGEN	      0x8C	/* raise SIGFPE */
 
 #ifndef RC_INVOKED
 
-#ifdef	__cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
 
 /* Set the FPU control word as cw = (cw & ~unMask) | (unNew & unMask),
  * i.e. change the bits in unMask to have the values they have in unNew,
- * leaving other bits unchanged. */
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _controlfp (unsigned int unNew, unsigned int unMask);
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _control87 (unsigned int unNew, unsigned int unMask);
+ * leaving other bits unchanged.
+ */
+_CRTIMP __cdecl __MINGW_NOTHROW  unsigned int _controlfp (unsigned int unNew, unsigned int unMask);
+_CRTIMP __cdecl __MINGW_NOTHROW  unsigned int _control87 (unsigned int unNew, unsigned int unMask);
 
+#define _clear87   _clearfp
+#define _status87  _statusfp
 
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _clearfp (void);	/* Clear the FPU status word */
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _statusfp (void);	/* Report the FPU status word */
-#define		_clear87	_clearfp
-#define		_status87	_statusfp
+_CRTIMP __cdecl __MINGW_NOTHROW  unsigned int _clearfp (void);	/* Clear the FPU status word */
+_CRTIMP __cdecl __MINGW_NOTHROW  unsigned int _statusfp (void);	/* Report the FPU status word */
 
 
-/*
-   MSVCRT.dll _fpreset initializes the control register to 0x27f,
-   the status register to zero and the tag word to 0FFFFh.
-   This differs from asm instruction finit/fninit which set control
-   word to 0x37f (64 bit mantissa precison rather than 53 bit).
-   By default, the mingw version of _fpreset sets fp control as
-   per fninit. To use the MSVCRT.dll _fpreset, include CRT_fp8.o when
-   building your application.
-*/
-void __cdecl __MINGW_NOTHROW _fpreset (void);
-void __cdecl __MINGW_NOTHROW fpreset (void);
+/* MSVCRT.DLL provides _fpreset() to initialize the FPU; it initializes
+ * the control register to 0x27F, (thus selecting 53-bit precision), the
+ * status register to zero and the tag word to 0FFFFh.  This differs from
+ * Intel's default configuration, (as established by the asm instructions
+ * "finit" and "fninit"), which set the control word to 0x37F, (yielding
+ * 64-bit precison rather than 53-bit).
+ *
+ * Nominally, MinGW prefers to configure the FPU for 64-bit precision, as
+ * that is a better fit for support of GCC's 10-byte long doubles.  This
+ * was formerly achieved by provision of an alternative implementation of
+ * _fpreset(), intended to be statically linked into MinGW applications,
+ * (with variants enabling 64-bit precision by default, or alternatively,
+ * when the application is explicitly linked with CRT_fp8.o, providing
+ * 53-bit precision instead).  Unfortunately, this linking strategy may
+ * lead to non-deterministic ambiguity over which _fpreset() variant is
+ * called, in the event of the call originating in any user implemented,
+ * or third party DLL.  Consequently, support for this strategy has been
+ * withdrawn.  _fpreset() now ALWAYS refers to the MSVCRT.DLL function,
+ * (and thus ALWAYS selects 53-bit precision); MinGW applications should
+ * now use the ISO-C99 standard fesetenv() function to configure the FPU,
+ * (as the start-up code now does, to enable 64-bit precision by default,
+ * but continuing to support linking with CRT_fp8.o, to initialize the
+ * configuration to 53-bit precision).
+ */
+_CRTIMP __cdecl __MINGW_NOTHROW  void _fpreset (void);
 
-/* Global 'variable' for the current floating point error code. */
-_CRTIMP int * __cdecl __MINGW_NOTHROW __fpecode(void);
-#define	_fpecode	(*(__fpecode()))
+/* Former MinGW releases also provided fpreset(), implemented as an alias
+ * for _fpreset(), (in whichever guise it was deployed); deprecate this,
+ * but retain the association for backward compatibility, (noting that it
+ * will now redirect the call to fesetenv(), as recommended above, with
+ * the configuration selection set to FE_DFL_ENV).
+ */
+__cdecl __MINGW_NOTHROW  void fpreset (void) __MINGW_ATTRIB_DEPRECATED;
 
-/*
- * IEEE recommended functions.  MS puts them in float.h
+#ifndef __NO_INLINE__
+/* Provide the implementation of fpreset() as an inline stub; for this,
+ * we need to expose a minimal opaque subset of <fenv.h>, and we assume
+ * that FE_DFL_ENV is equivalent to (const fenv_t *)(0), (as it is, in
+ * the MinGW implementation of <fenv.h>).
+ */
+typedef struct __fenv_t fenv_t;
+__cdecl __MINGW_NOTHROW  int fesetenv (const fenv_t *);
+
+__CRT_ALIAS __LIBIMPL__( FUNCTION = fpreset )
+void fpreset (void){ fesetenv ((const fenv_t *)(0)); }
+#endif
+
+/* Global 'variable' for the current floating point error code.
+ */
+#define _fpecode  (*(__fpecode()))
+_CRTIMP __cdecl __MINGW_NOTHROW  int *__fpecode (void);
+
+/* IEEE recommended functions.  Microsoft puts them in <float.h>,
  * but they really belong in math.h.
  */
+_CRTIMP __cdecl __MINGW_NOTHROW  double _chgsign (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  double _copysign (double, double);
+_CRTIMP __cdecl __MINGW_NOTHROW  double _logb (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  double _nextafter (double, double);
+_CRTIMP __cdecl __MINGW_NOTHROW  double _scalb (double, long);
 
-_CRTIMP double __cdecl __MINGW_NOTHROW _chgsign	(double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _copysign (double, double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _logb (double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _nextafter (double, double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _scalb (double, long);
+_CRTIMP __cdecl __MINGW_NOTHROW  int _finite (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  int _fpclass (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  int _isnan (double);
 
-_CRTIMP int __cdecl __MINGW_NOTHROW _finite (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _fpclass (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _isnan (double);
+_END_C_DECLS
 
-#ifdef	__cplusplus
-}
-#endif
+#endif	/* ! RC_INVOKED */
+#endif	/* !__STRICT_ANSI__ */
 
-#endif	/* Not RC_INVOKED */
-
-#endif	/* Not __STRICT_ANSI__ */
-
-#endif /* _MINGW_FLOAT_H_ */
-
+#endif	/* _MINGW_FLOAT_H: $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/fesetenv.c b/mingwrt/mingwex/fesetenv.c
--- a/mingwrt/mingwex/fesetenv.c
+++ b/mingwrt/mingwex/fesetenv.c
@@ -1,57 +1,130 @@
+/*
+ * fesetenv.c
+ *
+ * Implements the fesetenv(3) function, per ISO-C99 section 7.6.4.3
+ *
+ * $Id$
+ *
+ * Written by Danny Smith  <[email protected]>
+ * Copyright (C) 2002, 2005, 2006, 2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#define __USE_CRTIMP
+
 #include <fenv.h>
 #include <float.h>
 #include "cpu_features.h"
 
-/* 7.6.4.3
-   The fesetenv function establishes the floating-point environment
-   represented by the object pointed to by envp. The argument envp
-   points to an object set by a call to fegetenv or feholdexcept, or
-   equal the macro FE_DFL_ENV or an implementation-defined environment
-   macro. Note that fesetenv merely installs the state of the exception
-   flags represented through its argument, and does not raise these
-   exceptions.
- */
+int fesetenv( const fenv_t *fenvp )
+{
+  /* Specified by ISO-C99 section 7.6.4.3
+   *
+   * The fesetenv() function establishes the floating-point environment
+   * represented by the object pointed to by "envp".  The argument "envp"
+   * points to an object set by a call to fegetenv() or feholdexcept(), or
+   * equals the macro, FE_DFL_ENV, or an implementation-defined environment
+   * macro.  Note that fesetenv() merely sets the state of the exception
+   * flags represented through its argument; it does not raise these
+   * exceptions.
+   *
+   *
+   * The following static variable stores the predefined environment
+   * which is associated with FE_DFL_ENV; initialize it to represent
+   * the Intel X87 default configuration.
+   */
+  static const fenv_t *fenv_default = FE_PC64_ENV;
 
-extern void (*_imp___fpreset)( void ) ;
+  /* Before anything else, establish a default exception handling
+   * policy for SSE instructions, to be used in conjunction with the
+   * predefined FPU state macros, (establishing an effective default
+   * MXCSR status value of 0x1F80, so masking all exceptions, while
+   * leaving all other bits as zero), in the event that SSE support
+   * is available.
+   */
+  unsigned fenv_mxcsr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT;
 
-int fesetenv (const fenv_t * envp)
-{
-  /* Default mxcsr status is to mask all exceptions.  All other bits
-     are zero.  */
+  if( fenvp == FE_PD64_ENV )
+    /* This is a request to both initialize the FPU state, to the
+     * FE_PC64_ENV predefined state, and to store that state as the
+     * application default.
+     */
+    fenvp = fenv_default = FE_PC64_ENV;
 
-  unsigned int _csr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT /*= 0x1f80 */;
+  else if( fenvp == FE_PD53_ENV )
+    /* Conversely, this requests initialization of FPU state to the
+     * FE_PC53_ENV predefined state, and to store that state as the
+     * new application default.
+     */
+    fenvp = fenv_default = FE_PC53_ENV;
 
-  if (envp == FE_PC64_ENV)
-   /*
-    *  fninit initializes the control register to 0x37f,
-    *  the status register to zero and the tag word to 0FFFFh.
-    *  The other registers are unaffected.
-    */
-    __asm__ ("fninit");
+  else if( fenvp == FE_DFL_ENV )
+    /* This simply requests initialization of FPU state to whichever
+     * of the two preceding predefined states has been previously set
+     * as the application default.
+     */
+    fenvp = fenv_default;
 
-  else if (envp == FE_PC53_ENV)
-   /*
-    * MS _fpreset() does same *except* it sets control word
-    * to 0x27f (53-bit precison).
-    * We force calling _fpreset in msvcrt.dll
-    */
+  if( fenvp == FE_PC64_ENV )
+    /* The FPU's "fninit" instruction initializes the FPU control
+     * word register to 0x37F, the status register to zero and the
+     * tag word to 0xFFFF.  The other registers are unaffected.
+     */
+    __asm__( "fninit" );
 
-   (*_imp___fpreset)();
-
-  else if (envp == FE_DFL_ENV)
-    /* Use the choice made at app startup */
+  else if( fenvp == FE_PC53_ENV )
+    /* Microsoft's _fpreset() does the same, EXCEPT that it sets
+     * the control word to 0x27F (53-bit precison).  Here, we want
+     * to force a call to _fpreset() in MSVCRT.DLL
+     */
     _fpreset();
 
   else
-    {
-      __asm__ ("fldenv %0;" : : "m" (*envp));
-       /* Setting the reserved high order bits of MXCSR causes a segfault */
-       _csr = envp ->__mxcsr & 0xffff;
-    }
+  { /* The requested FPU state is not represented by any of the
+     * predefined state macros; assume it is a properly constructed
+     * fenv_t structure, and load it to the FPU as is.
+     */
+    __asm__( "fldenv %0" :: "m" (*fenvp) );
 
-  /* Set MXCSR */
-   if (__HAS_SSE)
-     __asm__ volatile ("ldmxcsr %0" : : "m" (_csr));
+    /* Also, in the event that SSE instructions may be supported,
+     * extract the MXCSR flags from this same structure, to be used
+     * instead of the defaults which have been established for use
+     * in conjunction with the predefined state macros, noting that
+     * attempting to set any of the reserved high-order flags will
+     * induce a segmentation fault, so mask them off.
+     */
+    fenv_mxcsr = fenvp->__mxcsr & 0xFFFF;
+  }
 
+  if( __HAS_SSE )
+    /* Finally, if SSE instructions are supported, set the MXCSR
+     * exception handling policy flags...
+     */
+    __asm__( "ldmxcsr %0" :: "m" (fenv_mxcsr) );
+
+  /* ...and we are done; there is no mechanism for us to detect
+   * failure, so simply return zero, indicating success.
+   */
   return 0;
 }
+
+/* $RCSfile$: end of file */

--------------060504060502040700080608
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
--------------060504060502040700080608
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
MinGW-dvlpr mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr

--------------060504060502040700080608--