Back to index

glibc  2.9
fraiseexcpt.c
Go to the documentation of this file.
00001 /* Raise given exceptions.
00002    Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <fenv.h>
00022 #include <math.h>
00023 
00024 int
00025 __feraiseexcept (int excepts)
00026 {
00027   /* Raise exceptions represented by EXPECTS.  But we must raise only
00028      one signal at a time.  It is important that if the overflow/underflow
00029      exception and the inexact exception are given at the same time,
00030      the overflow/underflow exception follows the inexact exception.  */
00031 
00032   /* First: invalid exception.  */
00033   if ((FE_INVALID & excepts) != 0)
00034     {
00035       /* One example of a invalid operation is 0.0 / 0.0.  */
00036       double d;
00037       __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d));
00038       (void) &d;
00039     }
00040 
00041   /* Next: division by zero.  */
00042   if ((FE_DIVBYZERO & excepts) != 0)
00043     {
00044       double d;
00045       __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait"
00046                          : "=t" (d));
00047       (void) &d;
00048     }
00049 
00050   /* Next: overflow.  */
00051   if ((FE_OVERFLOW & excepts) != 0)
00052     {
00053       /* There is no way to raise only the overflow flag.  Do it the
00054         hard way.  */
00055       fenv_t temp;
00056 
00057       /* Bah, we have to clear selected exceptions.  Since there is no
00058         `fldsw' instruction we have to do it the hard way.  */
00059       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
00060 
00061       /* Set the relevant bits.  */
00062       temp.__status_word |= FE_OVERFLOW;
00063 
00064       /* Put the new data in effect.  */
00065       __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
00066 
00067       /* And raise the exception.  */
00068       __asm__ __volatile__ ("fwait");
00069     }
00070 
00071   /* Next: underflow.  */
00072   if ((FE_UNDERFLOW & excepts) != 0)
00073     {
00074       /* There is no way to raise only the underflow flag.  Do it the
00075         hard way.  */
00076       fenv_t temp;
00077 
00078       /* Bah, we have to clear selected exceptions.  Since there is no
00079         `fldsw' instruction we have to do it the hard way.  */
00080       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
00081 
00082       /* Set the relevant bits.  */
00083       temp.__status_word |= FE_UNDERFLOW;
00084 
00085       /* Put the new data in effect.  */
00086       __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
00087 
00088       /* And raise the exception.  */
00089       __asm__ __volatile__ ("fwait");
00090     }
00091 
00092   /* Last: inexact.  */
00093   if ((FE_INEXACT & excepts) != 0)
00094     {
00095       /* There is no way to raise only the inexact flag.  Do it the
00096         hard way.  */
00097       fenv_t temp;
00098 
00099       /* Bah, we have to clear selected exceptions.  Since there is no
00100         `fldsw' instruction we have to do it the hard way.  */
00101       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
00102 
00103       /* Set the relevant bits.  */
00104       temp.__status_word |= FE_INEXACT;
00105 
00106       /* Put the new data in effect.  */
00107       __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
00108 
00109       /* And raise the exception.  */
00110       __asm__ __volatile__ ("fwait");
00111     }
00112 
00113   /* Success.  */
00114   return 0;
00115 }
00116 
00117 #include <shlib-compat.h>
00118 #if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2)
00119 strong_alias (__feraiseexcept, __old_feraiseexcept)
00120 compat_symbol (libm, __old_feraiseexcept, feraiseexcept, GLIBC_2_1);
00121 #endif
00122 
00123 libm_hidden_ver (__feraiseexcept, feraiseexcept)
00124 versioned_symbol (libm, __feraiseexcept, feraiseexcept, GLIBC_2_2);