1 /* Raise given exceptions.
2    Copyright (C) 2013 Imagination Technologies Ltd.
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; see the file COPYING.LIB.  If
17    not, see <http://www.gnu.org/licenses/>.  */
18 
19 #include <fenv.h>
20 #include <math.h>
21 
libm_hidden_proto(feraiseexcept)22 libm_hidden_proto(feraiseexcept)
23 
24 int
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       /* Reciprocal square root of a negative number is invalid. */
36       __asm__ volatile(
37 		   "F MOV FX.0,#0xc000 ! -2\n"
38 		   "F RSQ FX.1,FX.0\n"
39 		   );
40     }
41 
42   /* Next: division by zero.  */
43   if ((FE_DIVBYZERO & excepts) != 0)
44     {
45       __asm__ volatile(
46 		   "F MOV FX.0,#0\n"
47 		   "F RCP FX.1,FX.0\n"
48 		   );
49     }
50 
51   /* Next: overflow.  */
52   if ((FE_OVERFLOW & excepts) != 0)
53     {
54       /* Adding a large number in single precision can cause overflow. */
55       __asm__ volatile(
56 		   "  MOVT D0.0,#0x7f7f\n"
57 		   "  ADD  D0.0,D0.0,#0xffff\n"
58 		   "F MOV  FX.0,D0.0\n"
59 		   "F ADD  FX.1,FX.0,FX.0\n"
60 		   );
61     }
62 
63   /* Next: underflow.  */
64   if ((FE_UNDERFLOW & excepts) != 0)
65     {
66       /* Multiplying a small value by 0.5 will cause an underflow. */
67       __asm__ volatile(
68 		   "  MOV  D0.0,#1\n"
69 		   "F MOV  FX.0,D0.0\n"
70 		   "  MOVT D0.0,#0x3f00\n"
71 		   "F MOV  FX.1,D0.0\n"
72 		   "F MUL  FX.2,FX.1,FX.0\n"
73 		   );
74     }
75 
76   /* Last: inexact.  */
77   if ((FE_INEXACT & excepts) != 0)
78     {
79       /* Converting a small single precision value to half precision
80 	 can cause an inexact exception. */
81       __asm__ volatile(
82 		   "  MOV  D0.0,#0x0001\n"
83 		   "F MOV  FX.0,D0.0\n"
84 		   "F FTOH FX.1,FX.0\n"
85 		   );
86     }
87 
88   /* Success.  */
89   return 0;
90 }
91 libm_hidden_def(feraiseexcept)
92