(root)/
gcc-13.2.0/
libgcc/
config/
pa/
sfp-exceptions.c
       1  /*
       2   * Copyright (C) 1997-2023 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  }