Back to index

glibc  2.9
fesetenv.c
Go to the documentation of this file.
00001 /* Install given floating-point environment.
00002    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <fenv.h>
00021 #include <assert.h>
00022 
00023 
00024 int
00025 fesetenv (const fenv_t *envp)
00026 {
00027   fenv_t temp;
00028 
00029   /* Install the environment specified by ENVP.  But there are a few
00030      values which we do not want to come from the saved environment.
00031      Therefore, we get the current environment and replace the values
00032      we want to use from the environment specified by the parameter.  */
00033   __asm__ ("fnstenv %0\n"
00034           "stmxcsr %1" : "=m" (*&temp), "=m" (*&temp.__mxcsr));
00035 
00036   if (envp == FE_DFL_ENV)
00037     {
00038       temp.__control_word |= FE_ALL_EXCEPT;
00039       temp.__control_word &= ~FE_TOWARDZERO;
00040       temp.__status_word &= ~FE_ALL_EXCEPT;
00041       temp.__eip = 0;
00042       temp.__cs_selector = 0;
00043       temp.__opcode = 0;
00044       temp.__data_offset = 0;
00045       temp.__data_selector = 0;
00046       /* Set mask for SSE MXCSR.  */
00047       temp.__mxcsr |= (FE_ALL_EXCEPT << 7);
00048       /* Set rounding to FE_TONEAREST.  */
00049       temp.__mxcsr &= ~ 0x6000;
00050       temp.__mxcsr |= (FE_TONEAREST << 3);
00051     }
00052   else if (envp == FE_NOMASK_ENV)
00053     {
00054       temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO);
00055       temp.__status_word &= ~FE_ALL_EXCEPT;
00056       temp.__eip = 0;
00057       temp.__cs_selector = 0;
00058       temp.__opcode = 0;
00059       temp.__data_offset = 0;
00060       temp.__data_selector = 0;
00061       /* Set mask for SSE MXCSR.  */
00062       /* Set rounding to FE_TONEAREST.  */
00063       temp.__mxcsr &= ~ 0x6000;
00064       temp.__mxcsr |= (FE_TONEAREST << 3);
00065       /* Do not mask exceptions.  */
00066       temp.__mxcsr &= ~(FE_ALL_EXCEPT << 7);
00067     }
00068   else
00069     {
00070       temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO);
00071       temp.__control_word |= (envp->__control_word
00072                            & (FE_ALL_EXCEPT | FE_TOWARDZERO));
00073       temp.__status_word &= ~FE_ALL_EXCEPT;
00074       temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT;
00075       temp.__eip = envp->__eip;
00076       temp.__cs_selector = envp->__cs_selector;
00077       temp.__opcode = envp->__opcode;
00078       temp.__data_offset = envp->__data_offset;
00079       temp.__data_selector = envp->__data_selector;
00080       temp.__mxcsr = envp->__mxcsr;
00081     }
00082 
00083   __asm__ ("fldenv %0\n"
00084           "ldmxcsr %1" : : "m" (temp), "m" (temp.__mxcsr));
00085 
00086   /* Success.  */
00087   return 0;
00088 }
00089 libm_hidden_def (fesetenv)