Home | History | Annotate | Line # | Download | only in pa
      1 /*
      2  * Copyright (C) 1997-2024 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
     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