Home | History | Annotate | Line # | Download | only in i386
sfp-exceptions.c revision 1.1.1.11
      1 /*
      2  * Copyright (C) 2012-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 #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
     95