OSDN Git Service

Adjust repository version following WSL-5.2.2 release.
[mingw/mingw-org-wsl.git] / mingwrt / mingwex / fesetenv.c
1 /*
2  * fesetenv.c
3  *
4  * Implements the fesetenv(3) function, per ISO-C99 section 7.6.4.3
5  *
6  * $Id$
7  *
8  * Written by Danny Smith  <dannysmith@users.sourceforge.net>
9  * Copyright (C) 2002, 2005, 2006, 2017, MinGW.org Project.
10  *
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice, this permission notice, and the following
20  * disclaimer shall be included in all copies or substantial portions of
21  * the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
29  * DEALINGS IN THE SOFTWARE.
30  *
31  */
32 #define __USE_CRTIMP
33
34 #include <fenv.h>
35 #include <float.h>
36 #include "cpu_features.h"
37
38 int fesetenv( const fenv_t *fenvp )
39 {
40   /* Specified by ISO-C99 section 7.6.4.3
41    *
42    * The fesetenv() function establishes the floating-point environment
43    * represented by the object pointed to by "envp".  The argument "envp"
44    * points to an object set by a call to fegetenv() or feholdexcept(), or
45    * equals the macro, FE_DFL_ENV, or an implementation-defined environment
46    * macro.  Note that fesetenv() merely sets the state of the exception
47    * flags represented through its argument; it does not raise these
48    * exceptions.
49    *
50    *
51    * The following static variable stores the predefined environment
52    * which is associated with FE_DFL_ENV; initialize it to represent
53    * the Intel X87 default configuration.
54    */
55   static const fenv_t *fenv_default = FE_PC64_ENV;
56
57   /* Before anything else, establish a default exception handling
58    * policy for SSE instructions, to be used in conjunction with the
59    * predefined FPU state macros, (establishing an effective default
60    * MXCSR status value of 0x1F80, so masking all exceptions, while
61    * leaving all other bits as zero), in the event that SSE support
62    * is available.
63    */
64   unsigned fenv_mxcsr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT;
65
66   if( fenvp == FE_PD64_ENV )
67     /* This is a request to both initialize the FPU state, to the
68      * FE_PC64_ENV predefined state, and to store that state as the
69      * application default.
70      */
71     fenvp = fenv_default = FE_PC64_ENV;
72
73   else if( fenvp == FE_PD53_ENV )
74     /* Conversely, this requests initialization of FPU state to the
75      * FE_PC53_ENV predefined state, and to store that state as the
76      * new application default.
77      */
78     fenvp = fenv_default = FE_PC53_ENV;
79
80   else if( fenvp == FE_DFL_ENV )
81     /* This simply requests initialization of FPU state to whichever
82      * of the two preceding predefined states has been previously set
83      * as the application default.
84      */
85     fenvp = fenv_default;
86
87   if( fenvp == FE_PC64_ENV )
88     /* The FPU's "fninit" instruction initializes the FPU control
89      * word register to 0x37F, the status register to zero and the
90      * tag word to 0xFFFF.  The other registers are unaffected.
91      */
92     __asm__( "fninit" );
93
94   else if( fenvp == FE_PC53_ENV )
95     /* Microsoft's _fpreset() does the same, EXCEPT that it sets
96      * the control word to 0x27F (53-bit precison).  Here, we want
97      * to force a call to _fpreset() in MSVCRT.DLL
98      */
99     _fpreset();
100
101   else
102   { /* The requested FPU state is not represented by any of the
103      * predefined state macros; assume it is a properly constructed
104      * fenv_t structure, and load it to the FPU as is.
105      */
106     __asm__( "fldenv %0" :: "m" (*fenvp) );
107
108     /* Also, in the event that SSE instructions may be supported,
109      * extract the MXCSR flags from this same structure, to be used
110      * instead of the defaults which have been established for use
111      * in conjunction with the predefined state macros, noting that
112      * attempting to set any of the reserved high-order flags will
113      * induce a segmentation fault, so mask them off.
114      */
115     fenv_mxcsr = fenvp->__mxcsr & 0xFFFF;
116   }
117
118   if( __HAS_SSE )
119     /* Finally, if SSE instructions are supported, set the MXCSR
120      * exception handling policy flags...
121      */
122     __asm__( "ldmxcsr %0" :: "m" (fenv_mxcsr) );
123
124   /* ...and we are done; there is no mechanism for us to detect
125    * failure, so simply return zero, indicating success.
126    */
127   return 0;
128 }
129
130 /* $RCSfile$: end of file */