Back to index

glibc  2.9
fraiseexcpt.c
Go to the documentation of this file.
00001 /* Raise given exceptions.
00002    Copyright (C) 2004, 2005 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 General Public License
00016    along with GCC; see the file COPYING.  If not, write to the Free
00017    Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
00018    02110-1301, USA.  */
00019 
00020 #include <fpu_control.h>
00021 #include <fenv.h>
00022 #include <float.h>
00023 
00024 #include <unistd.h>
00025 #include <ldsodefs.h>
00026 #include <dl-procinfo.h>
00027 #include <sysdep.h>
00028 
00029 int
00030 feraiseexcept (int excepts)
00031 {
00032   if (GLRO (dl_hwcap) & HWCAP_ARM_VFP)
00033     {
00034       int fpscr;
00035       const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX,
00036                   fp_min = FLT_MIN, fp_1e32 = 1.0e32f, fp_two = 2.0,
00037                 fp_three = 3.0;
00038 
00039       /* Raise exceptions represented by EXPECTS.  But we must raise only
00040         one signal at a time.  It is important that if the overflow/underflow
00041         exception and the inexact exception are given at the same time,
00042         the overflow/underflow exception follows the inexact exception.  After
00043         each exception we read from the fpscr, to force the exception to be
00044         raised immediately.  */
00045 
00046       /* There are additional complications because this file may be compiled
00047          without VFP support enabled, and we also can't assume that the
00048         assembler has VFP instructions enabled. To get around this we use the
00049         generic coprocessor mnemonics and avoid asking GCC to put float values
00050         in VFP registers.  */
00051 
00052       /* First: invalid exception.  */
00053       if (FE_INVALID & excepts)
00054        __asm__ __volatile__ (
00055          "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */
00056          "cdp p10, 8, cr0, cr0, cr0, 0\n\t"            /* fdivs s0, s0, s0  */
00057          "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */
00058                                      : "m" (fp_zero)
00059                                    : "s0");
00060 
00061       /* Next: division by zero.  */
00062       if (FE_DIVBYZERO & excepts)
00063        __asm__ __volatile__ (
00064          "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */
00065          "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */
00066          "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */
00067          "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */
00068                                      : "m" (fp_one), "m" (fp_zero)
00069                                    : "s0", "s1");
00070 
00071       /* Next: overflow.  */
00072       if (FE_OVERFLOW & excepts)
00073        /* There's no way to raise overflow without also raising inexact.  */
00074        __asm__ __volatile__ (
00075          "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */
00076          "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */
00077          "cdp p10, 3, cr0, cr0, cr0, 1\n\t"            /* fadds s0, s0, s1  */
00078          "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */
00079                                      : "m" (fp_max), "m" (fp_1e32)
00080                                    : "s0", "s1");
00081 
00082       /* Next: underflow.  */
00083       if (FE_UNDERFLOW & excepts)
00084        __asm__ __volatile__ (
00085          "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */
00086          "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */
00087          "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */
00088          "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */
00089                                      : "m" (fp_min), "m" (fp_three)
00090                                    : "s0", "s1");
00091 
00092       /* Last: inexact.  */
00093       if (FE_INEXACT & excepts)
00094        __asm__ __volatile__ (
00095          "ldc p10, cr0, %1\n\t"                        /* flds s0, %1  */
00096          "ldcl p10, cr0, %2\n\t"                       /* flds s1, %2  */
00097          "cdp p10, 8, cr0, cr0, cr0, 1\n\t"            /* fdivs s0, s0, s1  */
00098          "mrc p10, 7, %0, cr1, cr0, 0" : "=r" (fpscr)  /* fmrx %0, fpscr  */
00099                                      : "m" (fp_two), "m" (fp_three)
00100                                    : "s0", "s1");
00101 
00102       /* Success.  */
00103       return 0;
00104     }
00105 
00106   /* Unsupported, so fail.  */
00107   return 1;
00108 }
00109 
00110 libm_hidden_def (feraiseexcept)