xref: /netbsd-src/external/gpl3/gcc/dist/libgcc/config/pa/sfp-exceptions.c (revision b1e838363e3c6fc78a55519254d99869742dd33c)
1 /*
2  * Copyright (C) 1997-2022 Free Software Foundation, Inc.
3  *
4  * This file is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 3, or (at your option) any
7  * later version.
8  *
9  * This file is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * Under Section 7 of GPL version 3, you are granted additional
15  * permissions described in the GCC Runtime Library Exception, version
16  * 3.1, as published by the Free Software Foundation.
17  *
18  * You should have received a copy of the GNU General Public License and
19  * a copy of the GCC Runtime Library Exception along with this program;
20  * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
21  * <http://www.gnu.org/licenses/>.
22  */
23 
24 
25 #include "sfp-machine.h"
26 
27 #define HUGE_VAL (__builtin_huge_val ())
28 
29 /* Please see section 10,
30    page 10-5 "Delayed Trapping" in the PA-RISC 2.0 Architecture manual */
31 
32 void
__sfp_handle_exceptions(int _fex)33 __sfp_handle_exceptions (int _fex)
34 {
35   /* Raise exceptions represented by _FEX.  But we must raise only one
36      signal at a time.  It is important that if the overflow/underflow
37      exception and the divide by zero exception are given at the same
38      time, the overflow/underflow exception follows the divide by zero
39      exception.  */
40 
41   /* We do these bits in assembly to be certain GCC doesn't optimize
42      away something important, and so we can force delayed traps to
43      occur. */
44 
45   /* We use "fldd 0(%%sr0,%%sp),%0" to flush the delayed exception */
46 
47   /* First: Invalid exception.  */
48   if (_fex & FP_EX_INVALID)
49     {
50       /* One example of an invalid operation is 0 * Infinity.  */
51       double d = HUGE_VAL;
52       __asm__ __volatile__ (
53 		"	fcpy,dbl %%fr0,%%fr22\n"
54 		"	fmpy,dbl %0,%%fr22,%0\n"
55 		"	fldd 0(%%sr0,%%sp),%0"
56 		: "+f" (d) : : "%fr22" );
57     }
58 
59   /* Second: Division by zero.  */
60   if (_fex & FP_EX_DIVZERO)
61     {
62       double d = 1.0;
63       __asm__ __volatile__ (
64 		"	fcpy,dbl %%fr0,%%fr22\n"
65 		"	fdiv,dbl %0,%%fr22,%0\n"
66 		"	fldd 0(%%sr0,%%sp),%0"
67 		: "+f" (d) : : "%fr22" );
68     }
69 
70   /* Third: Overflow.  */
71   if (_fex & FP_EX_OVERFLOW)
72     {
73       double d = __DBL_MAX__;
74       __asm__ __volatile__ (
75 		"	fadd,dbl %0,%0,%0\n"
76 		"	fldd 0(%%sr0,%%sp),%0"
77 		: "+f" (d) );
78     }
79 
80   /* Fourth: Underflow.  */
81   if (_fex & FP_EX_UNDERFLOW)
82     {
83       double d = __DBL_MIN__;
84       double e = 3.0;
85       __asm__ __volatile__ (
86 		"	fdiv,dbl %0,%1,%0\n"
87 		"	fldd 0(%%sr0,%%sp),%0"
88 		: "+f" (d) : "f" (e) );
89     }
90 
91   /* Fifth: Inexact */
92   if (_fex & FP_EX_INEXACT)
93     {
94       double d = 3.14159265358979323846;
95       double e = 69.69;
96       __asm__ __volatile__ (
97 		"	fdiv,dbl %0,%1,%%fr22\n"
98 		"	fcnvfxt,dbl,sgl %%fr22,%%fr22L\n"
99 		"	fldd 0(%%sr0,%%sp),%%fr22"
100 		: : "f" (d), "f" (e) : "%fr22" );
101     }
102 }
103