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
32void
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