Blame IexMath/IexMathFpu.cpp

Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
//
Packit 8dc392
// Copyright (c) 1997, Industrial Light & Magic, a division of Lucas
Packit 8dc392
// Digital Ltd. LLC
Packit 8dc392
// 
Packit 8dc392
// All rights reserved.
Packit 8dc392
// 
Packit 8dc392
// Redistribution and use in source and binary forms, with or without
Packit 8dc392
// modification, are permitted provided that the following conditions are
Packit 8dc392
// met:
Packit 8dc392
// *       Redistributions of source code must retain the above copyright
Packit 8dc392
// notice, this list of conditions and the following disclaimer.
Packit 8dc392
// *       Redistributions in binary form must reproduce the above
Packit 8dc392
// copyright notice, this list of conditions and the following disclaimer
Packit 8dc392
// in the documentation and/or other materials provided with the
Packit 8dc392
// distribution.
Packit 8dc392
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 8dc392
// its contributors may be used to endorse or promote products derived
Packit 8dc392
// from this software without specific prior written permission. 
Packit 8dc392
// 
Packit 8dc392
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 8dc392
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 8dc392
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 8dc392
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 8dc392
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 8dc392
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 8dc392
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 8dc392
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 8dc392
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 8dc392
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 8dc392
//
Packit 8dc392
///////////////////////////////////////////////////////////////////////////
Packit 8dc392
Packit 8dc392
Packit 8dc392
//------------------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//	Functions to control floating point exceptions.
Packit 8dc392
//
Packit 8dc392
//------------------------------------------------------------------------
Packit 8dc392
Packit 8dc392
#include "IexMathFpu.h"
Packit 8dc392
Packit 8dc392
#include <stdint.h>
Packit 8dc392
#include <IlmBaseConfig.h>
Packit 8dc392
#include <stdio.h>
Packit 8dc392
Packit 8dc392
#if 0
Packit 8dc392
    #include <iostream>
Packit 8dc392
    #define debug(x) (std::cout << x << std::flush)
Packit 8dc392
#else
Packit 8dc392
    #define debug(x)
