]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/i386/fpu/fesetenv.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / sysdeps / i386 / fpu / fesetenv.c
CommitLineData
63551311 1/* Install given floating-point environment.
04277e02 2 Copyright (C) 1997-2019 Free Software Foundation, Inc.
63551311
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
63551311
UD
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 14 Lesser General Public License for more details.
63551311 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
63551311
UD
19
20#include <fenv.h>
2145f97c 21#include <fpu_control.h>
63551311 22#include <assert.h>
77d08aca
JM
23#include <unistd.h>
24#include <ldsodefs.h>
25#include <dl-procinfo.h>
63551311
UD
26
27
2145f97c
JM
28/* All exceptions, including the x86-specific "denormal operand"
29 exception. */
30#define FE_ALL_EXCEPT_X86 (FE_ALL_EXCEPT | __FE_DENORM)
31
32
63ae7b63
UD
33int
34__fesetenv (const fenv_t *envp)
63551311
UD
35{
36 fenv_t temp;
37
38 /* The memory block used by fstenv/fldenv has a size of 28 bytes. */
39 assert (sizeof (fenv_t) == 28);
40
41 /* Install the environment specified by ENVP. But there are a few
42 values which we do not want to come from the saved environment.
43 Therefore, we get the current environment and replace the values
44 we want to use from the environment specified by the parameter. */
45 __asm__ ("fnstenv %0" : "=m" (*&temp));
46
47 if (envp == FE_DFL_ENV)
48 {
2145f97c 49 temp.__control_word |= FE_ALL_EXCEPT_X86;
33d1a2c5 50 temp.__control_word &= ~FE_TOWARDZERO;
2145f97c
JM
51 temp.__control_word |= _FPU_EXTENDED;
52 temp.__status_word &= ~FE_ALL_EXCEPT_X86;
63551311
UD
53 }
54 else if (envp == FE_NOMASK_ENV)
55 {
33d1a2c5 56 temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO);
2145f97c
JM
57 /* Keep the "denormal operand" exception masked. */
58 temp.__control_word |= __FE_DENORM;
59 temp.__control_word |= _FPU_EXTENDED;
60 temp.__status_word &= ~FE_ALL_EXCEPT_X86;
63551311
UD
61 }
62 else
63 {
2145f97c
JM
64 temp.__control_word &= ~(FE_ALL_EXCEPT_X86
65 | FE_TOWARDZERO
66 | _FPU_EXTENDED);
33d1a2c5 67 temp.__control_word |= (envp->__control_word
2145f97c
JM
68 & (FE_ALL_EXCEPT_X86
69 | FE_TOWARDZERO
70 | _FPU_EXTENDED));
71 temp.__status_word &= ~FE_ALL_EXCEPT_X86;
72 temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT_X86;
63551311 73 }
77d08aca
JM
74 temp.__eip = 0;
75 temp.__cs_selector = 0;
76 temp.__opcode = 0;
77 temp.__data_offset = 0;
78 temp.__data_selector = 0;
63551311
UD
79
80 __asm__ ("fldenv %0" : : "m" (temp));
63ae7b63 81
bf773019 82 if (HAS_CPU_FEATURE (SSE))
77d08aca
JM
83 {
84 unsigned int mxcsr;
85 __asm__ ("stmxcsr %0" : "=m" (mxcsr));
86
87 if (envp == FE_DFL_ENV)
88 {
0b9af583 89 /* Clear SSE exceptions. */
2145f97c 90 mxcsr &= ~FE_ALL_EXCEPT_X86;
77d08aca 91 /* Set mask for SSE MXCSR. */
2145f97c 92 mxcsr |= (FE_ALL_EXCEPT_X86 << 7);
77d08aca
JM
93 /* Set rounding to FE_TONEAREST. */
94 mxcsr &= ~0x6000;
95 mxcsr |= (FE_TONEAREST << 3);
2145f97c
JM
96 /* Clear the FZ and DAZ bits. */
97 mxcsr &= ~0x8040;
77d08aca
JM
98 }
99 else if (envp == FE_NOMASK_ENV)
100 {
0b9af583 101 /* Clear SSE exceptions. */
2145f97c 102 mxcsr &= ~FE_ALL_EXCEPT_X86;
77d08aca
JM
103 /* Do not mask exceptions. */
104 mxcsr &= ~(FE_ALL_EXCEPT << 7);
2145f97c
JM
105 /* Keep the "denormal operand" exception masked. */
106 mxcsr |= (__FE_DENORM << 7);
77d08aca
JM
107 /* Set rounding to FE_TONEAREST. */
108 mxcsr &= ~0x6000;
109 mxcsr |= (FE_TONEAREST << 3);
2145f97c
JM
110 /* Clear the FZ and DAZ bits. */
111 mxcsr &= ~0x8040;
77d08aca
JM
112 }
113 else
114 mxcsr = envp->__eip;
115
116 __asm__ ("ldmxcsr %0" : : "m" (mxcsr));
117 }
118
63ae7b63
UD
119 /* Success. */
120 return 0;
63551311 121}
4eb8a862
RM
122
123#include <shlib-compat.h>
124#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
63ae7b63 125strong_alias (__fesetenv, __old_fesetenv)
e97ed6dd 126compat_symbol (libm, __old_fesetenv, fesetenv, GLIBC_2_1);
4eb8a862
RM
127#endif
128
cd42798a 129libm_hidden_def (__fesetenv)
76f2646f 130libm_hidden_ver (__fesetenv, fesetenv)
e97ed6dd 131versioned_symbol (libm, __fesetenv, fesetenv, GLIBC_2_2);