OSDN Git Service

Make floating point environment more robust.
authorKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 27 Feb 2017 17:46:27 +0000 (17:46 +0000)
committerKeith Marshall <keithmarshall@users.sourceforge.net>
Mon, 27 Feb 2017 17:46:27 +0000 (17:46 +0000)
mingwrt/CRT_fenv.c [new file with mode: 0644]
mingwrt/CRT_fp10.c [deleted file]
mingwrt/CRT_fp8.c [deleted file]
mingwrt/ChangeLog
mingwrt/Makefile.in
mingwrt/crt1.c
mingwrt/include/fenv.h
mingwrt/include/float.h
mingwrt/mingwex/fesetenv.c

diff --git a/mingwrt/CRT_fenv.c b/mingwrt/CRT_fenv.c
new file mode 100644 (file)
index 0000000..ac7dfbc
--- /dev/null
@@ -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 <keithmarshall@users.sourceforge.net>
+ * 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 (file)
index 516c86c..0000000
+++ /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 (file)
index 78f4b7e..0000000
+++ /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
index ec6c8f5..5dfed08 100644 (file)
@@ -1,3 +1,51 @@
+2017-02-24  Keith Marshall  <keithmarshall@users.sourceforge.net>
+
+       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.
+
 2017-02-21  Keith Marshall  <keithmarshall@users.sourceforge.net>
 
        Make mingwrt and w32api test suites consistent.
index a830b63..3eb6abd 100644 (file)
@@ -236,11 +236,18 @@ $(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
index c207702..439f9e8 100644 (file)
@@ -1,23 +1,46 @@
 /*
  * 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 <colin@bird.fu.is.saga-u.ac.jp>
+ * 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.
+ */
 #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>
@@ -83,8 +106,7 @@ 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.
    *
@@ -98,17 +120,17 @@ void _mingw32_init_mainargs()
 
 # 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
 }
 
@@ -138,16 +160,15 @@ extern int _fmode;
 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)
   {
@@ -167,9 +188,9 @@ _mingw32_init_fmode (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
 }
 
@@ -184,42 +205,46 @@ _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
   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:
@@ -232,33 +257,57 @@ _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
       /* 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.
+ */
+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 void  __MINGW_ATTRIB_NORETURN
-__mingw_CRTStartup (void)
+static __MINGW_ATTRIB_NORETURN  void __mingw_CRTStartup (void)
 {
   int nRet;
 
@@ -274,19 +323,18 @@ __mingw_CRTStartup (void)
    */
   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 ();
 
@@ -299,31 +347,32 @@ __mingw_CRTStartup (void)
    */
   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)
@@ -334,8 +383,7 @@ mainCRTStartup (void)
   __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.
  */
@@ -348,20 +396,15 @@ WinMainCRTStartup (void)
   __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 */
index 9b3cec3..58e470a 100644 (file)
-#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 <dannysmith@users.sourceforge.net>
+ * 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 control word rounding flags */
-#define FE_TONEAREST   0x0000
-#define FE_DOWNWARD    0x0400
-#define FE_UPWARD      0x0800
-#define FE_TOWARDZERO  0x0c00
-
-/* The MXCSR exception flags are the same as the
-   FE flags. */
-#define __MXCSR_EXCEPT_FLAG_SHIFT 0
-
-/* How much to shift FE status word exception flags
-   to get the MXCSR exeptions masks,  */
-#define __MXCSR_EXCEPT_MASK_SHIFT 7
-
-/* How much to shift FE control word rounding flags
-   to get MXCSR rounding flags,  */
-#define __MXCSR_ROUND_FLAG_SHIFT 3
+/* 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,
+
+  /* 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)
+};
+
+#define __FE_EXCEPT(__NAME__)   (0x01 << __FE_##__NAME__##_EXCEPT_FLAG_SHIFT)
+
+#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)
+
+/* 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 C99 standard (7.6.9) allows us to define implementation-specific macros for
-  different fp environments */
-
-/* The default Intel x87 floating point environment (64-bit mantissa) */
-#define FE_PC64_ENV ((const fenv_t *)-1)
-
-/* 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
+/* 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))
+
+/* 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 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))
+
+_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);
-
-/* 7.6.3 Rounding */
-
-extern int __cdecl __MINGW_NOTHROW fegetround (void);
-extern int __cdecl __MINGW_NOTHROW fesetround (int mode);
-
-/* 7.6.4 Environment */
-
-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 */
+/* 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);
+
+/* 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);
+
+/* 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 *);
+
+_END_C_DECLS
+
+#endif /* ! RC_INVOKED */
+#endif /* !_FENV_H: $RCSfile$: end of file */
index 74ae1ca..ac5e77b 100644 (file)
@@ -1,18 +1,38 @@
-#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 <colin@bird.fu.is.saga-u.ac.jp>
+ * 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:
  *
  * 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 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. */
+/* 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
+
 #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 */
-
-/*  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 ); */
+/* 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 */
 
 #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);
 
-_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
+#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);
-
-/* Global 'variable' for the current floating point error code. */
-_CRTIMP int * __cdecl __MINGW_NOTHROW __fpecode(void);
-#define        _fpecode        (*(__fpecode()))
 
-/*
- * IEEE recommended functions.  MS puts them in float.h
- * but they really belong in math.h.
+/* 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);
 
-_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);
+/* 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;
 
-_CRTIMP int __cdecl __MINGW_NOTHROW _finite (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _fpclass (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _isnan (double);
+#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 *);
 
-#ifdef __cplusplus
-}
+__CRT_ALIAS __LIBIMPL__( FUNCTION = fpreset )
+void fpreset (void){ fesetenv ((const fenv_t *)(0)); }
 #endif
 
-#endif /* Not RC_INVOKED */
+/* 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 __cdecl __MINGW_NOTHROW  int _finite (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  int _fpclass (double);
+_CRTIMP __cdecl __MINGW_NOTHROW  int _isnan (double);
 
-#endif /* Not __STRICT_ANSI__ */
+_END_C_DECLS
 
-#endif /* _MINGW_FLOAT_H_ */
+#endif /* ! RC_INVOKED */
+#endif /* !__STRICT_ANSI__ */
 
+#endif /* _MINGW_FLOAT_H: $RCSfile$: end of file */
index 4a5e633..a209aa8 100644 (file)
+/*
+ * fesetenv.c
+ *
+ * Implements the fesetenv(3) function, per ISO-C99 section 7.6.4.3
+ *
+ * $Id$
+ *
+ * Written by Danny Smith  <dannysmith@users.sourceforge.net>
+ * 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.  */
-
-  unsigned int _csr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT /*= 0x1f80 */;
-
-  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 (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
-    */
-
-   (*_imp___fpreset)();
-
-  else if (envp == FE_DFL_ENV)
-    /* Use the choice made at app startup */
+  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;
+
+  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;
+
+  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;
+
+  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" );
+
+  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 */