Packit 8dc392
#endif
Packit 8dc392
Packit 8dc392
#if defined(HAVE_UCONTEXT_H) && (defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || defined(_M_IX86))
Packit 8dc392
Packit 8dc392
#include <ucontext.h>
Packit 8dc392
#include <signal.h>
Packit 8dc392
#include <iostream>
Packit 8dc392
#include <stdint.h>
Packit 8dc392
Packit 8dc392
Packit 8dc392
IEX_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 8dc392
Packit 8dc392
Packit 8dc392
Packit 8dc392
namespace FpuControl
Packit 8dc392
{
Packit 8dc392
Packit 8dc392
//-------------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//    Modern x86 processors and all AMD64 processors have two
Packit 8dc392
//    sets of floating-point control/status registers: cw and sw
Packit 8dc392
//    for legacy x87 stack-based arithmetic, and mxcsr for
Packit 8dc392
//    SIMD arithmetic.  When setting exception masks or checking
Packit 8dc392
//    for exceptions, we must set/check all relevant registers,
Packit 8dc392
//    since applications may contain code that uses either FP
Packit 8dc392
//    model.
Packit 8dc392
//
Packit 8dc392
//    These functions handle both FP models for x86 and AMD64.
Packit 8dc392
//
Packit 8dc392
//-------------------------------------------------------------------
Packit 8dc392
Packit 8dc392
//-------------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//    Restore the control register state from a signal handler
Packit 8dc392
//    user context, optionally clearing the exception bits
Packit 8dc392
//    in the restored control register, if applicable.
Packit 8dc392
//
Packit 8dc392
//-------------------------------------------------------------------
Packit 8dc392
Packit 8dc392
void restoreControlRegs (const ucontext_t & ucon,
Packit 8dc392
			 bool clearExceptions = false);
Packit 8dc392
Packit 8dc392
Packit 8dc392
//------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//    Set exception mask bits in the control register state.
Packit 8dc392
//    A value of 1 means the exception is masked, a value of
Packit 8dc392
//    0 means the exception is enabled.
Packit 8dc392
//
Packit 8dc392
//    setExceptionMask returns the previous mask value.  If
Packit 8dc392
//    the 'exceptions' pointer is non-null, it returns in 
Packit 8dc392
//    this argument the FPU exception bits.
Packit 8dc392
//
Packit 8dc392
//------------------------------------------------------------
Packit 8dc392
Packit 8dc392
const int INVALID_EXC   = (1<<0);
Packit 8dc392
const int DENORMAL_EXC  = (1<<1);
Packit 8dc392
const int DIVZERO_EXC   = (1<<2);
Packit 8dc392
const int OVERFLOW_EXC  = (1<<3);
Packit 8dc392
const int UNDERFLOW_EXC = (1<<4);
Packit 8dc392
const int INEXACT_EXC   = (1<<5);
Packit 8dc392
const int ALL_EXC       = INVALID_EXC  | DENORMAL_EXC  | DIVZERO_EXC |
Packit 8dc392
                          OVERFLOW_EXC | UNDERFLOW_EXC | INEXACT_EXC;
Packit 8dc392
Packit 8dc392
int setExceptionMask (int mask, int * exceptions = 0);
Packit 8dc392
int getExceptionMask ();
Packit 8dc392
Packit 8dc392
Packit 8dc392
//---------------------------------------------
Packit 8dc392
//
Packit 8dc392
//    Get/clear the exception bits in the FPU.
Packit 8dc392
//
Packit 8dc392
//---------------------------------------------
Packit 8dc392
Packit 8dc392
int  getExceptions ();
Packit 8dc392
void clearExceptions ();
Packit 8dc392
Packit 8dc392
Packit 8dc392
//------------------------------------------------------------------
Packit 8dc392
//
Packit 8dc392
//    Everything below here is implementation.  Do not use these
Packit 8dc392
//    constants or functions in your applications or libraries.
Packit 8dc392
//    This is not the code you're looking for.  Move along.
Packit 8dc392
//
Packit 8dc392
//    Optimization notes -- on a Pentium 4, at least, it appears
Packit 8dc392
//    to be faster to get the mxcsr first and then the cw; and to
Packit 8dc392
//    set the cw first and then the mxcsr.  Also, it seems to
Packit 8dc392
//    be faster to clear the sw exception bits after setting
Packit 8dc392
//    cw and mxcsr.
Packit 8dc392
//
Packit 8dc392
//------------------------------------------------------------------
Packit 8dc392
Packit 8dc392
static inline uint16_t
Packit 8dc392
getSw ()
Packit 8dc392
{
Packit 8dc392
    uint16_t sw;
Packit 8dc392
    asm volatile ("fnstsw %0" : "=m" (sw) : );
Packit 8dc392
    return sw;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
static inline void
Packit 8dc392
setCw (uint16_t cw)
Packit 8dc392
{
Packit 8dc392
    asm volatile ("fldcw %0" : : "m" (cw) );
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
static inline uint16_t
Packit 8dc392
getCw ()
Packit 8dc392
{
Packit 8dc392
    uint16_t cw;
Packit 8dc392
    asm volatile ("fnstcw %0" : "=m" (cw) : );
Packit 8dc392
    return cw;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
static inline void
Packit 8dc392
setMxcsr (uint32_t mxcsr, bool clearExceptions)
Packit 8dc392
{
Packit 8dc392
    mxcsr &= clearExceptions ? 0xffffffc0 : 0xffffffff;
Packit 8dc392
    asm volatile ("ldmxcsr %0" : : "m" (mxcsr) );
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
static inline uint32_t
Packit 8dc392
getMxcsr ()
Packit 8dc392
{
Packit 8dc392
    uint32_t mxcsr;
Packit 8dc392
    asm volatile ("stmxcsr %0" : "=m" (mxcsr) : );
Packit 8dc392
    return mxcsr;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
static inline int
Packit 8dc392
calcMask (uint16_t cw, uint32_t mxcsr)
Packit 8dc392
{
Packit 8dc392
    //
Packit 8dc392
    // Hopefully, if the user has been using FpuControl functions,
Packit 8dc392
    // the masks are the same, but just in case they're not, we
Packit 8dc392
    // AND them together to report the proper subset of the masks.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    return (cw & ALL_EXC) & ((mxcsr >> 7) & ALL_EXC);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
inline int
Packit 8dc392
setExceptionMask (int mask, int * exceptions)
Packit 8dc392
{
Packit 8dc392
    uint16_t cw = getCw ();
Packit 8dc392
    uint32_t mxcsr = getMxcsr ();
Packit 8dc392
    
Packit 8dc392
    if (exceptions)
Packit 8dc392
	*exceptions = (mxcsr & ALL_EXC) | (getSw () & ALL_EXC);
Packit 8dc392
Packit 8dc392
    int oldmask = calcMask (cw, mxcsr);
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // The exception constants are chosen very carefully so that
Packit 8dc392
    // we can do a simple mask and shift operation to insert
Packit 8dc392
    // them into the control words.  The mask operation is for 
Packit 8dc392
    // safety, in case the user accidentally set some other
Packit 8dc392
    // bits in the exception mask.
Packit 8dc392
    //
Packit 8dc392
Packit 8dc392
    mask &= ALL_EXC;
Packit 8dc392
    cw = (cw & ~ALL_EXC) | mask;
Packit 8dc392
    mxcsr = (mxcsr & ~(ALL_EXC << 7)) | (mask << 7);
Packit 8dc392
Packit 8dc392
    setCw (cw);
Packit 8dc392
    setMxcsr (mxcsr, false);
Packit 8dc392
Packit 8dc392
    return oldmask;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
inline int
Packit 8dc392
getExceptionMask ()
Packit 8dc392
{
Packit 8dc392
    uint32_t mxcsr = getMxcsr ();
Packit 8dc392
    uint16_t cw = getCw ();
Packit 8dc392
    return calcMask (cw, mxcsr);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
inline int
Packit 8dc392
getExceptions ()
Packit 8dc392
{
Packit 8dc392
    return (getMxcsr () | getSw ()) & ALL_EXC;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
clearExceptions ()
Packit 8dc392
{
Packit 8dc392
    uint32_t mxcsr = getMxcsr () & 0xffffffc0;
Packit 8dc392
    asm volatile ("ldmxcsr %0\n"
Packit 8dc392
		  "fnclex"
Packit 8dc392
		  : : "m" (mxcsr) );
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
// If the fpe was taken while doing a float-to-int cast using the x87,
Packit 8dc392
// the rounding mode and possibly the precision will be wrong.  So instead
Packit 8dc392
// of restoring to the state as of the fault, we force the rounding mode
Packit 8dc392
// to be 'nearest' and the precision to be double extended.
Packit 8dc392
//
Packit 8dc392
// rounding mode is in bits 10-11, value 00 == round to nearest
Packit 8dc392
// precision is in bits 8-9, value 11 == double extended (80-bit)
Packit 8dc392
//
Packit 8dc392
const uint16_t cwRestoreMask = ~((3 << 10) | (3 << 8));
Packit 8dc392
const uint16_t cwRestoreVal = (0 << 10) | (3 << 8);
Packit 8dc392
Packit 8dc392
Packit 8dc392
#ifdef ILMBASE_HAVE_CONTROL_REGISTER_SUPPORT
Packit 8dc392
Packit 8dc392
inline void
Packit 8dc392
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
Packit 8dc392
{
Packit 8dc392
    setCw ((ucon.uc_mcontext.fpregs->cwd & cwRestoreMask) | cwRestoreVal);
Packit 8dc392
    setMxcsr (ucon.uc_mcontext.fpregs->mxcsr, clearExceptions);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
#else
Packit 8dc392
Packit 8dc392
//
Packit 8dc392
// Ugly, the mxcsr isn't defined in GNU libc ucontext_t, but
Packit 8dc392
// it's passed to the signal handler by the kernel.  Use
Packit 8dc392
// the kernel's version of the ucontext to get it, see
Packit 8dc392
// <asm/sigcontext.h>
Packit 8dc392
//
Packit 8dc392
Packit 8dc392
#include <asm/sigcontext.h>
Packit 8dc392
Packit 8dc392
inline void
Packit 8dc392
restoreControlRegs (const ucontext_t & ucon, bool clearExceptions)
Packit 8dc392
{
Packit 8dc392
    setCw ((ucon.uc_mcontext.fpregs->cw & cwRestoreMask) | cwRestoreVal);
Packit 8dc392
    
Packit 8dc392
    _fpstate * kfp = reinterpret_cast<_fpstate *> (ucon.uc_mcontext.fpregs);
Packit 8dc392
    setMxcsr (kfp->magic == 0 ? kfp->mxcsr : 0, clearExceptions);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
#endif
Packit 8dc392
Packit 8dc392
} // namespace FpuControl
Packit 8dc392
Packit 8dc392
Packit 8dc392
namespace {
Packit 8dc392
Packit 8dc392
volatile FpExceptionHandler fpeHandler = 0;
Packit 8dc392
Packit 8dc392
extern "C" void
Packit 8dc392
catchSigFpe (int sig, siginfo_t *info, ucontext_t *ucon)
Packit 8dc392
{
Packit 8dc392
    debug ("catchSigFpe (sig = "<< sig << ", ...)\n");
Packit 8dc392
Packit 8dc392
    FpuControl::restoreControlRegs (*ucon, true);
Packit 8dc392
Packit 8dc392
    if (fpeHandler == 0)
Packit 8dc392
	return;
Packit 8dc392
Packit 8dc392
    if (info->si_code == SI_USER)
Packit 8dc392
    {
Packit 8dc392
	fpeHandler (0, "Floating-point exception, caused by "
Packit 8dc392
		       "a signal sent from another process.");
Packit 8dc392
	return;
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    if (sig == SIGFPE)
Packit 8dc392
    {
Packit 8dc392
	switch (info->si_code)
Packit 8dc392
	{
Packit 8dc392
	  //
Packit 8dc392
	  // IEEE 754 floating point exceptions:
Packit 8dc392
	  //
Packit 8dc392
Packit 8dc392
	  case FPE_FLTDIV:
Packit 8dc392
	    fpeHandler (IEEE_DIVZERO, "Floating-point division by zero.");
Packit 8dc392
	    return;
Packit 8dc392
Packit 8dc392
	  case FPE_FLTOVF:
Packit 8dc392
	    fpeHandler (IEEE_OVERFLOW, "Floating-point overflow.");
Packit 8dc392
	    return;
Packit 8dc392
Packit 8dc392
	  case FPE_FLTUND:
Packit 8dc392
	    fpeHandler (IEEE_UNDERFLOW, "Floating-point underflow.");
Packit 8dc392
	    return;
Packit 8dc392
Packit 8dc392
	  case FPE_FLTRES:
Packit 8dc392
	    fpeHandler (IEEE_INEXACT, "Inexact floating-point result.");
Packit 8dc392
	    return;
Packit 8dc392
Packit 8dc392
	  case FPE_FLTINV:
Packit 8dc392
	    fpeHandler (IEEE_INVALID, "Invalid floating-point operation.");
Packit 8dc392
	    return;
Packit 8dc392
Packit 8dc392
	  //
Packit 8dc392
	  // Other arithmetic exceptions which can also
Packit 8dc392
	  // be trapped by the operating system:
Packit 8dc392
	  //
Packit 8dc392
Packit 8dc392
	  case FPE_INTDIV:
Packit 8dc392
	    fpeHandler (0, "Integer division by zero.");
Packit 8dc392
	    break;
Packit 8dc392
Packit 8dc392
	  case FPE_INTOVF:
Packit 8dc392
	    fpeHandler (0, "Integer overflow.");
Packit 8dc392
	    break;
Packit 8dc392
Packit 8dc392
	  case FPE_FLTSUB:
Packit 8dc392
	    fpeHandler (0, "Subscript out of range.");
Packit 8dc392
	    break;
Packit 8dc392
	}
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    fpeHandler (0, "Floating-point exception.");
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
} // namespace
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
setFpExceptions (int when)
Packit 8dc392
{
Packit 8dc392
    int mask = FpuControl::ALL_EXC;
Packit 8dc392
Packit 8dc392
    if (when & IEEE_OVERFLOW)
Packit 8dc392
	mask &= ~FpuControl::OVERFLOW_EXC;
Packit 8dc392
    if (when & IEEE_UNDERFLOW)
Packit 8dc392
	mask &= ~FpuControl::UNDERFLOW_EXC;
Packit 8dc392
    if (when & IEEE_DIVZERO)
Packit 8dc392
	mask &= ~FpuControl::DIVZERO_EXC;
Packit 8dc392
    if (when & IEEE_INEXACT)
Packit 8dc392
	mask &= ~FpuControl::INEXACT_EXC;
Packit 8dc392
    if (when & IEEE_INVALID)
Packit 8dc392
	mask &= ~FpuControl::INVALID_EXC;
Packit 8dc392
Packit 8dc392
    //
Packit 8dc392
    // The Linux kernel apparently sometimes passes
Packit 8dc392
    // incorrect si_info to signal handlers unless
Packit 8dc392
    // the exception flags are cleared.
Packit 8dc392
    //
Packit 8dc392
    // XXX is this still true on 2.4+ kernels?
Packit 8dc392
    //
Packit 8dc392
    
Packit 8dc392
    FpuControl::setExceptionMask (mask);
Packit 8dc392
    FpuControl::clearExceptions ();
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
int
Packit 8dc392
fpExceptions ()
Packit 8dc392
{
Packit 8dc392
    int mask = FpuControl::getExceptionMask ();
Packit 8dc392
Packit 8dc392
    int when = 0;
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::OVERFLOW_EXC))
Packit 8dc392
	when |= IEEE_OVERFLOW;
Packit 8dc392
    if (!(mask & FpuControl::UNDERFLOW_EXC))
Packit 8dc392
	when |= IEEE_UNDERFLOW;
Packit 8dc392
    if (!(mask & FpuControl::DIVZERO_EXC))
Packit 8dc392
	when |= IEEE_DIVZERO;
Packit 8dc392
    if (!(mask & FpuControl::INEXACT_EXC))
Packit 8dc392
	when |= IEEE_INEXACT;
Packit 8dc392
    if (!(mask & FpuControl::INVALID_EXC))
Packit 8dc392
	when |= IEEE_INVALID;
Packit 8dc392
Packit 8dc392
    return when;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
handleExceptionsSetInRegisters()
Packit 8dc392
{
Packit 8dc392
    if (fpeHandler == 0)
Packit 8dc392
	return;
Packit 8dc392
Packit 8dc392
    int mask = FpuControl::getExceptionMask ();
Packit 8dc392
Packit 8dc392
    int exc = FpuControl::getExceptions();
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::DIVZERO_EXC) && (exc & FpuControl::DIVZERO_EXC))
Packit 8dc392
    {
Packit 8dc392
        fpeHandler(IEEE_DIVZERO, "Floating-point division by zero.");
Packit 8dc392
        return;
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::OVERFLOW_EXC) && (exc & FpuControl::OVERFLOW_EXC))
Packit 8dc392
    {
Packit 8dc392
        fpeHandler(IEEE_OVERFLOW, "Floating-point overflow.");
Packit 8dc392
        return;
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::UNDERFLOW_EXC) && (exc & FpuControl::UNDERFLOW_EXC))
Packit 8dc392
    {
Packit 8dc392
        fpeHandler(IEEE_UNDERFLOW, "Floating-point underflow.");
Packit 8dc392
        return;
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::INEXACT_EXC) && (exc & FpuControl::INEXACT_EXC))
Packit 8dc392
    {
Packit 8dc392
        fpeHandler(IEEE_INEXACT, "Inexact floating-point result.");
Packit 8dc392
        return;
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    if (!(mask & FpuControl::INVALID_EXC) && (exc & FpuControl::INVALID_EXC))
Packit 8dc392
    {
Packit 8dc392
        fpeHandler(IEEE_INVALID, "Invalid floating-point operation.");
Packit 8dc392
        return;
Packit 8dc392
    }
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
setFpExceptionHandler (FpExceptionHandler handler)
Packit 8dc392
{
Packit 8dc392
    if (fpeHandler == 0)
Packit 8dc392
    {
Packit 8dc392
	struct sigaction action;
Packit 8dc392
	sigemptyset (&action.sa_mask);
Packit 8dc392
	action.sa_flags = SA_SIGINFO | SA_NOMASK;
Packit 8dc392
	action.sa_sigaction = (void (*) (int, siginfo_t *, void *)) catchSigFpe;
Packit 8dc392
	action.sa_restorer = 0;
Packit 8dc392
Packit 8dc392
	sigaction (SIGFPE, &action, 0);
Packit 8dc392
    }
Packit 8dc392
Packit 8dc392
    fpeHandler = handler;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
IEX_INTERNAL_NAMESPACE_SOURCE_EXIT
Packit 8dc392
Packit 8dc392
Packit 8dc392
#else
Packit 8dc392
Packit 8dc392
#include <signal.h>
Packit 8dc392
#include <assert.h>
Packit 8dc392
Packit 8dc392
IEX_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 8dc392
Packit 8dc392
Packit 8dc392
namespace 
Packit 8dc392
{
Packit 8dc392
	volatile FpExceptionHandler fpeHandler = 0;
Packit 8dc392
	void fpExc_(int x)
Packit 8dc392
	{
Packit 8dc392
	    if (fpeHandler != 0)
Packit 8dc392
	    {
Packit 8dc392
		fpeHandler(x, "");
Packit 8dc392
	    }
Packit 8dc392
	    else
Packit 8dc392
	    {
Packit 8dc392
		assert(0 != "Floating point exception");
Packit 8dc392
	    }
Packit 8dc392
	}
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
setFpExceptions( int )
Packit 8dc392
{
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
setFpExceptionHandler (FpExceptionHandler handler)
Packit 8dc392
{
Packit 8dc392
    // improve floating point exception handling nanoscopically above "nothing at all"
Packit 8dc392
    fpeHandler = handler;
Packit 8dc392
    signal(SIGFPE, fpExc_);
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
int
Packit 8dc392
fpExceptions()
Packit 8dc392
{
Packit 8dc392
    return 0;
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
void
Packit 8dc392
handleExceptionsSetInRegisters()
Packit 8dc392
{
Packit 8dc392
    // No implementation on this platform
Packit 8dc392
}
Packit 8dc392
Packit 8dc392
IEX_INTERNAL_NAMESPACE_SOURCE_EXIT
Packit 8dc392
Packit 8dc392
#endif