1 /* Raise given exceptions.
2    Copyright (C) 2018-2021 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, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <fenv.h>
20 #include <fenv_libc.h>
21 #include <fpu_control.h>
22 #include <float.h>
23 #include <math.h>
24 
25 int
__feraiseexcept(int excepts)26 __feraiseexcept (int excepts)
27 {
28     /* Raise exceptions represented by EXCEPTS.  But we must raise only one
29      signal at a time.  It is important that if the overflow/underflow
30      exception and the divide by zero exception are given at the same
31      time, the overflow/underflow exception follows the divide by zero
32      exception.  */
33 
34 # ifndef __csky_fpuv1__
35     /* First: invalid exception.  */
36     if (FE_INVALID & excepts)
37     {
38       /* One example of a invalid operation is 0 * Infinity.  */
39       float x = HUGE_VALF, y = 0.0f;
40       __asm__ __volatile__ ("fmuls %0, %0, %1" : "+v" (x) : "v" (y));
41     }
42 
43     /* Next: division by zero.  */
44     if (FE_DIVBYZERO & excepts)
45     {
46       float x = 1.0f, y = 0.0f;
47       __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
48     }
49 
50     /* Next: overflow.  */
51     if (FE_OVERFLOW & excepts)
52     {
53       float x = FLT_MAX;
54       __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
55     }
56     /* Next: underflow.  */
57     if (FE_UNDERFLOW & excepts)
58     {
59       float x = -FLT_MIN;
60 
61       __asm__ __volatile__ ("fmuls %0, %0, %0" : "+v" (x));
62     }
63 
64     /* Last: inexact.  */
65     if (FE_INEXACT & excepts)
66     {
67       float x = 1.0f, y = 3.0f;
68       __asm__ __volatile__ ("fdivs %0, %0, %1" : "+v" (x) : "v" (y));
69     }
70 
71     if (__FE_DENORMAL & excepts)
72     {
73       double x = 4.9406564584124654e-324;
74       __asm__ __volatile__ ("fstod %0, %0" : "+v" (x));
75     }
76 # else
77      int tmp = 0;
78     /* First: invalid exception.  */
79     if (FE_INVALID & excepts)
80     {
81       /* One example of a invalid operation is 0 * Infinity.  */
82       float x = HUGE_VALF, y = 0.0f;
83       __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
84                     : "+f" (x), "+r"(tmp) : "f" (y));
85     }
86 
87     /* Next: division by zero.  */
88     if (FE_DIVBYZERO & excepts)
89     {
90       float x = 1.0f, y = 0.0f;
91       __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
92                     : "+f" (x), "+r"(tmp) : "f" (y));
93     }
94 
95     /* Next: overflow.  */
96     if (FE_OVERFLOW & excepts)
97     {
98       float x = FLT_MAX, y = FLT_MAX;
99       __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
100                     : "+f" (x), "+r"(tmp) : "f" (y));
101     }
102 
103     /* Next: underflow.  */
104     if (FE_UNDERFLOW & excepts)
105     {
106       float x = -FLT_MIN, y = -FLT_MIN;
107 
108       __asm__ __volatile__ ("fmuls %0, %0, %2, %1"
109                     : "+f" (x), "+r"(tmp) : "f" (y));
110     }
111 
112     /* Last: inexact.  */
113     if (FE_INEXACT & excepts)
114     {
115       float x = 1.0f, y = 3.0f;
116       __asm__ __volatile__ ("fdivs %0, %0, %2, %1"
117                     : "+f" (x), "+r"(tmp) : "f" (y));
118     }
119 # endif /* __csky_fpuv2__ */
120 
121     /* Success.  */
122     return 0;
123 }
124 libm_hidden_def (__feraiseexcept)
125 weak_alias (__feraiseexcept, feraiseexcept)
126 libm_hidden_weak (feraiseexcept)
127