From: Keith Marshall Date: Mon, 27 Feb 2017 17:46:27 +0000 (+0000) Subject: Make floating point environment more robust. X-Git-Tag: wsl-5.0-release~3 X-Git-Url: http://git.osdn.net/view?p=mingw%2Fmingw-org-wsl.git;a=commitdiff_plain;h=571d98ec8e36bff2636531788d61fe2c3ac490ae Make floating point environment more robust. --- diff --git a/mingwrt/CRT_fenv.c b/mingwrt/CRT_fenv.c new file mode 100644 index 0000000..ac7dfbc --- /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 , 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 + * 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 + +#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 index 516c86c..0000000 --- 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 index 78f4b7e..0000000 --- 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/ChangeLog b/mingwrt/ChangeLog index ec6c8f5..5dfed08 100644 --- a/mingwrt/ChangeLog +++ b/mingwrt/ChangeLog @@ -1,3 +1,51 @@ +2017-02-24 Keith Marshall + + 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 Make mingwrt and w32api test suites consistent. diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in index a830b63..3eb6abd 100644 --- a/mingwrt/Makefile.in +++ b/mingwrt/Makefile.in @@ -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 diff --git a/mingwrt/crt1.c b/mingwrt/crt1.c index c207702..439f9e8 100644 --- a/mingwrt/crt1.c +++ b/mingwrt/crt1.c @@ -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 + * 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 + * , to avoid problems with older GCC. + */ #include #include #include #include -#include +#include + #define WIN32_LEAN_AND_MEAN #include #include @@ -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 , 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 + * 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 */ diff --git a/mingwrt/include/fenv.h b/mingwrt/include/fenv.h index 9b3cec3..58e470a 100644 --- 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 + * 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 */ diff --git a/mingwrt/include/float.h b/mingwrt/include/float.h index 74ae1ca..ac5e77b 100644 --- a/mingwrt/include/float.h +++ b/mingwrt/include/float.h @@ -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 + * 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: * @@ -23,147 +43,185 @@ * 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 +# define _MINGW_FLOAT_H_ 1 /* GCC's needs to see this */ +# include_next /* !__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 ; 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 , and we assume + * that FE_DFL_ENV is equivalent to (const fenv_t *)(0), (as it is, in + * the MinGW implementation of ). + */ +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 , + * 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 */ diff --git a/mingwrt/mingwex/fesetenv.c b/mingwrt/mingwex/fesetenv.c index 4a5e633..a209aa8 100644 --- 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 + * 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 #include #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 */