sigfpe(3C)

handle_sigfpes - Floating-point exception handler package

As shipped in IRIX 6.5.22. Last changed in IRIX 6.5.19.

NAME
     handle_sigfpes - Floating-point exception handler package

SYNOPSIS
     #include <sigfpe.h>

     void handle_sigfpes
      (int onoff, int en_mask,
      void (*user_routine)(unsigned[5], int[2]),
      int abort_action,
      void (*abort_routine)(unsigned int **));
      void (*user_routine)(unsigned[5], int[2]),
      int abort_action,
      void (*abort_routine)(unsigned int **));

     typedef void (*user_t)(unsigned[5], int[2]);

     typedef void (*abort_t)(unsigned int **);

     struct sigfpe_template
      {
      int repls;
      int count;
      int trace;
      int abort;
      int exit;
     };

     extern struct sigfpe_template sigfpe_[_N_EXCEPTION_TYPES+1];

     extern int invalidop_results_[_N_INVALIDOP_RESULTS+1];

     extern int invalidop_operands_[_N_INVALIDOP_OPERANDS+1];

DESCRIPTION
     The floating-point accelerator may raise floating-point exceptions,
     signal SIGFPE, due to five conditions:  _OVERFL(overflow),
     _UNDERFL(underflow), _DIVZERO(divide-by-zero), _INEXACT(inexact
     result), or _INVALID(invalid operand, e.g., infinity).  Usually these
     conditions are masked, and do not cause a floating-point exception.
     Instead, a default value is substituted for the result of the
     operation, and the program continues silently.  This event may be
     intercepted by causing an exception to be raised.  When this occurs,
     the operating system generates a SIGFPE signal.

     The integer arithmetic instructions add, addi, dadd, daddi, sub, and
     dsub also generate a SIGFPE signal when the result of the operation
     overflows (condition _INT_OVERFL).  (Currently, SGI compilers generate
     only unsigned versions of these instructions, which do not generate a
     signal on overflow.  However, it is still possible to generate these
     instructions via assembly language).

     For -o32 programs, the compiler generates additional instructions to
     detect and trap on integer-divide-by-zero.  No similar detection code
     sequences are generated in -n32 or -64 programs.

     Once an exception is raised, the specific conditions which caused the
     exception may be determined, and more appropriate action taken.

     The libfpe.so library provides two methods to unmask and handle these
     conditions: the subroutine handle_sigfpes, and the environment
     variable TRAP_FPE.  Both methods provide a mechanism for unmasking
     each of these conditions except _INEXACT, for handling and classifying
     exceptions arising from them, and for substituting either a default
     value or a chosen one.  They also provide mechanisms to count, trace,
     exit or abort on enabled exceptions.  If you supply your own call to
     handle_sigfpes, you should leave environment variable TRAP_FPE
     undefined or set to OFF.  TRAP_FPE is supported for Fortran, C, C++
     and Pascal.  handle_sigfpes is supported for C, C++ and Fortran.

     Calling the subroutine is the preferred method when preparing software
     for others to use, since it relieves the user of any need to know
     about the TRAP_FPE environment variable.

     The environment variable is preferable if you want to experiment or
     allow any user to experiment with different trap behaviors with
     minimum effort.

     libfpe uses System V signal handling and will not work with programs
     that use Berkeley signal handling.

     Note that the preferred method for flushing denormals to zero is to
     set the FS bit to 1 in the floating point control status register.  If
     the FS bit is set to 1, the user should not handle underflows through
     the floating point trap handler, because a denormal result flushed to
     zero will cause an underflow.  Note that calls to the floating point
     trap handler consume many thousands of cpu cycles.  The following
     routine (written in C) can be used to set/clear the FS bit.

          #include <sys/fpu.h>

          void
          flush_to_zero(int on_off)
          {
          union fpc_csr  n;

               n.fc_word = get_fpc_csr();
               if ( on_off == 0 ) {
                    n.fc_struct.flush = 0;
               } else {
                    n.fc_struct.flush = 1;
               }
               set_fpc_csr(n.fc_word);
          }

     Note that if the FS bit in the floating point control status register
     is set, it remains set after calling handle_sigfpes(_OFF, ...

     Be sure to read the NOTES FOR R8000 section on this man page, which
     describes the behavior of libfpe.so on the R8000 processor.

HANDLE_SIGFPES SUBROUTINE
     The values in the global arrays are described in the "WHEN AN
     EXCEPTION IS ENCOUNTERED" section on this man page.

     The arguments to handle_sigfpes are as follows:

     onoff
          Indicates whether handling is turned on (onoff == _ON) or off
          (onoff == _OFF).  Specifying (onoff == _DEBUG) is another way to
          turn on handling.  Information from the sigfpe structure will be
          printed if (onoff == _DEBUG).  (The names used in this document
          are defined in sigfpe.h.)

     en_mask
          Indicates which of the five conditions should be unmasked,
          enabling them to raise floating-point exceptions/or an integer
          overflow exception.  en_mask is valid only if onoff == _ON  or
          onoff == _DEBUG, and is the bitwise or of one or more of the
          constants _EN_UNDERFL, _EN_OVERFL,_EN_DIVZERO, _EN_INVALID, and
          _EN_INT_OVERFL (defined in sigfpe.h).

     user_routine:
          handle_sigfpes provides a mechanism for setting the result of the
          operation to any one of a set of well-known values.  If full
          control over the value of selected operations is desired for one
          or more exception conditions, a function user_routine must be
          provided.  For these selected exception conditions, user_routine
          will be called to set the value resulting from the operation.
          Pass a 0 (plain 0 is adequate) if you do not want to provide a
          user_routine.  Typedef user_t is defined in sigfpe.h for
          convenience in programming.

     abort_action:
          If the handler encounters an unexpected condition or an
          inconsistency, the flag abort_action indicates what action should
          be taken.  Another option is for you to specify that you are
          supplying your own floating point exception handler as the
          default handler.  The following legal values can be specified:

          _TURN_OFF_HANDLER_ON_ERROR
               Instruct the floating-point-accelerator to cease causing
               exceptions and continue (i.e., disable handling).

          _ABORT_ON_ERROR
               Kill the process after giving an error message and calling a
               user-supplied cleanup routine if one is provided via the
               abort_routine parameter.

          _REPLACE_HANDLER_ON_ERROR
               Install the indicated user routine as the handler when such
               an error is encountered.  Future floating-point exceptions
               will branch to the user-routine (see signal(2)).

          _USER_HANDLER
               Install the indicated user routine as the handler
               immediately.  Future floating-point exceptions will branch
               to the user-routine (see signal(2)).

     abort_routine:
          When a fatal error (i.e., one described under abort_action) is
          encountered, abort_routine is used as the address of a user
          routine.

          If abort_action is _ABORT_ON_ERROR, and abort_routine is valid,
          it is called before aborting, and passed a pointer to the address
          of the instruction causing the exception as its single argument.
          In this case, the user's abort_routine should be defined as
          follows:

          void abort_routine( ptr_to_pc )
          unsigned int **ptr_to_pc;

     If abort_action is _REPLACE_HANDLER_ON_ERROR, and abort_routine is
     valid, it will be installed as the new handler.  In this case,
     abort_routine will be called immediately to handle the current
     exception.  (see signal(2)) Pass a 0 (plain 0 is adequate) if you do
     not want to provide an abort_action routine.

     If abort_action is _USER_HANDLER, and abort_routine is valid, it will
     be installed immediately as the default floating point exception
     handler.

     If abort_routine is to be invoked as a floating point exception
     handler, the following prototype should be used (see <sigfpe.h>,
     <sys/signal.h>, and signal(2)):

          int user_handler( sig, code, sc )
          int sig, code;
          struct sigcontext *sc;

     Typedef abort_t is defined in sigfpe.h for convenience in programming.

     Routine user_handler should return 0 to continue processing of the
     user's code and a non-zero value to disconnect user_handler as the
     floating point exception handler.  User_handler should not issue a
     call to signal(), nor should it update the program counter in the
     sigcontext area, because these actions are done in the routine which
     calls it.  A user handler can determine which type of exception has
     occurred by calling routine __fpe_trap_type().  This routine returns
     one of _UNDERFL, _OVERFL, etc. as appropriate.

     Users can supply separate handlers for each exception type by making
     multiple calls to handle_sigfpes.  See example 3 that follows.
     Similarly, trap handling for one or more exception types can be turned
     off by or-ing the appropriate combination of masks in the second
     parameter to handle_sigfpes.

          handle_sigfpes(OFF, 0, ...

          disables handling of all SIGFPE signals.

EXAMPLES OF CALLS TO HANDLE_SIGFPES
     The following example sets up traps of underflow which change the
     resulting value to zero:

          #include <sigfpe.h>

          /* call this during program startup
             to set underflowing values to zero
          */

          void  my_underflow_to_zero(void)
          {
            /* underflow to zero */

            sigfpe_[_UNDERFL].repls = _ZERO;

            /* only trap on underflow */

            handle_sigfpes(_ON, _EN_UNDERFL , 0, _ABORT_ON_ERROR, 0);
          }

     The following example counts all traps, traces the first five
     exceptions of each kind, aborts on the first divide by zero, or the
     100th overflow.  It replaces zero for underflows, max float/double for
     overflows, max integer for integer overflows, and the default values
     for divide by zero, invalid operands, and integer overflows.  The
     environment variable example below does the same thing.

          #include <limits.h> /* to get INT_MAX */
          #include <sigfpe.h>

          main()
          {
            /* underflow to zero */

            sigfpe_[_UNDERFL].repls = _ZERO;

            /* substitute max float/double on overflow */

            sigfpe_[_OVERFL].repls=_MAX;

            /* trace first 5 exceptions of each kind */

            sigfpe_[_UNDERFL].trace=5;
            sigfpe_[_OVERFL].trace =5;
            sigfpe_[_DIVZERO].trace=5;
            sigfpe_[_INVALID].trace=5;
            sigfpe_[_INT_OVERFL].trace=5;

            /* counts at end */

            sigfpe_[_UNDERFL].count=INT_MAX;
            sigfpe_[_OVERFL].count =INT_MAX;
            sigfpe_[_DIVZERO].count=INT_MAX;
            sigfpe_[_INVALID].count=INT_MAX;
            sigfpe_[_INT_OVERFL].count=INT_MAX;

            /* abort after 100 */

            sigfpe_[_UNDERFL].abort=100;
            sigfpe_[_OVERFL].abort =100;
            sigfpe_[_INVALID].abort=100;
            sigfpe_[_INT_OVERFL].abort=100;

            /* abort on first divide by zero */

            sigfpe_[_DIVZERO].abort=1;



            handle_sigfpes(_ON, _EN_UNDERFL| _EN_OVERFL|_EN_DIVZERO
              | _EN_INVALID | _EN_INT_OVERFL, 0, _ABORT_ON_ERROR, 0);

            /* do the real application work here */
          }

     The last example shows how to enable different handlers for various
     exception types:

          #include <limits.h> /* to get INT_MAX */
          #include <sigfpe.h>

          extern user_t  my_invalid_handler;

          main()
          {
            /* counts at end */

            sigfpe_[_UNDERFL].count=INT_MAX;
            sigfpe_[_OVERFL].count =INT_MAX;
            sigfpe_[_DIVZERO].count=INT_MAX;
            sigfpe_[_INVALID].count=INT_MAX;
            sigfpe_[_INT_OVERFL].count=INT_MAX;

            /* enable trapping on overflow, using libfpe's trap handler */

            handle_sigfpes(_ON, _EN_OVERFL, 0, 0, 0);

            /* enable trapping on invalid, using user's own trap handler */

            handle_sigfpes(_ON, _EN_INVALID, my_invalid_handler, 0, 0);

            /* do the real application work here */

            ....

            /* turn off trapping of overflows */

            handle_sigfpes(_OFF, _EN_OVERFL, 0, 0, 0);

            ....

            /* turn off all handling of SIGFPE signals */

            handle_sigfpes(_OFF, 0, 0, 0, 0);

            ....

The TRAP_FPE Environment Variable
     If the code has been linked with libfpe.so, the runtime startup
     routine will check for the environment variable TRAP_FPE.  The string
     read as the value of TRAP_FPE will be interpreted and handle_sigfpes
     will be called with the resulting values.

     TRAP_FPE is read in uppercase letters only.  The string assigned to
     TRAP_FPE may be in uppercase or lowercase.  TRAP_FPE can take one of
     two forms: either a global value, or a list of individual items.

     Global values:

     "" or OFF      Execute the program with no trap handling enabled.
                    Same as TRAP_FPE undefined.  Same as linking without
                    libfpe.so

     ON             Same as TRAP_FPE="ALL=DEFAULT".

                    Alternately, replacement values and actions may be
                    specified for each of the possible trap types
                    individually.  This is accomplished by setting the
                    environment variable as follows:

          setenv TRAP_FPE "item;item;item...."

     An item can be one of the following:

     traptype=statuslist
                    Where traptype defines the specific floating point
                    exception to enable, and statuslist defines the list of
                    actions upon encountering the trap.

     DEBUG          Confirm the parsing of the environment variable and the
                    trap actions.

                    Traptype can be one of the following literal strings:

                    UNDERFL        underflow

                    OVERFL         overflow

                    DIVZERO        divide by zero

                    INVALID        invalid operand

                    INT_OVERFL     integer overflow

                    ALL            all of the above

     Statuslist is a list separated by commas.  It contains an optional
     symbolic replacement value, and an optional list of actions.

     Symbolic replacement values:

     DEFAULT        Do not override the predefined default values.

     IEEE           Maps to integer code _APPROPRIATE.

     APPROPRIATE    Maps to integer code _APPROPRIATE.

     ZERO           Maps to integer code _ZERO.

     FLUSH_ZERO     Maps to integer code _FLUSH_ZERO (R4000 and later
                    processors).

     FLUSH_ZERO     Maps to integer code _ZERO (other processors).

     MIN            Maps to integer code _MIN.

     MAX            Maps to integer code _MAX.

     INF            Maps to integer code _INF.

     NAN            Maps to integer code _NAN.

                    All actions take an optional integer in parentheses:

     Note: for any traps that have an action and no specified replacement
     value, the DEFAULT replacement value will be used.

     COUNT(n)       A count of the trap type will be printed to stderr
                    every nth trap, and at the end of the program.  Default
                    is INT_MAX.

     ABORT(n)       Core dump and abort the program upon encountering the
                    nth trap.  Default is 1.

     EXIT(n)        Exit program upon encountering the nth trap.  Default
                    is 1.

     TRACE(n)       If a trap is encountered, print a stack trace to stderr
                    up to n times.  Default is 10.

EXAMPLES OF TRAP_FPE
     The following example counts all traps, traces the first five
     overflows, aborts on the first divide by zero, or the 100th overflow.
     It replaces zero for underflows, the "appropriate" value for
     overflows, and the default values for divide by zero, invalid
     operands, and integer overflows.

          setenv TRAP_FPE "ALL=COUNT; UNDERFL=ZERO; OVERFL=IEEE,TRACE(5),
          ABORT(100); DIVZERO=ABORT"

WHEN AN EXCEPTION IS ENCOUNTERED
     When an exception is encountered, the handler examines the instruction
     causing the exception, the state of the floating-point accelerator and
     the sigfpe structure to determine the correct action to take, and the
     program is continued.  In the cases of _UNDERFL, _OVERFL, _DIVZERO,
     _INT_OVERFL, and some instances of _INVALID, an appropriate value is
     substituted for the result of the operation, and the instruction which
     caused the exception is skipped.  For most exceptions arising due to
     an invalid operand ( exceptions), more meaningful behavior may be
     obtained by replacing an erroneous operand.  For these conditions, the
     operand is replaced, and the instruction re-issued.

     sigfpe:        For each enabled exception, the sigfpe structure
                    contains the following fields: repls, count, trace,
                    exit and abort.  For each enabled exception <p>, and
                    each non-zero entry <n> in the sigfpe structure, the
                    trap handler will take the following actions:

     count:         A count of all enabled traps will be printed to stderr
                    at the end of execution of the program, and every at
                    <n>th exception <p>.

     trace:         A dbx stack trace will be printed to stderr every
                    exception <p>, up to <n> times.  You must have dbx
                    installed on your system to use this option.

     abort:         Core dump and abort program upon encountering the <n>th
                    exception <p>.  The abort option takes precedence over
                    the exit option.

     exit:          Exit program upon encountering the <n>th exception <p>.

     repls:         Each of the exceptions _UNDERFL, _OVERFL, _DIVZERO, and
                    _INT_OVERFL has an associated default value which is
                    used as the result of the operation causing the
                    exception.  These default values may be overridden by
                    initializing this integer value.  This value is
                    interpreted as an integer code used to select one of a
                    set of replacement values, or to indicate that the
                    user_routine routine is responsible for setting the
                    value.  These integer codes are listed below:

     _ZERO          Use zero as the replacement value

     _FLUSH_ZERO    Set the flush_zero bit in the Control Status register.
                    This causes a flush to zero without invoking the trap
                    handler.  Works only for underflow traps on the R4000
                    and later processors.  Works like _ZERO for the R3000.

     _MIN           Use the appropriately-typed minimum value as the
                    replacement (i.e., the smallest number which is
                    representable in that format without denormalizing).

     _MAX           Use the appropriately-typed maximum value as the
                    replacement.

     _INF           Use the appropriately-typed value for infinity as the
                    replacement.

     _NAN           Use the appropriately-typed value for not-a-number as
                    the replacement.  (A quiet not-a-number is used.)

     _APPROPRIATE   Use IEEE standard results as the return result for
                    _UNDERFL, _OVERFL, _DIVZERO, and _INVALID exceptions.

     _USER_DETERMINED
                    Invoke the routine user_routine (see note) to set the
                    value of the operation.  If this is the code used for
                    exceptions, all such exceptions will defer to
                    user_routine to set their value.  In this case,
                    invalidop_results_ and invalidop_operands_ will be
                    ignored.

     _NEG           Use the negative of the argument as the replacement
                    operand.  This code is valid only for the cases
                    _SQRT_NEG_X and _RSQRT_NEG_X (see below).

     The default values used as the results of floating-point exceptions
     are:

     ----------------------------------------------------------------------

       #

             Element
             mnemonic


                           Exception condition


                                                    Default value

     ----------------------------------------------------------------------

       0
            (none)
                          (ignored)

       1
            _UNDERFL
                          underflow
                                                    _APPROPRIATE

       2
            _OVERFL
                          overflow
                                                    _APPROPRIATE

       3
            _DIVZERO
                          divide-by-zero
                                                    _APPROPRIATE

       4
            _INVALID
                          invalid operand
                                                    (use tables)

       5
            _INT_OVERFL
                          integer overflow
                                                    _MAX

     ----------------------------------------------------------------------

     The default values for _UNDERFL, _OVERFL, _DIVZERO, and _INVALID
     exceptions will produce the same results as if the instruction were
     re-issued with the original operand(s) and floating-point traps
     disabled.

     Valid values for sigfpe_[_INT_OVERFL].repls are:  _MAX, APPROPRIATE,
     _ZERO, and _USER_DETERMINED, the default being _MAX.

     For  exceptions, the correct action may be either to set the result
     and skip the instruction, or to replace an operand and retry the
     instruction.  There are four cases in which the result is set.  The
     array named invalidop_results_ is consulted for replacement codes for
     these cases:

     ----------------------------------------------------------------------

       #


             Element mnemonic


                                      Exception condition

                                                               Default
                                                               value

     ----------------------------------------------------------------------

       0
            (none)
                                      (ignored)

       1
            _MAGNITUDE_INF_SUBTRACTION
                                      oo - oo
                                                               _NAN

       2
            _ZERO_TIMES_INF
                                      0 * oo
                                                               _NAN

       3
            _ZERO_DIV_ZERO
                                      0/0
                                                               _NAN

       4
            _INF_DIV_INF
                                      oo / oo
                                                               _NAN

     ----------------------------------------------------------------------

     There are ten cases in which an offending operand is replaced.  An
     array named invalidop_operands_ is consulted for user-initialized
     codes for these cases.  Cases 8 through 11 are valid only for the
     mips3 and later architectures.  Array invalidop_operands_ has only 8
     entries (0-7) for the earlier processors.  Each element governs the
     following cases:

     ----------------------------------------------------------------------

       #

             Element
             mnemonic


                           Exception condition


                                                    Default value

     ----------------------------------------------------------------------

       0
            (none)
                          (ignored)

       1
            _SQRT_NEG_X
                          sqrt(-x)
                                                    reissue

       2
            (unused)
                          (ignored)
                                                    with original

       3
            _CVTW_OVERFL
                          conversion to integer
                          caused target to
                          overflow
                                                    operands and



       4
            _CVTW_NA
                          conversion of NaN to int
                                                    floating point

       5
            _CVTW_INF
                          conversion of oo to int
                                                    traps disabled

       6
            _UNORDERED_CMP
                          comparison to NaN

       7
            _SNAN_OP
                          operand was Signaling
                          NaN


       8
            _CVTL_OVERFL
                          conversion to long long
                          caused target to
                          overflow



       9
            _CVTL_NAN
                          conversion of NaN to
                          long long


      10
            _CVTL_INF
                          conversion of oo to long
                          long


      11
            _RSQRT_NEG_X
                          reciprocal sqrt(-x)

     ----------------------------------------------------------------------

WARNINGS
     handle_sigfpes is not reentrant.  In particular, it must not be called
     from within an exception handler.

NOTES
     "Use of user_routine to set values"
          If the integer code defining the replacement value for a
          particular exception condition is _USER_DETERMINED, the user-
          supplied routine user_routine is called:

     (*user_routine)(exception_parameters, value);
     value
          An array of two ints into which user_routine should store the
          replacement value.  If an operand is being replaced, value has a
          copy of the current operand.

     exception_parameters
          An array of five unsigned ints which describe the following
          exception condition:

     --------------------------------------------------------------------
       #

             Element mnemonic

                                      Description

     --------------------------------------------------------------------

       0
             _EXCEPTION_TYPE
                                      The exception type (_DIVZERO, etc).

       1
             _INVALID_ACTION
                                      value = _SET_RESULT if result is
                                      being set.  value = _REPL_OPERAND
                                      if an operand is being replaced.
                                      This element is meaningful only if
                                      the exception type is .





       2
             _INVALID_TYPE
                                      This element is meaningful only if
                                      the exception type is .  It is the
                                      index corresponding to the
                                      particular conditions giving rise
                                      to the exception.  In conjunction
                                      with element 1, this value uniquely
                                      determines the exception condition.
                                      (e.g., if _INVALID_ACTION is
                                      _SET_RESULT and _INVALID_TYPE is 2,
                                      the  exception is due to
                                      _ZERO_TIMES_INF.)











       3
             _VALUE_TYPE
                                      The type of the replacement value -
                                      either _SINGLE, _DOUBLE, _WORD, or
                                      _LONGWORD



       4
             _VALUE_SIGN    T{
                                      The suggested sign user_routine
                                      should use for the replacement
                                      value - either _POSITIVE or
                                      _NEGATIVE.




     --------------------------------------------------------------------

NOTES FOR R8000
     Due to the nature of parallel operations on the R8000 processor, it is
     not possible to determine the true value of the program counter when a
     floating point exception occurs.  Therefore, on that processor,
     libfpe.so will not update either operands or results when floating
     point exceptions occur.  Another anomaly on this processor is that
     counts of floating point exceptions for a particular program may vary
     from run to run.

     When the R8000 processor executes in precise exception mode, libfpe
     behaves as it does on other processors, i.e. operands and results can
     be updated when floating point exceptions occur.  See fpmode(1).

SEE ALSO
     fpc(3c), fsigfpe(3f), get_fpc_csr(3c), set_fpc_csr(3c), signal(3c)