chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / sysdeps / x86_64 / fpu / fraiseexcpt.c
1 /* Raise given exceptions.
2    Copyright (C) 2001, 2002 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <fenv.h>
21 #include <math.h>
22
23 int
24 feraiseexcept (int excepts)
25 {
26   /* Raise exceptions represented by EXPECTS.  But we must raise only
27      one signal at a time.  It is important that if the overflow/underflow
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     {
34       /* One example of a invalid operation is 0.0 / 0.0.  */
35       float f = 0.0;
36
37       __asm__ __volatile__ ("divss %0, %0 " : : "x" (f));
38       (void) &f;
39     }
40
41   /* Next: division by zero.  */
42   if ((FE_DIVBYZERO & excepts) != 0)
43     {
44       float f = 1.0;
45       float g = 0.0;
46
47       __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g));
48       (void) &f;
49     }
50
51   /* Next: overflow.  */
52   if ((FE_OVERFLOW & excepts) != 0)
53     {
54       /* XXX: Is it ok to only set the x87 FPU?  */
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       /* XXX: Is it ok to only set the x87 FPU?  */
77       /* There is no way to raise only the underflow flag.  Do it the
78          hard way.  */
79       fenv_t temp;
80
81       /* Bah, we have to clear selected exceptions.  Since there is no
82          `fldsw' instruction we have to do it the hard way.  */
83       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
84
85       /* Set the relevant bits.  */
86       temp.__status_word |= FE_UNDERFLOW;
87
88       /* Put the new data in effect.  */
89       __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
90
91       /* And raise the exception.  */
92       __asm__ __volatile__ ("fwait");
93     }
94
95   /* Last: inexact.  */
96   if ((FE_INEXACT & excepts) != 0)
97     {
98       /* XXX: Is it ok to only set the x87 FPU?  */
99       /* There is no way to raise only the inexact flag.  Do it the
100          hard way.  */
101       fenv_t temp;
102
103       /* Bah, we have to clear selected exceptions.  Since there is no
104          `fldsw' instruction we have to do it the hard way.  */
105       __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
106
107       /* Set the relevant bits.  */
108       temp.__status_word |= FE_INEXACT;
109
110       /* Put the new data in effect.  */
111       __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
112
113       /* And raise the exception.  */
114       __asm__ __volatile__ ("fwait");
115     }
116
117   /* Success.  */
118   return 0;
119 }
120 libm_hidden_def (feraiseexcept)