FSIGFPE(3F) FSIGFPE(3F)
handle_sigfpes - floating-point exception handler package
#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
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
Page 1
FSIGFPE(3F) FSIGFPE(3F)
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.
Page 2
FSIGFPE(3F) FSIGFPE(3F)
#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 [Toc] [Back] 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).
Page 3
FSIGFPE(3F) FSIGFPE(3F)
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:
____________________________________________________________
FPE_TURN_OFF_HANDLER_ON_ERROR |nstruct the floating- |
|oint-accelerator to cease |
|ausing exceptions and |
|ontinue. (i.e., disable |
|andling) |
_________________________________|__________________________ |
FPE_ABORT_ON_ERROR |ill the process after |
|iving an error message |
|nd calling a user- |
|upplied cleanup routine |
|f one is provided via the |
|bort_routine parameter. |
_________________________________|__________________________ |
FPE_REPLACE_HANDLER_ON_ERROR |nstall the indicated user |
|outine as the handler |
|hen such an error is |
|ncountered. Future |
|loating-point exceptions |
|ill branch to the user- |
|outine. (see signal(2)) |
_________________________________|__________________________ |
|nstall the indicated user |
|outine as the handler |
|mmediately. Future |
|loating-point exceptions |
|ill branch to the user- |
|outine. (see signal(2)) |
Page 4
FSIGFPE(3F) FSIGFPE(3F)
| FPE_USER_HANDLER |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
Page 5
FSIGFPE(3F) FSIGFPE(3F)
_|___________________________________________________________|
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.
Page 6
FSIGFPE(3F) FSIGFPE(3F)
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
Page 7
FSIGFPE(3F) FSIGFPE(3F)
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
Page 8
FSIGFPE(3F) FSIGFPE(3F)
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:
"" or OFF Execute the program with no
trap handling enabled. Same as
TRAP_FPE undefined. Same as
linking without libfpe.so
ON Same as TRAP_FPE="ALL=DEFAULT".
Alternately, replacement values and actions may be specified for each of
the possible trap types individually. This is accomplished by setting
the environment variable as follows:
setenv TRAP_FPE "item;item;item...."
an item can be one of the following:
traptype=statuslist Where traptype defines the
specific floating point
exception to enable, and
statuslist defines the
list of actions upon
encountering the trap.
DEBUG Confirm the parsing of the
environment variable, and
the trap actions.
Traptype can be one of the following literal strings:
Page 9
FSIGFPE(3F) FSIGFPE(3F)
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.
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.
Page 10
FSIGFPE(3F) FSIGFPE(3F)
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.
Page 11
FSIGFPE(3F) FSIGFPE(3F)
These integer codes are listed below:
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-anumber
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
(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_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
Page 12
FSIGFPE(3F) FSIGFPE(3F)
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 reissued
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:
Page 13
FSIGFPE(3F) FSIGFPE(3F)
__________________________________________________________________________
| 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 |
|3 FPE_CVTW_OVERFL | conversion to integer caused | operands and |
| | target to overflow | |
|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 | |
|7 FPE_SNAN_OP | operand was Signaling Nan | |
|8 FPE_CVTL_OVERFL | conversion to long long caused | |
| | target to overflow | |
|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) | |
|_______________________|________________________________|________________|
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:
Page 14
FSIGFPE(3F) FSIGFPE(3F)
____________________________________________________________________
| array exception_parameters |
| element |
|# mnemonic | description |
|_______________________|___________________________________________|
|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. |
|_______________________|___________________________________________|
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).
Use of the 6.2 beta version of libfpe requires a 6.2 beta operating
system (or later version).
signal(3c), sigfpe(3c), fpc(3c), get_fpc_csr(3c), set_fp_csr(3c)
PPPPaaaaggggeeee 11115555 [ Back ]
|