FSIGFPE(3F)FSIGFPE(3F)


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
     This routine is only available with the MIPSpro Fortran 77 compiler.

     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)

     * 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 - an integer overflow).  SGI
     compilers currently 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 an assembly
     language.

     After 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 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 you supply your own call to handle_sigfpes, 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, because 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 with
     different trap behaviors with minimum effort.

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

     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
     causes an underflow. Calls to the floating point trap handler consume
     thousands of CPU cycles.

     The following C routine 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 )

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

     The "Notes for R8000" subsection describes the behavior of libfpe.so
     on the R8000 processor.

HANDLE_SIGFPES SUBROUTINE
     The values in the global arrays are described in the "Exceptions"
     section, later in this man page.

     The arguments to handle_sigfpes are as follows:

     onoff          A flag indicating if handling is being turned on (onoff
                    == FPE_ON) or off (onoff == FPE_OFF).

                    (onoff == FPE_DEBUG) is another way to enable 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 user_routine subroutine 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 abort_action flag
                    indicates what action should be taken.  Another option
                    is for the user to specify a different floating point
                    exception handler as the default handler.

                    Legal values for abort_action are the following:

                    FPE_TURN_OFF_HANDLER_ON_ERROR
                                        Instruct the floating-point-
                                        accelerator to cease causing
                                        exceptions and continue (disables
                                        handling).

                    FPE_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
                                        argument.

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

                    FPE_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 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 the following:

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

     This disables handling of all SIGFPE signals.

THE ENVIRONMENT VARIABLE TRAP_FPE
     If the code has been linked with libfpe.so the runtime startup routine
     checks for the environment variable TRAP_FPE.  The  value of TRAP_FPE
     is interpreted and handle_sigfpes is 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.

     The global values can be one of the following:

     " " 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 traptype defines the specific floating point
                         exception to enable, and statuslist defines the
                         list of actions upon encountering the trap.

                         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.

                         The symbolic replacement values can be the
                         following:

                         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 optional actions take an optional integer in
                         parentheses; for any traps that have an action and
                         no specified replacement value, the DEFAULT
                         replacement value is used.  The actions can be the
                         following:

                         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.

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

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:

          call user_routine(exception_parameters, value)

     value is an array of two int * 4 into which user_routine will 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 * 4 which describe the
     exception condition:

     number & element              exception_parameters

     0 FPE_EXCEPTION_TYPE          The exception type (FPE_DIVZERO, etc)

     1 FPE_INVALID_ACTION          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.

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

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

     4 FPE_VALUE_SIGN              The suggested sign user_routine should
                                   use for the replacement value - either
                                   FPE_POSITIVE or FPE_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 does 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).

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

EXAMPLES
   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

          This 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 following environment variable example 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)

   Example of TRAP_FPE
     The following example counts all traps, traces 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.

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

   Exceptions
     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 these
     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 at every nth
               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     Dumps core and aborts program upon encountering the nth
               exception p. The abort option takes precedence over the exit
               option.

     exit      Exit program upon encountering the nth 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 user_routine is responsible for setting
               the value.

               The following are the integer codes used for this purpose:

               FPE_ZERO       Use zero as the replacement value

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

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

               FPE_MAX        Use the appropriately-typed maximum value as
                              the replacement

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

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

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

               FPE_USER_DETERMINED
                              Invoke the routine user_routine 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_
                              are ignored.

               FPE_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 the following:

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

     #


element
mnemonic


exception
condition


defaultvalue


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


     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(usetables)


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

     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:

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

     #


menmonic


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  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:

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

     #


elementmnemonic


exception
condition


defaultvalue


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


     0

(none)

(ignored)


     1

FPE_SQRT_NEG_X

sqrt(-x)

reissuewithoriginal
                                                 operands and floating
                                                 point traps disabled


     2

(unused)

(ignored)


     3

FPE_CVTW_OVERFL

conversionto
                             integer caused
                             target to
                             overflow


     4

FPE_CVTW_NAN

conversionofNaN
                             to int


     5

FPE_CVTW_INF

conversionofoo
                             to int


     6

FPE_UNORDERED_CMP

comparisontoNaN


     7

FPE_SNAN_OP

operandwas
                             Signaling Nan


     8

FPE_CVTL_OVERFL

conversionto
                             long long caused
                             target to
                             overflow.ad


     9

FPE_CVTL_NAN

conversionofNaN
                             to long long


     10

FPE_CVTL_INF

conversionofoo
                             to long long


     11

FPE_RSQRT_NEG_X

reciprocal
                             sqrt(-x)


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

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