(root)/
gcc-13.2.0/
libgcc/
config/
i386/
sfp-exceptions.c
       1  /*
       2   * Copyright (C) 2012-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  #ifndef _SOFT_FLOAT
      25  #include "sfp-machine.h"
      26  
      27  struct fenv
      28  {
      29    unsigned short int __control_word;
      30    unsigned short int __unused1;
      31    unsigned short int __status_word;
      32    unsigned short int __unused2;
      33    unsigned short int __tags;
      34    unsigned short int __unused3;
      35    unsigned int __eip;
      36    unsigned short int __cs_selector;
      37    unsigned int __opcode:11;
      38    unsigned int __unused4:5;
      39    unsigned int __data_offset;
      40    unsigned short int __data_selector;
      41    unsigned short int __unused5;
      42  } __attribute__ ((gcc_struct));
      43  
      44  #ifdef __SSE_MATH__
      45  # define __math_force_eval_div(x, y) \
      46    do { asm ("" : "+x" (x)); asm volatile ("" : : "x" (x / y)); } while (0)
      47  #else
      48  # define __math_force_eval_div(x, y) \
      49    do { asm ("" : "+t" (x)); asm volatile ("" : : "f" (x / y)); } while (0)
      50  #endif
      51  
      52  void
      53  __sfp_handle_exceptions (int _fex)
      54  {
      55    struct fenv temp;
      56  
      57    if (_fex & FP_EX_INVALID)
      58      {
      59        float f = 0.0f;
      60        __math_force_eval_div (f, f);
      61      }
      62    if (_fex & FP_EX_DENORM)
      63      {
      64        asm volatile ("fnstenv\t%0" : "=m" (temp));
      65        temp.__status_word |= FP_EX_DENORM;
      66        asm volatile ("fldenv\t%0" : : "m" (temp));
      67        asm volatile ("fwait");
      68      }
      69    if (_fex & FP_EX_DIVZERO)
      70      {
      71        float f = 1.0f, g = 0.0f;
      72        __math_force_eval_div (f, g);
      73      }
      74    if (_fex & FP_EX_OVERFLOW)
      75      {
      76        asm volatile ("fnstenv\t%0" : "=m" (temp));
      77        temp.__status_word |= FP_EX_OVERFLOW;
      78        asm volatile ("fldenv\t%0" : : "m" (temp));
      79        asm volatile ("fwait");
      80      }
      81    if (_fex & FP_EX_UNDERFLOW)
      82      {
      83        asm volatile ("fnstenv\t%0" : "=m" (temp));
      84        temp.__status_word |= FP_EX_UNDERFLOW;
      85        asm volatile ("fldenv\t%0" : : "m" (temp));
      86        asm volatile ("fwait");
      87      }
      88    if (_fex & FP_EX_INEXACT)
      89      {
      90        float f = 1.0f, g = 3.0f;
      91        __math_force_eval_div (f, g);
      92      }
      93  }
      94  #endif