fsigfpe(3F)

handle_sigfpes - floating-point exception handler package

As shipped in IRIX 6.5. First release of IRIX 6.5.

NAME
     handle_sigfpes - floating-point exception handler package

SYNOPSIS
     #include <fsigfpe.h>

     subroutine
     handle_sigfpes(onoff,en_mask,user_routine,abort_action,abort_routine)
     integer *4 onoff, en_mask, abort_action
     integer *4 abort_routine, user_routine
     external abort_routine, user_routine

     structure /sigfpe_template/
     integer * 4 repls
     integer * 4 count
     integer * 4 trace
     integer * 4 abort
     integer * 4 exit
     end structure

     record /sigfpe_template/ fsigfpe (0:FPE_N_EXCEPTION_TYPES)

     common / sigfpe / fsigfpe (0:FPE_N_EXCEPTION_TYPES)

     integer * 4 results(0:FPE_N_INVALIDOP_RESULTS)
     common / invalidop_results / results

     integer * 4 invop(0:FPE_N_INVALIDOP_OPERANDS)
     common / invalidop_operands / invop

     subroutine user_routine (context, result)
     integer * 4 context (5)
     integer * 4 result (2)

     subroutine abort_routine (pc)
     integer * 4 pc


     For 64 bit programs, use the following prototype for abort_routine:

     subroutine abort_routine (pc)
     integer * 8 pc


