1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 /*
  26  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  27  * Use is subject to license terms.
  28  */
  29 
  30 #pragma weak __feclearexcept = feclearexcept
  31 #pragma weak __feraiseexcept = feraiseexcept
  32 #pragma weak __fetestexcept = fetestexcept
  33 #pragma weak __fegetexceptflag = fegetexceptflag
  34 #pragma weak __fesetexceptflag = fesetexceptflag
  35 
  36 #pragma weak feclearexcept96 = feclearexcept
  37 #pragma weak feraiseexcept96 = feraiseexcept
  38 #pragma weak fetestexcept96 = fetestexcept
  39 #pragma weak fegetexceptflag96 = fegetexceptflag
  40 #pragma weak fesetexceptflag96 = fesetexceptflag
  41 
  42 #include <fenv.h>
  43 #include <sys/ieeefp.h>
  44 #include <ucontext.h>
  45 #include <thread.h>
  46 #include "fex_handler.h"
  47 #include "fenv_inlines.h"
  48 
  49 
  50 int feclearexcept(int e)
  51 {
  52         unsigned long   fsr;
  53 
  54         __fenv_getfsr(&fsr);
  55         __fenv_set_ex(fsr, __fenv_get_ex(fsr) & ~e);
  56         __fenv_setfsr(&fsr);
  57         if (fex_get_log())
  58                 __fex_update_te();
  59         return 0;
  60 }
  61 
  62 /*
  63 *  note - __fex_hdlr depends on fetestexcept following feraiseexcept
  64 */
  65 int feraiseexcept(int e)
  66 {
  67         volatile double t;
  68         unsigned long   fsr;
  69 
  70         if (e & FE_INVALID) {
  71                 t = 0.0;
  72                 t /= 0.0;
  73         }
  74         if (e & FE_DIVBYZERO) {
  75                 t = 1.0e300;
  76                 t /= 0.0;
  77         }
  78         if (e & FE_OVERFLOW) {
  79                 /* if overflow is not trapped, avoid raising inexact */
  80                 __fenv_getfsr(&fsr);
  81                 if (!(__fenv_get_te(fsr) & (1 << fp_trap_overflow))) {
  82                         __fenv_set_ex(fsr, __fenv_get_ex(fsr) | FE_OVERFLOW);
  83                         __fenv_setfsr(&fsr);
  84                 }
  85                 else {
  86                         t = 1.0e300;
  87                         t *= 1.0e300;
  88                 }
  89         }
  90         if (e & FE_UNDERFLOW) {
  91                 /* if underflow is not trapped, avoid raising inexact */
  92                 __fenv_getfsr(&fsr);
  93                 if (!(__fenv_get_te(fsr) & (1 << fp_trap_underflow))) {
  94                         __fenv_set_ex(fsr, __fenv_get_ex(fsr) | FE_UNDERFLOW);
  95                         __fenv_setfsr(&fsr);
  96                 }
  97                 else {
  98                         t = 1.0e-307;
  99                         t -= 1.001e-307;
 100                 }
 101         }
 102         if (e & FE_INEXACT) {
 103                 t = 1.0e300;
 104                 t += 1.0e-307;
 105         }
 106         return 0;
 107 }
 108 
 109 int fetestexcept(int e)
 110 {
 111         unsigned long   fsr;
 112 
 113         __fenv_getfsr(&fsr);
 114         return (int)__fenv_get_ex(fsr) & e;
 115 }
 116 
 117 int fegetexceptflag(fexcept_t *p, int e)
 118 {
 119         unsigned long   fsr;
 120 
 121         __fenv_getfsr(&fsr);
 122         *p = (int)__fenv_get_ex(fsr) & e;
 123         return 0;
 124 }
 125 
 126 int fesetexceptflag(const fexcept_t *p, int e)
 127 {
 128         unsigned long   fsr;
 129 
 130         __fenv_getfsr(&fsr);
 131         __fenv_set_ex(fsr, (((int)__fenv_get_ex(fsr) & ~e) | (*p & e)) &
 132                 FE_ALL_EXCEPT);
 133         __fenv_setfsr(&fsr);
 134         if (fex_get_log())
 135                 __fex_update_te();
 136         return 0;
 137 }