Back to index

glibc  2.9
fraiseexcpt.c
Go to the documentation of this file.
00001 /* Raise given exceptions.
00002    Copyright (C) 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by David Huggins-Daines <dhd@debian.org>
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 <float.h>
00023 #include <math.h>
00024 
00025 /* Please see section 10, 
00026    page 10-5 "Delayed Trapping" in the PA-RISC 2.0 Architecture manual */
00027 
00028 int
00029 feraiseexcept (int excepts)
00030 {
00031   /* Raise exceptions represented by EXCEPTS.  But we must raise only one
00032      signal at a time.  It is important that if the overflow/underflow
00033      exception and the divide by zero exception are given at the same
00034      time, the overflow/underflow exception follows the divide by zero
00035      exception.  */
00036 
00037   /* We do these bits in assembly to be certain GCC doesn't optimize
00038      away something important, and so we can force delayed traps to
00039      occur. */
00040 
00041   /* We use "fldd 0(%%sr0,%%sp),%0" to flush the delayed exception */
00042        
00043   /* First: Invalid exception.  */
00044   if (excepts & FE_INVALID)
00045     {
00046       /* One example of a invalid operation is 0 * Infinity.  */
00047       double d = HUGE_VAL;
00048       __asm__ __volatile__ (
00049               "      fcpy,dbl %%fr0,%%fr22\n"
00050               "      fmpy,dbl %0,%%fr22,%0\n"
00051               "      fldd 0(%%sr0,%%sp),%0"
00052               : "+f" (d) : : "%fr22" );
00053     }
00054 
00055   /* Second: Division by zero.  */
00056   if (excepts & FE_DIVBYZERO)
00057     {
00058       double d = 1.0;
00059       __asm__ __volatile__ (
00060               "      fcpy,dbl %%fr0,%%fr22\n"
00061               "      fdiv,dbl %0,%%fr22,%0\n"
00062               "      fldd 0(%%sr0,%%sp),%0"
00063               : "+f" (d) : : "%fr22" );
00064     }
00065 
00066   /* Third: Overflow.  */
00067   if (excepts & FE_OVERFLOW)
00068     {
00069       double d = DBL_MAX;
00070       __asm__ __volatile__ (
00071               "      fadd,dbl %0,%0,%0\n"
00072               "      fldd 0(%%sr0,%%sp),%0"
00073               : "+f" (d) );
00074     }
00075 
00076   /* Fourth: Underflow.  */
00077   if (excepts & FE_UNDERFLOW)
00078     {
00079       double d = DBL_MIN;
00080       double e = 3.0;
00081       __asm__ __volatile__ (
00082               "      fdiv,dbl %0,%1,%0\n"
00083               "      fldd 0(%%sr0,%%sp),%0"
00084               : "+f" (d) : "f" (e) );
00085     }
00086 
00087   /* Fifth: Inexact */
00088   if (excepts & FE_INEXACT)
00089     {
00090       double d = M_PI;
00091       double e = 69.69;
00092       __asm__ __volatile__ (
00093               "      fdiv,dbl %0,%1,%%fr22\n"
00094               "      fcnvfxt,dbl,sgl %%fr22,%%fr22L\n"
00095               "      fldd 0(%%sr0,%%sp),%%fr22"
00096               : : "f" (d), "f" (e) : "%fr22" );
00097     }
00098 
00099   /* Success.  */
00100   return 0;
00101 }
00102 libm_hidden_def (feraiseexcept)