Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ sigfpe(3C) — IRIX 6.5.3f

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

signal(3c)

fsigfpe(3f)

fpc(3c)

get_fpc_csr(3c)

set_fpc_csr(3c)



SIGFPE(3C)                                                          SIGFPE(3C)



NAME
     handle_sigfpes - floating-point exception handler package

SYNOPSIS
     #include <sigfpe.h>

     void handlesigfpes (int onoff, int enmask,
                          void (*userroutine)(unsigned[5], int[2]),
                          int abortaction,
                          void (*abortroutine)(unsigned int **));

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

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

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

     extern struct sigfpetemplate sigfpe[NEXCEPTIONTYPES+1];

     extern int invalidopresults[NINVALIDOPRESULTS+1];

     extern int invalidopoperands[NINVALIDOPOPERANDS+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).  (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).

     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.




                                                                        Page 1





SIGFPE(3C)                                                          SIGFPE(3C)



     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 handlesigfpes, and the environment variable
     TRAPFPE.  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 the user supplies his own call to
     handlesigfpes he should leave environment variable TRAPFPE undefined or
     set to OFF.  TRAPFPE is supported for Fortran, C, C++ and Pascal.
     Handlesigfpes 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 TRAPFPE environment variable.

     The environment variable is preferable if one wants 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
     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);
          }

     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 section NOTES FOR R8000, below, which describes the
     behavior of libfpe.so on the R8000 processor.





                                                                        Page 2





SIGFPE(3C)                                                          SIGFPE(3C)



HANDLESIGFPES 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 ==
     _ON) or off (onoff == _OFF). (onoff == _DEBUG) is another way to turn on
     handling.  Information from the sigfpe structure will be printed if
     (onoff == _DEBUG).  (all 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 only valid 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: handlesigfpes 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 wish to provide a user_routine. Typedef usert 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 the user to specify that he is supplying
     his own floating point exception handler as the default handler.  Legal
     values are:






















                                                                        Page 3





SIGFPE(3C)                                                          SIGFPE(3C)



             _________________________________________________________
             |_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
above) 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
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 wish 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.
Page 4


SIGFPE(3C)                                                          SIGFPE(3C)



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

     handle_sigfpes(OFF, 0, ...

     disables handling of all SIGFPE signals.

EXAMPLES OF CALLS TO HANDLESIGFPES
          #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 above example does one thing only: it sets up traps of underflow
     which change the resulting value to zero.






                                                                        Page 5





SIGFPE(3C)                                                          SIGFPE(3C)



     The following is a more complicated example.

          #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 */
          }






                                                                        Page 6





SIGFPE(3C)                                                          SIGFPE(3C)



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

                 ....






                                                                        Page 7





SIGFPE(3C)                                                          SIGFPE(3C)



THE ENVIRONMENT VARIABLE TRAPFPE
     If the code has been linked with libfpe.so the runtime startup routine
     will check for the environment variable "TRAPFPE".  The string read as
     the value of TRAPFPE will be interpreted and handlesigfpes will be
     called with the resulting values.

     TRAPFPE is read in upper case letters only. The string assigned to
     TRAPFPE may be in upper case or lower case.  TRAPFPE 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
                                TRAPFPE undefined.  Same as
                                linking without libfpe.so
                           ON   Same as TRAPFPE="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 TRAPFPE "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: Page 8


SIGFPE(3C)                                                          SIGFPE(3C)



                              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.
EXAMPLE OF TRAPFPE
setenv TRAPFPE "ALL=COUNT; UNDERFL=ZERO; OVERFL=IEEE,TRACE(5),
ABORT(100); DIVZERO=ABORT"
Page 9


SIGFPE(3C)                                                          SIGFPE(3C)



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

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,
     INTOVERFL, 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 (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 UNDERFL, OVERFL, DIVZERO, and
     INTOVERFL 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:



















                                                                       Page 10





SIGFPE(3C)                                                          SIGFPE(3C)



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

                           _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:
Page 11


SIGFPE(3C)                                                          SIGFPE(3C)



             ________________________________________________________
              |              values for sigfpe_.repls                |
              |    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 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 array
named invalidop_results_ is consulted for replacement codes for these
cases:
____________________________________________________________
| array invalidop_results_ |
|# element exception |
| |
| mnemonic 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: Page 12


SIGFPE(3C)                                                          SIGFPE(3C)



      _______________________________________________________________________
      |                      array invalidop_operands_                       |
      |      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 operands and |
| |
| target to overflow |
| |
|4 _CVTW_NAN 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) |
| |
|____________________|________________________________|________________|
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:
(*userroutine)(exceptionparameters, value);
value is 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 is an array of five unsigned ints which describe the
exception condition:
Page 13


SIGFPE(3C)                                                          SIGFPE(3C)



          ______________________________________________________________
          |                 array exception_parameters                  |
          |      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 INVALID. |
|
|2 _INVALID_TYPE This element is meaningful only if |
|
| the exception type is 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 _INVALID_ACTION is |
|
| _SET_RESULT and _INVALID_TYPE is 2, |
|
| the INVALID 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 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 signal(3c), fsigfpe(3f), fpc(3c), get_fpc_csr(3c), set_fpc_csr(3c) Page 14

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026