DESCRIPTION
     The MIPS floating-point accelerator may raise floating-point exceptions,
     signal SIGFPE, due to five conditions:  FPE_OVERFL(overflow),
     FPE_UNDERFL(underflow), FPE_DIVZERO(divide-by-zero), FPE_INEXACT(inexact
     result), or FPE_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 FPE_INT_OVERFL(integer overflow)).  (At the moment, 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).

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

     The library libfpe.so 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 condition
     except FPE_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 the user supplies his own call to handle_sigfpes he
     should leave environment variable TRAP_FPE undefined or set to OFF.
     TRAP_FPE is supported for Fortran, C and Pascal.  Handle_sigfpes is
     supported for 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 one wants to experiment or
     allow any user to experiment with with different trap behaviors with
     minimum effort.

     Libfpe uses System V signal handling and will not work with programs
     which 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.  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);
          }

     Example:

          integer flag

     c    enable flush to zero

          flag = 1

          call flush_to_zero( flag )

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

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

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

     The arguments to handle_sigfpes are as follows:

     onoff is a flag indicating whether handling is being turned on (onoff ==
     FPE_ON) or off (onoff == FPE_OFF). (onoff == FPE_DEBUG) is another way to
     turn on handling.  Information from the fsigfpe structure will be printed
     if (onoff == FPE_DEBUG).  (all the names used in this document are
     defined in fsigfpe.h).

     en_mask indicates which of the five conditions should be unmasked,
     enabling them to raise floating-point exceptions. en_mask is only valid
     if onoff == FPE_ON or onoff == FPE_DEBUG, and is the bitwise or of one or
     more of the constants FPE_EN_UNDERFL, FPE_EN_OVERFL, FPE_EN_DIVZERO,
     FPE_EN_INVALID, and FPE_EN_INT_OVERFL (defined in fsigfpe.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 subroutine 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 wish to provide a user_routine .

     abort_action: If the handler encounters an unexpected condition, an
     inconsistency, or begins looping, the flag abort_action indicates what
     action should be taken.  Another option is for the user to specify that
     he is supplying his own floating point exception handler as the default
     handler.

     Legal values are:

           ____________________________________________________________
                                            instruct the floating-
                                            point-accelerator to cease
                                            causing exceptions and
                                            continue.  (i.e., disable
                                            handling)
            FPE_TURN_OFF_HANDLER_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.
                       FPE_ABORT_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))
             FPE_REPLACE_HANDLER_ON_ERROR






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

























                                                                                                        |

                         FPE_USER_HANDLER

















































           |
















































                                                                       |

          _____________________________________________________________
           |
                                                                       |


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

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

                           subroutine abort_routine(pc)
                                   integer *4 pc

     for 32 bit programs.  (Use integer *8 for 64 bit programs.)

     If abort_action is FPE_REPLACE_HANDLER_ON_ERROR, and abort_routine is
     valid, it will be installed as the new handler.  In this case, the
     instruction which caused the unexpected exception will be re-executed,
     causing a new exception, and abort_routine entered.  Pass a %val(0) if
     you do not wish to provide an abort_action routine.

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

     If the user routine is to be invoked as a floating point exception
     handler, the following prototype (written in c) should be used (see
     <sigfpe.h> and signal(5)):

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

     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
     FPE_UNDERFL, FPE_OVERFL, etc. as appropriate.

     Users can supply separate handlers for each exception type by making
     multiple calls to handle_sigfpes.  See the third example below.
     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.

     call handle_sigfpes(FPE_OFF, 0, ...

     disables handling of all SIGFPE signals.
EXAMPLE OF HANDLE_SIGFPES
          #include <fsigfpe.h>
          C     call this during program startup
          C     to set underflowing values to zero
          C
          C     underflow to zero

                fsigfpe(FPE_UNDERFL).repls = FPE_ZERO
          C
          C     only trap on underflow
                handle_sigfpes(_ON, FPE_EN_UNDERFL , %val(0), FPE_ABORT_ON_ERROR, %val(0));

     The above example does one thing only: it sets up traps of underflow
     which change the resulting value to zero.

     The following is a more complicated example.

          #include <fsigfpe.h>
          C   underflow to zero

                fsigfpe(FPE_UNDERFL).repls = FPE_ZERO

          C     substitute max real/double precision value on overflow

                fsigfpe(FPE_OVERFL).repls=FPE_MAX

          C     trace after 5

                fsigfpe(FPE_UNDERFL).trace=5
                fsigfpe(FPE_OVERFL).trace =5
                fsigfpe(FPE_DIVZERO).trace=5
                fsigfpe(FPE_INVALID).trace=5
                fsigfpe(FPE_INT_OVERFL).trace=5

          C     counts at end

                fsigfpe(FPE_UNDERFL).count=2147483647
                fsigfpe(FPE_OVERFL).count =2147483647
                fsigfpe(FPE_DIVZERO).count=2147483647
                fsigfpe(FPE_INVALID).count=2147483647
                fsigfpe(FPE_INT_OVERFL).count=2147483647

          C     abort after 100 underflows or 100 overflows

                fsigfpe(FPE_UNDERFL).abort=100
                fsigfpe(FPE_OVERFL).abort =100

          C     abort on first divide by zero or hundredth invalid

                fsigfpe(FPE_DIVZERO).abort=1
                fsigfpe(FPE_INVALID).abort=100

                call handle_sigfpes(FPE_ON,
               x                    FPE_EN_UNDERFL +  FPE_EN_OVERFL +
               x                    FPE_EN_DIVZERO +  FPE_EN_INVALID,
               x                    %val(0),
               x                    FPE_ABORT_ON_ERROR,
               x                    %val(0))

          C    do the real application work here

          The 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.

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

                 #include <fsigfpe.h>

                     external                my_invalid_handler

                 c counts at end

                     fsigfpe(FPE_UNDERFL).count=2147483647
                     fsigfpe(FPE_OVERFL).count =2147483647
                     fsigfpe(FPE_DIVZERO).count=2147483647
                     fsigfpe(FPE_INVALID).count=2147483647
                     fsigfpe(FPE_INT_OVERFL).count=2147483647

                 c enable trapping on overflow, using libfpe's trap handler

                     call handle_sigfpes(FPE_ON, FPE_EN_OVERFL, 0, 0, 0)

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

                     call handle_sigfpes(FPE_ON, FPE_EN_INVALID, my_invalid_handler, 0, 0)

                 c do the real application work here

                 ...

                 c turn off trapping of overflows

                     call handle_sigfpes(FPE_OFF, FPE_EN_OVERFL, 0, 0, 0)

                 ...

                 c turn off all handling of SIGFPE signals

                     call handle_sigfpes(FPE_OFF, 0, 0, 0, 0)

THE ENVIRONMENT VARIABLE TRAP_FPE
     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 upper case letters only. The string assigned to
     TRAP_FPE may be in upper case or lower case.  TRAP_FPE can take one of
     two forms: either a global value, or a list of individual items.

     global values:

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



                           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:

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





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


     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 FPE_APPROPRIATE.
  APPROPRIATE   Maps to integer code FPE_APPROPRIATE.
         ZERO   Maps to integer code FPE_ZERO.
   FLUSH_ZERO   Maps to integer code FPE_FLUSH_ZERO (R4000 and later processors).
   FLUSH_ZERO   Maps to integer code FPE_ZERO (other processors).
          MIN   Maps to integer code FPE_MIN.
          MAX   Maps to integer code FPE_MAX.
          INF   Maps to integer code FPE_INF.
          NAN   Maps to integer code FPE_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.

                                  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.
                       COUNT(n)





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




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



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

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

     The example counts all traps, trace the first five overflows, abort on
     the first divide by zero, or the 100th overflow.  It Replaces zero for
     underflows, the "appropriate" value for overflows, divide by zero, and
     invalid operands.

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 FPE_UNDERFL, FPE_OVERFL,
     FPE_DIVZERO, and some instances of FPE_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 (FPE_INVALID 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
     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 FPE_UNDERFL, FPE_OVERFL, FPE_DIVZERO and
     FPE_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 routine user_routine is responsible for
     setting the value.

     These integer codes are listed below:

     FPE_ZERO              use zero as the replacement value

                           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 FPE_ZERO for the
                           R3000.
     FPE_FLUSH_ZERO








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





                           use the appropriately-typed
                           maximum value as the replacement
     FPE_MAX


                           use the appropriately-typed value
                           for infinity as the replacement
     FPE_INF


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




                           use IEEE standard results as the
                           return result for FPE_UNDERFL,
                           FPE_OVERFL, FPE_DIVZERO, and
                           FPE_INVALID exceptions.
     FPE_APPROPRIATE




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










                           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
     FPE_NEG

                           below).







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

             _________________________________________________________
                            values for fsigfpe().repls
                  element
              #   mnemonic      exception condition   default value
             _________________________________________________________
              0   (none)        (ignored)
              1   FPE_UNDERFL   underflow             FPE_APPROPRIATE
              2   FPE_OVERFL    overflow              FPE_APPROPRIATE
              3   FPE_DIVZERO   divide-by-zero        FPE_APPROPRIATE
              4   FPE_INVALID   invalid operand       0 (use tables)
             _________________________________________________________
             |








                              |






                                                    |






                                                                      |











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


     For FPE_INVALID 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
     integer array constituting the named common invalidop_results is
     consulted for replacement codes for these cases:

     _________________________________________________________________________
                     array in common block invalidop_results
                   element
      #   mnemonic                        exception condition   default value
     _________________________________________________________________________
      0   (none)                          (ignored)
      1   FPE_MAGNITUDE_INF_SUBTRACTION   oo - oo               FPE_NAN
      2   FPE_ZERO_TIMES_INF              0 * oo                FPE_NAN
      3   FPE_ZERO_DIV_ZERO               0/0                   FPE_NAN
      4   FPE_INF_DIV_INF                 oo / oo               FPE_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:

    __________________________________________________________________________
                            array invalidop_operands_
            element
     #    mnemonic            exception condition              default value
    __________________________________________________________________________
     0    (none)              (ignored)
     1    FPE_SQRT_NEG_X      sqrt(-x)                         reissue
     2    (unused)            (ignored)                        with original
                              conversion to integer caused
                              target to overflow
     3    FPE_CVTW_OVERFL                                      operands and

     4    FPE _CVTW_NAN       conversion of NaN to int         floating point
     5    FPE_CVTW_INF        conversion of oo to int          traps disabled
     6    FPE_UNORDERED_CMP   comparison to NaN
                              operand was Signaling Nan
     7    FPE_SNAN_OP
                              conversion to long long caused
                              target to overflow
     8    FPE_CVTL_OVERFL

     9    FPE_CVTL_NAN        conversion of NaN to long long
     10   FPE_CVTL_INF        conversion of oo to long long
     11   FPE_RSQRT_NEG_X     reciprocal sqrt(-x)
    __________________________________________________________________________
    |

















                            |















                                                             |















                                                                              |



















NOTE
     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:
                 call user_routine(exception_parameters, value)
     value is an array of two int * 4s 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 is an array of five int * 4s which describe the
     exception condition:

       ____________________________________________________________________
                            array exception_parameters
               element
        #   mnemonic             description
       ____________________________________________________________________
        0   FPE_EXCEPTION_TYPE   the exception type (FPE_DIVZERO, etc).
                                 value = FPE_SET_RESULT if result is
                                 being set.  value = FPE_REPL_OPERAND
                                 if an operand is being replaced.  This
                                 element is meaningful only if the
                                 exception type is FPE_INVALID.
        1   FPE_INVALID_ACTION




                                 This element is meaningful only if the
                                 exception type is FPE_INVALID.  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 FPE_INVALID_ACTION is
                                 FPE_SET_RESULT and FPE_INVALID_TYPE is
                                 2, the FPE_INVALID exception is due to
                                 FPE_ZERO_TIMES_INF.)
        2   FPE_INVALID_TYPE










                                 the type of the replacement value -
                                 either FPE_SINGLE, FPE_DOUBLE,
                                 FPE_WORD, or FPE_LONGWORD.
        3   FPE_VALUE_TYPE


                                 the suggested sign user_routine should
                                 use for the replacement value - either
                                 FPE_POSITIVE or FPE_NEGATIVE.
        4   FPE_VALUE_SIGN


       ____________________________________________________________________
       |


























                               |
























                                                                           |




























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).

NOTES
     Use of the 6.2 beta version of libfpe requires a 6.2 beta operating
     system (or later version).


SEE ALSO
     signal(3c), sigfpe(3c), fpc(3c), get_fpc_csr(3c), set_fp_csr(3c)