1/* Raise given exceptions. 2 Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. 5 6 The GNU C Library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 The GNU C Library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with the GNU C Library; if not, write to the Free 18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 19 02111-1307 USA. */ 20 21#include <fenv.h> 22#include <math.h> 23 24int 25__feraiseexcept (int excepts) 26{ 27 /* Raise exceptions represented by EXPECTS. But we must raise only 28 one signal at a time. It is important that if the overflow/underflow 29 exception and the inexact exception are given at the same time, 30 the overflow/underflow exception follows the inexact exception. */ 31 32 /* First: invalid exception. */ 33 if ((FE_INVALID & excepts) != 0) 34 { 35 /* One example of a invalid operation is 0.0 / 0.0. */ 36 double d; 37 __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d)); 38 (void) &d; 39 } 40 41 /* Next: division by zero. */ 42 if ((FE_DIVBYZERO & excepts) != 0) 43 { 44 double d; 45 __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait" 46 : "=t" (d)); 47 (void) &d; 48 } 49 50 /* Next: overflow. */ 51 if ((FE_OVERFLOW & excepts) != 0) 52 { 53 /* There is no way to raise only the overflow flag. Do it the 54 hard way. */ 55 fenv_t temp; 56 57 /* Bah, we have to clear selected exceptions. Since there is no 58 `fldsw' instruction we have to do it the hard way. */ 59 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); 60 61 /* Set the relevant bits. */ 62 temp.__status_word |= FE_OVERFLOW; 63 64 /* Put the new data in effect. */ 65 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); 66 67 /* And raise the exception. */ 68 __asm__ __volatile__ ("fwait"); 69 } 70 71 /* Next: underflow. */ 72 if ((FE_UNDERFLOW & excepts) != 0) 73 { 74 /* There is no way to raise only the underflow flag. Do it the 75 hard way. */ 76 fenv_t temp; 77 78 /* Bah, we have to clear selected exceptions. Since there is no 79 `fldsw' instruction we have to do it the hard way. */ 80 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); 81 82 /* Set the relevant bits. */ 83 temp.__status_word |= FE_UNDERFLOW; 84 85 /* Put the new data in effect. */ 86 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); 87 88 /* And raise the exception. */ 89 __asm__ __volatile__ ("fwait"); 90 } 91 92 /* Last: inexact. */ 93 if ((FE_INEXACT & excepts) != 0) 94 { 95 /* There is no way to raise only the inexact flag. Do it the 96 hard way. */ 97 fenv_t temp; 98 99 /* Bah, we have to clear selected exceptions. Since there is no 100 `fldsw' instruction we have to do it the hard way. */ 101 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); 102 103 /* Set the relevant bits. */ 104 temp.__status_word |= FE_INEXACT; 105 106 /* Put the new data in effect. */ 107 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); 108 109 /* And raise the exception. */ 110 __asm__ __volatile__ ("fwait"); 111 } 112 113 /* Success. */ 114 return 0; 115} 116 117#include <shlib-compat.h> 118#if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2) 119strong_alias (__feraiseexcept, __old_feraiseexcept) 120compat_symbol (libm, __old_feraiseexcept, feraiseexcept, GLIBC_2_1); 121#endif 122 123libm_hidden_ver (__feraiseexcept, feraiseexcept) 124versioned_symbol (libm, __feraiseexcept, feraiseexcept, GLIBC_2_2); 125