4 * Implements the fesetenv(3) function, per ISO-C99 section 7.6.4.3
8 * Written by Danny Smith <dannysmith@users.sourceforge.net>
9 * Copyright (C) 2002, 2005, 2006, 2017, MinGW.org Project.
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:
19 * The above copyright notice, this permission notice, and the following
20 * disclaimer shall be included in all copies or substantial portions of
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.
36 #include "cpu_features.h"
38 int fesetenv( const fenv_t *fenvp )
40 /* Specified by ISO-C99 section 7.6.4.3
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
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.
55 static const fenv_t *fenv_default = FE_PC64_ENV;
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
64 unsigned fenv_mxcsr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT;
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.
71 fenvp = fenv_default = FE_PC64_ENV;
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.
78 fenvp = fenv_default = FE_PC53_ENV;
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.
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.
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
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.
106 __asm__( "fldenv %0" :: "m" (*fenvp) );
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.
115 fenv_mxcsr = fenvp->__mxcsr & 0xFFFF;
119 /* Finally, if SSE instructions are supported, set the MXCSR
120 * exception handling policy flags...
122 __asm__( "ldmxcsr %0" :: "m" (fenv_mxcsr) );
124 /* ...and we are done; there is no mechanism for us to detect
125 * failure, so simply return zero, indicating success.
130 /* $RCSfile$: end of file */