From bce5bba7a01fb090f67fec5f79218c505c841af3 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Sat, 19 Jan 2008 15:23:14 +0000 Subject: - add C99 floating point environment, rounding and exception handling functions for i386. UCLIBC_HAS_FENV --- libm/i386/Makefile.arch | 24 ++++++++++ libm/i386/fclrexcpt.c | 61 ++++++++++++++++++++++++ libm/i386/fedisblxcpt.c | 55 ++++++++++++++++++++++ libm/i386/feenablxcpt.c | 55 ++++++++++++++++++++++ libm/i386/fegetenv.c | 34 ++++++++++++++ libm/i386/fegetexcept.c | 32 +++++++++++++ libm/i386/fegetround.c | 31 +++++++++++++ libm/i386/feholdexcpt.c | 59 ++++++++++++++++++++++++ libm/i386/fesetenv.c | 80 ++++++++++++++++++++++++++++++++ libm/i386/fesetround.c | 52 +++++++++++++++++++++ libm/i386/feupdateenv.c | 56 ++++++++++++++++++++++ libm/i386/fgetexcptflg.c | 35 ++++++++++++++ libm/i386/fraiseexcpt.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ libm/i386/fsetexcptflg.c | 62 +++++++++++++++++++++++++ libm/i386/ftestexcept.c | 40 ++++++++++++++++ 15 files changed, 794 insertions(+) create mode 100644 libm/i386/Makefile.arch create mode 100644 libm/i386/fclrexcpt.c create mode 100644 libm/i386/fedisblxcpt.c create mode 100644 libm/i386/feenablxcpt.c create mode 100644 libm/i386/fegetenv.c create mode 100644 libm/i386/fegetexcept.c create mode 100644 libm/i386/fegetround.c create mode 100644 libm/i386/feholdexcpt.c create mode 100644 libm/i386/fesetenv.c create mode 100644 libm/i386/fesetround.c create mode 100644 libm/i386/feupdateenv.c create mode 100644 libm/i386/fgetexcptflg.c create mode 100644 libm/i386/fraiseexcpt.c create mode 100644 libm/i386/fsetexcptflg.c create mode 100644 libm/i386/ftestexcept.c (limited to 'libm/i386') diff --git a/libm/i386/Makefile.arch b/libm/i386/Makefile.arch new file mode 100644 index 000000000..e1be961f2 --- /dev/null +++ b/libm/i386/Makefile.arch @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# The routines included in this math library are derived from +# glibc's libm. +# + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) + diff --git a/libm/i386/fclrexcpt.c b/libm/i386/fclrexcpt.c new file mode 100644 index 000000000..a34060ce8 --- /dev/null +++ b/libm/i386/fclrexcpt.c @@ -0,0 +1,61 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1997,99,2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feclearexcept (int excepts) +{ + fenv_t temp; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + /* Clear the relevant bits. */ + temp.__status_word &= excepts ^ FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we clear the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Clear the relevant bits. */ + xnew_exc &= ~excepts; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/libm/i386/fedisblxcpt.c b/libm/i386/fedisblxcpt.c new file mode 100644 index 000000000..75dc17897 --- /dev/null +++ b/libm/i386/fedisblxcpt.c @@ -0,0 +1,55 @@ +/* Disable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fedisableexcept (int excepts) +{ + unsigned short int new_exc, old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc |= excepts << 7; + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/libm/i386/feenablxcpt.c b/libm/i386/feenablxcpt.c new file mode 100644 index 000000000..174f9f1ad --- /dev/null +++ b/libm/i386/feenablxcpt.c @@ -0,0 +1,55 @@ +/* Enable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feenableexcept (int excepts) +{ + unsigned short int new_exc; + unsigned short int old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + excepts &= FE_ALL_EXCEPT; + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + new_exc &= ~excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc &= ~(excepts << 7); + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/libm/i386/fegetenv.c b/libm/i386/fegetenv.c new file mode 100644 index 000000000..abbf179e0 --- /dev/null +++ b/libm/i386/fegetenv.c @@ -0,0 +1,34 @@ +/* Store current floating-point environment. + Copyright (C) 1997,1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetenv (fenv_t *envp) +{ + __asm__ ("fnstenv %0" : "=m" (*envp)); + /* And load it right back since the processor changes the mask. + Intel thought this opcode to be used in interrupt handlers which + would block all exceptions. */ + __asm__ ("fldenv %0" : : "m" (*envp)); + + /* Success. */ + return 0; +} diff --git a/libm/i386/fegetexcept.c b/libm/i386/fegetexcept.c new file mode 100644 index 000000000..71bac788b --- /dev/null +++ b/libm/i386/fegetexcept.c @@ -0,0 +1,32 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexcept (void) +{ + unsigned short int exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&exc)); + + return (~exc) & FE_ALL_EXCEPT; +} diff --git a/libm/i386/fegetround.c b/libm/i386/fegetround.c new file mode 100644 index 000000000..8ae0c3aff --- /dev/null +++ b/libm/i386/fegetround.c @@ -0,0 +1,31 @@ +/* Return current rounding direction. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetround (void) +{ + int cw; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} diff --git a/libm/i386/feholdexcpt.c b/libm/i386/feholdexcpt.c new file mode 100644 index 000000000..d283e9e44 --- /dev/null +++ b/libm/i386/feholdexcpt.c @@ -0,0 +1,59 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997, 1999, 2003, 2004, 2005, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + fenv_t temp; + + /* Store the environment. */ + __asm__ ("fnstenv %0" : "=m" (temp)); + *envp = temp; + + /* Now set all exceptions to non-stop. */ + temp.__control_word |= 0x3f; + + /* And clear all exceptions. */ + temp.__status_word &= ~0x3f; + + __asm__ ("fldenv %0" : : "m" (temp)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xwork; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xwork)); + + /* Set all exceptions to non-stop and clear them. */ + xwork = (xwork | 0x1f80) & ~0x3f; + + __asm__ ("ldmxcsr %0" : : "m" (*&xwork)); + } +#endif + + return 0; +} diff --git a/libm/i386/fesetenv.c b/libm/i386/fesetenv.c new file mode 100644 index 000000000..fdb4fcc92 --- /dev/null +++ b/libm/i386/fesetenv.c @@ -0,0 +1,80 @@ +/* Install given floating-point environment. + Copyright (C) 1997,98,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* The memory block used by fstenv/fldenv has a size of 28 bytes. */ + assert (sizeof (fenv_t) == 28); + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + if (envp == FE_DFL_ENV) + { + temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word &= ~FE_TOWARDZERO; + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else if (envp == FE_NOMASK_ENV) + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word |= (envp->__control_word + & (FE_ALL_EXCEPT | FE_TOWARDZERO)); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + temp.__eip = envp->__eip; + temp.__cs_selector = envp->__cs_selector; + temp.__opcode = envp->__opcode; + temp.__data_offset = envp->__data_offset; + temp.__data_selector = envp->__data_selector; + } + + __asm__ ("fldenv %0" : : "m" (temp)); + + /* Success. */ + return 0; +} +libm_hidden_def(fesetenv) diff --git a/libm/i386/fesetround.c b/libm/i386/fesetround.c new file mode 100644 index 000000000..e1ba16975 --- /dev/null +++ b/libm/i386/fesetround.c @@ -0,0 +1,52 @@ +/* Set current rounding direction. + Copyright (C) 1997, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fesetround (int round) +{ + unsigned short int cw; + + if ((round & ~0xc00) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + __asm__ ("fldcw %0" : : "m" (*&cw)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xcw; + + __asm__ ("stmxcsr %0" : "=m" (*&xcw)); + xcw &= ~0x6000; + xcw |= round << 3; + __asm__ ("ldmxcsr %0" : : "m" (*&xcw)); + } +#endif + + return 0; +} diff --git a/libm/i386/feupdateenv.c b/libm/i386/feupdateenv.c new file mode 100644 index 000000000..91b535dc6 --- /dev/null +++ b/libm/i386/feupdateenv.c @@ -0,0 +1,56 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1997,99,2000,01,07 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) +libm_hidden_proto(feraiseexcept) + +int +feupdateenv (const fenv_t *envp) +{ + fexcept_t temp; + /* unsigned int xtemp = 0; */ + + /* Save current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); + + temp = (temp | xtemp) & FE_ALL_EXCEPT; +#else + temp &= FE_ALL_EXCEPT; +#endif + + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidently for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept ((int) temp); + + /* Success. */ + return 0; +} diff --git a/libm/i386/fgetexcptflg.c b/libm/i386/fgetexcptflg.c new file mode 100644 index 000000000..f99122610 --- /dev/null +++ b/libm/i386/fgetexcptflg.c @@ -0,0 +1,35 @@ +/* Store current representation for exceptions. + Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t temp; + + /* Get the current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/libm/i386/fraiseexcpt.c b/libm/i386/fraiseexcpt.c new file mode 100644 index 000000000..fcb3d0e84 --- /dev/null +++ b/libm/i386/fraiseexcpt.c @@ -0,0 +1,118 @@ +/* Raise given exceptions. + Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(feraiseexcept) + +int +feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if ((FE_INVALID & excepts) != 0) + { + /* One example of a invalid operation is 0.0 / 0.0. */ + double d; + __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d)); + (void) &d; + } + + /* Next: division by zero. */ + if ((FE_DIVBYZERO & excepts) != 0) + { + double d; + __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait" + : "=t" (d)); + (void) &d; + } + + /* Next: overflow. */ + if ((FE_OVERFLOW & excepts) != 0) + { + /* There is no way to raise only the overflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_OVERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Next: underflow. */ + if ((FE_UNDERFLOW & excepts) != 0) + { + /* There is no way to raise only the underflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_UNDERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Last: inexact. */ + if ((FE_INEXACT & excepts) != 0) + { + /* There is no way to raise only the inexact flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_INEXACT; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Success. */ + return 0; +} +libm_hidden_def(feraiseexcept) diff --git a/libm/i386/fsetexcptflg.c b/libm/i386/fsetexcptflg.c new file mode 100644 index 000000000..bdd1dcca0 --- /dev/null +++ b/libm/i386/fsetexcptflg.c @@ -0,0 +1,62 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997,99,2000,01, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fenv_t temp; + + /* Get the current environment. We have to do this since we cannot + separately set the status word. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + temp.__status_word &= ~(excepts & FE_ALL_EXCEPT); + temp.__status_word |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed unless + the next floating-point instruction. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Set the relevant bits. */ + xnew_exc &= ~(excepts & FE_ALL_EXCEPT); + xnew_exc |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/libm/i386/ftestexcept.c b/libm/i386/ftestexcept.c new file mode 100644 index 000000000..ad6bf8954 --- /dev/null +++ b/libm/i386/ftestexcept.c @@ -0,0 +1,40 @@ +/* Test exception in current environment. + Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fetestexcept (int excepts) +{ + int temp; + int xtemp = 0; + + /* Get current exceptions. */ + __asm__ ("fnstsw %0" : "=a" (temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); +#endif + + return (temp | xtemp) & excepts & FE_ALL_EXCEPT; +} -- cgit v1.2.3