]>
Commit | Line | Data |
---|---|---|
63551311 | 1 | /* Raise given exceptions. |
d4697bc9 | 2 | Copyright (C) 1997-2014 Free Software Foundation, Inc. |
63551311 UD |
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 | |
41bdb6e2 AJ |
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. | |
63551311 UD |
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 | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
63551311 | 15 | |
41bdb6e2 | 16 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
63551311 UD |
19 | |
20 | #include <fenv.h> | |
21 | #include <math.h> | |
22 | ||
63ae7b63 UD |
23 | int |
24 | __feraiseexcept (int excepts) | |
63551311 UD |
25 | { |
26 | /* Raise exceptions represented by EXPECTS. But we must raise only | |
5ae3e846 | 27 | one signal at a time. It is important that if the overflow/underflow |
63551311 UD |
28 | exception and the inexact exception are given at the same time, |
29 | the overflow/underflow exception follows the inexact exception. */ | |
30 | ||
31 | /* First: invalid exception. */ | |
32 | if ((FE_INVALID & excepts) != 0) | |
33 | { | |
c0c3f78a | 34 | /* One example of an invalid operation is 0.0 / 0.0. */ |
bca973bc | 35 | double d; |
f41c8091 | 36 | __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d)); |
63551311 | 37 | (void) &d; |
63551311 UD |
38 | } |
39 | ||
40 | /* Next: division by zero. */ | |
41 | if ((FE_DIVBYZERO & excepts) != 0) | |
42 | { | |
43 | double d; | |
f41c8091 UD |
44 | __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait" |
45 | : "=t" (d)); | |
63551311 UD |
46 | (void) &d; |
47 | } | |
48 | ||
49 | /* Next: overflow. */ | |
50 | if ((FE_OVERFLOW & excepts) != 0) | |
51 | { | |
bca973bc UD |
52 | /* There is no way to raise only the overflow flag. Do it the |
53 | hard way. */ | |
54 | fenv_t temp; | |
55 | ||
56 | /* Bah, we have to clear selected exceptions. Since there is no | |
57 | `fldsw' instruction we have to do it the hard way. */ | |
f41c8091 | 58 | __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); |
bca973bc UD |
59 | |
60 | /* Set the relevant bits. */ | |
33d1a2c5 | 61 | temp.__status_word |= FE_OVERFLOW; |
bca973bc UD |
62 | |
63 | /* Put the new data in effect. */ | |
f41c8091 | 64 | __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); |
bca973bc UD |
65 | |
66 | /* And raise the exception. */ | |
f41c8091 | 67 | __asm__ __volatile__ ("fwait"); |
63551311 UD |
68 | } |
69 | ||
70 | /* Next: underflow. */ | |
71 | if ((FE_UNDERFLOW & excepts) != 0) | |
72 | { | |
762a2918 | 73 | /* There is no way to raise only the underflow flag. Do it the |
bca973bc UD |
74 | hard way. */ |
75 | fenv_t temp; | |
76 | ||
77 | /* Bah, we have to clear selected exceptions. Since there is no | |
78 | `fldsw' instruction we have to do it the hard way. */ | |
f41c8091 | 79 | __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); |
bca973bc UD |
80 | |
81 | /* Set the relevant bits. */ | |
33d1a2c5 | 82 | temp.__status_word |= FE_UNDERFLOW; |
bca973bc UD |
83 | |
84 | /* Put the new data in effect. */ | |
f41c8091 | 85 | __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); |
bca973bc UD |
86 | |
87 | /* And raise the exception. */ | |
f41c8091 | 88 | __asm__ __volatile__ ("fwait"); |
63551311 UD |
89 | } |
90 | ||
91 | /* Last: inexact. */ | |
92 | if ((FE_INEXACT & excepts) != 0) | |
93 | { | |
762a2918 | 94 | /* There is no way to raise only the inexact flag. Do it the |
5ae3e846 UD |
95 | hard way. */ |
96 | fenv_t temp; | |
97 | ||
98 | /* Bah, we have to clear selected exceptions. Since there is no | |
99 | `fldsw' instruction we have to do it the hard way. */ | |
f41c8091 | 100 | __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); |
5ae3e846 UD |
101 | |
102 | /* Set the relevant bits. */ | |
33d1a2c5 | 103 | temp.__status_word |= FE_INEXACT; |
5ae3e846 UD |
104 | |
105 | /* Put the new data in effect. */ | |
f41c8091 | 106 | __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); |
5ae3e846 UD |
107 | |
108 | /* And raise the exception. */ | |
f41c8091 | 109 | __asm__ __volatile__ ("fwait"); |
63551311 | 110 | } |
63ae7b63 UD |
111 | |
112 | /* Success. */ | |
113 | return 0; | |
63551311 | 114 | } |
4eb8a862 RM |
115 | |
116 | #include <shlib-compat.h> | |
117 | #if SHLIB_COMPAT (libm, GLIBC_2_1, GLIBC_2_2) | |
63ae7b63 | 118 | strong_alias (__feraiseexcept, __old_feraiseexcept) |
4eb8a862 RM |
119 | compat_symbol (libm, __old_feraiseexcept, feraiseexcept, GLIBC_2_1); |
120 | #endif | |
121 | ||
0747f818 | 122 | libm_hidden_def (__feraiseexcept) |
76f2646f | 123 | libm_hidden_ver (__feraiseexcept, feraiseexcept) |
4eb8a862 | 124 | versioned_symbol (libm, __feraiseexcept, feraiseexcept, GLIBC_2_2); |