1 | /* Copyright (C) 1997-2022 Free Software Foundation, Inc. |
2 | |
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 License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | 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 <fpu_control.h> |
21 | #include <float.h> |
22 | |
23 | int |
24 | __feraiseexcept (int excepts) |
25 | { |
26 | int fpsr; |
27 | const float fp_zero = 0.0; |
28 | const float fp_one = 1.0; |
29 | const float fp_max = FLT_MAX; |
30 | const float fp_min = FLT_MIN; |
31 | const float fp_1e32 = 1.0e32f; |
32 | const float fp_two = 2.0; |
33 | const float fp_three = 3.0; |
34 | |
35 | /* Raise exceptions represented by EXCEPTS. But we must raise only |
36 | one signal at a time. It is important that if the OVERFLOW or |
37 | UNDERFLOW exception and the inexact exception are given at the |
38 | same time, the OVERFLOW or UNDERFLOW exception precedes the |
39 | INEXACT exception. |
40 | |
41 | After each exception we read from the FPSR, to force the |
42 | exception to be raised immediately. */ |
43 | |
44 | if (FE_INVALID & excepts) |
45 | __asm__ __volatile__ ( |
46 | "ldr s0, %1\n\t" |
47 | "fdiv s0, s0, s0\n\t" |
48 | "mrs %0, fpsr" : "=r" (fpsr) |
49 | : "m" (fp_zero) |
50 | : "d0" ); |
51 | |
52 | if (FE_DIVBYZERO & excepts) |
53 | __asm__ __volatile__ ( |
54 | "ldr s0, %1\n\t" |
55 | "ldr s1, %2\n\t" |
56 | "fdiv s0, s0, s1\n\t" |
57 | "mrs %0, fpsr" : "=r" (fpsr) |
58 | : "m" (fp_one), "m" (fp_zero) |
59 | : "d0" , "d1" ); |
60 | |
61 | if (FE_OVERFLOW & excepts) |
62 | /* There's no way to raise overflow without also raising inexact. */ |
63 | __asm__ __volatile__ ( |
64 | "ldr s0, %1\n\t" |
65 | "ldr s1, %2\n\t" |
66 | "fadd s0, s0, s1\n\t" |
67 | "mrs %0, fpsr" : "=r" (fpsr) |
68 | : "m" (fp_max), "m" (fp_1e32) |
69 | : "d0" , "d1" ); |
70 | |
71 | if (FE_UNDERFLOW & excepts) |
72 | __asm__ __volatile__ ( |
73 | "ldr s0, %1\n\t" |
74 | "ldr s1, %2\n\t" |
75 | "fdiv s0, s0, s1\n\t" |
76 | "mrs %0, fpsr" : "=r" (fpsr) |
77 | : "m" (fp_min), "m" (fp_three) |
78 | : "d0" , "d1" ); |
79 | |
80 | if (FE_INEXACT & excepts) |
81 | __asm__ __volatile__ ( |
82 | "ldr s0, %1\n\t" |
83 | "ldr s1, %2\n\t" |
84 | "fdiv s0, s0, s1\n\t" |
85 | "mrs %0, fpsr" : "=r" (fpsr) |
86 | : "m" (fp_two), "m" (fp_three) |
87 | : "d0" , "d1" ); |
88 | |
89 | return 0; |
90 | } |
91 | libm_hidden_def (__feraiseexcept) |
92 | weak_alias (__feraiseexcept, feraiseexcept) |
93 | libm_hidden_weak (feraiseexcept) |
94 | |