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