Update copyright notices with scripts/update-copyrights
[glibc.git] / sysdeps / x86_64 / fpu / fraiseexcpt.c
blob5aeaf30040c10e15bc32d9722ff5c9f91146219b
1 /* Raise given exceptions.
2 Copyright (C) 2001-2014 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #include <fenv.h>
20 #include <math.h>
22 int
23 __feraiseexcept (int excepts)
25 /* Raise exceptions represented by EXPECTS. But we must raise only
26 one signal at a time. It is important that if the overflow/underflow
27 exception and the inexact exception are given at the same time,
28 the overflow/underflow exception follows the inexact exception. */
30 /* First: invalid exception. */
31 if ((FE_INVALID & excepts) != 0)
33 /* One example of an invalid operation is 0.0 / 0.0. */
34 float f = 0.0;
36 __asm__ __volatile__ ("divss %0, %0 " : : "x" (f));
37 (void) &f;
40 /* Next: division by zero. */
41 if ((FE_DIVBYZERO & excepts) != 0)
43 float f = 1.0;
44 float g = 0.0;
46 __asm__ __volatile__ ("divss %1, %0" : : "x" (f), "x" (g));
47 (void) &f;
50 /* Next: overflow. */
51 if ((FE_OVERFLOW & excepts) != 0)
53 /* XXX: Is it ok to only set the x87 FPU? */
54 /* There is no way to raise only the overflow flag. Do it the
55 hard way. */
56 fenv_t temp;
58 /* Bah, we have to clear selected exceptions. Since there is no
59 `fldsw' instruction we have to do it the hard way. */
60 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
62 /* Set the relevant bits. */
63 temp.__status_word |= FE_OVERFLOW;
65 /* Put the new data in effect. */
66 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
68 /* And raise the exception. */
69 __asm__ __volatile__ ("fwait");
72 /* Next: underflow. */
73 if ((FE_UNDERFLOW & excepts) != 0)
75 /* XXX: Is it ok to only set the x87 FPU? */
76 /* There is no way to raise only the underflow flag. Do it the
77 hard way. */
78 fenv_t temp;
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));
84 /* Set the relevant bits. */
85 temp.__status_word |= FE_UNDERFLOW;
87 /* Put the new data in effect. */
88 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
90 /* And raise the exception. */
91 __asm__ __volatile__ ("fwait");
94 /* Last: inexact. */
95 if ((FE_INEXACT & excepts) != 0)
97 /* XXX: Is it ok to only set the x87 FPU? */
98 /* There is no way to raise only the inexact flag. Do it the
99 hard way. */
100 fenv_t temp;
102 /* Bah, we have to clear selected exceptions. Since there is no
103 `fldsw' instruction we have to do it the hard way. */
104 __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp));
106 /* Set the relevant bits. */
107 temp.__status_word |= FE_INEXACT;
109 /* Put the new data in effect. */
110 __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp));
112 /* And raise the exception. */
113 __asm__ __volatile__ ("fwait");
116 /* Success. */
117 return 0;
119 strong_alias (__feraiseexcept, feraiseexcept)
120 libm_hidden_def (feraiseexcept)