blob: fcb3d0e84ad3241123174d7c5a16446056193de2 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* 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
24libm_hidden_proto(feraiseexcept)
25
26int
27feraiseexcept (int excepts)
28{
29 /* Raise exceptions represented by EXPECTS. But we must raise only
30 one signal at a time. It is important that if the overflow/underflow
31 exception and the inexact exception are given at the same time,
32 the overflow/underflow exception follows the inexact exception. */
33
34 /* First: invalid exception. */
35 if ((FE_INVALID & excepts) != 0)
36 {
37 /* One example of a invalid operation is 0.0 / 0.0. */
38 double d;
39 __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d));
40 (void) &d;
41 }
42
43 /* Next: division by zero. */
44 if ((FE_DIVBYZERO & excepts) != 0)
45 {
46 double d;
47 __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait"
48 : "=t" (d));
49 (void) &d;
50 }
51
52 /* Next: overflow. */
53 if ((FE_OVERFLOW & excepts) != 0)
54 {
55 /* There is no way to raise only the overflow flag. Do it the
56 hard way. */
57 fenv_t temp;
58
59 /* Bah, we have to clear selected exceptions. Since there is no
60 `fldsw' instruction we have to do it the hard way. */
61 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
62
63 /* Set the relevant bits. */
64 temp.__status_word |= FE_OVERFLOW;
65
66 /* Put the new data in effect. */
67 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
68
69 /* And raise the exception. */
70 __asm__ __volatile__ ("fwait");
71 }
72
73 /* Next: underflow. */
74 if ((FE_UNDERFLOW & excepts) != 0)
75 {
76 /* There is no way to raise only the underflow flag. Do it the
77 hard way. */
78 fenv_t temp;
79
80 /* Bah, we have to clear selected exceptions. Since there is no
81 `fldsw' instruction we have to do it the hard way. */
82 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
83
84 /* Set the relevant bits. */
85 temp.__status_word |= FE_UNDERFLOW;
86
87 /* Put the new data in effect. */
88 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
89
90 /* And raise the exception. */
91 __asm__ __volatile__ ("fwait");
92 }
93
94 /* Last: inexact. */
95 if ((FE_INEXACT & excepts) != 0)
96 {
97 /* There is no way to raise only the inexact flag. Do it the
98 hard way. */
99 fenv_t temp;
100
101 /* Bah, we have to clear selected exceptions. Since there is no
102 `fldsw' instruction we have to do it the hard way. */
103 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
104
105 /* Set the relevant bits. */
106 temp.__status_word |= FE_INEXACT;
107
108 /* Put the new data in effect. */
109 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
110
111 /* And raise the exception. */
112 __asm__ __volatile__ ("fwait");
113 }
114
115 /* Success. */
116 return 0;
117}
118libm_hidden_def(feraiseexcept)